@joai/core 4.16.0 → 5.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.d.mts +44 -4
- package/dist/index.mjs +60 -2
- package/package.json +2 -13
- package/dist/react/index.d.mts +0 -362
- package/dist/react/index.mjs +0 -729
package/dist/index.d.mts
CHANGED
|
@@ -584,7 +584,7 @@ type Media = {
|
|
|
584
584
|
};
|
|
585
585
|
//#endregion
|
|
586
586
|
//#region src/integration/types.d.ts
|
|
587
|
-
type IntegrationType = 'none' | 'webhook' | 'api-token' | 'telegram' | 'slack' | 'whatsapp' | 'whatsapp-personal' | 'twilio' | 'sms' | 'n8n' | 'apple-health' | 'mcp' | 'x' | 'xchat' | 'instagram' | 'facebook' | 'linkedin' | 'grok' | 'cloudflare' | 'email' | 'calendar' | 'embed' | 'discord' | 'github' | 'push' | 'sentry' | 'readwise';
|
|
587
|
+
type IntegrationType = 'none' | 'webhook' | 'api-token' | 'telegram' | 'slack' | 'whatsapp' | 'whatsapp-personal' | 'twilio' | 'sms' | 'n8n' | 'apple-health' | 'mcp' | 'x' | 'xchat' | 'instagram' | 'facebook' | 'linkedin' | 'grok' | 'cloudflare' | 'google-search-console' | 'email' | 'calendar' | 'embed' | 'discord' | 'github' | 'push' | 'sentry' | 'readwise';
|
|
588
588
|
type IntegrationDetails = {
|
|
589
589
|
type: IntegrationType;
|
|
590
590
|
name: string;
|
|
@@ -1128,6 +1128,7 @@ declare const NativeApps: {
|
|
|
1128
1128
|
readonly Social: "social";
|
|
1129
1129
|
readonly Studio: "studio";
|
|
1130
1130
|
readonly Loyalty: "loyalty";
|
|
1131
|
+
readonly Documents: "documents";
|
|
1131
1132
|
};
|
|
1132
1133
|
type NativeApp = (typeof NativeApps)[keyof typeof NativeApps];
|
|
1133
1134
|
declare const nativeAppSlugs: NativeApp[];
|
|
@@ -2440,7 +2441,7 @@ type AppointmentRequest = {
|
|
|
2440
2441
|
};
|
|
2441
2442
|
//#endregion
|
|
2442
2443
|
//#region src/automation/types.d.ts
|
|
2443
|
-
type AutomationTriggerType = 'prop' | 'segment' | 'manual' | 'webhook';
|
|
2444
|
+
type AutomationTriggerType = 'prop' | 'segment' | 'manual' | 'webhook' | 'site_monthly_report';
|
|
2444
2445
|
type AutomationActionType = 'wait' | 'halt' | 'warp' | 'branch';
|
|
2445
2446
|
type AutomationEnrollmentStatus = 'active' | 'completed' | 'skipped';
|
|
2446
2447
|
type AutomationEnrollmentChange = 'created' | 'advanced' | 'sent' | 'completed' | 'skipped' | 'errored';
|
|
@@ -2654,6 +2655,45 @@ type PatchContentInput = {
|
|
|
2654
2655
|
publish?: boolean;
|
|
2655
2656
|
};
|
|
2656
2657
|
//#endregion
|
|
2658
|
+
//#region src/content/image-processing.d.ts
|
|
2659
|
+
type ImageDimensions = {
|
|
2660
|
+
width: number;
|
|
2661
|
+
height: number;
|
|
2662
|
+
};
|
|
2663
|
+
type ImageCropState = {
|
|
2664
|
+
x: number;
|
|
2665
|
+
y: number;
|
|
2666
|
+
zoom: number;
|
|
2667
|
+
};
|
|
2668
|
+
type ImageCropRectangle = {
|
|
2669
|
+
x: number;
|
|
2670
|
+
y: number;
|
|
2671
|
+
width: number;
|
|
2672
|
+
height: number;
|
|
2673
|
+
};
|
|
2674
|
+
type ImageDimensionRules = {
|
|
2675
|
+
minWidth?: number;
|
|
2676
|
+
minHeight?: number;
|
|
2677
|
+
maxWidth?: number;
|
|
2678
|
+
maxHeight?: number;
|
|
2679
|
+
maxPixels?: number;
|
|
2680
|
+
};
|
|
2681
|
+
type ImageCompressionOptions = {
|
|
2682
|
+
maxWidth?: number;
|
|
2683
|
+
maxHeight?: number;
|
|
2684
|
+
mimeType?: 'image/jpeg' | 'image/png' | 'image/webp';
|
|
2685
|
+
quality?: number;
|
|
2686
|
+
};
|
|
2687
|
+
type ImageCropOptions = {
|
|
2688
|
+
aspectRatio: number;
|
|
2689
|
+
outputWidth?: number;
|
|
2690
|
+
outputHeight?: number;
|
|
2691
|
+
};
|
|
2692
|
+
declare const validateImageDimensions: (dimensions: ImageDimensions, rules: ImageDimensionRules) => "too-small" | "too-large" | null;
|
|
2693
|
+
declare const imageCropRectangle: (dimensions: ImageDimensions, aspectRatio: number, crop: ImageCropState) => ImageCropRectangle;
|
|
2694
|
+
declare const containedImageDimensions: (source: ImageDimensions, options: ImageCompressionOptions) => ImageDimensions;
|
|
2695
|
+
declare const cropOutputDimensions: (source: ImageDimensions, options: ImageCropOptions, compression: ImageCompressionOptions) => ImageDimensions;
|
|
2696
|
+
//#endregion
|
|
2657
2697
|
//#region src/address/formatAddressSnapshot.d.ts
|
|
2658
2698
|
/** Accepts camelCase API snapshots and legacy snake_case stored snapshots. */
|
|
2659
2699
|
declare const formatAddressSnapshotLines: (address: AddressSnapshot | null | undefined) => string[];
|
|
@@ -3204,7 +3244,7 @@ declare const buildMcpServerName: (slug: string, teamName?: string) => string;
|
|
|
3204
3244
|
declare const buildAgentMcpServerName: (agentName: string, teamName?: string) => string;
|
|
3205
3245
|
//#endregion
|
|
3206
3246
|
//#region src/metric/types.d.ts
|
|
3207
|
-
type MetricSource = 'cloudflare';
|
|
3247
|
+
type MetricSource = 'cloudflare' | 'google_search_console';
|
|
3208
3248
|
type Metric = {
|
|
3209
3249
|
key: string;
|
|
3210
3250
|
value: number;
|
|
@@ -4865,4 +4905,4 @@ type CliSessionStatus = {
|
|
|
4865
4905
|
meta: CliSessionMeta | null;
|
|
4866
4906
|
};
|
|
4867
4907
|
//#endregion
|
|
4868
|
-
export { AUTOMATION_SEND_CHANNELS, Achievement, Address, AddressCreatePayload, AddressInput, AddressSnapshot, type AddressType, AddressTypes, AddressUpdatePayload, Affiliate, AffiliateStatus, AffiliateTier, AffiliateTierName, Agent, AgentActionHistoryEntry, AgentCharacter, AgentDelegatable, AgentEngine, AgentExecuteHandler, AgentExecuteOptions, AgentGender, AgentMessageMeta, AgentMessageOptions, AgentPrivate, AgentSettings, AgentSetupTarget, AgentSimple, AgentToolingAccess, AgentTrustedActionRule, AgentWalletMode, AggregatedRoute, AiCostEntry, AiCostsResponse, AiCostsSummary, Alert, ApiToken, AppAccessRule, AppEnv, AppFile, AppFileType, AppIngestion, AppSetupTarget, AppendKvEntryResult, AppointmentAvailability, AppointmentAvailabilityService, AppointmentAvailabilitySlot, AppointmentBooking, AppointmentBookingContext, AppointmentPolicy, AppointmentPolicySync, AppointmentPolicyUpsert, AppointmentRequest, AppointmentSlot, Artifact, ArtifactBlock, ArtifactBlockType, ArtifactContactSummary, ArtifactCreatePayload, ArtifactDeliverIntegration, ArtifactDeliverPayload, ArtifactDelivery, ArtifactLink, ArtifactStatus, ArtifactType, ArtifactUpdatePayload, AuthUser, Automation, AutomationAction, AutomationActionConfig, AutomationActionInput, AutomationActionType, AutomationAudiencePreview, AutomationCreatePayload, AutomationEnrollment, AutomationEnrollmentChange, AutomationEnrollmentStatus, AutomationEnrollmentUpdatedPayload, AutomationSendChannel, AutomationSendChannelId, AutomationSkipReason, AutomationStats, AutomationTriggerConfig, AutomationTriggerType, AutomationUpdatePayload, BillingManageAccess, Blueprint, BlueprintOnboardingStep, BlueprintRedirect, BlueprintSettings, BlueprintShortcut, BlueprintTask, BlueprintTeam, BoardSummaryViewable, BookmarkEntry, BrandBackend, BrandIntegration, BrandIntegrationAction, BrandIntegrationProvider, BrandSearchHit, BrandSiteConfig, BrandSourceConfig, Budget, ByokProviderConfig, ByokProviderName, ByokProviders, CAMPAIGN_CHANNELS, CONTACT_MESSAGE_SEND_WARP, CalendarProvider, CalendarStatus, Campaign, CampaignApproval, CampaignAudiencePreview, CampaignAudiencePreviewPayload, CampaignCategory, CampaignChannel, CampaignChannelId, CampaignCreatePayload, CampaignRecipient, CampaignRecipientStatus, CampaignSkipReason, CampaignSkipReasons, CampaignStats, CampaignStatus, CampaignUpdatePayload, Card, Cart, CartItem, CartLine, Challenge, Challenges, ChangelogEntry, Character, ChatClientAction, ChatClientThought, ChatStreamData, ChatStreamEventType, CheckoutSnapshot, CheckoutSnapshotRequest, CliSessionMeta, CliSessionStatus, CommissionAgreement, Configuration, Contact, ContactActivity, ContactActivityAuthor, ContactActivityType, ContactConsent, ContactConsentStatus, ContactCreatePayload, ContactFormData, ContactHealth, ContactRelation, ContactRelationCategory, ContactRelationContact, ContactRelationDirection, ContactRelationPayload, ContactRelationType, ContactRelationUpdatePayload, ContactViewable, Content, ContentDefinition, ContentEntry, ContentField, ContentFieldType, ContentPatch, ContentStatus, ContentValue, ContentVersion, Contract, ContractCategoryDisplayNames, ContractCategoryName, ContractCodeMetadata, ContractEntity, ContractOnNetwork, ContractVersion, ContractsAddressConfig, CortexExecuteOptions, Coupon, CouponCondition, CouponRestrictedItem, CouponRestrictedItemType, CreateContentInput, CreateHookPayload, CreateInboundHookPayload, CreateInternalHookPayload, CreateKvFieldPayload, CreateWarpLinkedHookPayload, CreateWebHookPayload, DefaultAppLocale, DefaultCodeMetadata, DefaultInviteTeamRole, DemoFlow, DemoMessage, Desk, DeskItem, DeskItemRole, Document, EarnResponse, Earning, Element, ElementSpec, ElementType, ElementVariation, EmailProvider, EmbedStatus, EncryptionStatus, Entity, EntityDirectExecuteRequest, EntityProposable, EntitySignable, EntityTemplate, Experience, FeatureSetupTarget, FileInfo, FileMetadata, Flow, FlowCategory, FlowInputMapping, FlowStatus, FlowStep, Fulfillment, FulfillmentFlowAction, FulfillmentFlowStep, FulfillmentLocation, type FulfillmentMethod, FulfillmentMethods, type FulfillmentStatus, FulfillmentStatuses, GamificationData, GamificationEventType, Goal, GoalCreatePayload, GoalPriority, GoalProgressViewable, GoalStatus, GuestBuyer, HintOptions, HintPosition, Hook, HookSample, HookTrigger, HookTriggerCondition, HookTriggerInput, HttpService, IAppResponse, IHttpService, IRequestOptions, IngestionSourceType, IngestionStatus, Inquiry, InquiryStatus, InquiryType, Integration, IntegrationConnectionDetails, IntegrationDetails, IntegrationMeta, IntegrationType, Intent, InviteableTeamRoles, Item, ItemCreatePayload, ItemExecutionStatus, ItemPriority, ItemStatus, ItemUpdatePayload, ItemViewable, JoaiUrls, JsonValue, KvEntry, KvEntryPayload, KvField, KvFieldWithEntries, KvValue, Kyc, KycStatus, Link, LinkCreatePayload, LinkScanHistory, LinkStats, LinkUpdatePayload, LinkVariation, LinkVariationBatchCreatePayload, LinkVariationCreatePayload, LocalAgentWallet, LoyaltyAccount, LoyaltyMember, LoyaltyNextTier, LoyaltyProgram, LoyaltyPromotion, LoyaltyReward, LoyaltyStatus, LoyaltyTier, LoyaltyTierInfo, LoyaltyTransaction, McpToolCall, McpToolCallBroadcast, McpToolCallStatus, Media, MediaAspectRatio, MediaAttributes, MediaItems, MediaLibraryAttributes, MediaMime, Meeting, MeetingConferenceProvider, MeetingFeature, MeetingJoinInfo, MeetingJoinTeam, MeetingParticipant, MeetingSessionState, MeetingSpeakerAssignment, MeetingStatus, MeetingSummary, MeetingTranscriptEntry, MeetingUsage, Memory, Message, MessageId, MessageRole, Metric, MetricSource, MetricsResult, Milestone, MilestoneType, Mission, MissionBudget, MissionCreatePayload, MissionPlan, MissionPriority, MissionSchedule, MissionStatus, MissionViewable, MollieTerminalPaymentResult, MultimodalContent, MultimodalFile, NATIVE_AUTH_TOKEN_PARAM, NativeApp, NativeApps, Notification, NotificationAction, NotificationAgent, NotificationChannel, NotificationSetting, OG_IMAGE_CONFIG, OG_IMAGE_HEIGHT, OG_IMAGE_WIDTH, ORDER_FULFILLMENT_STATUSES, ORDER_POST_CHECKOUT_STATUSES, OUTBOUND_CHANNELS, OfficeAgent, OfficeEntity, OfficeEntityKind, OfficeLiveOverrides, OfficeMember, OfficeSnapshot, OfficeStatus, OfficeStatusFilter, OfficeTypeFilter, OgImageColors, Order, OrderConfigurationItem, OrderContext, OrderItem, OrderPriceMode, OrderSource, OrderStatus, OrderStatusDisplay, OrderType, OutboundChannel, OutboundChannelId, PLATFORM_CURRENCY, PaginatedResponse, Pass, PatchContentInput, PaymentAccount, PaymentAccountOnboarding, PaymentProvider, PayoutEntry, PeriodTypeLabels, PeriodTypeOptions, PermissionConfigType, PermissionPresetName, PermissionPresetNames, PersonaQuestionable, PickupNextAction, Plan, PlanBenefit, PlanExtra, PlanFeature, PlanInterval, PolicyMethod, PolicySetting, PricingModel, Product, ProductDetailKind, ProductDetailRow, ProductDetailSection, ProductDetailText, ProductDiscount, ProductMeta, ProductPieces, ProductRating, ProductRelation, ProductRelationType, ProductVariation, ProductVariationMeta, ProductVariationType, ProgramSettings, Project, ProjectAspectRatio, ProjectAssembly, ProjectCaptionStyle, ProjectClipCandidate, ProjectClips, ProjectExport, ProjectExportAsset, ProjectExportResponse, ProjectImages, ProjectInputAssistIntent, ProjectInputAssistResponse, ProjectMutation, ProjectOutputPreset, ProjectOutputType, ProjectPlan, ProjectRender, ProjectRenderMode, ProjectSelectedClip, ProjectShot, ProjectSoundtrack, ProjectSourceMedia, ProjectStatus, ProjectStudioHistoryEntry, ProjectStudioQuestion, ProjectStudioResponse, ProjectStudioStage, ProjectStudioState, ProjectStudioSummary, ProjectStyleDirection, ProjectTranscript, ProjectTranscriptSegment, Proposal, ProposalAction, ProposalActionPayment, ProposalActionPaymentSerializable, ProposalActionSerializable, ProposalPollOption, ProposalStatus, PublicFormResults, PurchaseOptions, PurchaseResult, RampProvider, RampProviderInfo, Reactions, RecentExperience, RedeemResponse, Reminder, Return, type ReturnStatus, ReturnStatuses, ReturnUpdateStatus, ReturnUpdateStatuses, Room, RoomId, RoomKind, ScInfo, SchedulePreset, SecretAuthorizable, SecretSettable, Segment, SegmentCondition, SegmentConditionType, SegmentCountPayload, SegmentCountResult, SegmentCreatePayload, SegmentGroup, SendableActivityUpdate, SendableAgentAction, SendableAgentMessage, SendableAgentThought, SendableMedia, SendableUserMessage, Service, SetKvEntryResult, SharedSocialPost, ShippingCarrierOption, ShippingRate, ShippingZone, Shortcut, Site, SiteAgent, SiteBrand, SiteRoute, SiteTeam, SiteType, Skill, SkillMediaBindingRole, SkillMediaBindingRoleValue, SkillScope, SkillScopeValue, SkillType, SkillTypeValue, SocialAuthProvider, SocialBot, SocialPlatform, SocialPost, SocialPostConnection, SocialPostCreatePayload, SocialPostGenerateCaptionPayload, SocialPostGeneratedCaption, SocialPostPlatform, SocialPostStatus, SocialPostUpdatePayload, StampResponse, StoreAgent, StoreCheckoutItem, StoreData, StoreEntityType, StoreInfo, StoreItem, StoreListing, StorePriceTier, StorePricing, StorePurchasable, StorePurchaseResult, Streak, Subscription, SubscriptionDelivery, SubscriptionInterval, SubscriptionPlan, SubscriptionStatus, SupportedAppLocale, SupportedAppLocales, Swarm, Tag, TagType, Task, TaxBreakdownRow, TaxClass, Team, TeamAccessCatalog, TeamAccessConfig, TeamBrand, TeamCategory, TeamCurrencySource, TeamEarning, TeamEarningsBalance, TeamFeature, TeamFeatureAccess, TeamFeatureArea, TeamFeatureUsage, TeamManageAccess, TeamMember, TeamMeta, TeamOrderStats, TeamPayout, TeamPayoutAddress, TeamPlace, TeamPrivate, TeamSettings, TeamUsage, TeamViewAccess, TerminalConnectionToken, TerminalPaymentIntent, Tier, TierFeature, TierName, ToggleKvFieldResult, TranscriptEntry, TranscriptionCorrection, TranscriptionResponse, TranslatableValue, UNIFIED_MCP_SERVER_NAME, Update, UpdateCreatePayload, UpdateRelation, UpdateStats, UpdateStatus, UpdateType, UpdateUpdatePayload, Upgrade, UpgradeSourceType, UpgradeStatus, User, UserInterest, UserMode, type UserPermission, UserPermissions, UserPrivate, type UserRole, UserRoles, UserSettings, UserSocialAccount, UserStats, VolumePrice, Wallet, WalletList, WarpApprovable, WarpBackend, WarpBackendStatus, WarpBatchItem, WarpBatchable, WarpCloudExecutable, WarpCreateable, WarpExecutable, WarpExecutionBackend, WarpExtras, WarpExtrasFaq, WarpInputable, WarpScreenshotVariant, WarpSearchHit, WarpSelectable, WarpSelectableDetails, WarpSuggestion, WarpTestable, WarpViewable, WebHookTriggerEvent, WorkspaceCloudFile, WorkspaceContext, WorkspaceInfo, WorkspaceSettings, XIntegrationStatus, abbreviateNumber, addressTypeValues, automationSendChannel, buildAgentMcpServerName, buildAgentSetupClipboardText, buildAppSetupClipboardText, buildFeatureSetupClipboardText, buildMcpServerName, canOpenFulfillmentFlow, canTransitionOrderStatus, cartLineTotal, cartPayableTotal, createCursorMcpInstallLink, defaultInviteTeamRole, documentShareUrl, firstValidationMessage, formatAddressSnapshotLines, fulfillmentMethodValues, fulfillmentStatusValues, getAgentSetupPromptUrl, getAgentsBaseUrl, getApiBaseUrl, getAppBaseUrl, getAssetAppLogoUrl, getAssetChainLogoUrl, getAssetPartnerLogoUrl, getAssetTokenLogoUrl, getAssetWalletLogoUrl, getCortexBaseUrl, getDigestBaseUrl, getDocumentsBaseUrl, getEditableOrderStatuses, getFormsBaseUrl, getFulfillmentFlowAction, getFulfillmentFlowStepperIndex, getGenBaseUrl, getInvoiceEditableStatuses, getLoginUrl, getMcpServerAgentUrl, getMcpServerUrl, getPickupEditableStatuses, getPickupNextAction, getShippingEditableStatuses, getSiteUrl, getSitesBaseUrl, getSitesRootDomain, getStoreBaseUrl, getWarpScreenshotUrl, hasAllPermissions, hasAllTeamPermissions, hasAnyPermissions, hasPermission, hasTeamPermission, integrationSlugForChannel, inviteableTeamRoles, isAutomationSendChannelId, isCampaignChannelId, isCompleteAddressInput, isContactMessageAction, isContactMessageWarpId, isFileFormatAudio, isFileFormatImage, isFileFormatVideo, isNativeApp, isNativeAppAccessible, isNativeAppGated, isNativeAppLocked, isOrderCanceled, isOrderInFulfillment, isOrderPending, isOrderPostCheckout, isPickupOrderReady, isPickupReady, isSupportedAppLocale, isTeamFeatureAccessible, isTeamFeatureGated, isTeamFeatureLocked, isUnifiedMcpUrl, isUserRole, localize, nativeAppSlugs, normalizeAutomationActionType, ogImageUrl, outboundChannel, permissionPresetRules, resolveAccessCatalog, resolveAgentMcpUrl, resolveConnectMcpUrl, resolveFulfillmentFlowStep, resolveOrderStatusDisplay, resolveTeamCurrency, resolveWarpText, returnStatusValues, returnUpdateStatusValues, sanitizeAlphanumeric, sanitizeNumeric, slugifyMcpSegment, teamCategories, toCurrencyDisplay, toHexEncodedNonce, toNameInitials, toNftId, toPreviewText, userPermissionValues, userRoleValues, validationMessageFor, withRetry };
|
|
4908
|
+
export { AUTOMATION_SEND_CHANNELS, Achievement, Address, AddressCreatePayload, AddressInput, AddressSnapshot, type AddressType, AddressTypes, AddressUpdatePayload, Affiliate, AffiliateStatus, AffiliateTier, AffiliateTierName, Agent, AgentActionHistoryEntry, AgentCharacter, AgentDelegatable, AgentEngine, AgentExecuteHandler, AgentExecuteOptions, AgentGender, AgentMessageMeta, AgentMessageOptions, AgentPrivate, AgentSettings, AgentSetupTarget, AgentSimple, AgentToolingAccess, AgentTrustedActionRule, AgentWalletMode, AggregatedRoute, AiCostEntry, AiCostsResponse, AiCostsSummary, Alert, ApiToken, AppAccessRule, AppEnv, AppFile, AppFileType, AppIngestion, AppSetupTarget, AppendKvEntryResult, AppointmentAvailability, AppointmentAvailabilityService, AppointmentAvailabilitySlot, AppointmentBooking, AppointmentBookingContext, AppointmentPolicy, AppointmentPolicySync, AppointmentPolicyUpsert, AppointmentRequest, AppointmentSlot, Artifact, ArtifactBlock, ArtifactBlockType, ArtifactContactSummary, ArtifactCreatePayload, ArtifactDeliverIntegration, ArtifactDeliverPayload, ArtifactDelivery, ArtifactLink, ArtifactStatus, ArtifactType, ArtifactUpdatePayload, AuthUser, Automation, AutomationAction, AutomationActionConfig, AutomationActionInput, AutomationActionType, AutomationAudiencePreview, AutomationCreatePayload, AutomationEnrollment, AutomationEnrollmentChange, AutomationEnrollmentStatus, AutomationEnrollmentUpdatedPayload, AutomationSendChannel, AutomationSendChannelId, AutomationSkipReason, AutomationStats, AutomationTriggerConfig, AutomationTriggerType, AutomationUpdatePayload, BillingManageAccess, Blueprint, BlueprintOnboardingStep, BlueprintRedirect, BlueprintSettings, BlueprintShortcut, BlueprintTask, BlueprintTeam, BoardSummaryViewable, BookmarkEntry, BrandBackend, BrandIntegration, BrandIntegrationAction, BrandIntegrationProvider, BrandSearchHit, BrandSiteConfig, BrandSourceConfig, Budget, ByokProviderConfig, ByokProviderName, ByokProviders, CAMPAIGN_CHANNELS, CONTACT_MESSAGE_SEND_WARP, CalendarProvider, CalendarStatus, Campaign, CampaignApproval, CampaignAudiencePreview, CampaignAudiencePreviewPayload, CampaignCategory, CampaignChannel, CampaignChannelId, CampaignCreatePayload, CampaignRecipient, CampaignRecipientStatus, CampaignSkipReason, CampaignSkipReasons, CampaignStats, CampaignStatus, CampaignUpdatePayload, Card, Cart, CartItem, CartLine, Challenge, Challenges, ChangelogEntry, Character, ChatClientAction, ChatClientThought, ChatStreamData, ChatStreamEventType, CheckoutSnapshot, CheckoutSnapshotRequest, CliSessionMeta, CliSessionStatus, CommissionAgreement, Configuration, Contact, ContactActivity, ContactActivityAuthor, ContactActivityType, ContactConsent, ContactConsentStatus, ContactCreatePayload, ContactFormData, ContactHealth, ContactRelation, ContactRelationCategory, ContactRelationContact, ContactRelationDirection, ContactRelationPayload, ContactRelationType, ContactRelationUpdatePayload, ContactViewable, Content, ContentDefinition, ContentEntry, ContentField, ContentFieldType, ContentPatch, ContentStatus, ContentValue, ContentVersion, Contract, ContractCategoryDisplayNames, ContractCategoryName, ContractCodeMetadata, ContractEntity, ContractOnNetwork, ContractVersion, ContractsAddressConfig, CortexExecuteOptions, Coupon, CouponCondition, CouponRestrictedItem, CouponRestrictedItemType, CreateContentInput, CreateHookPayload, CreateInboundHookPayload, CreateInternalHookPayload, CreateKvFieldPayload, CreateWarpLinkedHookPayload, CreateWebHookPayload, DefaultAppLocale, DefaultCodeMetadata, DefaultInviteTeamRole, DemoFlow, DemoMessage, Desk, DeskItem, DeskItemRole, Document, EarnResponse, Earning, Element, ElementSpec, ElementType, ElementVariation, EmailProvider, EmbedStatus, EncryptionStatus, Entity, EntityDirectExecuteRequest, EntityProposable, EntitySignable, EntityTemplate, Experience, FeatureSetupTarget, FileInfo, FileMetadata, Flow, FlowCategory, FlowInputMapping, FlowStatus, FlowStep, Fulfillment, FulfillmentFlowAction, FulfillmentFlowStep, FulfillmentLocation, type FulfillmentMethod, FulfillmentMethods, type FulfillmentStatus, FulfillmentStatuses, GamificationData, GamificationEventType, Goal, GoalCreatePayload, GoalPriority, GoalProgressViewable, GoalStatus, GuestBuyer, HintOptions, HintPosition, Hook, HookSample, HookTrigger, HookTriggerCondition, HookTriggerInput, HttpService, IAppResponse, IHttpService, IRequestOptions, ImageCompressionOptions, ImageCropOptions, ImageCropRectangle, ImageCropState, ImageDimensionRules, ImageDimensions, IngestionSourceType, IngestionStatus, Inquiry, InquiryStatus, InquiryType, Integration, IntegrationConnectionDetails, IntegrationDetails, IntegrationMeta, IntegrationType, Intent, InviteableTeamRoles, Item, ItemCreatePayload, ItemExecutionStatus, ItemPriority, ItemStatus, ItemUpdatePayload, ItemViewable, JoaiUrls, JsonValue, KvEntry, KvEntryPayload, KvField, KvFieldWithEntries, KvValue, Kyc, KycStatus, Link, LinkCreatePayload, LinkScanHistory, LinkStats, LinkUpdatePayload, LinkVariation, LinkVariationBatchCreatePayload, LinkVariationCreatePayload, LocalAgentWallet, LoyaltyAccount, LoyaltyMember, LoyaltyNextTier, LoyaltyProgram, LoyaltyPromotion, LoyaltyReward, LoyaltyStatus, LoyaltyTier, LoyaltyTierInfo, LoyaltyTransaction, McpToolCall, McpToolCallBroadcast, McpToolCallStatus, Media, MediaAspectRatio, MediaAttributes, MediaItems, MediaLibraryAttributes, MediaMime, Meeting, MeetingConferenceProvider, MeetingFeature, MeetingJoinInfo, MeetingJoinTeam, MeetingParticipant, MeetingSessionState, MeetingSpeakerAssignment, MeetingStatus, MeetingSummary, MeetingTranscriptEntry, MeetingUsage, Memory, Message, MessageId, MessageRole, Metric, MetricSource, MetricsResult, Milestone, MilestoneType, Mission, MissionBudget, MissionCreatePayload, MissionPlan, MissionPriority, MissionSchedule, MissionStatus, MissionViewable, MollieTerminalPaymentResult, MultimodalContent, MultimodalFile, NATIVE_AUTH_TOKEN_PARAM, NativeApp, NativeApps, Notification, NotificationAction, NotificationAgent, NotificationChannel, NotificationSetting, OG_IMAGE_CONFIG, OG_IMAGE_HEIGHT, OG_IMAGE_WIDTH, ORDER_FULFILLMENT_STATUSES, ORDER_POST_CHECKOUT_STATUSES, OUTBOUND_CHANNELS, OfficeAgent, OfficeEntity, OfficeEntityKind, OfficeLiveOverrides, OfficeMember, OfficeSnapshot, OfficeStatus, OfficeStatusFilter, OfficeTypeFilter, OgImageColors, Order, OrderConfigurationItem, OrderContext, OrderItem, OrderPriceMode, OrderSource, OrderStatus, OrderStatusDisplay, OrderType, OutboundChannel, OutboundChannelId, PLATFORM_CURRENCY, PaginatedResponse, Pass, PatchContentInput, PaymentAccount, PaymentAccountOnboarding, PaymentProvider, PayoutEntry, PeriodTypeLabels, PeriodTypeOptions, PermissionConfigType, PermissionPresetName, PermissionPresetNames, PersonaQuestionable, PickupNextAction, Plan, PlanBenefit, PlanExtra, PlanFeature, PlanInterval, PolicyMethod, PolicySetting, PricingModel, Product, ProductDetailKind, ProductDetailRow, ProductDetailSection, ProductDetailText, ProductDiscount, ProductMeta, ProductPieces, ProductRating, ProductRelation, ProductRelationType, ProductVariation, ProductVariationMeta, ProductVariationType, ProgramSettings, Project, ProjectAspectRatio, ProjectAssembly, ProjectCaptionStyle, ProjectClipCandidate, ProjectClips, ProjectExport, ProjectExportAsset, ProjectExportResponse, ProjectImages, ProjectInputAssistIntent, ProjectInputAssistResponse, ProjectMutation, ProjectOutputPreset, ProjectOutputType, ProjectPlan, ProjectRender, ProjectRenderMode, ProjectSelectedClip, ProjectShot, ProjectSoundtrack, ProjectSourceMedia, ProjectStatus, ProjectStudioHistoryEntry, ProjectStudioQuestion, ProjectStudioResponse, ProjectStudioStage, ProjectStudioState, ProjectStudioSummary, ProjectStyleDirection, ProjectTranscript, ProjectTranscriptSegment, Proposal, ProposalAction, ProposalActionPayment, ProposalActionPaymentSerializable, ProposalActionSerializable, ProposalPollOption, ProposalStatus, PublicFormResults, PurchaseOptions, PurchaseResult, RampProvider, RampProviderInfo, Reactions, RecentExperience, RedeemResponse, Reminder, Return, type ReturnStatus, ReturnStatuses, ReturnUpdateStatus, ReturnUpdateStatuses, Room, RoomId, RoomKind, ScInfo, SchedulePreset, SecretAuthorizable, SecretSettable, Segment, SegmentCondition, SegmentConditionType, SegmentCountPayload, SegmentCountResult, SegmentCreatePayload, SegmentGroup, SendableActivityUpdate, SendableAgentAction, SendableAgentMessage, SendableAgentThought, SendableMedia, SendableUserMessage, Service, SetKvEntryResult, SharedSocialPost, ShippingCarrierOption, ShippingRate, ShippingZone, Shortcut, Site, SiteAgent, SiteBrand, SiteRoute, SiteTeam, SiteType, Skill, SkillMediaBindingRole, SkillMediaBindingRoleValue, SkillScope, SkillScopeValue, SkillType, SkillTypeValue, SocialAuthProvider, SocialBot, SocialPlatform, SocialPost, SocialPostConnection, SocialPostCreatePayload, SocialPostGenerateCaptionPayload, SocialPostGeneratedCaption, SocialPostPlatform, SocialPostStatus, SocialPostUpdatePayload, StampResponse, StoreAgent, StoreCheckoutItem, StoreData, StoreEntityType, StoreInfo, StoreItem, StoreListing, StorePriceTier, StorePricing, StorePurchasable, StorePurchaseResult, Streak, Subscription, SubscriptionDelivery, SubscriptionInterval, SubscriptionPlan, SubscriptionStatus, SupportedAppLocale, SupportedAppLocales, Swarm, Tag, TagType, Task, TaxBreakdownRow, TaxClass, Team, TeamAccessCatalog, TeamAccessConfig, TeamBrand, TeamCategory, TeamCurrencySource, TeamEarning, TeamEarningsBalance, TeamFeature, TeamFeatureAccess, TeamFeatureArea, TeamFeatureUsage, TeamManageAccess, TeamMember, TeamMeta, TeamOrderStats, TeamPayout, TeamPayoutAddress, TeamPlace, TeamPrivate, TeamSettings, TeamUsage, TeamViewAccess, TerminalConnectionToken, TerminalPaymentIntent, Tier, TierFeature, TierName, ToggleKvFieldResult, TranscriptEntry, TranscriptionCorrection, TranscriptionResponse, TranslatableValue, UNIFIED_MCP_SERVER_NAME, Update, UpdateCreatePayload, UpdateRelation, UpdateStats, UpdateStatus, UpdateType, UpdateUpdatePayload, Upgrade, UpgradeSourceType, UpgradeStatus, User, UserInterest, UserMode, type UserPermission, UserPermissions, UserPrivate, type UserRole, UserRoles, UserSettings, UserSocialAccount, UserStats, VolumePrice, Wallet, WalletList, WarpApprovable, WarpBackend, WarpBackendStatus, WarpBatchItem, WarpBatchable, WarpCloudExecutable, WarpCreateable, WarpExecutable, WarpExecutionBackend, WarpExtras, WarpExtrasFaq, WarpInputable, WarpScreenshotVariant, WarpSearchHit, WarpSelectable, WarpSelectableDetails, WarpSuggestion, WarpTestable, WarpViewable, WebHookTriggerEvent, WorkspaceCloudFile, WorkspaceContext, WorkspaceInfo, WorkspaceSettings, XIntegrationStatus, abbreviateNumber, addressTypeValues, automationSendChannel, buildAgentMcpServerName, buildAgentSetupClipboardText, buildAppSetupClipboardText, buildFeatureSetupClipboardText, buildMcpServerName, canOpenFulfillmentFlow, canTransitionOrderStatus, cartLineTotal, cartPayableTotal, containedImageDimensions, createCursorMcpInstallLink, cropOutputDimensions, defaultInviteTeamRole, documentShareUrl, firstValidationMessage, formatAddressSnapshotLines, fulfillmentMethodValues, fulfillmentStatusValues, getAgentSetupPromptUrl, getAgentsBaseUrl, getApiBaseUrl, getAppBaseUrl, getAssetAppLogoUrl, getAssetChainLogoUrl, getAssetPartnerLogoUrl, getAssetTokenLogoUrl, getAssetWalletLogoUrl, getCortexBaseUrl, getDigestBaseUrl, getDocumentsBaseUrl, getEditableOrderStatuses, getFormsBaseUrl, getFulfillmentFlowAction, getFulfillmentFlowStepperIndex, getGenBaseUrl, getInvoiceEditableStatuses, getLoginUrl, getMcpServerAgentUrl, getMcpServerUrl, getPickupEditableStatuses, getPickupNextAction, getShippingEditableStatuses, getSiteUrl, getSitesBaseUrl, getSitesRootDomain, getStoreBaseUrl, getWarpScreenshotUrl, hasAllPermissions, hasAllTeamPermissions, hasAnyPermissions, hasPermission, hasTeamPermission, imageCropRectangle, integrationSlugForChannel, inviteableTeamRoles, isAutomationSendChannelId, isCampaignChannelId, isCompleteAddressInput, isContactMessageAction, isContactMessageWarpId, isFileFormatAudio, isFileFormatImage, isFileFormatVideo, isNativeApp, isNativeAppAccessible, isNativeAppGated, isNativeAppLocked, isOrderCanceled, isOrderInFulfillment, isOrderPending, isOrderPostCheckout, isPickupOrderReady, isPickupReady, isSupportedAppLocale, isTeamFeatureAccessible, isTeamFeatureGated, isTeamFeatureLocked, isUnifiedMcpUrl, isUserRole, localize, nativeAppSlugs, normalizeAutomationActionType, ogImageUrl, outboundChannel, permissionPresetRules, resolveAccessCatalog, resolveAgentMcpUrl, resolveConnectMcpUrl, resolveFulfillmentFlowStep, resolveOrderStatusDisplay, resolveTeamCurrency, resolveWarpText, returnStatusValues, returnUpdateStatusValues, sanitizeAlphanumeric, sanitizeNumeric, slugifyMcpSegment, teamCategories, toCurrencyDisplay, toHexEncodedNonce, toNameInitials, toNftId, toPreviewText, userPermissionValues, userRoleValues, validateImageDimensions, validationMessageFor, withRetry };
|
package/dist/index.mjs
CHANGED
|
@@ -410,6 +410,63 @@ function integrationSlugForChannel(channel) {
|
|
|
410
410
|
return channel === "sms" ? "twilio" : channel;
|
|
411
411
|
}
|
|
412
412
|
//#endregion
|
|
413
|
+
//#region src/content/image-processing.ts
|
|
414
|
+
const positiveFinite = (value) => typeof value === "number" && Number.isFinite(value) && value > 0;
|
|
415
|
+
const validateImageDimensions = (dimensions, rules) => {
|
|
416
|
+
if (!positiveFinite(dimensions.width) || !positiveFinite(dimensions.height)) return "too-small";
|
|
417
|
+
if (rules.minWidth && dimensions.width < rules.minWidth || rules.minHeight && dimensions.height < rules.minHeight) return "too-small";
|
|
418
|
+
if (rules.maxWidth && dimensions.width > rules.maxWidth || rules.maxHeight && dimensions.height > rules.maxHeight || rules.maxPixels && dimensions.width * dimensions.height > rules.maxPixels) return "too-large";
|
|
419
|
+
return null;
|
|
420
|
+
};
|
|
421
|
+
const imageCropRectangle = (dimensions, aspectRatio, crop) => {
|
|
422
|
+
if (!positiveFinite(aspectRatio)) throw new RangeError("Crop aspect ratio must be a positive finite number.");
|
|
423
|
+
if (!positiveFinite(dimensions.width) || !positiveFinite(dimensions.height)) throw new RangeError("Image dimensions must be positive finite numbers.");
|
|
424
|
+
const sourceAspect = dimensions.width / dimensions.height;
|
|
425
|
+
const baseWidth = sourceAspect > aspectRatio ? dimensions.height * aspectRatio : dimensions.width;
|
|
426
|
+
const baseHeight = sourceAspect > aspectRatio ? dimensions.height : dimensions.width / aspectRatio;
|
|
427
|
+
const zoom = Number.isFinite(crop.zoom) ? Math.max(1, crop.zoom) : 1;
|
|
428
|
+
const positionX = Number.isFinite(crop.x) ? Math.max(-1, Math.min(1, crop.x)) : 0;
|
|
429
|
+
const positionY = Number.isFinite(crop.y) ? Math.max(-1, Math.min(1, crop.y)) : 0;
|
|
430
|
+
const width = baseWidth / zoom;
|
|
431
|
+
const height = baseHeight / zoom;
|
|
432
|
+
const availableX = dimensions.width - width;
|
|
433
|
+
const availableY = dimensions.height - height;
|
|
434
|
+
return {
|
|
435
|
+
x: availableX * ((positionX + 1) / 2),
|
|
436
|
+
y: availableY * ((positionY + 1) / 2),
|
|
437
|
+
width,
|
|
438
|
+
height
|
|
439
|
+
};
|
|
440
|
+
};
|
|
441
|
+
const containedImageDimensions = (source, options) => {
|
|
442
|
+
if (!positiveFinite(source.width) || !positiveFinite(source.height)) throw new RangeError("Image dimensions must be positive finite numbers.");
|
|
443
|
+
const maxWidth = positiveFinite(options.maxWidth) ? options.maxWidth : source.width;
|
|
444
|
+
const maxHeight = positiveFinite(options.maxHeight) ? options.maxHeight : source.height;
|
|
445
|
+
const scale = Math.min(1, maxWidth / source.width, maxHeight / source.height);
|
|
446
|
+
return {
|
|
447
|
+
width: Math.max(1, Math.round(source.width * scale)),
|
|
448
|
+
height: Math.max(1, Math.round(source.height * scale))
|
|
449
|
+
};
|
|
450
|
+
};
|
|
451
|
+
const cropOutputDimensions = (source, options, compression) => {
|
|
452
|
+
if (!positiveFinite(options.aspectRatio)) throw new RangeError("Crop aspect ratio must be a positive finite number.");
|
|
453
|
+
const width = positiveFinite(options.outputWidth) ? options.outputWidth : void 0;
|
|
454
|
+
const height = positiveFinite(options.outputHeight) ? options.outputHeight : void 0;
|
|
455
|
+
if (width && height) return {
|
|
456
|
+
width: Math.max(1, Math.round(width)),
|
|
457
|
+
height: Math.max(1, Math.round(height))
|
|
458
|
+
};
|
|
459
|
+
if (width) return {
|
|
460
|
+
width: Math.max(1, Math.round(width)),
|
|
461
|
+
height: Math.max(1, Math.round(width / options.aspectRatio))
|
|
462
|
+
};
|
|
463
|
+
if (height) return {
|
|
464
|
+
width: Math.max(1, Math.round(height * options.aspectRatio)),
|
|
465
|
+
height: Math.max(1, Math.round(height))
|
|
466
|
+
};
|
|
467
|
+
return containedImageDimensions(source, compression);
|
|
468
|
+
};
|
|
469
|
+
//#endregion
|
|
413
470
|
//#region src/address/enums.ts
|
|
414
471
|
const AddressTypes = {
|
|
415
472
|
Billing: "billing",
|
|
@@ -878,7 +935,8 @@ const NativeApps = {
|
|
|
878
935
|
Artifacts: "artifacts",
|
|
879
936
|
Social: "social",
|
|
880
937
|
Studio: "studio",
|
|
881
|
-
Loyalty: "loyalty"
|
|
938
|
+
Loyalty: "loyalty",
|
|
939
|
+
Documents: "documents"
|
|
882
940
|
};
|
|
883
941
|
const nativeAppSlugs = Object.values(NativeApps);
|
|
884
942
|
const isNativeApp = (value) => typeof value === "string" && nativeAppSlugs.includes(value);
|
|
@@ -976,4 +1034,4 @@ const DefaultInviteTeamRole = UserRoles.Member;
|
|
|
976
1034
|
const inviteableTeamRoles = () => [...InviteableTeamRoles];
|
|
977
1035
|
const defaultInviteTeamRole = () => DefaultInviteTeamRole;
|
|
978
1036
|
//#endregion
|
|
979
|
-
export { AUTOMATION_SEND_CHANNELS, AddressTypes, AgentToolingAccess, BillingManageAccess, CAMPAIGN_CHANNELS, CONTACT_MESSAGE_SEND_WARP, ContractCategoryDisplayNames, DefaultAppLocale, DefaultCodeMetadata, DefaultInviteTeamRole, FulfillmentMethods, FulfillmentStatuses, HttpService, InviteableTeamRoles, JoaiUrls, NATIVE_AUTH_TOKEN_PARAM, NativeApps, OG_IMAGE_CONFIG, OG_IMAGE_HEIGHT, OG_IMAGE_WIDTH, ORDER_FULFILLMENT_STATUSES, ORDER_POST_CHECKOUT_STATUSES, OUTBOUND_CHANNELS, OgImageColors, PLATFORM_CURRENCY, PeriodTypeLabels, PeriodTypeOptions, PermissionPresetNames, ReturnStatuses, ReturnUpdateStatuses, SkillMediaBindingRole, SkillScope, SkillType, SupportedAppLocales, TeamManageAccess, TeamViewAccess, UNIFIED_MCP_SERVER_NAME, UserPermissions, UserRoles, abbreviateNumber, addressTypeValues, automationSendChannel, buildAgentMcpServerName, buildAgentSetupClipboardText, buildAppSetupClipboardText, buildFeatureSetupClipboardText, buildMcpServerName, canOpenFulfillmentFlow, canTransitionOrderStatus, cartLineTotal, cartPayableTotal, createCursorMcpInstallLink, defaultInviteTeamRole, documentShareUrl, firstValidationMessage, formatAddressSnapshotLines, fulfillmentMethodValues, fulfillmentStatusValues, getAgentSetupPromptUrl, getAgentsBaseUrl, getApiBaseUrl, getAppBaseUrl, getAssetAppLogoUrl, getAssetChainLogoUrl, getAssetPartnerLogoUrl, getAssetTokenLogoUrl, getAssetWalletLogoUrl, getCortexBaseUrl, getDigestBaseUrl, getDocumentsBaseUrl, getEditableOrderStatuses, getFormsBaseUrl, getFulfillmentFlowAction, getFulfillmentFlowStepperIndex, getGenBaseUrl, getInvoiceEditableStatuses, getLoginUrl, getMcpServerAgentUrl, getMcpServerUrl, getPickupEditableStatuses, getPickupNextAction, getShippingEditableStatuses, getSiteUrl, getSitesBaseUrl, getSitesRootDomain, getStoreBaseUrl, getWarpScreenshotUrl, hasAllPermissions, hasAllTeamPermissions, hasAnyPermissions, hasPermission, hasTeamPermission, integrationSlugForChannel, inviteableTeamRoles, isAutomationSendChannelId, isCampaignChannelId, isCompleteAddressInput, isContactMessageAction, isContactMessageWarpId, isFileFormatAudio, isFileFormatImage, isFileFormatVideo, isNativeApp, isNativeAppAccessible, isNativeAppGated, isNativeAppLocked, isOrderCanceled, isOrderInFulfillment, isOrderPending, isOrderPostCheckout, isPickupOrderReady, isPickupReady, isSupportedAppLocale, isTeamFeatureAccessible, isTeamFeatureGated, isTeamFeatureLocked, isUnifiedMcpUrl, isUserRole, localize, nativeAppSlugs, normalizeAutomationActionType, ogImageUrl, outboundChannel, permissionPresetRules, resolveAccessCatalog, resolveAgentMcpUrl, resolveConnectMcpUrl, resolveFulfillmentFlowStep, resolveOrderStatusDisplay, resolveTeamCurrency, resolveWarpText, returnStatusValues, returnUpdateStatusValues, sanitizeAlphanumeric, sanitizeNumeric, slugifyMcpSegment, teamCategories, toCurrencyDisplay, toHexEncodedNonce, toNameInitials, toNftId, toPreviewText, userPermissionValues, userRoleValues, validationMessageFor, withRetry };
|
|
1037
|
+
export { AUTOMATION_SEND_CHANNELS, AddressTypes, AgentToolingAccess, BillingManageAccess, CAMPAIGN_CHANNELS, CONTACT_MESSAGE_SEND_WARP, ContractCategoryDisplayNames, DefaultAppLocale, DefaultCodeMetadata, DefaultInviteTeamRole, FulfillmentMethods, FulfillmentStatuses, HttpService, InviteableTeamRoles, JoaiUrls, NATIVE_AUTH_TOKEN_PARAM, NativeApps, OG_IMAGE_CONFIG, OG_IMAGE_HEIGHT, OG_IMAGE_WIDTH, ORDER_FULFILLMENT_STATUSES, ORDER_POST_CHECKOUT_STATUSES, OUTBOUND_CHANNELS, OgImageColors, PLATFORM_CURRENCY, PeriodTypeLabels, PeriodTypeOptions, PermissionPresetNames, ReturnStatuses, ReturnUpdateStatuses, SkillMediaBindingRole, SkillScope, SkillType, SupportedAppLocales, TeamManageAccess, TeamViewAccess, UNIFIED_MCP_SERVER_NAME, UserPermissions, UserRoles, abbreviateNumber, addressTypeValues, automationSendChannel, buildAgentMcpServerName, buildAgentSetupClipboardText, buildAppSetupClipboardText, buildFeatureSetupClipboardText, buildMcpServerName, canOpenFulfillmentFlow, canTransitionOrderStatus, cartLineTotal, cartPayableTotal, containedImageDimensions, createCursorMcpInstallLink, cropOutputDimensions, defaultInviteTeamRole, documentShareUrl, firstValidationMessage, formatAddressSnapshotLines, fulfillmentMethodValues, fulfillmentStatusValues, getAgentSetupPromptUrl, getAgentsBaseUrl, getApiBaseUrl, getAppBaseUrl, getAssetAppLogoUrl, getAssetChainLogoUrl, getAssetPartnerLogoUrl, getAssetTokenLogoUrl, getAssetWalletLogoUrl, getCortexBaseUrl, getDigestBaseUrl, getDocumentsBaseUrl, getEditableOrderStatuses, getFormsBaseUrl, getFulfillmentFlowAction, getFulfillmentFlowStepperIndex, getGenBaseUrl, getInvoiceEditableStatuses, getLoginUrl, getMcpServerAgentUrl, getMcpServerUrl, getPickupEditableStatuses, getPickupNextAction, getShippingEditableStatuses, getSiteUrl, getSitesBaseUrl, getSitesRootDomain, getStoreBaseUrl, getWarpScreenshotUrl, hasAllPermissions, hasAllTeamPermissions, hasAnyPermissions, hasPermission, hasTeamPermission, imageCropRectangle, integrationSlugForChannel, inviteableTeamRoles, isAutomationSendChannelId, isCampaignChannelId, isCompleteAddressInput, isContactMessageAction, isContactMessageWarpId, isFileFormatAudio, isFileFormatImage, isFileFormatVideo, isNativeApp, isNativeAppAccessible, isNativeAppGated, isNativeAppLocked, isOrderCanceled, isOrderInFulfillment, isOrderPending, isOrderPostCheckout, isPickupOrderReady, isPickupReady, isSupportedAppLocale, isTeamFeatureAccessible, isTeamFeatureGated, isTeamFeatureLocked, isUnifiedMcpUrl, isUserRole, localize, nativeAppSlugs, normalizeAutomationActionType, ogImageUrl, outboundChannel, permissionPresetRules, resolveAccessCatalog, resolveAgentMcpUrl, resolveConnectMcpUrl, resolveFulfillmentFlowStep, resolveOrderStatusDisplay, resolveTeamCurrency, resolveWarpText, returnStatusValues, returnUpdateStatusValues, sanitizeAlphanumeric, sanitizeNumeric, slugifyMcpSegment, teamCategories, toCurrencyDisplay, toHexEncodedNonce, toNameInitials, toNftId, toPreviewText, userPermissionValues, userRoleValues, validateImageDimensions, validationMessageFor, withRetry };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@joai/core",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0",
|
|
4
4
|
"description": "JoAi shared types, HTTP service, and config",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"type": "module",
|
|
@@ -10,10 +10,6 @@
|
|
|
10
10
|
".": {
|
|
11
11
|
"import": "./dist/index.mjs",
|
|
12
12
|
"types": "./dist/index.d.mts"
|
|
13
|
-
},
|
|
14
|
-
"./react": {
|
|
15
|
-
"import": "./dist/react/index.mjs",
|
|
16
|
-
"types": "./dist/react/index.d.mts"
|
|
17
13
|
}
|
|
18
14
|
},
|
|
19
15
|
"files": [
|
|
@@ -26,17 +22,10 @@
|
|
|
26
22
|
"test:watch": "jest --watch"
|
|
27
23
|
},
|
|
28
24
|
"peerDependencies": {
|
|
29
|
-
"@joai/warps": ">=4.0.0"
|
|
30
|
-
"react": ">=18.0.0"
|
|
31
|
-
},
|
|
32
|
-
"peerDependenciesMeta": {
|
|
33
|
-
"react": {
|
|
34
|
-
"optional": true
|
|
35
|
-
}
|
|
25
|
+
"@joai/warps": ">=4.0.0"
|
|
36
26
|
},
|
|
37
27
|
"devDependencies": {
|
|
38
28
|
"@types/jest": "^30.0.0",
|
|
39
|
-
"@types/react": "^19.2.14",
|
|
40
29
|
"jest": "^30.3.0",
|
|
41
30
|
"ts-jest": "^29.4.6",
|
|
42
31
|
"tsdown": "^0.21.0",
|
package/dist/react/index.d.mts
DELETED
|
@@ -1,362 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import * as _$react from "react";
|
|
3
|
-
import { ReactNode } from "react";
|
|
4
|
-
|
|
5
|
-
//#region src/react/types.d.ts
|
|
6
|
-
type EmbedChatItem = {
|
|
7
|
-
content: string;
|
|
8
|
-
byUser: boolean;
|
|
9
|
-
streaming?: boolean;
|
|
10
|
-
error?: boolean;
|
|
11
|
-
};
|
|
12
|
-
//#endregion
|
|
13
|
-
//#region src/react/guest.d.ts
|
|
14
|
-
declare function getOrCreateGuestId(storageKey?: string): string;
|
|
15
|
-
declare function loadRoom(storageKey: string): string | null;
|
|
16
|
-
declare function saveRoom(storageKey: string, roomId: string): void;
|
|
17
|
-
declare function clearRoom(storageKey: string): void;
|
|
18
|
-
//#endregion
|
|
19
|
-
//#region src/react/stream-connection.d.ts
|
|
20
|
-
type StreamDataHandler = (data: unknown) => void;
|
|
21
|
-
declare function openEventSourceStream(url: string, onData: StreamDataHandler, options?: {
|
|
22
|
-
withCredentials?: boolean;
|
|
23
|
-
onError?: (e: unknown) => void;
|
|
24
|
-
onConnectionError?: (e: Event | null) => void;
|
|
25
|
-
}): () => void;
|
|
26
|
-
//#endregion
|
|
27
|
-
//#region src/react/components.d.ts
|
|
28
|
-
type ListClassNames = {
|
|
29
|
-
container?: string;
|
|
30
|
-
userBubble?: string;
|
|
31
|
-
agentBubble?: string;
|
|
32
|
-
errorBubble?: string;
|
|
33
|
-
thinkingWrapper?: string;
|
|
34
|
-
dot?: string;
|
|
35
|
-
};
|
|
36
|
-
type EmbedChatListProps = {
|
|
37
|
-
items: EmbedChatItem[];
|
|
38
|
-
agentName: string;
|
|
39
|
-
awaitingResponse: boolean;
|
|
40
|
-
classNames?: ListClassNames;
|
|
41
|
-
renderEmptyState?: () => ReactNode;
|
|
42
|
-
renderAgentContent?: (item: EmbedChatItem) => ReactNode;
|
|
43
|
-
};
|
|
44
|
-
declare function EmbedChatList({
|
|
45
|
-
items,
|
|
46
|
-
agentName,
|
|
47
|
-
awaitingResponse,
|
|
48
|
-
classNames,
|
|
49
|
-
renderEmptyState,
|
|
50
|
-
renderAgentContent
|
|
51
|
-
}: EmbedChatListProps): string | number | bigint | boolean | Iterable<ReactNode> | Promise<string | number | bigint | boolean | _$react.ReactPortal | _$react.ReactElement<unknown, string | _$react.JSXElementConstructor<any>> | Iterable<ReactNode> | null | undefined> | _$react.JSX.Element | null | undefined;
|
|
52
|
-
type EmbedChatInputProps = {
|
|
53
|
-
onSend: (message: string) => void;
|
|
54
|
-
disabled: boolean;
|
|
55
|
-
placeholder?: string;
|
|
56
|
-
maxLength?: number;
|
|
57
|
-
classNames?: {
|
|
58
|
-
container?: string;
|
|
59
|
-
textarea?: string;
|
|
60
|
-
};
|
|
61
|
-
renderSendButton: (props: {
|
|
62
|
-
onClick: () => void;
|
|
63
|
-
disabled: boolean;
|
|
64
|
-
}) => ReactNode;
|
|
65
|
-
};
|
|
66
|
-
declare function EmbedChatInput({
|
|
67
|
-
onSend,
|
|
68
|
-
disabled,
|
|
69
|
-
placeholder,
|
|
70
|
-
maxLength,
|
|
71
|
-
classNames,
|
|
72
|
-
renderSendButton
|
|
73
|
-
}: EmbedChatInputProps): _$react.JSX.Element;
|
|
74
|
-
//#endregion
|
|
75
|
-
//#region src/http/types.d.ts
|
|
76
|
-
interface IHttpService {
|
|
77
|
-
readonly baseUrl: string;
|
|
78
|
-
readonly authToken: string | null;
|
|
79
|
-
onNetworkError: (error: Error) => void;
|
|
80
|
-
onUnauthorized: (response: IAppResponse<any>) => void;
|
|
81
|
-
onSuccessfulResponse: (response: IAppResponse<any>) => void;
|
|
82
|
-
onMaintenanceMode: (response: IAppResponse<any>) => void;
|
|
83
|
-
onTooManyRequests: (response: IAppResponse<any>) => void;
|
|
84
|
-
get: <T>(url: string, options?: IRequestOptions) => Promise<IAppResponse<T>>;
|
|
85
|
-
post: <T>(url: string, data?: any, options?: IRequestOptions) => Promise<IAppResponse<T>>;
|
|
86
|
-
put: <T>(url: string, data?: any, options?: IRequestOptions) => Promise<IAppResponse<T>>;
|
|
87
|
-
patch: <T>(url: string, data?: any, options?: IRequestOptions) => Promise<IAppResponse<T>>;
|
|
88
|
-
delete: <T>(url: string, options?: IRequestOptions) => Promise<IAppResponse<T>>;
|
|
89
|
-
}
|
|
90
|
-
interface IAppResponse<T> {
|
|
91
|
-
data: T;
|
|
92
|
-
meta?: any;
|
|
93
|
-
body: any;
|
|
94
|
-
errors: any;
|
|
95
|
-
ok: boolean;
|
|
96
|
-
paymentRequired: boolean;
|
|
97
|
-
noContent: boolean;
|
|
98
|
-
original: Response;
|
|
99
|
-
}
|
|
100
|
-
interface IRequestOptions {
|
|
101
|
-
isJson?: boolean;
|
|
102
|
-
headers?: {
|
|
103
|
-
[name: string]: string;
|
|
104
|
-
};
|
|
105
|
-
}
|
|
106
|
-
//#endregion
|
|
107
|
-
//#region src/react/use-embed-chat.d.ts
|
|
108
|
-
type Options = {
|
|
109
|
-
agentUuid: string | null;
|
|
110
|
-
http: IHttpService;
|
|
111
|
-
cortexBaseUrl: string;
|
|
112
|
-
guestId: string;
|
|
113
|
-
roomStorageKey: string;
|
|
114
|
-
enabled?: boolean;
|
|
115
|
-
extraPayload?: Record<string, unknown>;
|
|
116
|
-
};
|
|
117
|
-
declare function useEmbedChat({
|
|
118
|
-
agentUuid,
|
|
119
|
-
http,
|
|
120
|
-
cortexBaseUrl,
|
|
121
|
-
guestId,
|
|
122
|
-
roomStorageKey,
|
|
123
|
-
enabled,
|
|
124
|
-
extraPayload
|
|
125
|
-
}: Options): {
|
|
126
|
-
items: EmbedChatItem[];
|
|
127
|
-
setItems: _$react.Dispatch<_$react.SetStateAction<EmbedChatItem[]>>;
|
|
128
|
-
sending: boolean;
|
|
129
|
-
awaitingResponse: boolean;
|
|
130
|
-
roomId: string | null;
|
|
131
|
-
setRoomId: _$react.Dispatch<_$react.SetStateAction<string | null>>;
|
|
132
|
-
send: (message: string) => Promise<void>;
|
|
133
|
-
connectionError: boolean;
|
|
134
|
-
};
|
|
135
|
-
//#endregion
|
|
136
|
-
//#region src/content/types.d.ts
|
|
137
|
-
type ContentStatus = 'draft' | 'published' | 'archived';
|
|
138
|
-
type ContentFieldType = 'text' | 'richText' | 'number' | 'boolean' | 'url' | 'image' | 'media' | 'list' | 'object' | 'reference';
|
|
139
|
-
type ContentField = {
|
|
140
|
-
key: string;
|
|
141
|
-
type: ContentFieldType;
|
|
142
|
-
label?: string;
|
|
143
|
-
required?: boolean;
|
|
144
|
-
};
|
|
145
|
-
type ContentDefinition = {
|
|
146
|
-
fields: ContentField[];
|
|
147
|
-
};
|
|
148
|
-
type ContentValue = string | number | boolean | null | ContentValue[] | {
|
|
149
|
-
[key: string]: ContentValue;
|
|
150
|
-
};
|
|
151
|
-
type ContentEntry = {
|
|
152
|
-
key: string;
|
|
153
|
-
value: ContentValue;
|
|
154
|
-
updatedAt: string;
|
|
155
|
-
};
|
|
156
|
-
type ContentVersion = {
|
|
157
|
-
id: string;
|
|
158
|
-
number: number;
|
|
159
|
-
status: ContentStatus;
|
|
160
|
-
entries: ContentEntry[];
|
|
161
|
-
snapshotHash: string;
|
|
162
|
-
origin: string;
|
|
163
|
-
createdAt: string;
|
|
164
|
-
updatedAt: string;
|
|
165
|
-
publishedAt: string | null;
|
|
166
|
-
};
|
|
167
|
-
type Content = {
|
|
168
|
-
id: string;
|
|
169
|
-
name: string;
|
|
170
|
-
slug: string;
|
|
171
|
-
schema: string | null;
|
|
172
|
-
definition: ContentDefinition;
|
|
173
|
-
metadata: Record<string, ContentValue>;
|
|
174
|
-
version: ContentVersion | null;
|
|
175
|
-
createdAt: string;
|
|
176
|
-
updatedAt: string;
|
|
177
|
-
};
|
|
178
|
-
type ContentPatch = {
|
|
179
|
-
key: string;
|
|
180
|
-
value: ContentValue;
|
|
181
|
-
};
|
|
182
|
-
type PatchContentInput = {
|
|
183
|
-
expectedVersion: number;
|
|
184
|
-
patches: ContentPatch[];
|
|
185
|
-
origin?: 'api' | 'inlineEditor' | 'joai' | 'mcp';
|
|
186
|
-
publish?: boolean;
|
|
187
|
-
};
|
|
188
|
-
//#endregion
|
|
189
|
-
//#region src/json/types.d.ts
|
|
190
|
-
type JsonValue = string | number | boolean | null | JsonValue[] | {
|
|
191
|
-
[key: string]: JsonValue;
|
|
192
|
-
};
|
|
193
|
-
//#endregion
|
|
194
|
-
//#region src/media/types.d.ts
|
|
195
|
-
type MediaLibraryAttributes = {
|
|
196
|
-
uuid: string;
|
|
197
|
-
order: number;
|
|
198
|
-
name: string;
|
|
199
|
-
custom_properties: {
|
|
200
|
-
[key: string]: JsonValue;
|
|
201
|
-
};
|
|
202
|
-
preview_url: null | string;
|
|
203
|
-
original_url: null | string;
|
|
204
|
-
extension?: string;
|
|
205
|
-
size?: number;
|
|
206
|
-
};
|
|
207
|
-
type MediaMime = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/webp' | 'video/mp4' | 'video/webm' | 'video/quicktime' | 'video/x-msvideo' | 'audio/mpeg' | 'audio/mp3' | 'audio/ogg' | 'audio/wav' | 'audio/webm' | 'audio/aac' | 'audio/m4a' | 'audio/m4b' | 'audio/m4p' | 'audio/m4v' | 'application/pdf' | 'application/json';
|
|
208
|
-
type Media = {
|
|
209
|
-
id: string;
|
|
210
|
-
name: string;
|
|
211
|
-
mime: MediaMime;
|
|
212
|
-
url: string;
|
|
213
|
-
library: MediaLibraryAttributes;
|
|
214
|
-
tags?: string[];
|
|
215
|
-
copyright?: string | null;
|
|
216
|
-
aiGenerated?: boolean;
|
|
217
|
-
};
|
|
218
|
-
//#endregion
|
|
219
|
-
//#region src/react/content/types.d.ts
|
|
220
|
-
type ContentResource = {
|
|
221
|
-
get: (contentId: string) => Promise<{
|
|
222
|
-
ok: boolean;
|
|
223
|
-
data?: Content;
|
|
224
|
-
}>;
|
|
225
|
-
getPublic: (slug: string) => Promise<{
|
|
226
|
-
ok: boolean;
|
|
227
|
-
data?: Content;
|
|
228
|
-
}>;
|
|
229
|
-
patch: (contentId: string, input: PatchContentInput) => Promise<{
|
|
230
|
-
ok: boolean;
|
|
231
|
-
data?: ContentVersion;
|
|
232
|
-
}>;
|
|
233
|
-
publish: (contentId: string, expectedVersion: number) => Promise<{
|
|
234
|
-
ok: boolean;
|
|
235
|
-
data?: ContentVersion;
|
|
236
|
-
}>;
|
|
237
|
-
};
|
|
238
|
-
type ContentClient = {
|
|
239
|
-
content: ContentResource;
|
|
240
|
-
media?: {
|
|
241
|
-
list: (team: string, params?: {
|
|
242
|
-
page?: number;
|
|
243
|
-
mime?: string;
|
|
244
|
-
}) => Promise<{
|
|
245
|
-
ok: boolean;
|
|
246
|
-
data?: Media[];
|
|
247
|
-
}>;
|
|
248
|
-
upload: (data: {
|
|
249
|
-
team: string;
|
|
250
|
-
file: File;
|
|
251
|
-
type: 'output';
|
|
252
|
-
label?: string;
|
|
253
|
-
}) => Promise<{
|
|
254
|
-
ok: boolean;
|
|
255
|
-
data?: Media;
|
|
256
|
-
}>;
|
|
257
|
-
};
|
|
258
|
-
};
|
|
259
|
-
type ContentContextValue = {
|
|
260
|
-
content: Content | null;
|
|
261
|
-
values: Record<string, ContentValue>;
|
|
262
|
-
isLoading: boolean;
|
|
263
|
-
isSaving: boolean;
|
|
264
|
-
isEditing: boolean;
|
|
265
|
-
isDirty: boolean;
|
|
266
|
-
canEdit: boolean;
|
|
267
|
-
canPublish: boolean;
|
|
268
|
-
teamSlug?: string;
|
|
269
|
-
media?: ContentClient['media'];
|
|
270
|
-
error: string | null;
|
|
271
|
-
setEditing: (editing: boolean) => void;
|
|
272
|
-
setValue: (key: string, value: ContentValue) => void;
|
|
273
|
-
save: () => Promise<boolean>;
|
|
274
|
-
publish: () => Promise<boolean>;
|
|
275
|
-
};
|
|
276
|
-
type ContentProviderProp = {
|
|
277
|
-
children: ReactNode;
|
|
278
|
-
client: ContentClient;
|
|
279
|
-
contentId?: string;
|
|
280
|
-
publicSlug?: string;
|
|
281
|
-
initialContent?: Content;
|
|
282
|
-
canEdit?: boolean;
|
|
283
|
-
canPublish?: boolean;
|
|
284
|
-
teamSlug?: string;
|
|
285
|
-
};
|
|
286
|
-
type EditableContentProp = {
|
|
287
|
-
field: string;
|
|
288
|
-
as?: 'span' | 'p' | 'div' | 'h1' | 'h2' | 'h3';
|
|
289
|
-
className?: string;
|
|
290
|
-
placeholder?: string;
|
|
291
|
-
multiline?: boolean;
|
|
292
|
-
};
|
|
293
|
-
type EditableImageProp = {
|
|
294
|
-
field: string;
|
|
295
|
-
alt?: string;
|
|
296
|
-
className?: string;
|
|
297
|
-
onSelect?: () => void;
|
|
298
|
-
inputClassName?: string;
|
|
299
|
-
placeholder?: string;
|
|
300
|
-
};
|
|
301
|
-
type ContentToolbarProp = {
|
|
302
|
-
className?: string;
|
|
303
|
-
confirmPublish?: () => boolean | Promise<boolean>;
|
|
304
|
-
labels?: {
|
|
305
|
-
edit?: string;
|
|
306
|
-
save?: string;
|
|
307
|
-
publish?: string;
|
|
308
|
-
cancel?: string;
|
|
309
|
-
};
|
|
310
|
-
};
|
|
311
|
-
//#endregion
|
|
312
|
-
//#region src/react/content/provider.d.ts
|
|
313
|
-
declare function ContentProvider({
|
|
314
|
-
children,
|
|
315
|
-
client,
|
|
316
|
-
contentId,
|
|
317
|
-
publicSlug,
|
|
318
|
-
initialContent,
|
|
319
|
-
canEdit,
|
|
320
|
-
canPublish,
|
|
321
|
-
teamSlug
|
|
322
|
-
}: ContentProviderProp): _$react.JSX.Element;
|
|
323
|
-
//#endregion
|
|
324
|
-
//#region src/react/content/editable-content.d.ts
|
|
325
|
-
declare function EditableContent({
|
|
326
|
-
field,
|
|
327
|
-
as: Tag,
|
|
328
|
-
className,
|
|
329
|
-
placeholder,
|
|
330
|
-
multiline
|
|
331
|
-
}: EditableContentProp): _$react.JSX.Element;
|
|
332
|
-
declare function useContentValue<T extends ContentValue = ContentValue>(key: string): T | undefined;
|
|
333
|
-
//#endregion
|
|
334
|
-
//#region src/react/content/editable-image.d.ts
|
|
335
|
-
declare function EditableImage({
|
|
336
|
-
field,
|
|
337
|
-
alt,
|
|
338
|
-
className,
|
|
339
|
-
inputClassName,
|
|
340
|
-
placeholder,
|
|
341
|
-
onSelect
|
|
342
|
-
}: EditableImageProp): _$react.JSX.Element | null;
|
|
343
|
-
//#endregion
|
|
344
|
-
//#region src/react/content/toolbar.d.ts
|
|
345
|
-
declare function ContentToolbar({
|
|
346
|
-
className,
|
|
347
|
-
labels,
|
|
348
|
-
confirmPublish
|
|
349
|
-
}: ContentToolbarProp): _$react.JSX.Element | null;
|
|
350
|
-
//#endregion
|
|
351
|
-
//#region src/react/content/content-editor.d.ts
|
|
352
|
-
type Prop = ContentProviderProp & {
|
|
353
|
-
children: ReactNode;
|
|
354
|
-
title?: string;
|
|
355
|
-
};
|
|
356
|
-
declare function ContentEditor({
|
|
357
|
-
children,
|
|
358
|
-
title,
|
|
359
|
-
...provider
|
|
360
|
-
}: Prop): _$react.JSX.Element;
|
|
361
|
-
//#endregion
|
|
362
|
-
export { ContentClient, ContentContextValue, ContentEditor, ContentProvider, ContentProviderProp, ContentResource, ContentToolbar, ContentToolbarProp, EditableContent, EditableContentProp, EditableImage, EditableImageProp, EmbedChatInput, EmbedChatItem, EmbedChatList, StreamDataHandler, clearRoom, getOrCreateGuestId, loadRoom, openEventSourceStream, saveRoom, useContentValue, useEmbedChat };
|
package/dist/react/index.mjs
DELETED
|
@@ -1,729 +0,0 @@
|
|
|
1
|
-
'use client';
|
|
2
|
-
import { createContext, useCallback, useContext, useEffect, useMemo, useRef, useState } from "react";
|
|
3
|
-
import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
4
|
-
//#region src/react/guest.ts
|
|
5
|
-
function safeGet(key) {
|
|
6
|
-
try {
|
|
7
|
-
return localStorage.getItem(key);
|
|
8
|
-
} catch {
|
|
9
|
-
return null;
|
|
10
|
-
}
|
|
11
|
-
}
|
|
12
|
-
function safeSet(key, value) {
|
|
13
|
-
try {
|
|
14
|
-
localStorage.setItem(key, value);
|
|
15
|
-
} catch {}
|
|
16
|
-
}
|
|
17
|
-
function safeRemove(key) {
|
|
18
|
-
try {
|
|
19
|
-
localStorage.removeItem(key);
|
|
20
|
-
} catch {}
|
|
21
|
-
}
|
|
22
|
-
function getOrCreateGuestId(storageKey = "joai_embed_guest") {
|
|
23
|
-
if (typeof window === "undefined") return "";
|
|
24
|
-
const existing = safeGet(storageKey);
|
|
25
|
-
if (existing) return existing;
|
|
26
|
-
const id = crypto.randomUUID();
|
|
27
|
-
safeSet(storageKey, id);
|
|
28
|
-
return id;
|
|
29
|
-
}
|
|
30
|
-
function loadRoom(storageKey) {
|
|
31
|
-
return safeGet(storageKey);
|
|
32
|
-
}
|
|
33
|
-
function saveRoom(storageKey, roomId) {
|
|
34
|
-
safeSet(storageKey, roomId);
|
|
35
|
-
}
|
|
36
|
-
function clearRoom(storageKey) {
|
|
37
|
-
safeRemove(storageKey);
|
|
38
|
-
}
|
|
39
|
-
//#endregion
|
|
40
|
-
//#region src/react/stream-connection.ts
|
|
41
|
-
function openEventSourceStream(url, onData, options) {
|
|
42
|
-
const es = new EventSource(url, { withCredentials: options?.withCredentials ?? false });
|
|
43
|
-
es.onmessage = (event) => {
|
|
44
|
-
try {
|
|
45
|
-
onData(JSON.parse(event.data));
|
|
46
|
-
} catch (e) {
|
|
47
|
-
options?.onError?.(e);
|
|
48
|
-
}
|
|
49
|
-
};
|
|
50
|
-
es.onerror = (event) => {
|
|
51
|
-
options?.onConnectionError?.(event);
|
|
52
|
-
};
|
|
53
|
-
return () => es.close();
|
|
54
|
-
}
|
|
55
|
-
//#endregion
|
|
56
|
-
//#region src/react/components.tsx
|
|
57
|
-
function EmbedChatList({ items, agentName, awaitingResponse, classNames = {}, renderEmptyState, renderAgentContent }) {
|
|
58
|
-
const containerRef = useRef(null);
|
|
59
|
-
useEffect(() => {
|
|
60
|
-
const el = containerRef.current;
|
|
61
|
-
if (!el) return;
|
|
62
|
-
if (el.scrollHeight - el.scrollTop - el.clientHeight < 120) el.scrollTop = el.scrollHeight;
|
|
63
|
-
}, [items, awaitingResponse]);
|
|
64
|
-
if (items.length === 0 && !awaitingResponse) return renderEmptyState ? renderEmptyState() : /* @__PURE__ */ jsx("div", {
|
|
65
|
-
className: classNames.container,
|
|
66
|
-
children: /* @__PURE__ */ jsxs("p", { children: [
|
|
67
|
-
"Send ",
|
|
68
|
-
agentName,
|
|
69
|
-
" a message to start chatting"
|
|
70
|
-
] })
|
|
71
|
-
});
|
|
72
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
73
|
-
ref: containerRef,
|
|
74
|
-
className: classNames.container,
|
|
75
|
-
role: "log",
|
|
76
|
-
"aria-live": "polite",
|
|
77
|
-
children: [items.map((item, i) => /* @__PURE__ */ jsx(EmbedChatBubble, {
|
|
78
|
-
item,
|
|
79
|
-
classNames,
|
|
80
|
-
renderAgentContent
|
|
81
|
-
}, i)), awaitingResponse && /* @__PURE__ */ jsx(EmbedThinkingIndicator, {
|
|
82
|
-
wrapperClassName: classNames.thinkingWrapper,
|
|
83
|
-
dotClassName: classNames.dot
|
|
84
|
-
})]
|
|
85
|
-
});
|
|
86
|
-
}
|
|
87
|
-
function EmbedChatBubble({ item, classNames, renderAgentContent }) {
|
|
88
|
-
if (item.byUser) return /* @__PURE__ */ jsx("div", {
|
|
89
|
-
className: classNames.userBubble,
|
|
90
|
-
children: item.content
|
|
91
|
-
});
|
|
92
|
-
return /* @__PURE__ */ jsx("div", {
|
|
93
|
-
className: item.error ? classNames.errorBubble : classNames.agentBubble,
|
|
94
|
-
children: renderAgentContent ? renderAgentContent(item) : /* @__PURE__ */ jsxs(Fragment, { children: [item.content, item.streaming && /* @__PURE__ */ jsx("span", { className: "inline-block w-1 h-3 ml-1 bg-current animate-pulse rounded-full" })] })
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
function EmbedThinkingIndicator({ wrapperClassName, dotClassName }) {
|
|
98
|
-
return /* @__PURE__ */ jsx("div", {
|
|
99
|
-
className: wrapperClassName,
|
|
100
|
-
children: /* @__PURE__ */ jsxs("span", {
|
|
101
|
-
className: "inline-flex gap-1",
|
|
102
|
-
children: [
|
|
103
|
-
/* @__PURE__ */ jsx("span", {
|
|
104
|
-
className: dotClassName,
|
|
105
|
-
style: { animationDelay: "0ms" }
|
|
106
|
-
}),
|
|
107
|
-
/* @__PURE__ */ jsx("span", {
|
|
108
|
-
className: dotClassName,
|
|
109
|
-
style: { animationDelay: "150ms" }
|
|
110
|
-
}),
|
|
111
|
-
/* @__PURE__ */ jsx("span", {
|
|
112
|
-
className: dotClassName,
|
|
113
|
-
style: { animationDelay: "300ms" }
|
|
114
|
-
})
|
|
115
|
-
]
|
|
116
|
-
})
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
function EmbedChatInput({ onSend, disabled, placeholder = "Type a message...", maxLength = 4e3, classNames = {}, renderSendButton }) {
|
|
120
|
-
const [text, setText] = useState("");
|
|
121
|
-
const textareaRef = useRef(null);
|
|
122
|
-
function handleSend() {
|
|
123
|
-
const trimmed = text.trim();
|
|
124
|
-
if (!trimmed || disabled) return;
|
|
125
|
-
onSend(trimmed);
|
|
126
|
-
setText("");
|
|
127
|
-
if (textareaRef.current) textareaRef.current.style.height = "auto";
|
|
128
|
-
}
|
|
129
|
-
function handleKeyDown(e) {
|
|
130
|
-
if (e.key === "Enter" && !e.shiftKey) {
|
|
131
|
-
e.preventDefault();
|
|
132
|
-
handleSend();
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
function handleInput() {
|
|
136
|
-
if (textareaRef.current) {
|
|
137
|
-
textareaRef.current.style.height = "auto";
|
|
138
|
-
textareaRef.current.style.height = Math.min(textareaRef.current.scrollHeight, 120) + "px";
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
142
|
-
className: classNames.container,
|
|
143
|
-
children: [/* @__PURE__ */ jsx("textarea", {
|
|
144
|
-
ref: textareaRef,
|
|
145
|
-
value: text,
|
|
146
|
-
onChange: (e) => setText(e.target.value),
|
|
147
|
-
onKeyDown: handleKeyDown,
|
|
148
|
-
onInput: handleInput,
|
|
149
|
-
placeholder,
|
|
150
|
-
"aria-label": "Message input",
|
|
151
|
-
maxLength,
|
|
152
|
-
rows: 1,
|
|
153
|
-
disabled,
|
|
154
|
-
className: classNames.textarea
|
|
155
|
-
}), renderSendButton({
|
|
156
|
-
onClick: handleSend,
|
|
157
|
-
disabled: disabled || !text.trim()
|
|
158
|
-
})]
|
|
159
|
-
});
|
|
160
|
-
}
|
|
161
|
-
//#endregion
|
|
162
|
-
//#region src/react/use-embed-chat.ts
|
|
163
|
-
const RESPONSE_TIMEOUT_MS = 3e4;
|
|
164
|
-
function useEmbedChat({ agentUuid, http, cortexBaseUrl, guestId, roomStorageKey, enabled = true, extraPayload }) {
|
|
165
|
-
const [items, setItems] = useState([]);
|
|
166
|
-
const [sending, setSending] = useState(false);
|
|
167
|
-
const [awaitingResponse, setAwaitingResponse] = useState(false);
|
|
168
|
-
const [roomId, setRoomId] = useState(null);
|
|
169
|
-
const [connectionError, setConnectionError] = useState(false);
|
|
170
|
-
const roomIdRef = useRef(null);
|
|
171
|
-
roomIdRef.current = roomId;
|
|
172
|
-
const extraPayloadRef = useRef(extraPayload);
|
|
173
|
-
extraPayloadRef.current = extraPayload;
|
|
174
|
-
useEffect(() => {
|
|
175
|
-
if (!roomId) return;
|
|
176
|
-
setConnectionError(false);
|
|
177
|
-
return openEventSourceStream(`${cortexBaseUrl}/agents/stream/${roomId}`, (raw) => {
|
|
178
|
-
setConnectionError(false);
|
|
179
|
-
const data = raw;
|
|
180
|
-
if (data.type === "response:chunk") {
|
|
181
|
-
setAwaitingResponse(false);
|
|
182
|
-
setItems((prev) => {
|
|
183
|
-
const last = prev[prev.length - 1];
|
|
184
|
-
if (last && last.streaming && !last.byUser) {
|
|
185
|
-
const updated = [...prev];
|
|
186
|
-
updated[updated.length - 1] = {
|
|
187
|
-
...last,
|
|
188
|
-
content: last.content + (data.content ?? "")
|
|
189
|
-
};
|
|
190
|
-
return updated;
|
|
191
|
-
}
|
|
192
|
-
return [...prev, {
|
|
193
|
-
content: data.content ?? "",
|
|
194
|
-
byUser: false,
|
|
195
|
-
streaming: true
|
|
196
|
-
}];
|
|
197
|
-
});
|
|
198
|
-
} else if (data.type === "response") {
|
|
199
|
-
setAwaitingResponse(false);
|
|
200
|
-
setItems((prev) => {
|
|
201
|
-
const updated = [...prev];
|
|
202
|
-
const lastIdx = updated.length - 1;
|
|
203
|
-
if (lastIdx >= 0 && updated[lastIdx].streaming) updated[lastIdx] = {
|
|
204
|
-
...updated[lastIdx],
|
|
205
|
-
content: data.content ?? updated[lastIdx].content,
|
|
206
|
-
streaming: false
|
|
207
|
-
};
|
|
208
|
-
else updated.push({
|
|
209
|
-
content: data.content ?? "",
|
|
210
|
-
byUser: false
|
|
211
|
-
});
|
|
212
|
-
return updated;
|
|
213
|
-
});
|
|
214
|
-
} else if (data.type === "complete") {
|
|
215
|
-
setAwaitingResponse(false);
|
|
216
|
-
setItems((prev) => prev.map((item) => item.streaming ? {
|
|
217
|
-
...item,
|
|
218
|
-
streaming: false
|
|
219
|
-
} : item));
|
|
220
|
-
}
|
|
221
|
-
}, { onConnectionError: () => setConnectionError(true) });
|
|
222
|
-
}, [roomId, cortexBaseUrl]);
|
|
223
|
-
useEffect(() => {
|
|
224
|
-
if (!awaitingResponse) return;
|
|
225
|
-
const timer = setTimeout(() => {
|
|
226
|
-
setAwaitingResponse(false);
|
|
227
|
-
setItems((prev) => [...prev, {
|
|
228
|
-
content: "Response timed out. Please try again.",
|
|
229
|
-
byUser: false,
|
|
230
|
-
error: true
|
|
231
|
-
}]);
|
|
232
|
-
}, RESPONSE_TIMEOUT_MS);
|
|
233
|
-
return () => clearTimeout(timer);
|
|
234
|
-
}, [awaitingResponse]);
|
|
235
|
-
return {
|
|
236
|
-
items,
|
|
237
|
-
setItems,
|
|
238
|
-
sending,
|
|
239
|
-
awaitingResponse,
|
|
240
|
-
roomId,
|
|
241
|
-
setRoomId,
|
|
242
|
-
send: useCallback(async (message) => {
|
|
243
|
-
if (!enabled || sending || !agentUuid) return;
|
|
244
|
-
setItems((prev) => [...prev, {
|
|
245
|
-
content: message,
|
|
246
|
-
byUser: true
|
|
247
|
-
}]);
|
|
248
|
-
setSending(true);
|
|
249
|
-
setConnectionError(false);
|
|
250
|
-
try {
|
|
251
|
-
const res = await http.post(`integrations/embed/${agentUuid}/execute`, {
|
|
252
|
-
message,
|
|
253
|
-
guestId,
|
|
254
|
-
...extraPayloadRef.current
|
|
255
|
-
});
|
|
256
|
-
if (!res.ok) {
|
|
257
|
-
const msg = res.data && typeof res.data === "object" && "message" in res.data ? res.data.message : "Something went wrong. Please try again.";
|
|
258
|
-
setItems((prev) => [...prev, {
|
|
259
|
-
content: msg,
|
|
260
|
-
byUser: false,
|
|
261
|
-
error: true
|
|
262
|
-
}]);
|
|
263
|
-
return;
|
|
264
|
-
}
|
|
265
|
-
setAwaitingResponse(true);
|
|
266
|
-
const newRoomId = res.data?.roomId;
|
|
267
|
-
if (newRoomId && !roomIdRef.current) {
|
|
268
|
-
setRoomId(newRoomId);
|
|
269
|
-
saveRoom(roomStorageKey, newRoomId);
|
|
270
|
-
}
|
|
271
|
-
} catch {
|
|
272
|
-
setItems((prev) => [...prev, {
|
|
273
|
-
content: "Something went wrong. Please try again.",
|
|
274
|
-
byUser: false,
|
|
275
|
-
error: true
|
|
276
|
-
}]);
|
|
277
|
-
} finally {
|
|
278
|
-
setSending(false);
|
|
279
|
-
}
|
|
280
|
-
}, [
|
|
281
|
-
enabled,
|
|
282
|
-
sending,
|
|
283
|
-
agentUuid,
|
|
284
|
-
http,
|
|
285
|
-
guestId,
|
|
286
|
-
roomStorageKey
|
|
287
|
-
]),
|
|
288
|
-
connectionError
|
|
289
|
-
};
|
|
290
|
-
}
|
|
291
|
-
//#endregion
|
|
292
|
-
//#region src/react/content/context.ts
|
|
293
|
-
const ContentContext = createContext(null);
|
|
294
|
-
function useContent() {
|
|
295
|
-
const context = useContext(ContentContext);
|
|
296
|
-
if (!context) throw new Error("useContent must be used within a ContentProvider.");
|
|
297
|
-
return context;
|
|
298
|
-
}
|
|
299
|
-
//#endregion
|
|
300
|
-
//#region src/react/content/content-cache.ts
|
|
301
|
-
const contentCache = /* @__PURE__ */ new Map();
|
|
302
|
-
const pendingLoads = /* @__PURE__ */ new Map();
|
|
303
|
-
function cacheContent(content) {
|
|
304
|
-
contentCache.set(`id:${content.id}`, content);
|
|
305
|
-
contentCache.set(`slug:${content.slug}`, content);
|
|
306
|
-
}
|
|
307
|
-
async function loadContent(client, contentId, publicSlug) {
|
|
308
|
-
const target = contentId ?? publicSlug;
|
|
309
|
-
if (!target) return null;
|
|
310
|
-
const key = contentId ? `id:${contentId}` : `slug:${publicSlug}`;
|
|
311
|
-
const cached = contentCache.get(key);
|
|
312
|
-
if (cached) return cached;
|
|
313
|
-
const pending = pendingLoads.get(key);
|
|
314
|
-
if (pending) return pending;
|
|
315
|
-
const request = (contentId ? client.content.get(target) : client.content.getPublic(target)).then((result) => result.ok && result.data ? result.data : null).then((content) => {
|
|
316
|
-
if (content) cacheContent(content);
|
|
317
|
-
return content;
|
|
318
|
-
}).finally(() => pendingLoads.delete(key));
|
|
319
|
-
pendingLoads.set(key, request);
|
|
320
|
-
return request;
|
|
321
|
-
}
|
|
322
|
-
//#endregion
|
|
323
|
-
//#region src/react/content/state.ts
|
|
324
|
-
function contentValues(content) {
|
|
325
|
-
return Object.fromEntries(content?.version?.entries.map((entry) => [entry.key, entry.value]) ?? []);
|
|
326
|
-
}
|
|
327
|
-
function contentPatches(content, values) {
|
|
328
|
-
const original = contentValues(content);
|
|
329
|
-
return Object.entries(values).filter(([key, value]) => JSON.stringify(value) !== JSON.stringify(original[key])).map(([key, value]) => ({
|
|
330
|
-
key,
|
|
331
|
-
value
|
|
332
|
-
}));
|
|
333
|
-
}
|
|
334
|
-
//#endregion
|
|
335
|
-
//#region src/react/content/provider.tsx
|
|
336
|
-
function ContentProvider({ children, client, contentId, publicSlug, initialContent, canEdit = false, canPublish = false, teamSlug }) {
|
|
337
|
-
const [content, setContent] = useState(initialContent ?? null);
|
|
338
|
-
const [values, setValues] = useState(() => contentValues(initialContent ?? null));
|
|
339
|
-
const [isLoading, setIsLoading] = useState(!initialContent && Boolean(contentId || publicSlug));
|
|
340
|
-
const [isSaving, setIsSaving] = useState(false);
|
|
341
|
-
const [isEditing, setEditing] = useState(false);
|
|
342
|
-
const [error, setError] = useState(null);
|
|
343
|
-
useEffect(() => {
|
|
344
|
-
if (initialContent && !contentId) {
|
|
345
|
-
cacheContent(initialContent);
|
|
346
|
-
setContent(initialContent);
|
|
347
|
-
setValues(contentValues(initialContent));
|
|
348
|
-
setIsLoading(false);
|
|
349
|
-
return;
|
|
350
|
-
}
|
|
351
|
-
const load = async () => {
|
|
352
|
-
if (!contentId && !publicSlug) return;
|
|
353
|
-
setIsLoading(true);
|
|
354
|
-
setError(null);
|
|
355
|
-
const nextContent = await loadContent(client, contentId, publicSlug);
|
|
356
|
-
if (!nextContent) setError("Content could not be loaded.");
|
|
357
|
-
else {
|
|
358
|
-
setContent(nextContent);
|
|
359
|
-
setValues(contentValues(nextContent));
|
|
360
|
-
}
|
|
361
|
-
setIsLoading(false);
|
|
362
|
-
};
|
|
363
|
-
load();
|
|
364
|
-
}, [
|
|
365
|
-
contentId,
|
|
366
|
-
initialContent,
|
|
367
|
-
publicSlug
|
|
368
|
-
]);
|
|
369
|
-
const setValue = useCallback((key, value) => {
|
|
370
|
-
setValues((current) => ({
|
|
371
|
-
...current,
|
|
372
|
-
[key]: value
|
|
373
|
-
}));
|
|
374
|
-
}, []);
|
|
375
|
-
const isDirty = contentPatches(content, values).length > 0;
|
|
376
|
-
const save = useCallback(async () => {
|
|
377
|
-
if (!content?.version || !contentId || !canEdit) return false;
|
|
378
|
-
const patches = contentPatches(content, values);
|
|
379
|
-
if (patches.length === 0) return true;
|
|
380
|
-
setIsSaving(true);
|
|
381
|
-
setError(null);
|
|
382
|
-
const result = await client.content.patch(contentId, {
|
|
383
|
-
expectedVersion: content.version.number,
|
|
384
|
-
patches,
|
|
385
|
-
origin: "inlineEditor"
|
|
386
|
-
});
|
|
387
|
-
setIsSaving(false);
|
|
388
|
-
if (!result.ok || !result.data) {
|
|
389
|
-
setError("Changes could not be saved. Refresh and try again.");
|
|
390
|
-
return false;
|
|
391
|
-
}
|
|
392
|
-
const nextContent = {
|
|
393
|
-
...content,
|
|
394
|
-
version: result.data,
|
|
395
|
-
updatedAt: result.data.updatedAt
|
|
396
|
-
};
|
|
397
|
-
cacheContent(nextContent);
|
|
398
|
-
setContent(nextContent);
|
|
399
|
-
setValues(contentValues(nextContent));
|
|
400
|
-
return true;
|
|
401
|
-
}, [
|
|
402
|
-
canEdit,
|
|
403
|
-
content,
|
|
404
|
-
contentId,
|
|
405
|
-
values
|
|
406
|
-
]);
|
|
407
|
-
const publish = useCallback(async () => {
|
|
408
|
-
if (!content?.version || !contentId || !canPublish) return false;
|
|
409
|
-
const patches = contentPatches(content, values);
|
|
410
|
-
setIsSaving(true);
|
|
411
|
-
setError(null);
|
|
412
|
-
const result = patches.length > 0 ? await client.content.patch(contentId, {
|
|
413
|
-
expectedVersion: content.version.number,
|
|
414
|
-
patches,
|
|
415
|
-
origin: "inlineEditor",
|
|
416
|
-
publish: true
|
|
417
|
-
}) : await client.content.publish(contentId, content.version.number);
|
|
418
|
-
setIsSaving(false);
|
|
419
|
-
if (!result.ok || !result.data) {
|
|
420
|
-
setError("Changes could not be published. Refresh and try again.");
|
|
421
|
-
return false;
|
|
422
|
-
}
|
|
423
|
-
const nextContent = {
|
|
424
|
-
...content,
|
|
425
|
-
version: result.data,
|
|
426
|
-
updatedAt: result.data.updatedAt
|
|
427
|
-
};
|
|
428
|
-
cacheContent(nextContent);
|
|
429
|
-
setContent(nextContent);
|
|
430
|
-
setValues(contentValues(nextContent));
|
|
431
|
-
setEditing(false);
|
|
432
|
-
return true;
|
|
433
|
-
}, [
|
|
434
|
-
canPublish,
|
|
435
|
-
content,
|
|
436
|
-
contentId,
|
|
437
|
-
values
|
|
438
|
-
]);
|
|
439
|
-
const context = useMemo(() => ({
|
|
440
|
-
content,
|
|
441
|
-
values,
|
|
442
|
-
isLoading,
|
|
443
|
-
isSaving,
|
|
444
|
-
isEditing,
|
|
445
|
-
isDirty,
|
|
446
|
-
canEdit,
|
|
447
|
-
canPublish,
|
|
448
|
-
teamSlug,
|
|
449
|
-
media: client.media,
|
|
450
|
-
error,
|
|
451
|
-
setEditing,
|
|
452
|
-
setValue,
|
|
453
|
-
save,
|
|
454
|
-
publish
|
|
455
|
-
}), [
|
|
456
|
-
canEdit,
|
|
457
|
-
canPublish,
|
|
458
|
-
content,
|
|
459
|
-
error,
|
|
460
|
-
isDirty,
|
|
461
|
-
isEditing,
|
|
462
|
-
isLoading,
|
|
463
|
-
isSaving,
|
|
464
|
-
publish,
|
|
465
|
-
save,
|
|
466
|
-
setValue,
|
|
467
|
-
teamSlug,
|
|
468
|
-
values
|
|
469
|
-
]);
|
|
470
|
-
return /* @__PURE__ */ jsx(ContentContext.Provider, {
|
|
471
|
-
value: context,
|
|
472
|
-
children
|
|
473
|
-
});
|
|
474
|
-
}
|
|
475
|
-
//#endregion
|
|
476
|
-
//#region src/react/content/editable-content.tsx
|
|
477
|
-
function EditableContent({ field, as: Tag = "span", className, placeholder = "Add text", multiline = false }) {
|
|
478
|
-
const { values, isEditing, canEdit, setValue } = useContent();
|
|
479
|
-
const value = values[field];
|
|
480
|
-
const text = typeof value === "string" || typeof value === "number" ? String(value) : "";
|
|
481
|
-
if (!canEdit || !isEditing) return /* @__PURE__ */ jsx(Tag, {
|
|
482
|
-
className,
|
|
483
|
-
children: text
|
|
484
|
-
});
|
|
485
|
-
if (multiline) return /* @__PURE__ */ jsx("textarea", {
|
|
486
|
-
"aria-label": field,
|
|
487
|
-
className,
|
|
488
|
-
placeholder,
|
|
489
|
-
value: text,
|
|
490
|
-
onChange: (event) => setValue(field, event.target.value)
|
|
491
|
-
});
|
|
492
|
-
return /* @__PURE__ */ jsx("input", {
|
|
493
|
-
"aria-label": field,
|
|
494
|
-
className,
|
|
495
|
-
placeholder,
|
|
496
|
-
value: text,
|
|
497
|
-
onChange: (event) => setValue(field, event.target.value)
|
|
498
|
-
});
|
|
499
|
-
}
|
|
500
|
-
function useContentValue(key) {
|
|
501
|
-
return useContent().values[key];
|
|
502
|
-
}
|
|
503
|
-
//#endregion
|
|
504
|
-
//#region src/react/content/editable-image.tsx
|
|
505
|
-
function EditableImage({ field, alt = "", className, inputClassName, placeholder = "Image URL", onSelect }) {
|
|
506
|
-
const { values, isEditing, canEdit, media, setValue, teamSlug } = useContent();
|
|
507
|
-
const source = typeof values[field] === "string" ? values[field] : "";
|
|
508
|
-
const [isPickerOpen, setPickerOpen] = useState(false);
|
|
509
|
-
const [images, setImages] = useState([]);
|
|
510
|
-
const [isUploading, setUploading] = useState(false);
|
|
511
|
-
useEffect(() => {
|
|
512
|
-
if (!isPickerOpen || !media || !teamSlug) return;
|
|
513
|
-
media.list(teamSlug, { mime: "image/" }).then((result) => setImages(result.ok ? result.data ?? [] : []));
|
|
514
|
-
}, [
|
|
515
|
-
isPickerOpen,
|
|
516
|
-
media,
|
|
517
|
-
teamSlug
|
|
518
|
-
]);
|
|
519
|
-
const upload = async (file) => {
|
|
520
|
-
if (!media || !teamSlug || !file.type.startsWith("image/")) return;
|
|
521
|
-
setUploading(true);
|
|
522
|
-
const result = await media.upload({
|
|
523
|
-
team: teamSlug,
|
|
524
|
-
file,
|
|
525
|
-
type: "output",
|
|
526
|
-
label: file.name
|
|
527
|
-
});
|
|
528
|
-
setUploading(false);
|
|
529
|
-
if (!result.ok || !result.data) return;
|
|
530
|
-
setImages((current) => [result.data, ...current]);
|
|
531
|
-
setValue(field, result.data.url);
|
|
532
|
-
setPickerOpen(false);
|
|
533
|
-
};
|
|
534
|
-
if (!canEdit || !isEditing) return source ? /* @__PURE__ */ jsx("img", {
|
|
535
|
-
src: source,
|
|
536
|
-
alt,
|
|
537
|
-
className
|
|
538
|
-
}) : null;
|
|
539
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
540
|
-
className,
|
|
541
|
-
children: [
|
|
542
|
-
source && /* @__PURE__ */ jsx("img", {
|
|
543
|
-
src: source,
|
|
544
|
-
alt
|
|
545
|
-
}),
|
|
546
|
-
onSelect && /* @__PURE__ */ jsx("button", {
|
|
547
|
-
className: "rounded-lg bg-blue-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-blue-500",
|
|
548
|
-
type: "button",
|
|
549
|
-
onClick: onSelect,
|
|
550
|
-
children: "Choose image"
|
|
551
|
-
}),
|
|
552
|
-
!onSelect && media && teamSlug && /* @__PURE__ */ jsx("button", {
|
|
553
|
-
className: "rounded-lg bg-blue-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-blue-500",
|
|
554
|
-
type: "button",
|
|
555
|
-
onClick: () => setPickerOpen(true),
|
|
556
|
-
children: "Choose image"
|
|
557
|
-
}),
|
|
558
|
-
/* @__PURE__ */ jsx(ImagePicker, {
|
|
559
|
-
open: isPickerOpen,
|
|
560
|
-
onClose: () => setPickerOpen(false),
|
|
561
|
-
images,
|
|
562
|
-
isUploading,
|
|
563
|
-
onUpload: upload,
|
|
564
|
-
onSelect: (url) => {
|
|
565
|
-
setValue(field, url);
|
|
566
|
-
setPickerOpen(false);
|
|
567
|
-
}
|
|
568
|
-
}),
|
|
569
|
-
/* @__PURE__ */ jsx("input", {
|
|
570
|
-
"aria-label": field,
|
|
571
|
-
className: inputClassName,
|
|
572
|
-
type: "url",
|
|
573
|
-
placeholder,
|
|
574
|
-
value: source,
|
|
575
|
-
onChange: (event) => setValue(field, event.target.value)
|
|
576
|
-
})
|
|
577
|
-
]
|
|
578
|
-
});
|
|
579
|
-
}
|
|
580
|
-
function ImagePicker({ open, onClose, images, isUploading, onUpload, onSelect }) {
|
|
581
|
-
if (!open) return null;
|
|
582
|
-
return /* @__PURE__ */ jsx("div", {
|
|
583
|
-
className: "fixed inset-0 z-[1100] grid place-items-center bg-slate-950/45 p-4",
|
|
584
|
-
role: "dialog",
|
|
585
|
-
"aria-modal": "true",
|
|
586
|
-
"aria-label": "Image library",
|
|
587
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
588
|
-
className: "max-h-[min(44rem,calc(100vh-2rem))] w-full max-w-2xl overflow-y-auto rounded-xl bg-white p-5 shadow-2xl",
|
|
589
|
-
children: [
|
|
590
|
-
/* @__PURE__ */ jsxs("div", {
|
|
591
|
-
className: "flex items-start justify-between gap-4",
|
|
592
|
-
children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("h2", {
|
|
593
|
-
className: "text-lg font-semibold text-slate-950",
|
|
594
|
-
children: "Image library"
|
|
595
|
-
}), /* @__PURE__ */ jsx("p", {
|
|
596
|
-
className: "mt-1 text-sm text-slate-500",
|
|
597
|
-
children: "Choose an existing image or upload a new one."
|
|
598
|
-
})] }), /* @__PURE__ */ jsx("button", {
|
|
599
|
-
className: "rounded-lg px-3 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-100",
|
|
600
|
-
type: "button",
|
|
601
|
-
onClick: onClose,
|
|
602
|
-
children: "Close"
|
|
603
|
-
})]
|
|
604
|
-
}),
|
|
605
|
-
/* @__PURE__ */ jsxs("label", {
|
|
606
|
-
className: "mt-5 flex cursor-pointer items-center justify-center rounded-lg border border-dashed border-slate-300 px-4 py-6 text-sm font-medium text-slate-600 transition hover:border-blue-400 hover:text-blue-600",
|
|
607
|
-
children: [/* @__PURE__ */ jsx("input", {
|
|
608
|
-
className: "sr-only",
|
|
609
|
-
type: "file",
|
|
610
|
-
accept: "image/*",
|
|
611
|
-
onChange: (event) => {
|
|
612
|
-
const file = event.target.files?.[0];
|
|
613
|
-
if (file) onUpload(file);
|
|
614
|
-
}
|
|
615
|
-
}), "Upload image"]
|
|
616
|
-
}),
|
|
617
|
-
isUploading && /* @__PURE__ */ jsx("span", {
|
|
618
|
-
className: "mt-3 block text-sm text-slate-500",
|
|
619
|
-
children: "Uploading…"
|
|
620
|
-
}),
|
|
621
|
-
/* @__PURE__ */ jsx("div", {
|
|
622
|
-
className: "mt-5 grid grid-cols-2 gap-3 sm:grid-cols-3",
|
|
623
|
-
role: "list",
|
|
624
|
-
children: images.map((image) => /* @__PURE__ */ jsxs("button", {
|
|
625
|
-
className: "overflow-hidden rounded-lg border border-slate-200 text-left transition-opacity hover:opacity-75",
|
|
626
|
-
type: "button",
|
|
627
|
-
onClick: () => onSelect(image.url),
|
|
628
|
-
children: [/* @__PURE__ */ jsx("img", {
|
|
629
|
-
className: "aspect-square w-full object-cover",
|
|
630
|
-
src: image.url,
|
|
631
|
-
alt: image.name
|
|
632
|
-
}), /* @__PURE__ */ jsx("span", {
|
|
633
|
-
className: "block truncate p-2 text-xs text-slate-700",
|
|
634
|
-
children: image.name
|
|
635
|
-
})]
|
|
636
|
-
}, image.id))
|
|
637
|
-
})
|
|
638
|
-
]
|
|
639
|
-
})
|
|
640
|
-
});
|
|
641
|
-
}
|
|
642
|
-
//#endregion
|
|
643
|
-
//#region src/react/content/toolbar.tsx
|
|
644
|
-
function ContentToolbar({ className, labels = {}, confirmPublish }) {
|
|
645
|
-
const { canEdit, canPublish, isDirty, isEditing, isSaving, error, setEditing, save, publish } = useContent();
|
|
646
|
-
if (!canEdit) return null;
|
|
647
|
-
const edit = labels.edit ?? "Edit";
|
|
648
|
-
const saveLabel = labels.save ?? "Save draft";
|
|
649
|
-
const publishLabel = labels.publish ?? "Publish";
|
|
650
|
-
const cancel = labels.cancel ?? "Cancel";
|
|
651
|
-
const handlePublish = async () => {
|
|
652
|
-
if (confirmPublish && !await confirmPublish()) return;
|
|
653
|
-
await publish();
|
|
654
|
-
};
|
|
655
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
656
|
-
className: `flex flex-wrap items-center gap-2 ${className ?? ""}`,
|
|
657
|
-
role: "toolbar",
|
|
658
|
-
"aria-label": "Content editor",
|
|
659
|
-
children: [
|
|
660
|
-
!isEditing ? /* @__PURE__ */ jsx("button", {
|
|
661
|
-
className: "rounded-lg bg-blue-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-blue-500",
|
|
662
|
-
type: "button",
|
|
663
|
-
onClick: () => setEditing(true),
|
|
664
|
-
children: edit
|
|
665
|
-
}) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
666
|
-
/* @__PURE__ */ jsx("button", {
|
|
667
|
-
className: "rounded-lg bg-blue-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-blue-500 disabled:opacity-60",
|
|
668
|
-
type: "button",
|
|
669
|
-
disabled: isSaving,
|
|
670
|
-
onClick: () => void save(),
|
|
671
|
-
children: isSaving ? "Saving…" : saveLabel
|
|
672
|
-
}),
|
|
673
|
-
canPublish && /* @__PURE__ */ jsx("button", {
|
|
674
|
-
className: "rounded-lg bg-emerald-600 px-3 py-2 text-sm font-medium text-white transition hover:bg-emerald-500 disabled:opacity-60",
|
|
675
|
-
type: "button",
|
|
676
|
-
disabled: isSaving,
|
|
677
|
-
onClick: () => void handlePublish(),
|
|
678
|
-
children: publishLabel
|
|
679
|
-
}),
|
|
680
|
-
/* @__PURE__ */ jsx("button", {
|
|
681
|
-
className: "rounded-lg px-3 py-2 text-sm font-medium text-slate-700 transition hover:bg-slate-100 disabled:opacity-60",
|
|
682
|
-
type: "button",
|
|
683
|
-
disabled: isSaving,
|
|
684
|
-
onClick: () => setEditing(false),
|
|
685
|
-
children: cancel
|
|
686
|
-
})
|
|
687
|
-
] }),
|
|
688
|
-
error && /* @__PURE__ */ jsx("span", {
|
|
689
|
-
className: "w-full text-sm text-red-600 dark:text-red-400",
|
|
690
|
-
role: "alert",
|
|
691
|
-
children: error
|
|
692
|
-
}),
|
|
693
|
-
isEditing && isDirty && /* @__PURE__ */ jsx("span", {
|
|
694
|
-
className: "w-full text-xs text-slate-500",
|
|
695
|
-
"aria-live": "polite",
|
|
696
|
-
children: "Unsaved changes"
|
|
697
|
-
})
|
|
698
|
-
]
|
|
699
|
-
});
|
|
700
|
-
}
|
|
701
|
-
//#endregion
|
|
702
|
-
//#region src/react/content/content-editor.tsx
|
|
703
|
-
function EditorPanel({ title }) {
|
|
704
|
-
const { canEdit } = useContent();
|
|
705
|
-
if (!canEdit) return null;
|
|
706
|
-
return /* @__PURE__ */ jsxs("div", {
|
|
707
|
-
className: "fixed right-4 bottom-4 z-[1000] w-[min(24rem,calc(100vw-2rem))] rounded-xl border border-slate-200 bg-white p-3 text-slate-950 shadow-xl",
|
|
708
|
-
children: [/* @__PURE__ */ jsx("strong", {
|
|
709
|
-
className: "mb-2 block text-sm font-semibold",
|
|
710
|
-
children: title
|
|
711
|
-
}), /* @__PURE__ */ jsx(ContentToolbar, { labels: {
|
|
712
|
-
edit: "Edit",
|
|
713
|
-
save: "Save draft",
|
|
714
|
-
publish: "Publish",
|
|
715
|
-
cancel: "Cancel"
|
|
716
|
-
} })]
|
|
717
|
-
});
|
|
718
|
-
}
|
|
719
|
-
function ContentEditor({ children, title = "JoAi Content", ...provider }) {
|
|
720
|
-
return /* @__PURE__ */ jsx(ContentProvider, {
|
|
721
|
-
...provider,
|
|
722
|
-
children: /* @__PURE__ */ jsxs("div", {
|
|
723
|
-
"data-joai-content-editor": "true",
|
|
724
|
-
children: [/* @__PURE__ */ jsx(EditorPanel, { title }), children]
|
|
725
|
-
})
|
|
726
|
-
});
|
|
727
|
-
}
|
|
728
|
-
//#endregion
|
|
729
|
-
export { ContentEditor, ContentProvider, ContentToolbar, EditableContent, EditableImage, EmbedChatInput, EmbedChatList, clearRoom, getOrCreateGuestId, loadRoom, openEventSourceStream, saveRoom, useContentValue, useEmbedChat };
|