@postrun/react 3.2.0 → 4.0.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/dist/index.cjs +52 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +347 -933
- package/dist/index.d.ts +347 -933
- package/dist/index.js +55 -93
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,13 +1,12 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import { createContext, memo, useMemo, useState, Fragment as Fragment$1, useRef, useLayoutEffect, useCallback, useEffect, createElement, useContext, useId } from 'react';
|
|
3
|
-
import { useInfiniteQuery, useQuery, useMutation,
|
|
4
|
-
import { xPollDurationLabel, linkedinPollDurationLabel, captionMaxFor, UploadError, TIKTOK_CAPTION_MAX, createPostrunClient, profilesList, profilesGet, profilesCreate, profilesUpdate, profilesDelete, connectionsConnect, connectionsListByProfile, connectionsGet, connectionsListAccounts, connectionsSelect, connectionsDelete, mediaGet, mediaList, mediaUpdate, mediaDelete, postsList, postsGet, postsCreate, buildCreatePost, isPostPlatform, failedVariants, isPublished, postsValidate, postsUpdate, postsDelete, tiktokCreatorInfo,
|
|
3
|
+
import { useInfiniteQuery, useQuery, useMutation, QueryClient } from '@tanstack/react-query';
|
|
4
|
+
import { xPollDurationLabel, linkedinPollDurationLabel, captionMaxFor, UploadError, TIKTOK_CAPTION_MAX, createPostrunClient, profilesList, profilesGet, profilesCreate, profilesUpdate, profilesDelete, connectionsConnect, connectionsListByProfile, connectionsGet, connectionsListAccounts, connectionsSelect, connectionsDelete, mediaGet, mediaList, mediaUpdate, mediaDelete, postsList, postsGet, postsCreate, buildCreatePost, isPostPlatform, failedVariants, isPublished, postsValidate, postsUpdate, postsDelete, tiktokCreatorInfo, audiencePrivacyOptions, audienceUnselected, parsePrivacyLevel, TIKTOK_AUDIENCE_REQUIRED_HINT, commercialLabelNotice, commercialDisclosureIncomplete, brandedContentDisabledReason, setCommercialDisclosure, setBrandKind, TIKTOK_DISCLOSURE_REQUIRED_HINT, TIKTOK_BRANDED_CONTENT_POLICY_URL, TIKTOK_MUSIC_CONFIRMATION_URL, interactionRows, interactionValueKey, toggleInteraction, tiktokOptionsReady, TIKTOK_PROCESSING_NOTICE, brandedContentDeclared, mediaCreate, uploadFile, waitForMedia, PostrunError } from '@postrun/js';
|
|
5
5
|
export { TIKTOK_CAPTION_MAX, UploadError, captionMaxFor } from '@postrun/js';
|
|
6
6
|
import Nango, { AuthError } from '@nangohq/frontend';
|
|
7
7
|
import pWaitFor, { TimeoutError } from 'p-wait-for';
|
|
8
8
|
import pLimit from 'p-limit';
|
|
9
9
|
import * as query_star from '@postrun/js/query';
|
|
10
|
-
import { googleGetAdTreeOptions } from '@postrun/js/query';
|
|
11
10
|
import { enrichTweet, TweetContainer, TweetHeader, TweetInReplyTo, TweetBody, TweetMedia, QuotedTweet } from 'react-tweet';
|
|
12
11
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
13
12
|
import { FiMessageCircle, FiRepeat, FiHeart, FiBarChart2, FiShare, FiGlobe, FiUsers, FiThumbsUp, FiMessageSquare, FiSend, FiBookmark, FiMoreHorizontal, FiFileText } from 'react-icons/fi';
|
|
@@ -65,7 +64,6 @@ __export(index_exports, {
|
|
|
65
64
|
profileKeys: () => profileKeys,
|
|
66
65
|
resolveVariantMedia: () => resolveVariantMedia,
|
|
67
66
|
tiktokKeys: () => tiktokKeys,
|
|
68
|
-
useAdTree: () => useAdTree,
|
|
69
67
|
useCalendar: () => useCalendar,
|
|
70
68
|
useConnect: () => useConnect,
|
|
71
69
|
useConnection: () => useConnection,
|
|
@@ -984,76 +982,6 @@ function useTikTokCreatorInfo(connectionId) {
|
|
|
984
982
|
queryClient
|
|
985
983
|
);
|
|
986
984
|
}
|
|
987
|
-
function useAdTree(params) {
|
|
988
|
-
const { connectionId, since, until, metrics, expanded = [] } = params;
|
|
989
|
-
const { client, queryClient } = usePostrun();
|
|
990
|
-
const enabled = Boolean(connectionId && since && until);
|
|
991
|
-
const path = { connection_id: connectionId };
|
|
992
|
-
const baseQuery = { since, until, metrics };
|
|
993
|
-
const campaign = useQuery(
|
|
994
|
-
{
|
|
995
|
-
...googleGetAdTreeOptions({ client, path, query: baseQuery }),
|
|
996
|
-
enabled
|
|
997
|
-
},
|
|
998
|
-
queryClient
|
|
999
|
-
);
|
|
1000
|
-
const combine = useCallback(
|
|
1001
|
-
(results) => {
|
|
1002
|
-
const nodes = results.flatMap((q) => q.data?.data ?? []);
|
|
1003
|
-
const loadingById2 = new Map(
|
|
1004
|
-
expanded.map((id, i) => [id, results[i]?.isLoading ?? false])
|
|
1005
|
-
);
|
|
1006
|
-
return { nodes, loadingById: loadingById2 };
|
|
1007
|
-
},
|
|
1008
|
-
// eslint-disable-next-line react-hooks/exhaustive-deps -- expanded is an array; join gives a stable string dep
|
|
1009
|
-
// biome-ignore lint/correctness/useExhaustiveDependencies: intentional string-join dep for array stability
|
|
1010
|
-
[expanded.join(",")]
|
|
1011
|
-
);
|
|
1012
|
-
const { nodes: subtreeNodes, loadingById } = useQueries(
|
|
1013
|
-
{
|
|
1014
|
-
queries: expanded.map((campaignId) => ({
|
|
1015
|
-
...googleGetAdTreeOptions({
|
|
1016
|
-
client,
|
|
1017
|
-
path,
|
|
1018
|
-
query: { ...baseQuery, campaign_id: campaignId }
|
|
1019
|
-
}),
|
|
1020
|
-
enabled
|
|
1021
|
-
})),
|
|
1022
|
-
combine
|
|
1023
|
-
},
|
|
1024
|
-
queryClient
|
|
1025
|
-
);
|
|
1026
|
-
const tree = useMemo(
|
|
1027
|
-
() => groupAdTree([...campaign.data?.data ?? [], ...subtreeNodes]),
|
|
1028
|
-
[campaign.data, subtreeNodes]
|
|
1029
|
-
);
|
|
1030
|
-
const isExpanding = useCallback(
|
|
1031
|
-
(campaignId) => loadingById.get(campaignId) ?? false,
|
|
1032
|
-
[loadingById]
|
|
1033
|
-
);
|
|
1034
|
-
const refetch = useCallback(
|
|
1035
|
-
(...args) => campaign.refetch(...args),
|
|
1036
|
-
[campaign.refetch]
|
|
1037
|
-
);
|
|
1038
|
-
return useMemo(
|
|
1039
|
-
() => ({
|
|
1040
|
-
tree,
|
|
1041
|
-
isLoading: campaign.isLoading,
|
|
1042
|
-
isError: campaign.isError,
|
|
1043
|
-
error: campaign.error,
|
|
1044
|
-
isExpanding,
|
|
1045
|
-
refetch
|
|
1046
|
-
}),
|
|
1047
|
-
[
|
|
1048
|
-
tree,
|
|
1049
|
-
campaign.isLoading,
|
|
1050
|
-
campaign.isError,
|
|
1051
|
-
campaign.error,
|
|
1052
|
-
isExpanding,
|
|
1053
|
-
refetch
|
|
1054
|
-
]
|
|
1055
|
-
);
|
|
1056
|
-
}
|
|
1057
985
|
|
|
1058
986
|
// src/query.ts
|
|
1059
987
|
var query_exports = {};
|
|
@@ -2788,10 +2716,10 @@ var ShareIcon = (p) => /* @__PURE__ */ jsx(Icon, { viewBox: "0 0 20 20", ...p, c
|
|
|
2788
2716
|
var PlusIcon = (p) => /* @__PURE__ */ jsx(Icon, { viewBox: "0 0 48 48", ...p, children: /* @__PURE__ */ jsx("path", { d: "M26 7a1 1 0 0 0-1-1h-2a1 1 0 0 0-1 1v15H7a1 1 0 0 0-1 1v2a1 1 0 0 0 1 1h15v15a1 1 0 0 0 1 1h2a1 1 0 0 0 1-1V26h15a1 1 0 0 0 1-1v-2a1 1 0 0 0-1-1H26V7Z" }) });
|
|
2789
2717
|
var DASH = "\u2011\u2011\u2011";
|
|
2790
2718
|
function commercialLabel(settings) {
|
|
2791
|
-
if (settings?.
|
|
2719
|
+
if (settings?.is_branded_content) {
|
|
2792
2720
|
return "Paid partnership";
|
|
2793
2721
|
}
|
|
2794
|
-
if (settings?.
|
|
2722
|
+
if (settings?.is_brand_organic) {
|
|
2795
2723
|
return "Promotional content";
|
|
2796
2724
|
}
|
|
2797
2725
|
return null;
|
|
@@ -2811,7 +2739,7 @@ function TikTokPostPreviewImpl({
|
|
|
2811
2739
|
const { creator } = creatorInfo;
|
|
2812
2740
|
const handle = creator.username || creator.nickname;
|
|
2813
2741
|
const label = commercialLabel(variant.settings);
|
|
2814
|
-
const isAigc = Boolean(variant.settings?.
|
|
2742
|
+
const isAigc = Boolean(variant.settings?.is_ai_generated);
|
|
2815
2743
|
const pending = resolved.length > 0 && readyMedia.length === 0;
|
|
2816
2744
|
return /* @__PURE__ */ jsxs("div", { className, style: { ...cardStyle4, ...style }, children: [
|
|
2817
2745
|
/* @__PURE__ */ jsx("style", { children: KEYFRAMES }),
|
|
@@ -3089,7 +3017,8 @@ function Notice({ children }) {
|
|
|
3089
3017
|
function CheckRow({
|
|
3090
3018
|
label,
|
|
3091
3019
|
checked,
|
|
3092
|
-
onChange
|
|
3020
|
+
onChange,
|
|
3021
|
+
disabledReason
|
|
3093
3022
|
}) {
|
|
3094
3023
|
const id = useId();
|
|
3095
3024
|
return /* @__PURE__ */ jsxs("label", { htmlFor: id, style: checkRowStyle, children: [
|
|
@@ -3099,11 +3028,13 @@ function CheckRow({
|
|
|
3099
3028
|
id,
|
|
3100
3029
|
type: "checkbox",
|
|
3101
3030
|
checked,
|
|
3031
|
+
disabled: disabledReason !== void 0,
|
|
3102
3032
|
onChange: (e) => onChange(e.target.checked),
|
|
3103
3033
|
style: { accentColor: ACCENT, width: 16, height: 16 }
|
|
3104
3034
|
}
|
|
3105
3035
|
),
|
|
3106
|
-
/* @__PURE__ */ jsx("span", { style: { fontSize: 14 }, children: label })
|
|
3036
|
+
/* @__PURE__ */ jsx("span", { style: { fontSize: 14 }, children: label }),
|
|
3037
|
+
disabledReason ? /* @__PURE__ */ jsx(Hint, { children: disabledReason }) : null
|
|
3107
3038
|
] });
|
|
3108
3039
|
}
|
|
3109
3040
|
var rowStyle3 = {
|
|
@@ -3160,8 +3091,10 @@ function AudienceSelect({
|
|
|
3160
3091
|
value,
|
|
3161
3092
|
onChange
|
|
3162
3093
|
}) {
|
|
3163
|
-
const
|
|
3164
|
-
const
|
|
3094
|
+
const choices = audiencePrivacyOptions(creatorInfo.privacy_options, value);
|
|
3095
|
+
const enabled = choices.flatMap((c) => c.disabled ? [] : [c.level]);
|
|
3096
|
+
const reason = choices.find((c) => c.disabled)?.disabledReason;
|
|
3097
|
+
const unselected = audienceUnselected(value, false);
|
|
3165
3098
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
3166
3099
|
/* @__PURE__ */ jsx(SectionLabel, { children: "Who can view this post" }),
|
|
3167
3100
|
/* @__PURE__ */ jsxs(
|
|
@@ -3171,17 +3104,27 @@ function AudienceSelect({
|
|
|
3171
3104
|
value: value.privacy_level ?? "",
|
|
3172
3105
|
onChange: (e) => onChange({
|
|
3173
3106
|
...value,
|
|
3174
|
-
// Validate against the
|
|
3175
|
-
//
|
|
3176
|
-
privacy_level: parsePrivacyLevel(e.target.value,
|
|
3107
|
+
// Validate against the ENABLED options so a manipulated value
|
|
3108
|
+
// (e.g. SELF_ONLY while branded) can't slip in.
|
|
3109
|
+
privacy_level: parsePrivacyLevel(e.target.value, enabled)
|
|
3177
3110
|
}),
|
|
3178
3111
|
style: selectStyle,
|
|
3179
3112
|
children: [
|
|
3180
3113
|
/* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Select who can view this post" }),
|
|
3181
|
-
|
|
3114
|
+
choices.map((choice) => /* @__PURE__ */ jsx(
|
|
3115
|
+
"option",
|
|
3116
|
+
{
|
|
3117
|
+
value: choice.level,
|
|
3118
|
+
disabled: choice.disabled,
|
|
3119
|
+
title: choice.disabledReason,
|
|
3120
|
+
children: choice.label
|
|
3121
|
+
},
|
|
3122
|
+
choice.level
|
|
3123
|
+
))
|
|
3182
3124
|
]
|
|
3183
3125
|
}
|
|
3184
3126
|
),
|
|
3127
|
+
reason ? /* @__PURE__ */ jsx(Hint, { children: reason }) : null,
|
|
3185
3128
|
unselected ? /* @__PURE__ */ jsx(Hint, { children: TIKTOK_AUDIENCE_REQUIRED_HINT }) : null
|
|
3186
3129
|
] });
|
|
3187
3130
|
}
|
|
@@ -3280,10 +3223,12 @@ var textareaStyle = {
|
|
|
3280
3223
|
};
|
|
3281
3224
|
function CommercialDisclosure({
|
|
3282
3225
|
value,
|
|
3283
|
-
onChange
|
|
3226
|
+
onChange,
|
|
3227
|
+
isVideo
|
|
3284
3228
|
}) {
|
|
3285
3229
|
const labelNotice = commercialLabelNotice(value);
|
|
3286
3230
|
const incomplete = commercialDisclosureIncomplete(value);
|
|
3231
|
+
const brandedLocked = isVideo ? void 0 : brandedContentDisabledReason(value);
|
|
3287
3232
|
return /* @__PURE__ */ jsxs("div", { style: { display: "flex", flexDirection: "column", gap: 8 }, children: [
|
|
3288
3233
|
/* @__PURE__ */ jsx(SectionLabel, { children: "Disclose post content" }),
|
|
3289
3234
|
/* @__PURE__ */ jsx(
|
|
@@ -3315,6 +3260,7 @@ function CommercialDisclosure({
|
|
|
3315
3260
|
{
|
|
3316
3261
|
label: "Branded content",
|
|
3317
3262
|
checked: value.branded_content,
|
|
3263
|
+
disabledReason: brandedLocked,
|
|
3318
3264
|
onChange: (next) => onChange(setBrandKind(value, "branded_content", next))
|
|
3319
3265
|
}
|
|
3320
3266
|
),
|
|
@@ -3404,7 +3350,7 @@ function TikTokPublishPanel({
|
|
|
3404
3350
|
const isVideo = postType === "video";
|
|
3405
3351
|
const captionOver = caption.length > captionMaxFor(postType);
|
|
3406
3352
|
const mediaOk = mediaCountValid(postType, variant.media?.length ?? 0);
|
|
3407
|
-
const ready = !captionOver && mediaOk && tiktokOptionsReady(options);
|
|
3353
|
+
const ready = !captionOver && mediaOk && tiktokOptionsReady(options, isVideo);
|
|
3408
3354
|
return /* @__PURE__ */ jsxs(
|
|
3409
3355
|
"div",
|
|
3410
3356
|
{
|
|
@@ -3425,8 +3371,17 @@ function TikTokPublishPanel({
|
|
|
3425
3371
|
postType
|
|
3426
3372
|
}
|
|
3427
3373
|
),
|
|
3428
|
-
/* @__PURE__ */
|
|
3429
|
-
|
|
3374
|
+
isVideo ? null : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3375
|
+
/* @__PURE__ */ jsx(Divider, {}),
|
|
3376
|
+
/* @__PURE__ */ jsx(
|
|
3377
|
+
AudienceSelect,
|
|
3378
|
+
{
|
|
3379
|
+
creatorInfo,
|
|
3380
|
+
value: options,
|
|
3381
|
+
onChange: onOptionsChange
|
|
3382
|
+
}
|
|
3383
|
+
)
|
|
3384
|
+
] }),
|
|
3430
3385
|
/* @__PURE__ */ jsx(Divider, {}),
|
|
3431
3386
|
/* @__PURE__ */ jsx(
|
|
3432
3387
|
InteractionToggles,
|
|
@@ -3438,7 +3393,14 @@ function TikTokPublishPanel({
|
|
|
3438
3393
|
}
|
|
3439
3394
|
),
|
|
3440
3395
|
/* @__PURE__ */ jsx(Divider, {}),
|
|
3441
|
-
/* @__PURE__ */ jsx(
|
|
3396
|
+
/* @__PURE__ */ jsx(
|
|
3397
|
+
CommercialDisclosure,
|
|
3398
|
+
{
|
|
3399
|
+
value: options,
|
|
3400
|
+
onChange: onOptionsChange,
|
|
3401
|
+
isVideo
|
|
3402
|
+
}
|
|
3403
|
+
),
|
|
3442
3404
|
isVideo ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3443
3405
|
/* @__PURE__ */ jsx(Divider, {}),
|
|
3444
3406
|
/* @__PURE__ */ jsx(
|
|
@@ -3449,9 +3411,9 @@ function TikTokPublishPanel({
|
|
|
3449
3411
|
control: /* @__PURE__ */ jsx(
|
|
3450
3412
|
Switch,
|
|
3451
3413
|
{
|
|
3452
|
-
checked: options.
|
|
3414
|
+
checked: options.ai_generated,
|
|
3453
3415
|
ariaLabel: "AI-generated content",
|
|
3454
|
-
onChange: (next) => onOptionsChange({ ...options,
|
|
3416
|
+
onChange: (next) => onOptionsChange({ ...options, ai_generated: next })
|
|
3455
3417
|
}
|
|
3456
3418
|
)
|
|
3457
3419
|
}
|
|
@@ -3504,6 +3466,6 @@ var postButtonStyle = {
|
|
|
3504
3466
|
transition: "opacity 160ms ease"
|
|
3505
3467
|
};
|
|
3506
3468
|
|
|
3507
|
-
export { ArticleCard, AudienceSelect, CommercialDisclosure, Connect, Declaration, DocumentCard, InstagramPostPreview, InteractionToggles, LinkedInPostPreview, Poll, PostrunProvider, ReelPreview, TikTokCaptionField, TikTokPostPreview, TikTokPublishPanel, XPoll, XPostPreview, connectionKeys, isReadyMedia, mediaKeys, postKeys, profileKeys, resolveVariantMedia, tiktokKeys,
|
|
3469
|
+
export { ArticleCard, AudienceSelect, CommercialDisclosure, Connect, Declaration, DocumentCard, InstagramPostPreview, InteractionToggles, LinkedInPostPreview, Poll, PostrunProvider, ReelPreview, TikTokCaptionField, TikTokPostPreview, TikTokPublishPanel, XPoll, XPostPreview, connectionKeys, isReadyMedia, mediaKeys, postKeys, profileKeys, resolveVariantMedia, tiktokKeys, useCalendar, useConnect, useConnection, useConnections, useCreatePost, useCreateProfile, useDeleteMedia, useDeletePost, useDeleteProfile, useDisconnect, useDiscoverableAccounts, useInfiniteList, useMedia, useMediaInfinite, useMediaList, useMediaUpload, usePost, usePostrun, usePostrunMutation, usePostrunQuery, usePosts, usePostsInfinite, useProfile, useProfiles, useProfilesInfinite, useSelectAccount, useTikTokCreatorInfo, useUpdateMedia, useUpdatePost, useUpdateProfile, useValidatePost };
|
|
3508
3470
|
//# sourceMappingURL=index.js.map
|
|
3509
3471
|
//# sourceMappingURL=index.js.map
|