@arbidocs/blocks 0.4.145 → 0.4.147
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/agents/index.cjs +266 -266
- package/dist/agents/index.js +9 -9
- package/dist/chat/index.cjs +1 -1
- package/dist/chat/index.js +1 -1
- package/dist/{chunk-ULPFRK3J.cjs → chunk-AINU3EJ6.cjs} +8 -8
- package/dist/{chunk-ULPFRK3J.cjs.map → chunk-AINU3EJ6.cjs.map} +1 -1
- package/dist/{chunk-KPO67GBR.cjs → chunk-AO7SK6WP.cjs} +32 -32
- package/dist/{chunk-KPO67GBR.cjs.map → chunk-AO7SK6WP.cjs.map} +1 -1
- package/dist/{chunk-NGDXDHLG.js → chunk-DAHCRVPM.js} +3 -3
- package/dist/{chunk-NGDXDHLG.js.map → chunk-DAHCRVPM.js.map} +1 -1
- package/dist/{chunk-FUTMU4FR.js → chunk-DGV7HQA7.js} +6 -179
- package/dist/chunk-DGV7HQA7.js.map +1 -0
- package/dist/chunk-EV7W64B6.js +134 -0
- package/dist/chunk-EV7W64B6.js.map +1 -0
- package/dist/{chunk-O6IEZDRC.cjs → chunk-GRGS5M6O.cjs} +181 -3
- package/dist/chunk-GRGS5M6O.cjs.map +1 -0
- package/dist/{chunk-J4M37SXY.js → chunk-H74HEPKT.js} +190 -7
- package/dist/chunk-H74HEPKT.js.map +1 -0
- package/dist/{chunk-NSNHRZBH.cjs → chunk-IL3WB3YX.cjs} +3 -3
- package/dist/{chunk-NSNHRZBH.cjs.map → chunk-IL3WB3YX.cjs.map} +1 -1
- package/dist/{chunk-34GDGE77.cjs → chunk-LTU35TQN.cjs} +192 -6
- package/dist/chunk-LTU35TQN.cjs.map +1 -0
- package/dist/{chunk-VVZ34A2P.js → chunk-LZRMXJIE.js} +3 -3
- package/dist/{chunk-VVZ34A2P.js.map → chunk-LZRMXJIE.js.map} +1 -1
- package/dist/{chunk-OPTBQSCV.cjs → chunk-MFY2ZNP6.cjs} +2 -181
- package/dist/{chunk-FUTMU4FR.js.map → chunk-MFY2ZNP6.cjs.map} +1 -1
- package/dist/{chunk-6HCJ3ZEU.js → chunk-R6VCPDPF.js} +178 -6
- package/dist/chunk-R6VCPDPF.js.map +1 -0
- package/dist/chunk-RXK3XP62.cjs +144 -0
- package/dist/chunk-RXK3XP62.cjs.map +1 -0
- package/dist/{chunk-KTSF4HFC.js → chunk-SUUPR735.js} +6 -6
- package/dist/{chunk-KTSF4HFC.js.map → chunk-SUUPR735.js.map} +1 -1
- package/dist/{chunk-WO7QAVTL.cjs → chunk-T5I4NRFP.cjs} +9 -9
- package/dist/{chunk-WO7QAVTL.cjs.map → chunk-T5I4NRFP.cjs.map} +1 -1
- package/dist/chunk-U37AYUPI.cjs +5371 -0
- package/dist/chunk-U37AYUPI.cjs.map +1 -0
- package/dist/{chunk-QOL3M4FJ.js → chunk-VUR63NMQ.js} +8 -8
- package/dist/{chunk-QOL3M4FJ.js.map → chunk-VUR63NMQ.js.map} +1 -1
- package/dist/chunk-WIZ7Z7FN.js +5179 -0
- package/dist/chunk-WIZ7Z7FN.js.map +1 -0
- package/dist/collaboration/index.cjs +81 -81
- package/dist/collaboration/index.js +3 -3
- package/dist/connect/docx.cjs +9 -9
- package/dist/connect/docx.js +6 -6
- package/dist/connect/index.cjs +1395 -132
- package/dist/connect/index.cjs.map +1 -1
- package/dist/connect/index.d.ts +2 -0
- package/dist/connect/index.js +1278 -24
- package/dist/connect/index.js.map +1 -1
- package/dist/connection/ConnectedNotificationRelevance.d.ts +4 -1
- package/dist/connection/connectors/ConnectedAppsSettings.d.ts +24 -0
- package/dist/connection/connectors/ConnectedDriveSyncDialog.d.ts +12 -0
- package/dist/connection/connectors/ConnectedMailboxSyncDialog.d.ts +12 -0
- package/dist/connection/connectors/index.d.ts +4 -0
- package/dist/connection/connectors/sync-labels.d.ts +21 -0
- package/dist/connection/settings-page/ConnectedSettingsPage.d.ts +4 -0
- package/dist/connection/settings-page/index.d.ts +1 -1
- package/dist/connection/workspace-settings/ConnectedWorkspaceSettings.d.ts +53 -0
- package/dist/connection/workspace-settings/index.d.ts +2 -0
- package/dist/connection/workspace-settings/useConnectedWorkspaceSettings.d.ts +85 -0
- package/dist/document-tools/index.cjs +1 -1
- package/dist/document-tools/index.js +1 -1
- package/dist/facts/index.cjs +1 -1
- package/dist/facts/index.js +1 -1
- package/dist/files/index.cjs +3 -3
- package/dist/files/index.js +3 -3
- package/dist/index.cjs +445 -618
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +23 -205
- package/dist/index.js.map +1 -1
- package/dist/settings/PlanBadge.d.ts +1 -1
- package/dist/settings/index.cjs +551 -3716
- package/dist/settings/index.cjs.map +1 -1
- package/dist/settings/index.js +8 -3525
- package/dist/settings/index.js.map +1 -1
- package/dist/shell/index.cjs +1 -1
- package/dist/shell/index.js +1 -1
- package/dist/site/index.cjs +10 -10
- package/dist/site/index.js +2 -2
- package/dist/studio/index.cjs +3 -3
- package/dist/studio/index.js +3 -3
- package/dist/workflow-canvas/index.cjs +22 -22
- package/dist/workflow-canvas/index.js +9 -9
- package/dist/workspaces/CommonWorkspaceToggle.d.ts +15 -0
- package/dist/workspaces/index.cjs +38 -107
- package/dist/workspaces/index.cjs.map +1 -1
- package/dist/workspaces/index.d.ts +1 -0
- package/dist/workspaces/index.js +5 -102
- package/dist/workspaces/index.js.map +1 -1
- package/node_modules/@arbidocs/coedit/package.json +1 -1
- package/package.json +4 -4
- package/dist/chunk-34GDGE77.cjs.map +0 -1
- package/dist/chunk-5YHEHEJT.js +0 -1667
- package/dist/chunk-5YHEHEJT.js.map +0 -1
- package/dist/chunk-6HCJ3ZEU.js.map +0 -1
- package/dist/chunk-J4M37SXY.js.map +0 -1
- package/dist/chunk-O6IEZDRC.cjs.map +0 -1
- package/dist/chunk-OPTBQSCV.cjs.map +0 -1
- package/dist/chunk-U73KPFYH.cjs +0 -1717
- package/dist/chunk-U73KPFYH.cjs.map +0 -1
package/dist/settings/index.js
CHANGED
|
@@ -1,3536 +1,19 @@
|
|
|
1
1
|
"use client";
|
|
2
|
+
export { ActiveSessionsDialog, AppearanceSettings, AvatarPicker, CONVERSATION_TITLE_MAX, CheckoutDialogFrame, ConfigSwitcherBar, ConnectionCard, ConnectionsEmpty, ConnectionsError, ConnectionsLoading, ConversationTitleSection, DEFAULT_ACTIVE_SESSIONS_DIALOG_LABELS, DEFAULT_APPEARANCE_PAIRING_IDS, DEFAULT_AVATAR_PICKER_LABELS, DEFAULT_CHECKOUT_DIALOG_LABELS, DEFAULT_CONFIG_SWITCHER_BAR_LABELS, DEFAULT_CONNECTION_CARD_LABELS, DEFAULT_CONVERSATION_TITLE_SECTION_LABELS, DEFAULT_DAILY_CAP_FIELD_LABELS, DEFAULT_DELETE_ACCOUNT_DIALOG_LABELS, DEFAULT_EMAIL_WORKSPACE_DIALOG_LABELS, DEFAULT_ERROR_DIALOG_LABELS, DEFAULT_IDENTITY_VERIFICATION_LABELS, DEFAULT_INLINE_NAME_EDITOR_LABELS, DEFAULT_INVITE_CONTACTS_DIALOG_LABELS, DEFAULT_INVOICES_DIALOG_LABELS, DEFAULT_LOGOUT_DIALOG_LABELS, DEFAULT_MEMBER_PROJECT_ROW_LABELS, DEFAULT_MODEL_SELECTION_SECTION_LABELS, DEFAULT_PASSWORD_CHANGE_DIALOG_LABELS, DEFAULT_PLAN_CARD_LABELS, DEFAULT_PROFILE_CARD_LABELS, DEFAULT_PROJECT_CARD_VIEW_LABELS, DEFAULT_PROJECT_DETAIL_HEADER_LABELS, DEFAULT_PROJECT_LIST_LABELS, DEFAULT_QUOTA_EXCEEDED_DIALOG_LABELS, DEFAULT_REFERRAL_REWARD_LABELS, DEFAULT_RENAME_DIALOG_LABELS, DEFAULT_SETTINGS_DANGER_ZONE_LABELS, DEFAULT_SHARED_PROJECTS_SECTION_LABELS, DEFAULT_SUBSCRIPTION_SECTION_LABELS, DEFAULT_SUBSCRIPTION_STATUS_LABELS, DEFAULT_SUPPORT_PANEL_LABELS, DEFAULT_SYNC_DIALOG_FOOTER_LABELS, DEFAULT_SYNC_FOLDER_ROW_LABELS, DEFAULT_TIPS_EDITOR_LABELS, DEFAULT_USAGE_LINE_CHART_LABELS, DEFAULT_USAGE_PANEL_LABELS, DEFAULT_USAGE_PROPORTION_BAR_LABELS, DEFAULT_WELCOME_DIALOG_LABELS, DEFAULT_WORK_OFFLINE_LABELS, DailyCapField, DeleteAccountDialog, DraggableHeader, EMAIL_NOTIFICATION_CATEGORIES, EMAIL_NOTIFICATION_KEYS, EmailWorkspaceDialogView, ErrorDialogView, FilterChip, FloatingPanel, IdentityVerificationCard, IdentityVerificationDialog, InlineNameEditor, InviteContactsDialog, InvoicesDialog, JsonTree, LogoutDialog, MemberProjectRow, MessageJsonTree, ModelProviderLabel, ModelSelectionSection, MoreInfo, MoreInfoList, NotificationCategoryList, PanelActionsRow, PanelAddButton, PanelFrame, PanelFrameBody, PanelNote, PanelScroll, PanelTitleBar, PasswordChangeDialog, PlanActionButton, PlanActionRow, PlanBadge, PlanCard, PlanCardGrid, PlanDialogFrame, PlanInfoPopover, PlanNotice, PlanPickerCard, PlanPickerHeader, PlanStack, PlanTierOption, PlanTransition, PremiumModelsFrame, PricingToggle, ProfileCard, ProjectCardView, ProjectDetailHeader, ProjectDetailSection, ProjectGroup, ProjectList, ProjectNameLabel, ProjectPlanPicker, ProjectRow, ProjectRowActions, PromoCodeInput, QuotaExceededDialogView, QuotaMeter, ReferralRewardBadge, ReferralRewardNote, ReferralRewardSummary, RenameDialog, RequireVerified, RowButton, RowIconAction, SegmentedControl, ServerConnectionButton, SettingsActionRow, SettingsCard, SettingsDangerZone, SettingsPage, SettingsPanel, SettingsRow, SettingsSection, SettingsSwitchGroup, SettingsSwitchRow, SharedProjectRow, SharedProjectsSection, SubscriptionSectionView, SubscriptionStatusView, SupportPanel, SupportUnavailable, SyncCheckList, SyncDialogBody, SyncDialogFooter, SyncField, SyncFolderRow, SyncFolderStatus, SyncLinkButton, SyncLinkRow, SyncLoading, SyncNote, SyncOptionToggle, SyncOptions, SyncReconnectNotice, SyncSelect, SyncSmallNote, SyncTreeFrame, ThreadPreviewDialog, TipsEditorDialog, UsageActionButton, UsageLegend, UsageLineChart, UsagePanel, UsageProportionBar, UsageQuotaHint, UsageSection, UsageSummary, UsageToggle, WelcomeDialog, WelcomeProjectPicker, WorkOfflineToggle, formatSessionTtl, resolveSettingsSection, serverConnectionView, toActiveSessionViews, toDeleteBlockerViews, toLogoutSessionViews, toNotificationCategories } from '../chunk-WIZ7Z7FN.js';
|
|
2
3
|
export { ModalBreadcrumbHeader, ModalCrumbs } from '../chunk-RC6VTY2H.js';
|
|
3
|
-
import
|
|
4
|
-
|
|
5
|
-
import { UsageMeter } from '../chunk-66TA5IBN.js';
|
|
6
|
-
import { getFontPairing } from '../chunk-NHZK64TQ.js';
|
|
7
|
-
import { ToneBadge } from '../chunk-5LXQPP2K.js';
|
|
4
|
+
import '../chunk-66TA5IBN.js';
|
|
5
|
+
import '../chunk-NHZK64TQ.js';
|
|
8
6
|
export { MultiSelect } from '../chunk-CQCC7LE7.js';
|
|
9
7
|
export { DEFAULT_DOCUMENT_PICKER_LABELS, DEFAULT_TRI_STATE_FILTER_MENU_LABELS, DocumentPicker, TriStateFilterMenu } from '../chunk-KSHKTOY2.js';
|
|
8
|
+
import '../chunk-5LXQPP2K.js';
|
|
10
9
|
import '../chunk-VILAPTCB.js';
|
|
11
10
|
export { ConfirmDialog, DEFAULT_CONFIRM_DIALOG_LABELS } from '../chunk-VHJHY7TT.js';
|
|
12
|
-
import
|
|
13
|
-
import
|
|
11
|
+
import '../chunk-4WWM3GQ5.js';
|
|
12
|
+
import '../chunk-AUS3KBHJ.js';
|
|
14
13
|
import '../chunk-NPLYHR2E.js';
|
|
15
|
-
import
|
|
16
|
-
import { ModalSection, ModalSectionTitle, ModalHeader, ModalScaffold } from '../chunk-TX2ZICS7.js';
|
|
14
|
+
import '../chunk-7F6CBP3Z.js';
|
|
17
15
|
export { MODAL_SECTION_TITLE_CLASS, ModalHeader, ModalScaffold, ModalSection, ModalSectionTitle } from '../chunk-TX2ZICS7.js';
|
|
18
|
-
import
|
|
16
|
+
import '../chunk-OXF2IFXG.js';
|
|
19
17
|
import '../chunk-VUNV25KB.js';
|
|
20
|
-
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
21
|
-
import { cn, DialogFooter, Select, SelectTrigger, SelectValue, SelectContent, SelectItem, Input, Button, Tooltip, TooltipTrigger, TooltipContent, Dialog, DialogContent, DialogTitle, DialogDescription, Label, Textarea, Checkbox, ScrollArea, DialogHeader, Badge, Progress } from '@arbidocs/react/ui';
|
|
22
|
-
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
23
|
-
import { useMemo, useState, useId, Fragment as Fragment$1 } from 'react';
|
|
24
|
-
import { Sun, Moon, History, Undo2, Star, Trash2, Users, Sparkles, Brain, ChevronDown, ChevronRight, Pencil, Plus, Loader2, Check, X, Info, Tag, Gift, PlugIcon, CheckCircle2, ExternalLink, ShieldCheck, Plug, AlertCircle, MessageCircleQuestionMark, BookOpen, UserPlus, ChartNoAxesColumn, FileText, Mail, Send, Clock, Infinity, ArrowRight, Copy, RefreshCw, LogOut, RotateCcw } from 'lucide-react';
|
|
25
|
-
import { cva } from 'class-variance-authority';
|
|
26
|
-
|
|
27
|
-
function SegmentedControl({
|
|
28
|
-
value,
|
|
29
|
-
onChange,
|
|
30
|
-
options,
|
|
31
|
-
ariaLabel,
|
|
32
|
-
className
|
|
33
|
-
}) {
|
|
34
|
-
return /* @__PURE__ */ jsx(
|
|
35
|
-
RadioGroupPrimitive.Root,
|
|
36
|
-
{
|
|
37
|
-
"data-slot": "segmented-control",
|
|
38
|
-
"aria-label": ariaLabel,
|
|
39
|
-
value,
|
|
40
|
-
onValueChange: (next) => onChange(next),
|
|
41
|
-
orientation: "horizontal",
|
|
42
|
-
className: cn("inline-flex rounded-lg border border-border bg-background p-1", className),
|
|
43
|
-
children: options.map((option) => /* @__PURE__ */ jsxs(
|
|
44
|
-
RadioGroupPrimitive.Item,
|
|
45
|
-
{
|
|
46
|
-
value: option.value,
|
|
47
|
-
"data-testid": option.testId,
|
|
48
|
-
className: cn(
|
|
49
|
-
"flex items-center gap-2 rounded-md px-4 py-1.5 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11 pointer-coarse:py-2.5",
|
|
50
|
-
option.value === value ? "bg-accent text-accent-foreground" : "text-muted-foreground hover:text-foreground"
|
|
51
|
-
),
|
|
52
|
-
children: [
|
|
53
|
-
option.icon,
|
|
54
|
-
option.label
|
|
55
|
-
]
|
|
56
|
-
},
|
|
57
|
-
option.value
|
|
58
|
-
))
|
|
59
|
-
}
|
|
60
|
-
);
|
|
61
|
-
}
|
|
62
|
-
function FloatingPanel({
|
|
63
|
-
panelId,
|
|
64
|
-
mode,
|
|
65
|
-
title,
|
|
66
|
-
subtitle,
|
|
67
|
-
headerIcon,
|
|
68
|
-
headerActions,
|
|
69
|
-
tabLabel,
|
|
70
|
-
modeSwitcher,
|
|
71
|
-
children,
|
|
72
|
-
footer,
|
|
73
|
-
onPanelClick,
|
|
74
|
-
className
|
|
75
|
-
}) {
|
|
76
|
-
const isRenderFunction = typeof children === "function";
|
|
77
|
-
const content = isRenderFunction ? children({ modeSwitcher }) : children;
|
|
78
|
-
const footerEl = footer && /* @__PURE__ */ jsx("div", { className: "relative z-10 flex-shrink-0 border-t border-border p-3", children: footer });
|
|
79
|
-
const body = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
80
|
-
/* @__PURE__ */ jsx("div", { className: cn("flex-1", isRenderFunction ? "overflow-hidden" : "overflow-auto p-3"), children: content }),
|
|
81
|
-
footerEl
|
|
82
|
-
] });
|
|
83
|
-
if (mode === "popout") {
|
|
84
|
-
return /* @__PURE__ */ jsxs(
|
|
85
|
-
"div",
|
|
86
|
-
{
|
|
87
|
-
"data-slot": "floating-panel",
|
|
88
|
-
className: cn("flex h-screen flex-col bg-background text-foreground", className),
|
|
89
|
-
children: [
|
|
90
|
-
!isRenderFunction && /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 items-start justify-between border-b border-border px-3 py-2", children: [
|
|
91
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 flex-col", children: [
|
|
92
|
-
(title || headerIcon) && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-base font-semibold text-primary", children: [
|
|
93
|
-
headerIcon,
|
|
94
|
-
title && /* @__PURE__ */ jsx("span", { children: title })
|
|
95
|
-
] }),
|
|
96
|
-
subtitle && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: subtitle }),
|
|
97
|
-
headerActions && /* @__PURE__ */ jsx("div", { className: title ? "mt-1.5" : "", children: headerActions })
|
|
98
|
-
] }),
|
|
99
|
-
modeSwitcher
|
|
100
|
-
] }),
|
|
101
|
-
body
|
|
102
|
-
]
|
|
103
|
-
}
|
|
104
|
-
);
|
|
105
|
-
}
|
|
106
|
-
return /* @__PURE__ */ jsxs(
|
|
107
|
-
"div",
|
|
108
|
-
{
|
|
109
|
-
"data-slot": "floating-panel",
|
|
110
|
-
"data-mode": mode,
|
|
111
|
-
className: cn("flex h-full flex-col bg-background text-foreground", className),
|
|
112
|
-
onClick: onPanelClick,
|
|
113
|
-
children: [
|
|
114
|
-
!isRenderFunction && /* @__PURE__ */ jsx(
|
|
115
|
-
TabHeader,
|
|
116
|
-
{
|
|
117
|
-
tabs: [{ id: panelId, label: tabLabel ?? title }],
|
|
118
|
-
activeTabId: panelId,
|
|
119
|
-
onTabChange: () => {
|
|
120
|
-
},
|
|
121
|
-
rightContent: modeSwitcher
|
|
122
|
-
}
|
|
123
|
-
),
|
|
124
|
-
body
|
|
125
|
-
]
|
|
126
|
-
}
|
|
127
|
-
);
|
|
128
|
-
}
|
|
129
|
-
var DEFAULT_CONFIG_SWITCHER_BAR_LABELS = {
|
|
130
|
-
placeholder: "Select configuration...",
|
|
131
|
-
save: "Save",
|
|
132
|
-
saving: "Saving...",
|
|
133
|
-
delete: "Delete"
|
|
134
|
-
};
|
|
135
|
-
var MARKERS = { default: Star, original: Undo2, "last-used": History };
|
|
136
|
-
function ConfigSwitcherBar({
|
|
137
|
-
options,
|
|
138
|
-
value,
|
|
139
|
-
onSelect,
|
|
140
|
-
hasUnsavedChanges,
|
|
141
|
-
unsavedTitle = "Unsaved Changes",
|
|
142
|
-
unsavedSubtitle = "Changes will be lost if you switch",
|
|
143
|
-
showNameField,
|
|
144
|
-
name,
|
|
145
|
-
onNameChange,
|
|
146
|
-
namePlaceholder,
|
|
147
|
-
saveLabel,
|
|
148
|
-
onSave,
|
|
149
|
-
isSaving,
|
|
150
|
-
canDelete,
|
|
151
|
-
onDelete,
|
|
152
|
-
isDeleting,
|
|
153
|
-
nameTestId,
|
|
154
|
-
saveTestId,
|
|
155
|
-
deleteTestId,
|
|
156
|
-
labels,
|
|
157
|
-
className
|
|
158
|
-
}) {
|
|
159
|
-
const l = useMemo(() => ({ ...DEFAULT_CONFIG_SWITCHER_BAR_LABELS, ...labels }), [labels]);
|
|
160
|
-
return /* @__PURE__ */ jsx(
|
|
161
|
-
DialogFooter,
|
|
162
|
-
{
|
|
163
|
-
"data-slot": "config-switcher-bar",
|
|
164
|
-
className: cn("flex-shrink-0 border-t bg-muted px-4 py-4", className),
|
|
165
|
-
children: /* @__PURE__ */ jsx("div", { className: "flex w-full flex-col gap-3", children: /* @__PURE__ */ jsxs("div", { className: "flex min-h-[36px] items-center gap-3", children: [
|
|
166
|
-
/* @__PURE__ */ jsxs(
|
|
167
|
-
Select,
|
|
168
|
-
{
|
|
169
|
-
value: hasUnsavedChanges ? "unsaved" : value,
|
|
170
|
-
onValueChange: (v) => {
|
|
171
|
-
if (v !== "unsaved") onSelect(v);
|
|
172
|
-
},
|
|
173
|
-
children: [
|
|
174
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "h-9 min-w-0 flex-1 border-0 bg-background", children: /* @__PURE__ */ jsx(SelectValue, { placeholder: l.placeholder }) }),
|
|
175
|
-
/* @__PURE__ */ jsxs(SelectContent, { position: "popper", children: [
|
|
176
|
-
hasUnsavedChanges && /* @__PURE__ */ jsx(SelectItem, { value: "unsaved", children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
177
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium", children: unsavedTitle }),
|
|
178
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: unsavedSubtitle })
|
|
179
|
-
] }) }),
|
|
180
|
-
options.map((o) => {
|
|
181
|
-
const Marker = o.marker ? MARKERS[o.marker] : null;
|
|
182
|
-
return /* @__PURE__ */ jsx(SelectItem, { value: o.value, children: /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
|
|
183
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col", children: [
|
|
184
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium", children: o.title }),
|
|
185
|
-
o.subtitle && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: o.subtitle })
|
|
186
|
-
] }),
|
|
187
|
-
Marker && /* @__PURE__ */ jsx(Marker, { className: "mt-0.5 size-3 flex-shrink-0 text-muted-foreground" })
|
|
188
|
-
] }) }, o.value);
|
|
189
|
-
})
|
|
190
|
-
] })
|
|
191
|
-
]
|
|
192
|
-
}
|
|
193
|
-
),
|
|
194
|
-
showNameField && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
195
|
-
/* @__PURE__ */ jsx(
|
|
196
|
-
Input,
|
|
197
|
-
{
|
|
198
|
-
value: name,
|
|
199
|
-
onChange: (e) => onNameChange(e.target.value),
|
|
200
|
-
placeholder: namePlaceholder,
|
|
201
|
-
className: "h-9 min-w-0 flex-1 bg-background",
|
|
202
|
-
"data-testid": testIdOr(nameTestId, { testId: "config-name-input" })
|
|
203
|
-
}
|
|
204
|
-
),
|
|
205
|
-
/* @__PURE__ */ jsx(
|
|
206
|
-
Button,
|
|
207
|
-
{
|
|
208
|
-
variant: "outline",
|
|
209
|
-
size: "sm",
|
|
210
|
-
className: "h-9",
|
|
211
|
-
onClick: onSave,
|
|
212
|
-
disabled: isSaving || !name.trim(),
|
|
213
|
-
"data-testid": testIdOr(saveTestId, { testId: "save-config-button" }),
|
|
214
|
-
children: isSaving ? l.saving : saveLabel
|
|
215
|
-
}
|
|
216
|
-
)
|
|
217
|
-
] }),
|
|
218
|
-
canDelete && /* @__PURE__ */ jsxs(
|
|
219
|
-
Button,
|
|
220
|
-
{
|
|
221
|
-
variant: "outline",
|
|
222
|
-
size: "sm",
|
|
223
|
-
className: "h-9 border-destructive text-destructive hover:bg-destructive hover:text-destructive-foreground",
|
|
224
|
-
onClick: onDelete,
|
|
225
|
-
disabled: isDeleting,
|
|
226
|
-
"data-testid": testIdOr(deleteTestId, { testId: "delete-config-button" }),
|
|
227
|
-
children: [
|
|
228
|
-
/* @__PURE__ */ jsx(Trash2, { className: "mr-2 size-4" }),
|
|
229
|
-
l.delete
|
|
230
|
-
]
|
|
231
|
-
}
|
|
232
|
-
)
|
|
233
|
-
] }) })
|
|
234
|
-
}
|
|
235
|
-
);
|
|
236
|
-
}
|
|
237
|
-
var CONVERSATION_TITLE_MAX = 50;
|
|
238
|
-
var DEFAULT_CONVERSATION_TITLE_SECTION_LABELS = {
|
|
239
|
-
title: "Conversation Title",
|
|
240
|
-
placeholder: "New Conversation",
|
|
241
|
-
share: "Share",
|
|
242
|
-
shared: "Shared",
|
|
243
|
-
ownerOnlyShare: "Only available to conversation owner",
|
|
244
|
-
makePrivate: "Make private again",
|
|
245
|
-
characters: (count, max) => `${count}/${max} characters`,
|
|
246
|
-
saving: "Saving...",
|
|
247
|
-
ownerOnlyEdit: "Only the conversation owner can edit the title"
|
|
248
|
-
};
|
|
249
|
-
var SECTION_CLASS = "rounded-md border bg-muted/50 p-4";
|
|
250
|
-
function ConversationTitleSection({
|
|
251
|
-
title,
|
|
252
|
-
onTitleChange,
|
|
253
|
-
onTitleCommit,
|
|
254
|
-
isOwner,
|
|
255
|
-
isShared,
|
|
256
|
-
isSharing,
|
|
257
|
-
isSavingTitle,
|
|
258
|
-
onShare,
|
|
259
|
-
onUnshare,
|
|
260
|
-
inputTestId,
|
|
261
|
-
shareTestId,
|
|
262
|
-
labels
|
|
263
|
-
}) {
|
|
264
|
-
const l = useMemo(() => ({ ...DEFAULT_CONVERSATION_TITLE_SECTION_LABELS, ...labels }), [labels]);
|
|
265
|
-
const trimmed = title.trim();
|
|
266
|
-
return /* @__PURE__ */ jsxs(ModalSection, { className: SECTION_CLASS, children: [
|
|
267
|
-
/* @__PURE__ */ jsx(ModalSectionTitle, { children: l.title }),
|
|
268
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
269
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
270
|
-
/* @__PURE__ */ jsx(
|
|
271
|
-
Input,
|
|
272
|
-
{
|
|
273
|
-
value: title,
|
|
274
|
-
onChange: (e) => {
|
|
275
|
-
if (isOwner && e.target.value.length <= CONVERSATION_TITLE_MAX) {
|
|
276
|
-
onTitleChange(e.target.value);
|
|
277
|
-
}
|
|
278
|
-
},
|
|
279
|
-
onBlur: () => {
|
|
280
|
-
if (isOwner && trimmed && trimmed.length <= CONVERSATION_TITLE_MAX) onTitleCommit();
|
|
281
|
-
},
|
|
282
|
-
placeholder: l.placeholder,
|
|
283
|
-
maxLength: 60,
|
|
284
|
-
disabled: !isOwner,
|
|
285
|
-
"data-testid": testIdOr(inputTestId, { testId: "conversation-title-input" })
|
|
286
|
-
}
|
|
287
|
-
),
|
|
288
|
-
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
289
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("span", { tabIndex: !isOwner ? 0 : void 0, children: /* @__PURE__ */ jsxs(
|
|
290
|
-
Button,
|
|
291
|
-
{
|
|
292
|
-
variant: isShared ? "secondary" : "outline",
|
|
293
|
-
size: "sm",
|
|
294
|
-
className: "h-9 px-3 pointer-coarse:h-11",
|
|
295
|
-
onClick: () => {
|
|
296
|
-
if (!isOwner) return;
|
|
297
|
-
if (isShared) onUnshare?.();
|
|
298
|
-
else onShare();
|
|
299
|
-
},
|
|
300
|
-
disabled: !isOwner || isShared && !onUnshare || isSharing,
|
|
301
|
-
title: isOwner && isShared && onUnshare ? l.makePrivate : void 0,
|
|
302
|
-
"data-testid": testIdOr(shareTestId, { testId: "share-conversation-button" }),
|
|
303
|
-
children: [
|
|
304
|
-
/* @__PURE__ */ jsx(Users, { className: "mr-1 size-3" }),
|
|
305
|
-
isShared ? l.shared : l.share
|
|
306
|
-
]
|
|
307
|
-
}
|
|
308
|
-
) }) }),
|
|
309
|
-
!isOwner && /* @__PURE__ */ jsx(TooltipContent, { children: /* @__PURE__ */ jsx("p", { children: l.ownerOnlyShare }) })
|
|
310
|
-
] })
|
|
311
|
-
] }),
|
|
312
|
-
isOwner ? /* @__PURE__ */ jsxs(
|
|
313
|
-
"p",
|
|
314
|
-
{
|
|
315
|
-
className: cn(
|
|
316
|
-
"text-sm",
|
|
317
|
-
title.length > CONVERSATION_TITLE_MAX ? "text-destructive" : "text-muted-foreground"
|
|
318
|
-
),
|
|
319
|
-
children: [
|
|
320
|
-
l.characters(title.length, CONVERSATION_TITLE_MAX),
|
|
321
|
-
isSavingTitle && /* @__PURE__ */ jsx("span", { className: "ml-2 text-primary", children: l.saving })
|
|
322
|
-
]
|
|
323
|
-
}
|
|
324
|
-
) : /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: l.ownerOnlyEdit })
|
|
325
|
-
] })
|
|
326
|
-
] });
|
|
327
|
-
}
|
|
328
|
-
var DEFAULT_MODEL_SELECTION_SECTION_LABELS = {
|
|
329
|
-
title: "AI Model Selection",
|
|
330
|
-
description: "Select the AI model to use for this conversation",
|
|
331
|
-
useDefaults: "Use defaults",
|
|
332
|
-
auto: "Auto",
|
|
333
|
-
default: "Default",
|
|
334
|
-
lastUsed: "Last used",
|
|
335
|
-
deepThinking: "Deep Thinking"
|
|
336
|
-
};
|
|
337
|
-
function ModelSelectionSection({
|
|
338
|
-
selector,
|
|
339
|
-
onUseDefaults,
|
|
340
|
-
defaultsTestId,
|
|
341
|
-
labels
|
|
342
|
-
}) {
|
|
343
|
-
const l = useMemo(() => ({ ...DEFAULT_MODEL_SELECTION_SECTION_LABELS, ...labels }), [labels]);
|
|
344
|
-
const legend = [
|
|
345
|
-
{ icon: Sparkles, label: l.auto },
|
|
346
|
-
{ icon: Star, label: l.default },
|
|
347
|
-
{ icon: History, label: l.lastUsed },
|
|
348
|
-
{ icon: Brain, label: l.deepThinking }
|
|
349
|
-
];
|
|
350
|
-
return /* @__PURE__ */ jsxs(ModalSection, { className: SECTION_CLASS, children: [
|
|
351
|
-
/* @__PURE__ */ jsx(ModalSectionTitle, { children: l.title }),
|
|
352
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
353
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: l.description }),
|
|
354
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
355
|
-
selector,
|
|
356
|
-
/* @__PURE__ */ jsxs(
|
|
357
|
-
Button,
|
|
358
|
-
{
|
|
359
|
-
variant: "outline",
|
|
360
|
-
size: "sm",
|
|
361
|
-
className: "flex h-8 items-center gap-1.5 px-3 pointer-coarse:h-11",
|
|
362
|
-
onClick: onUseDefaults,
|
|
363
|
-
"data-testid": testIdOr(defaultsTestId, { testId: "use-defaults-button" }),
|
|
364
|
-
children: [
|
|
365
|
-
/* @__PURE__ */ jsx(Star, { className: "size-4" }),
|
|
366
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm", children: l.useDefaults })
|
|
367
|
-
]
|
|
368
|
-
}
|
|
369
|
-
)
|
|
370
|
-
] }),
|
|
371
|
-
/* @__PURE__ */ jsx("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-1 text-sm text-muted-foreground", children: legend.map(({ icon: Icon, label }) => /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-1", children: [
|
|
372
|
-
/* @__PURE__ */ jsx(Icon, { className: "size-3" }),
|
|
373
|
-
/* @__PURE__ */ jsx("span", { children: label })
|
|
374
|
-
] }, label)) })
|
|
375
|
-
] })
|
|
376
|
-
] });
|
|
377
|
-
}
|
|
378
|
-
function ThreadPreviewDialog({
|
|
379
|
-
open,
|
|
380
|
-
onOpenChange,
|
|
381
|
-
crumbs,
|
|
382
|
-
description = "Thread visualization",
|
|
383
|
-
width,
|
|
384
|
-
testId,
|
|
385
|
-
children
|
|
386
|
-
}) {
|
|
387
|
-
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
|
|
388
|
-
DialogContent,
|
|
389
|
-
{
|
|
390
|
-
presentation: "sheet",
|
|
391
|
-
className: "flex flex-col overflow-hidden p-0",
|
|
392
|
-
style: { width: `${width}px`, maxWidth: "95vw", height: "80vh", maxHeight: "90vh" },
|
|
393
|
-
"data-testid": testId,
|
|
394
|
-
children: [
|
|
395
|
-
/* @__PURE__ */ jsxs(ModalHeader, { children: [
|
|
396
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children: crumbs.map((c, i) => /* @__PURE__ */ jsxs("span", { className: "flex items-center gap-3", children: [
|
|
397
|
-
i > 0 && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: "/" }),
|
|
398
|
-
c.icon,
|
|
399
|
-
/* @__PURE__ */ jsx("span", { children: c.label })
|
|
400
|
-
] }, i)) }) }),
|
|
401
|
-
/* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: description })
|
|
402
|
-
] }),
|
|
403
|
-
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto px-6 pb-6", children })
|
|
404
|
-
]
|
|
405
|
-
}
|
|
406
|
-
) });
|
|
407
|
-
}
|
|
408
|
-
var ITEMS = { one: "item", other: "items" };
|
|
409
|
-
function isInlineObject(data) {
|
|
410
|
-
if (data === null || data === void 0) return true;
|
|
411
|
-
if (typeof data !== "object") return true;
|
|
412
|
-
if (Array.isArray(data)) return data.length === 0;
|
|
413
|
-
const keys = Object.keys(data);
|
|
414
|
-
if (keys.length === 0) return true;
|
|
415
|
-
if (keys.length > 4) return false;
|
|
416
|
-
return Object.values(data).every(
|
|
417
|
-
(v) => v === null || v === void 0 || typeof v !== "object"
|
|
418
|
-
);
|
|
419
|
-
}
|
|
420
|
-
function inlineSummary(data) {
|
|
421
|
-
const parts = Object.entries(data).map(([k, v]) => {
|
|
422
|
-
if (v === null) return `${k}: null`;
|
|
423
|
-
if (typeof v === "string") return `${k}: "${v.length > 40 ? v.slice(0, 40) + "\u2026" : v}"`;
|
|
424
|
-
return `${k}: ${String(v)}`;
|
|
425
|
-
});
|
|
426
|
-
return `{ ${parts.join(", ")} }`;
|
|
427
|
-
}
|
|
428
|
-
function arrayPreview(data) {
|
|
429
|
-
if (data.length === 0) return "[]";
|
|
430
|
-
const first = data[0];
|
|
431
|
-
if (typeof first !== "object" || first === null) return `[${formatCount(data.length, ITEMS)}]`;
|
|
432
|
-
const obj = first;
|
|
433
|
-
const previewKeys = ["action", "step", "phase", "tool", "name", "type", "id"];
|
|
434
|
-
const parts = previewKeys.filter((k) => obj[k] !== void 0).slice(0, 3).map((k) => `${k}: ${JSON.stringify(obj[k])}`);
|
|
435
|
-
if (parts.length === 0) return `[${formatCount(data.length, ITEMS)}]`;
|
|
436
|
-
return `[${formatCount(data.length, ITEMS)} \u2014 { ${parts.join(", ")} }, \u2026]`;
|
|
437
|
-
}
|
|
438
|
-
var NAME_CLASS = "font-medium text-primary";
|
|
439
|
-
var COPY_CLASS = "rounded p-0.5 opacity-50 transition-opacity hover:bg-muted hover:opacity-100 focus-visible:opacity-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:flex pointer-coarse:size-11 pointer-coarse:items-center pointer-coarse:justify-center pointer-coarse:opacity-100";
|
|
440
|
-
function valueColor(data) {
|
|
441
|
-
if (data === null || data === void 0) return "text-muted-foreground";
|
|
442
|
-
switch (typeof data) {
|
|
443
|
-
case "string":
|
|
444
|
-
return "text-primary";
|
|
445
|
-
case "number":
|
|
446
|
-
return "text-primary";
|
|
447
|
-
case "boolean":
|
|
448
|
-
return "text-purple-700 dark:text-purple-400";
|
|
449
|
-
default:
|
|
450
|
-
return "text-foreground";
|
|
451
|
-
}
|
|
452
|
-
}
|
|
453
|
-
function plainValue(data) {
|
|
454
|
-
if (data === null) return "null";
|
|
455
|
-
if (data === void 0) return "undefined";
|
|
456
|
-
return typeof data === "string" ? `"${data}"` : String(data);
|
|
457
|
-
}
|
|
458
|
-
function JsonTree({
|
|
459
|
-
data,
|
|
460
|
-
name,
|
|
461
|
-
defaultExpanded = false,
|
|
462
|
-
level = 0,
|
|
463
|
-
path = [],
|
|
464
|
-
resolveHint,
|
|
465
|
-
formatValue: formatValue2
|
|
466
|
-
}) {
|
|
467
|
-
const [isExpanded, setIsExpanded] = useState(defaultExpanded || level < 2);
|
|
468
|
-
const [copied, setCopied] = useState(false);
|
|
469
|
-
const currentPath = name ? [...path, name] : path;
|
|
470
|
-
const hint = name && resolveHint ? resolveHint(currentPath, name) : null;
|
|
471
|
-
const displayName = hint?.displayName || name;
|
|
472
|
-
const handleCopy = (value) => {
|
|
473
|
-
const text = typeof value === "string" ? value : JSON.stringify(value, null, 2);
|
|
474
|
-
void navigator.clipboard.writeText(text).then(() => {
|
|
475
|
-
setCopied(true);
|
|
476
|
-
setTimeout(() => setCopied(false), 2e3);
|
|
477
|
-
});
|
|
478
|
-
};
|
|
479
|
-
const copyButton = (title, value) => /* @__PURE__ */ jsx(
|
|
480
|
-
"button",
|
|
481
|
-
{
|
|
482
|
-
type: "button",
|
|
483
|
-
onClick: () => handleCopy(value),
|
|
484
|
-
className: COPY_CLASS,
|
|
485
|
-
title,
|
|
486
|
-
"aria-label": title,
|
|
487
|
-
children: copied ? /* @__PURE__ */ jsx(Check, { size: 12, className: "text-green-text" }) : /* @__PURE__ */ jsx(Copy, { size: 12 })
|
|
488
|
-
}
|
|
489
|
-
);
|
|
490
|
-
const isArray = Array.isArray(data);
|
|
491
|
-
const isObject = typeof data === "object" && data !== null && !isArray;
|
|
492
|
-
if (!isObject && !isArray) {
|
|
493
|
-
const displayValue = hint && formatValue2 ? formatValue2(data, hint) : plainValue(data);
|
|
494
|
-
return /* @__PURE__ */ jsxs(
|
|
495
|
-
"div",
|
|
496
|
-
{
|
|
497
|
-
"data-slot": "json-tree-leaf",
|
|
498
|
-
className: "group flex items-center gap-2 py-0.5 font-mono text-sm",
|
|
499
|
-
children: [
|
|
500
|
-
displayName && /* @__PURE__ */ jsxs("span", { className: NAME_CLASS, title: hint?.description, children: [
|
|
501
|
-
displayName,
|
|
502
|
-
":"
|
|
503
|
-
] }),
|
|
504
|
-
/* @__PURE__ */ jsx("span", { className: valueColor(data), children: displayValue }),
|
|
505
|
-
hint?.formatType === "id" && typeof data === "string" && data.length > 20 && /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground", title: data, children: [
|
|
506
|
-
"(full: ",
|
|
507
|
-
data,
|
|
508
|
-
")"
|
|
509
|
-
] }),
|
|
510
|
-
copyButton("Copy value", data)
|
|
511
|
-
]
|
|
512
|
-
}
|
|
513
|
-
);
|
|
514
|
-
}
|
|
515
|
-
if (isObject && isInlineObject(data)) {
|
|
516
|
-
return /* @__PURE__ */ jsxs(
|
|
517
|
-
"div",
|
|
518
|
-
{
|
|
519
|
-
"data-slot": "json-tree-leaf",
|
|
520
|
-
className: "group flex items-center gap-2 py-0.5 font-mono text-sm",
|
|
521
|
-
children: [
|
|
522
|
-
displayName && /* @__PURE__ */ jsxs("span", { className: NAME_CLASS, children: [
|
|
523
|
-
displayName,
|
|
524
|
-
":"
|
|
525
|
-
] }),
|
|
526
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: inlineSummary(data) }),
|
|
527
|
-
copyButton("Copy object", data)
|
|
528
|
-
]
|
|
529
|
-
}
|
|
530
|
-
);
|
|
531
|
-
}
|
|
532
|
-
const Icon = isExpanded ? ChevronDown : ChevronRight;
|
|
533
|
-
const entries = isArray ? data.map((item, index) => [String(index), item]) : Object.entries(data);
|
|
534
|
-
const collapsedPreview = isArray ? arrayPreview(data) : `{${Object.keys(data).length} fields}`;
|
|
535
|
-
return /* @__PURE__ */ jsxs("div", { "data-slot": "json-tree", className: "font-mono text-sm", children: [
|
|
536
|
-
/* @__PURE__ */ jsxs("div", { className: "group flex items-center gap-1 py-0.5", children: [
|
|
537
|
-
/* @__PURE__ */ jsxs(
|
|
538
|
-
"button",
|
|
539
|
-
{
|
|
540
|
-
type: "button",
|
|
541
|
-
onClick: () => setIsExpanded(!isExpanded),
|
|
542
|
-
"aria-expanded": isExpanded,
|
|
543
|
-
className: "flex items-center gap-1 rounded p-0.5 transition-colors hover:bg-muted focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11",
|
|
544
|
-
title: hint?.description,
|
|
545
|
-
children: [
|
|
546
|
-
/* @__PURE__ */ jsx(Icon, { size: 14, className: "shrink-0" }),
|
|
547
|
-
displayName && /* @__PURE__ */ jsxs("span", { className: NAME_CLASS, children: [
|
|
548
|
-
displayName,
|
|
549
|
-
":"
|
|
550
|
-
] }),
|
|
551
|
-
!isExpanded && /* @__PURE__ */ jsx("span", { className: "max-w-[400px] truncate text-sm text-muted-foreground", children: collapsedPreview }),
|
|
552
|
-
isExpanded && isArray && /* @__PURE__ */ jsxs("span", { className: "text-sm text-muted-foreground", children: [
|
|
553
|
-
data.length,
|
|
554
|
-
" items"
|
|
555
|
-
] })
|
|
556
|
-
]
|
|
557
|
-
}
|
|
558
|
-
),
|
|
559
|
-
copyButton("Copy object", data)
|
|
560
|
-
] }),
|
|
561
|
-
isExpanded && /* @__PURE__ */ jsx("div", { className: "ml-4 border-l border-border/40 pl-2", children: entries.length === 0 ? /* @__PURE__ */ jsx("div", { className: "py-0.5 text-sm text-muted-foreground", children: isArray ? "empty array" : "empty object" }) : entries.map(([key, value]) => {
|
|
562
|
-
if (isArray && typeof value === "object" && value !== null && isInlineObject(value)) {
|
|
563
|
-
return /* @__PURE__ */ jsx("div", { className: "py-0.5 font-mono text-sm text-muted-foreground", children: inlineSummary(value) }, key);
|
|
564
|
-
}
|
|
565
|
-
return /* @__PURE__ */ jsx(
|
|
566
|
-
JsonTree,
|
|
567
|
-
{
|
|
568
|
-
name: isArray ? void 0 : key,
|
|
569
|
-
data: value,
|
|
570
|
-
level: level + 1,
|
|
571
|
-
path: currentPath,
|
|
572
|
-
resolveHint,
|
|
573
|
-
formatValue: formatValue2
|
|
574
|
-
},
|
|
575
|
-
key
|
|
576
|
-
);
|
|
577
|
-
}) })
|
|
578
|
-
] });
|
|
579
|
-
}
|
|
580
|
-
|
|
581
|
-
// src/settings/message-schema-hints.ts
|
|
582
|
-
var messageFieldHints = {
|
|
583
|
-
role: {
|
|
584
|
-
displayName: "Role",
|
|
585
|
-
formatType: "enum",
|
|
586
|
-
description: "Message role (user, assistant, or system)"
|
|
587
|
-
},
|
|
588
|
-
content: {
|
|
589
|
-
displayName: "Content",
|
|
590
|
-
formatType: "long-string",
|
|
591
|
-
description: "Message content text"
|
|
592
|
-
},
|
|
593
|
-
created_at: {
|
|
594
|
-
displayName: "Created At",
|
|
595
|
-
formatType: "timestamp",
|
|
596
|
-
description: "Message creation timestamp"
|
|
597
|
-
},
|
|
598
|
-
external_id: {
|
|
599
|
-
displayName: "Message ID",
|
|
600
|
-
formatType: "id",
|
|
601
|
-
description: "External message identifier"
|
|
602
|
-
},
|
|
603
|
-
conversation_ext_id: {
|
|
604
|
-
displayName: "Conversation ID",
|
|
605
|
-
formatType: "id",
|
|
606
|
-
description: "Parent conversation identifier"
|
|
607
|
-
},
|
|
608
|
-
parent_message_ext_id: {
|
|
609
|
-
displayName: "Parent Message ID",
|
|
610
|
-
formatType: "id",
|
|
611
|
-
description: "Parent message identifier (null for first message)"
|
|
612
|
-
},
|
|
613
|
-
created_by_ext_id: {
|
|
614
|
-
displayName: "Created By",
|
|
615
|
-
formatType: "id",
|
|
616
|
-
description: "User who created this message"
|
|
617
|
-
},
|
|
618
|
-
config_ext_id: {
|
|
619
|
-
displayName: "Config ID",
|
|
620
|
-
formatType: "id",
|
|
621
|
-
description: "Configuration used for this message"
|
|
622
|
-
},
|
|
623
|
-
shared: {
|
|
624
|
-
displayName: "Shared",
|
|
625
|
-
formatType: "boolean",
|
|
626
|
-
description: "Whether message is shared"
|
|
627
|
-
},
|
|
628
|
-
tools: {
|
|
629
|
-
displayName: "Tools",
|
|
630
|
-
formatType: "json",
|
|
631
|
-
description: "Tool outputs (citations, retrieval, trace)"
|
|
632
|
-
},
|
|
633
|
-
meta: {
|
|
634
|
-
displayName: "Metadata",
|
|
635
|
-
formatType: "json",
|
|
636
|
-
description: "Additional metadata"
|
|
637
|
-
}
|
|
638
|
-
};
|
|
639
|
-
var traceToolFieldHints = {
|
|
640
|
-
name: {
|
|
641
|
-
displayName: "Tool Name",
|
|
642
|
-
formatType: "enum",
|
|
643
|
-
description: "Execution trace tool"
|
|
644
|
-
},
|
|
645
|
-
description: {
|
|
646
|
-
displayName: "Description",
|
|
647
|
-
formatType: "string",
|
|
648
|
-
description: "Tool description"
|
|
649
|
-
},
|
|
650
|
-
trace_id: {
|
|
651
|
-
displayName: "Trace ID",
|
|
652
|
-
formatType: "id",
|
|
653
|
-
description: "Unique trace identifier"
|
|
654
|
-
},
|
|
655
|
-
start_time: {
|
|
656
|
-
displayName: "Start Time",
|
|
657
|
-
formatType: "timestamp",
|
|
658
|
-
description: "When execution started"
|
|
659
|
-
},
|
|
660
|
-
duration_seconds: {
|
|
661
|
-
displayName: "Duration (seconds)",
|
|
662
|
-
formatType: "number",
|
|
663
|
-
description: "Total execution time"
|
|
664
|
-
},
|
|
665
|
-
steps: {
|
|
666
|
-
displayName: "Execution Steps",
|
|
667
|
-
formatType: "json",
|
|
668
|
-
description: "Full execution trace with all steps"
|
|
669
|
-
}
|
|
670
|
-
};
|
|
671
|
-
var citationToolFieldHints = {
|
|
672
|
-
name: {
|
|
673
|
-
displayName: "Tool Name",
|
|
674
|
-
formatType: "enum",
|
|
675
|
-
description: "Model citation tool"
|
|
676
|
-
},
|
|
677
|
-
tool_responses: {
|
|
678
|
-
displayName: "Citations",
|
|
679
|
-
formatType: "json",
|
|
680
|
-
description: "Citation data mapped by citation number"
|
|
681
|
-
}
|
|
682
|
-
};
|
|
683
|
-
function getFieldHint(path, fieldName) {
|
|
684
|
-
if (path.length === 1 && path[0] === "message") {
|
|
685
|
-
return messageFieldHints[fieldName] || null;
|
|
686
|
-
}
|
|
687
|
-
if (path.length >= 3 && path[0] === "message" && path[1] === "tools" && path[2] === "trace") {
|
|
688
|
-
return traceToolFieldHints[fieldName] || null;
|
|
689
|
-
}
|
|
690
|
-
if (path.length >= 3 && path[0] === "message" && path[1] === "tools" && path[2] === "model_citations") {
|
|
691
|
-
return citationToolFieldHints[fieldName] || null;
|
|
692
|
-
}
|
|
693
|
-
if (fieldName === "external_id" || fieldName.endsWith("_ext_id")) {
|
|
694
|
-
return { formatType: "id", displayName: fieldName.replace(/_/g, " ") };
|
|
695
|
-
}
|
|
696
|
-
if (fieldName === "created_at" || fieldName === "updated_at" || fieldName.endsWith("_at")) {
|
|
697
|
-
return { formatType: "timestamp", displayName: fieldName.replace(/_/g, " ") };
|
|
698
|
-
}
|
|
699
|
-
if (fieldName.includes("time") && !fieldName.includes("duration")) {
|
|
700
|
-
return { formatType: "timestamp" };
|
|
701
|
-
}
|
|
702
|
-
if (fieldName.includes("duration")) {
|
|
703
|
-
return { formatType: "number", description: "Duration in seconds" };
|
|
704
|
-
}
|
|
705
|
-
if (path.length >= 2 && path[path.length - 2] === "tools" && fieldName === "trace") {
|
|
706
|
-
return {
|
|
707
|
-
displayName: "\u{1F50D} Execution Trace",
|
|
708
|
-
formatType: "json",
|
|
709
|
-
description: "Complete execution trace with all steps and timing"
|
|
710
|
-
};
|
|
711
|
-
}
|
|
712
|
-
return null;
|
|
713
|
-
}
|
|
714
|
-
function formatValue(value, hint) {
|
|
715
|
-
if (value === null) return "null";
|
|
716
|
-
if (value === void 0) return "undefined";
|
|
717
|
-
if (hint?.formatType === "timestamp" && typeof value === "string") {
|
|
718
|
-
try {
|
|
719
|
-
const date = new Date(value);
|
|
720
|
-
if (!isNaN(date.getTime())) {
|
|
721
|
-
return `${date.toLocaleString()} (${value})`;
|
|
722
|
-
}
|
|
723
|
-
} catch {
|
|
724
|
-
}
|
|
725
|
-
}
|
|
726
|
-
if (hint?.formatType === "timestamp" && typeof value === "number") {
|
|
727
|
-
const date = new Date(value * 1e3);
|
|
728
|
-
return `${date.toLocaleString()} (${value})`;
|
|
729
|
-
}
|
|
730
|
-
if (hint?.formatType === "id" && typeof value === "string") {
|
|
731
|
-
if (value.length > 20) {
|
|
732
|
-
return `${value.substring(0, 16)}...${value.substring(value.length - 4)}`;
|
|
733
|
-
}
|
|
734
|
-
}
|
|
735
|
-
if (typeof value === "string") {
|
|
736
|
-
if (value.length > 100) {
|
|
737
|
-
return `"${value.substring(0, 97)}..." (${value.length} chars)`;
|
|
738
|
-
}
|
|
739
|
-
return `"${value}"`;
|
|
740
|
-
}
|
|
741
|
-
return String(value);
|
|
742
|
-
}
|
|
743
|
-
function MessageJsonTree(props) {
|
|
744
|
-
return /* @__PURE__ */ jsx(JsonTree, { ...props, resolveHint: getFieldHint, formatValue });
|
|
745
|
-
}
|
|
746
|
-
var DEFAULT_TIPS_EDITOR_LABELS = {
|
|
747
|
-
titleList: "Edit tips",
|
|
748
|
-
titleNew: "New tip",
|
|
749
|
-
titleEdit: "Edit tip",
|
|
750
|
-
descriptionList: "All tips across every page. Change a tip's placement to move it to a page, show it everywhere, or hide it. Changes save instantly.",
|
|
751
|
-
descriptionNew: "Create a tip and choose where it shows.",
|
|
752
|
-
descriptionEdit: "Editing the tip below \u2014 change its copy, button, or placement.",
|
|
753
|
-
hiddenOff: "Hidden (off)",
|
|
754
|
-
customSuffix: " \xB7 custom",
|
|
755
|
-
editTip: "Edit tip",
|
|
756
|
-
deleteTip: "Delete tip",
|
|
757
|
-
addTip: "Add tip",
|
|
758
|
-
testerTitle: "Run a sequence (test)",
|
|
759
|
-
run: "Run",
|
|
760
|
-
cancel: "Cancel",
|
|
761
|
-
newTipIdentity: "New tip",
|
|
762
|
-
customTipIdentity: "Custom tip",
|
|
763
|
-
builtInTipIdentity: (code) => `Built-in tip \xB7 ${code}`,
|
|
764
|
-
yourNewTip: "Your new tip",
|
|
765
|
-
placement: "Placement",
|
|
766
|
-
message: "Message",
|
|
767
|
-
button: "Button",
|
|
768
|
-
noButton: "No button",
|
|
769
|
-
platformAction: "Platform action",
|
|
770
|
-
actionSequence: "Action sequence",
|
|
771
|
-
externalLink: "External link (new window)",
|
|
772
|
-
buttonLabel: "Button label",
|
|
773
|
-
action: "Action",
|
|
774
|
-
sequence: "Sequence",
|
|
775
|
-
url: "URL",
|
|
776
|
-
back: "Back",
|
|
777
|
-
save: "Save",
|
|
778
|
-
saving: "Saving\u2026"
|
|
779
|
-
};
|
|
780
|
-
function SelectField({
|
|
781
|
-
label,
|
|
782
|
-
value,
|
|
783
|
-
onValueChange,
|
|
784
|
-
options
|
|
785
|
-
}) {
|
|
786
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
787
|
-
/* @__PURE__ */ jsx(Label, { children: label }),
|
|
788
|
-
/* @__PURE__ */ jsxs(Select, { value, onValueChange, children: [
|
|
789
|
-
/* @__PURE__ */ jsx(SelectTrigger, { children: /* @__PURE__ */ jsx(SelectValue, {}) }),
|
|
790
|
-
/* @__PURE__ */ jsx(SelectContent, { children: options.map((o) => /* @__PURE__ */ jsx(SelectItem, { value: o.value, children: o.label }, o.value)) })
|
|
791
|
-
] })
|
|
792
|
-
] });
|
|
793
|
-
}
|
|
794
|
-
var ROW_BUTTON = "size-7 flex-shrink-0 pointer-coarse:size-11";
|
|
795
|
-
function TipsEditorDialog({
|
|
796
|
-
open,
|
|
797
|
-
onOpenChange,
|
|
798
|
-
form,
|
|
799
|
-
onFormChange,
|
|
800
|
-
onFormBack,
|
|
801
|
-
onFormSave,
|
|
802
|
-
rows,
|
|
803
|
-
onEditRow,
|
|
804
|
-
onDeleteRow,
|
|
805
|
-
onAdd,
|
|
806
|
-
busy,
|
|
807
|
-
error,
|
|
808
|
-
placementOptions,
|
|
809
|
-
actionOptions,
|
|
810
|
-
sequenceOptions,
|
|
811
|
-
activeSequenceId,
|
|
812
|
-
onRunSequence,
|
|
813
|
-
onCancelSequence,
|
|
814
|
-
messageMaxChars,
|
|
815
|
-
ctaLabelMaxChars,
|
|
816
|
-
labels
|
|
817
|
-
}) {
|
|
818
|
-
const tipCtaHrefId = useId();
|
|
819
|
-
const tipCtaLabelId = useId();
|
|
820
|
-
const tipMessageId = useId();
|
|
821
|
-
const l = useMemo(() => ({ ...DEFAULT_TIPS_EDITOR_LABELS, ...labels }), [labels]);
|
|
822
|
-
const isNew = form?.code === null;
|
|
823
|
-
const title = form ? isNew ? l.titleNew : l.titleEdit : l.titleList;
|
|
824
|
-
const description = form ? isNew ? l.descriptionNew : l.descriptionEdit : l.descriptionList;
|
|
825
|
-
const targetOptions = [
|
|
826
|
-
{ value: "none", label: l.noButton },
|
|
827
|
-
{ value: "action", label: l.platformAction },
|
|
828
|
-
{ value: "sequence", label: l.actionSequence },
|
|
829
|
-
{ value: "url", label: l.externalLink }
|
|
830
|
-
];
|
|
831
|
-
return /* @__PURE__ */ jsxs(
|
|
832
|
-
ModalScaffold,
|
|
833
|
-
{
|
|
834
|
-
open,
|
|
835
|
-
onOpenChange,
|
|
836
|
-
title,
|
|
837
|
-
description,
|
|
838
|
-
showDescription: true,
|
|
839
|
-
className: "max-w-lg",
|
|
840
|
-
children: [
|
|
841
|
-
error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error }),
|
|
842
|
-
form ? /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
|
|
843
|
-
/* @__PURE__ */ jsxs("div", { className: "rounded-md border border-l-4 border-l-red-500 bg-muted/40 px-3 py-2", children: [
|
|
844
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: isNew ? l.newTipIdentity : form.isCustom ? l.customTipIdentity : l.builtInTipIdentity(form.code ?? "") }),
|
|
845
|
-
/* @__PURE__ */ jsx("p", { className: "mt-0.5 truncate text-sm font-medium text-foreground", children: form.original || l.yourNewTip })
|
|
846
|
-
] }),
|
|
847
|
-
/* @__PURE__ */ jsx(
|
|
848
|
-
SelectField,
|
|
849
|
-
{
|
|
850
|
-
label: l.placement,
|
|
851
|
-
value: form.placement,
|
|
852
|
-
onValueChange: (placement) => onFormChange({ placement }),
|
|
853
|
-
options: placementOptions
|
|
854
|
-
}
|
|
855
|
-
),
|
|
856
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
857
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
858
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: tipMessageId, children: l.message }),
|
|
859
|
-
/* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
860
|
-
form.message.length,
|
|
861
|
-
"/",
|
|
862
|
-
messageMaxChars
|
|
863
|
-
] })
|
|
864
|
-
] }),
|
|
865
|
-
/* @__PURE__ */ jsx(
|
|
866
|
-
Textarea,
|
|
867
|
-
{
|
|
868
|
-
id: tipMessageId,
|
|
869
|
-
value: form.message,
|
|
870
|
-
onChange: (e) => onFormChange({ message: e.target.value.slice(0, messageMaxChars) }),
|
|
871
|
-
maxLength: messageMaxChars,
|
|
872
|
-
rows: 2
|
|
873
|
-
}
|
|
874
|
-
)
|
|
875
|
-
] }),
|
|
876
|
-
/* @__PURE__ */ jsx(
|
|
877
|
-
SelectField,
|
|
878
|
-
{
|
|
879
|
-
label: l.button,
|
|
880
|
-
value: form.target,
|
|
881
|
-
onValueChange: (v) => onFormChange({ target: v }),
|
|
882
|
-
options: targetOptions
|
|
883
|
-
}
|
|
884
|
-
),
|
|
885
|
-
form.target !== "none" && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
886
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: tipCtaLabelId, children: l.buttonLabel }),
|
|
887
|
-
/* @__PURE__ */ jsx(
|
|
888
|
-
Input,
|
|
889
|
-
{
|
|
890
|
-
id: tipCtaLabelId,
|
|
891
|
-
value: form.ctaLabel,
|
|
892
|
-
onChange: (e) => onFormChange({ ctaLabel: e.target.value.slice(0, ctaLabelMaxChars) }),
|
|
893
|
-
maxLength: ctaLabelMaxChars
|
|
894
|
-
}
|
|
895
|
-
)
|
|
896
|
-
] }),
|
|
897
|
-
form.target === "action" && /* @__PURE__ */ jsx(
|
|
898
|
-
SelectField,
|
|
899
|
-
{
|
|
900
|
-
label: l.action,
|
|
901
|
-
value: form.ctaAction,
|
|
902
|
-
onValueChange: (ctaAction) => onFormChange({ ctaAction }),
|
|
903
|
-
options: actionOptions
|
|
904
|
-
}
|
|
905
|
-
),
|
|
906
|
-
form.target === "sequence" && /* @__PURE__ */ jsx(
|
|
907
|
-
SelectField,
|
|
908
|
-
{
|
|
909
|
-
label: l.sequence,
|
|
910
|
-
value: form.ctaSequence,
|
|
911
|
-
onValueChange: (ctaSequence) => onFormChange({ ctaSequence }),
|
|
912
|
-
options: sequenceOptions
|
|
913
|
-
}
|
|
914
|
-
),
|
|
915
|
-
form.target === "url" && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
916
|
-
/* @__PURE__ */ jsx(Label, { htmlFor: tipCtaHrefId, children: l.url }),
|
|
917
|
-
/* @__PURE__ */ jsx(
|
|
918
|
-
Input,
|
|
919
|
-
{
|
|
920
|
-
id: tipCtaHrefId,
|
|
921
|
-
placeholder: "https://\u2026",
|
|
922
|
-
value: form.ctaHref,
|
|
923
|
-
onChange: (e) => onFormChange({ ctaHref: e.target.value })
|
|
924
|
-
}
|
|
925
|
-
)
|
|
926
|
-
] }),
|
|
927
|
-
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
928
|
-
/* @__PURE__ */ jsx(Button, { variant: "ghost", onClick: onFormBack, disabled: busy, children: l.back }),
|
|
929
|
-
/* @__PURE__ */ jsx(Button, { onClick: onFormSave, disabled: busy || !form.message.trim(), children: busy ? l.saving : l.save })
|
|
930
|
-
] })
|
|
931
|
-
] }) : /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
932
|
-
/* @__PURE__ */ jsx("ul", { className: "max-h-[55dvh] divide-y overflow-y-auto rounded border", children: rows.map((row) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2 p-2 text-sm", children: [
|
|
933
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
934
|
-
/* @__PURE__ */ jsx("p", { className: cn(row.isHidden && "text-muted-foreground line-through"), children: row.message }),
|
|
935
|
-
/* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
936
|
-
row.isHidden ? l.hiddenOff : row.placementLabel,
|
|
937
|
-
row.isCustom && l.customSuffix
|
|
938
|
-
] })
|
|
939
|
-
] }),
|
|
940
|
-
/* @__PURE__ */ jsx(
|
|
941
|
-
Button,
|
|
942
|
-
{
|
|
943
|
-
size: "icon",
|
|
944
|
-
variant: "ghost",
|
|
945
|
-
className: ROW_BUTTON,
|
|
946
|
-
onClick: () => onEditRow(row.code),
|
|
947
|
-
"aria-label": l.editTip,
|
|
948
|
-
children: /* @__PURE__ */ jsx(Pencil, { className: "size-3.5" })
|
|
949
|
-
}
|
|
950
|
-
),
|
|
951
|
-
row.isCustom && /* @__PURE__ */ jsx(
|
|
952
|
-
Button,
|
|
953
|
-
{
|
|
954
|
-
size: "icon",
|
|
955
|
-
variant: "ghost",
|
|
956
|
-
className: ROW_BUTTON,
|
|
957
|
-
disabled: busy,
|
|
958
|
-
onClick: () => onDeleteRow(row.code),
|
|
959
|
-
"aria-label": l.deleteTip,
|
|
960
|
-
children: /* @__PURE__ */ jsx(Trash2, { className: "size-3.5" })
|
|
961
|
-
}
|
|
962
|
-
)
|
|
963
|
-
] }, row.code)) }),
|
|
964
|
-
/* @__PURE__ */ jsxs(Button, { variant: "outline", size: "sm", onClick: onAdd, children: [
|
|
965
|
-
/* @__PURE__ */ jsx(Plus, { className: "mr-1 size-4" }),
|
|
966
|
-
" ",
|
|
967
|
-
l.addTip
|
|
968
|
-
] }),
|
|
969
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-2 rounded border border-dashed p-2", children: [
|
|
970
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground", children: l.testerTitle }),
|
|
971
|
-
/* @__PURE__ */ jsx("ul", { className: "divide-y rounded border", children: sequenceOptions.map((s) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2 p-2 text-sm", children: [
|
|
972
|
-
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: s.label }),
|
|
973
|
-
activeSequenceId === s.value ? /* @__PURE__ */ jsx(
|
|
974
|
-
Button,
|
|
975
|
-
{
|
|
976
|
-
size: "sm",
|
|
977
|
-
variant: "outline",
|
|
978
|
-
className: "h-7 flex-shrink-0 pointer-coarse:h-11",
|
|
979
|
-
onClick: onCancelSequence,
|
|
980
|
-
children: l.cancel
|
|
981
|
-
}
|
|
982
|
-
) : /* @__PURE__ */ jsx(
|
|
983
|
-
Button,
|
|
984
|
-
{
|
|
985
|
-
size: "sm",
|
|
986
|
-
variant: "outline",
|
|
987
|
-
className: "h-7 flex-shrink-0 pointer-coarse:h-11",
|
|
988
|
-
onClick: () => onRunSequence(s.value),
|
|
989
|
-
children: l.run
|
|
990
|
-
}
|
|
991
|
-
)
|
|
992
|
-
] }, s.value)) })
|
|
993
|
-
] })
|
|
994
|
-
] })
|
|
995
|
-
]
|
|
996
|
-
}
|
|
997
|
-
);
|
|
998
|
-
}
|
|
999
|
-
var DEFAULT_SYNC_DIALOG_FOOTER_LABELS = {
|
|
1000
|
-
cancel: "Cancel",
|
|
1001
|
-
save: "Save"
|
|
1002
|
-
};
|
|
1003
|
-
function SyncDialogFooter({
|
|
1004
|
-
onCancel,
|
|
1005
|
-
onSave,
|
|
1006
|
-
saveDisabled,
|
|
1007
|
-
isSaving,
|
|
1008
|
-
cancelButton,
|
|
1009
|
-
saveButton,
|
|
1010
|
-
labels
|
|
1011
|
-
}) {
|
|
1012
|
-
const l = { ...DEFAULT_SYNC_DIALOG_FOOTER_LABELS, ...labels };
|
|
1013
|
-
return /* @__PURE__ */ jsxs(DialogFooter, { "data-slot": "sync-dialog-footer", children: [
|
|
1014
|
-
/* @__PURE__ */ jsx(Button, { variant: "outline", size: "sm", onClick: onCancel, "data-testid": cancelButton?.testId, children: l.cancel }),
|
|
1015
|
-
/* @__PURE__ */ jsxs(
|
|
1016
|
-
Button,
|
|
1017
|
-
{
|
|
1018
|
-
size: "sm",
|
|
1019
|
-
onClick: onSave,
|
|
1020
|
-
disabled: saveDisabled || isSaving,
|
|
1021
|
-
"data-testid": saveButton?.testId,
|
|
1022
|
-
children: [
|
|
1023
|
-
isSaving && /* @__PURE__ */ jsx(Loader2, { className: "mr-1.5 size-3.5 animate-spin" }),
|
|
1024
|
-
l.save
|
|
1025
|
-
]
|
|
1026
|
-
}
|
|
1027
|
-
)
|
|
1028
|
-
] });
|
|
1029
|
-
}
|
|
1030
|
-
function SyncDialogBody({ children }) {
|
|
1031
|
-
return /* @__PURE__ */ jsx("div", { "data-slot": "sync-dialog-body", className: "space-y-4 py-2", children });
|
|
1032
|
-
}
|
|
1033
|
-
function SyncField({ label, htmlFor, actions, hint, children }) {
|
|
1034
|
-
return /* @__PURE__ */ jsxs("div", { "data-slot": "sync-field", className: "space-y-1.5", children: [
|
|
1035
|
-
(label || actions) && /* @__PURE__ */ jsxs("div", { className: cn(actions && "flex items-center justify-between"), children: [
|
|
1036
|
-
label && /* @__PURE__ */ jsx(Label, { htmlFor, children: label }),
|
|
1037
|
-
actions
|
|
1038
|
-
] }),
|
|
1039
|
-
children,
|
|
1040
|
-
hint && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: hint })
|
|
1041
|
-
] });
|
|
1042
|
-
}
|
|
1043
|
-
function SyncLinkButton({
|
|
1044
|
-
onClick,
|
|
1045
|
-
testId,
|
|
1046
|
-
children
|
|
1047
|
-
}) {
|
|
1048
|
-
return /* @__PURE__ */ jsx(
|
|
1049
|
-
"button",
|
|
1050
|
-
{
|
|
1051
|
-
type: "button",
|
|
1052
|
-
className: "text-xs font-medium text-primary hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11 pointer-coarse:px-1",
|
|
1053
|
-
onClick,
|
|
1054
|
-
"data-testid": testId,
|
|
1055
|
-
children
|
|
1056
|
-
}
|
|
1057
|
-
);
|
|
1058
|
-
}
|
|
1059
|
-
function SyncLinkRow({ children }) {
|
|
1060
|
-
return /* @__PURE__ */ jsx("div", { className: "flex items-center gap-3", children });
|
|
1061
|
-
}
|
|
1062
|
-
function SyncSelect({
|
|
1063
|
-
id,
|
|
1064
|
-
testId,
|
|
1065
|
-
value,
|
|
1066
|
-
onValueChange,
|
|
1067
|
-
options,
|
|
1068
|
-
placeholder
|
|
1069
|
-
}) {
|
|
1070
|
-
return /* @__PURE__ */ jsxs(Select, { value, onValueChange, children: [
|
|
1071
|
-
/* @__PURE__ */ jsx(SelectTrigger, { id, "data-testid": testId, children: /* @__PURE__ */ jsx(SelectValue, { placeholder }) }),
|
|
1072
|
-
/* @__PURE__ */ jsx(SelectContent, { children: options.map((o) => /* @__PURE__ */ jsx(SelectItem, { value: o.value, children: o.label }, o.value)) })
|
|
1073
|
-
] });
|
|
1074
|
-
}
|
|
1075
|
-
function SyncOptionToggle({
|
|
1076
|
-
checked,
|
|
1077
|
-
onCheckedChange,
|
|
1078
|
-
title,
|
|
1079
|
-
description,
|
|
1080
|
-
testId
|
|
1081
|
-
}) {
|
|
1082
|
-
return /* @__PURE__ */ jsxs("label", { className: "flex cursor-pointer items-start gap-2 text-sm", children: [
|
|
1083
|
-
/* @__PURE__ */ jsx(
|
|
1084
|
-
Checkbox,
|
|
1085
|
-
{
|
|
1086
|
-
className: "mt-0.5",
|
|
1087
|
-
checked,
|
|
1088
|
-
onCheckedChange: (v) => onCheckedChange(v === true),
|
|
1089
|
-
"data-testid": testId
|
|
1090
|
-
}
|
|
1091
|
-
),
|
|
1092
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
1093
|
-
title,
|
|
1094
|
-
description && /* @__PURE__ */ jsx("span", { className: "block text-xs text-muted-foreground", children: description })
|
|
1095
|
-
] })
|
|
1096
|
-
] });
|
|
1097
|
-
}
|
|
1098
|
-
function SyncOptions({ children }) {
|
|
1099
|
-
return /* @__PURE__ */ jsx("div", { "data-slot": "sync-options", className: "space-y-2.5", children });
|
|
1100
|
-
}
|
|
1101
|
-
function SyncLoading({ children, compact }) {
|
|
1102
|
-
return /* @__PURE__ */ jsxs(
|
|
1103
|
-
"div",
|
|
1104
|
-
{
|
|
1105
|
-
className: cn("flex items-center gap-2 text-sm text-muted-foreground", !compact && "py-2"),
|
|
1106
|
-
children: [
|
|
1107
|
-
/* @__PURE__ */ jsx(Loader2, { className: "size-3.5 animate-spin" }),
|
|
1108
|
-
" ",
|
|
1109
|
-
children
|
|
1110
|
-
]
|
|
1111
|
-
}
|
|
1112
|
-
);
|
|
1113
|
-
}
|
|
1114
|
-
function SyncNote({ children, testId }) {
|
|
1115
|
-
return /* @__PURE__ */ jsx("p", { className: "py-2 text-sm text-muted-foreground", "data-testid": testId, children });
|
|
1116
|
-
}
|
|
1117
|
-
function SyncSmallNote({ children, testId }) {
|
|
1118
|
-
return /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", "data-testid": testId, children });
|
|
1119
|
-
}
|
|
1120
|
-
function SyncReconnectNotice({
|
|
1121
|
-
message,
|
|
1122
|
-
onReconnect,
|
|
1123
|
-
isPending,
|
|
1124
|
-
testId,
|
|
1125
|
-
label = "Reconnect"
|
|
1126
|
-
}) {
|
|
1127
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-2 py-2", children: [
|
|
1128
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: message }),
|
|
1129
|
-
/* @__PURE__ */ jsxs(
|
|
1130
|
-
Button,
|
|
1131
|
-
{
|
|
1132
|
-
type: "button",
|
|
1133
|
-
size: "sm",
|
|
1134
|
-
onClick: onReconnect,
|
|
1135
|
-
disabled: isPending,
|
|
1136
|
-
"data-testid": testId,
|
|
1137
|
-
children: [
|
|
1138
|
-
isPending && /* @__PURE__ */ jsx(Loader2, { className: "mr-1.5 size-3.5 animate-spin" }),
|
|
1139
|
-
label
|
|
1140
|
-
]
|
|
1141
|
-
}
|
|
1142
|
-
)
|
|
1143
|
-
] });
|
|
1144
|
-
}
|
|
1145
|
-
function SyncTreeFrame({ children }) {
|
|
1146
|
-
return /* @__PURE__ */ jsx(ScrollArea, { className: "h-72 rounded-md border p-2", children });
|
|
1147
|
-
}
|
|
1148
|
-
function SyncCheckList({ items, selected, onToggle }) {
|
|
1149
|
-
return /* @__PURE__ */ jsx(ScrollArea, { className: "max-h-44 rounded-md border border-border", children: /* @__PURE__ */ jsx("div", { className: "space-y-1 p-2", children: items.map((c) => /* @__PURE__ */ jsxs(
|
|
1150
|
-
"label",
|
|
1151
|
-
{
|
|
1152
|
-
className: "flex cursor-pointer items-center gap-2 rounded px-1.5 py-1 text-sm hover:bg-muted/50 pointer-coarse:min-h-11",
|
|
1153
|
-
children: [
|
|
1154
|
-
/* @__PURE__ */ jsx(
|
|
1155
|
-
Checkbox,
|
|
1156
|
-
{
|
|
1157
|
-
checked: selected.includes(c.id),
|
|
1158
|
-
onCheckedChange: () => onToggle(c.id),
|
|
1159
|
-
"data-testid": c.testId
|
|
1160
|
-
}
|
|
1161
|
-
),
|
|
1162
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: c.label })
|
|
1163
|
-
]
|
|
1164
|
-
},
|
|
1165
|
-
c.id
|
|
1166
|
-
)) }) });
|
|
1167
|
-
}
|
|
1168
|
-
var DEFAULT_SYNC_FOLDER_ROW_LABELS = {
|
|
1169
|
-
collapse: "Collapse folder",
|
|
1170
|
-
expand: "Expand folder",
|
|
1171
|
-
loading: "Loading\u2026",
|
|
1172
|
-
noSubfolders: "No subfolders"
|
|
1173
|
-
};
|
|
1174
|
-
var INDENT = 18;
|
|
1175
|
-
function SyncFolderRow({
|
|
1176
|
-
id,
|
|
1177
|
-
name,
|
|
1178
|
-
depth,
|
|
1179
|
-
hasChildren,
|
|
1180
|
-
isExpanded,
|
|
1181
|
-
onToggleExpanded,
|
|
1182
|
-
isSelectable,
|
|
1183
|
-
checked,
|
|
1184
|
-
disabled,
|
|
1185
|
-
onCheckedChange,
|
|
1186
|
-
count,
|
|
1187
|
-
isCountLoading,
|
|
1188
|
-
children,
|
|
1189
|
-
labels
|
|
1190
|
-
}) {
|
|
1191
|
-
const l = { ...DEFAULT_SYNC_FOLDER_ROW_LABELS, ...labels };
|
|
1192
|
-
return /* @__PURE__ */ jsxs("div", { children: [
|
|
1193
|
-
/* @__PURE__ */ jsxs(
|
|
1194
|
-
"div",
|
|
1195
|
-
{
|
|
1196
|
-
className: "flex items-center gap-1.5 rounded px-1 py-1 text-sm hover:bg-muted/50 pointer-coarse:min-h-11",
|
|
1197
|
-
style: { paddingLeft: depth * INDENT + 4 },
|
|
1198
|
-
children: [
|
|
1199
|
-
hasChildren ? /* @__PURE__ */ jsx(
|
|
1200
|
-
"button",
|
|
1201
|
-
{
|
|
1202
|
-
type: "button",
|
|
1203
|
-
className: "flex size-4 shrink-0 items-center justify-center text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:size-8",
|
|
1204
|
-
onClick: onToggleExpanded,
|
|
1205
|
-
"aria-label": isExpanded ? l.collapse : l.expand,
|
|
1206
|
-
"aria-expanded": isExpanded,
|
|
1207
|
-
children: isExpanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "size-3.5" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "size-3.5" })
|
|
1208
|
-
}
|
|
1209
|
-
) : /* @__PURE__ */ jsx("span", { className: "size-4 shrink-0" }),
|
|
1210
|
-
isSelectable ? /* @__PURE__ */ jsxs(
|
|
1211
|
-
"label",
|
|
1212
|
-
{
|
|
1213
|
-
className: "flex flex-1 cursor-pointer items-center gap-2 truncate",
|
|
1214
|
-
"data-testid": `drive-folder-row-${id}`,
|
|
1215
|
-
children: [
|
|
1216
|
-
/* @__PURE__ */ jsx(
|
|
1217
|
-
Checkbox,
|
|
1218
|
-
{
|
|
1219
|
-
checked,
|
|
1220
|
-
disabled,
|
|
1221
|
-
onCheckedChange,
|
|
1222
|
-
"data-testid": `drive-folder-checkbox-${id}`
|
|
1223
|
-
}
|
|
1224
|
-
),
|
|
1225
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", "data-testid": `drive-folder-name-${id}`, children: name }),
|
|
1226
|
-
isCountLoading ? /* @__PURE__ */ jsx(Loader2, { className: "size-3 shrink-0 animate-spin text-muted-foreground" }) : typeof count === "number" ? /* @__PURE__ */ jsxs("span", { className: "shrink-0 text-xs text-muted-foreground", children: [
|
|
1227
|
-
"(",
|
|
1228
|
-
count.toLocaleString(),
|
|
1229
|
-
")"
|
|
1230
|
-
] }) : null
|
|
1231
|
-
]
|
|
1232
|
-
}
|
|
1233
|
-
) : /* @__PURE__ */ jsx(
|
|
1234
|
-
"span",
|
|
1235
|
-
{
|
|
1236
|
-
className: "flex flex-1 items-center truncate font-medium text-muted-foreground",
|
|
1237
|
-
"data-testid": `drive-folder-row-${id}`,
|
|
1238
|
-
children: /* @__PURE__ */ jsx("span", { className: "truncate", "data-testid": `drive-folder-name-${id}`, children: name })
|
|
1239
|
-
}
|
|
1240
|
-
)
|
|
1241
|
-
]
|
|
1242
|
-
}
|
|
1243
|
-
),
|
|
1244
|
-
isExpanded && /* @__PURE__ */ jsx("div", { children })
|
|
1245
|
-
] });
|
|
1246
|
-
}
|
|
1247
|
-
function SyncFolderStatus({
|
|
1248
|
-
depth,
|
|
1249
|
-
kind,
|
|
1250
|
-
labels
|
|
1251
|
-
}) {
|
|
1252
|
-
const l = { ...DEFAULT_SYNC_FOLDER_ROW_LABELS, ...labels };
|
|
1253
|
-
return /* @__PURE__ */ jsx(
|
|
1254
|
-
"div",
|
|
1255
|
-
{
|
|
1256
|
-
className: "flex items-center gap-2 py-1 text-xs text-muted-foreground",
|
|
1257
|
-
style: { paddingLeft: (depth + 1) * INDENT + 4 },
|
|
1258
|
-
children: kind === "loading" ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1259
|
-
/* @__PURE__ */ jsx(Loader2, { className: "size-3 animate-spin" }),
|
|
1260
|
-
" ",
|
|
1261
|
-
l.loading
|
|
1262
|
-
] }) : l.noSubfolders
|
|
1263
|
-
}
|
|
1264
|
-
);
|
|
1265
|
-
}
|
|
1266
|
-
function FilterChip({
|
|
1267
|
-
label,
|
|
1268
|
-
state,
|
|
1269
|
-
icon,
|
|
1270
|
-
color,
|
|
1271
|
-
onDismiss,
|
|
1272
|
-
dismissLabel,
|
|
1273
|
-
className,
|
|
1274
|
-
testId
|
|
1275
|
-
}) {
|
|
1276
|
-
const isExclude = state === "exclude";
|
|
1277
|
-
return /* @__PURE__ */ jsxs(
|
|
1278
|
-
"span",
|
|
1279
|
-
{
|
|
1280
|
-
className: cn(
|
|
1281
|
-
"inline-flex items-center gap-1 text-xs font-medium rounded px-1.5 py-0.5 flex-shrink-0 border",
|
|
1282
|
-
isExclude ? "bg-background text-red-text border-red-text" : "bg-primary text-white border-primary",
|
|
1283
|
-
className
|
|
1284
|
-
),
|
|
1285
|
-
"data-state": state,
|
|
1286
|
-
"data-testid": testId,
|
|
1287
|
-
children: [
|
|
1288
|
-
color ? (
|
|
1289
|
-
/* Filled square for include; empty square for exclude */
|
|
1290
|
-
isExclude ? /* @__PURE__ */ jsx(
|
|
1291
|
-
"span",
|
|
1292
|
-
{
|
|
1293
|
-
className: "w-3.5 h-3.5 rounded flex-shrink-0 border-2",
|
|
1294
|
-
style: { borderColor: color }
|
|
1295
|
-
}
|
|
1296
|
-
) : /* @__PURE__ */ jsx(
|
|
1297
|
-
"span",
|
|
1298
|
-
{
|
|
1299
|
-
className: "w-3.5 h-3.5 rounded flex items-center justify-center flex-shrink-0",
|
|
1300
|
-
style: { backgroundColor: color },
|
|
1301
|
-
children: /* @__PURE__ */ jsx(Check, { className: "w-2.5 h-2.5 text-white", strokeWidth: 3 })
|
|
1302
|
-
}
|
|
1303
|
-
)
|
|
1304
|
-
) : icon && /* @__PURE__ */ jsx("span", { className: "flex-none", children: icon }),
|
|
1305
|
-
/* @__PURE__ */ jsxs("span", { className: "truncate max-w-[80px]", title: label, children: [
|
|
1306
|
-
isExclude && /* @__PURE__ */ jsx("span", { className: "opacity-70 mr-0.5", children: "Not" }),
|
|
1307
|
-
label
|
|
1308
|
-
] }),
|
|
1309
|
-
onDismiss && /* @__PURE__ */ jsx(
|
|
1310
|
-
"button",
|
|
1311
|
-
{
|
|
1312
|
-
type: "button",
|
|
1313
|
-
onClick: onDismiss,
|
|
1314
|
-
"aria-label": dismissLabel ?? `Remove ${label}`,
|
|
1315
|
-
className: "flex-none ml-0.5 opacity-70 hover:opacity-100",
|
|
1316
|
-
"data-testid": testId ? `${testId}-remove` : void 0,
|
|
1317
|
-
children: /* @__PURE__ */ jsx(X, { className: "h-3 w-3", strokeWidth: 2.5 })
|
|
1318
|
-
}
|
|
1319
|
-
)
|
|
1320
|
-
]
|
|
1321
|
-
}
|
|
1322
|
-
);
|
|
1323
|
-
}
|
|
1324
|
-
var planBadgeVariants = cva(
|
|
1325
|
-
"inline-flex flex-shrink-0 items-center rounded-full border font-semibold leading-none",
|
|
1326
|
-
{
|
|
1327
|
-
variants: {
|
|
1328
|
-
/** free/dev = neutral, paid = accent tint, pending = payment trouble or cancelling. */
|
|
1329
|
-
tone: {
|
|
1330
|
-
free: `border-transparent ${TONE_SURFACE.neutral}`,
|
|
1331
|
-
dev: `border-transparent ${TONE_SURFACE.neutral}`,
|
|
1332
|
-
paid: "border-transparent bg-accent text-accent-foreground",
|
|
1333
|
-
pending: `${TONE_BORDER.warning} ${TONE_SURFACE.warning}`
|
|
1334
|
-
},
|
|
1335
|
-
/** `sm` fits dense rows and tables; `md` holds its own beside body text. */
|
|
1336
|
-
size: {
|
|
1337
|
-
sm: "h-5 px-2 text-xs",
|
|
1338
|
-
md: "h-6 px-2.5 text-sm"
|
|
1339
|
-
}
|
|
1340
|
-
},
|
|
1341
|
-
defaultVariants: { tone: "free", size: "sm" }
|
|
1342
|
-
}
|
|
1343
|
-
);
|
|
1344
|
-
function PlanBadge({
|
|
1345
|
-
label,
|
|
1346
|
-
tone,
|
|
1347
|
-
size,
|
|
1348
|
-
className,
|
|
1349
|
-
testId = "project-plan-chip"
|
|
1350
|
-
}) {
|
|
1351
|
-
return /* @__PURE__ */ jsx(
|
|
1352
|
-
"span",
|
|
1353
|
-
{
|
|
1354
|
-
"data-slot": "plan-badge",
|
|
1355
|
-
className: cn(planBadgeVariants({ tone, size }), className),
|
|
1356
|
-
"data-testid": testId,
|
|
1357
|
-
children: label
|
|
1358
|
-
}
|
|
1359
|
-
);
|
|
1360
|
-
}
|
|
1361
|
-
function MoreInfo({
|
|
1362
|
-
title,
|
|
1363
|
-
children,
|
|
1364
|
-
label = "More info",
|
|
1365
|
-
testId = "more-info",
|
|
1366
|
-
className
|
|
1367
|
-
}) {
|
|
1368
|
-
const [open, setOpen] = useState(false);
|
|
1369
|
-
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
1370
|
-
/* @__PURE__ */ jsxs(
|
|
1371
|
-
"button",
|
|
1372
|
-
{
|
|
1373
|
-
type: "button",
|
|
1374
|
-
onClick: () => setOpen(true),
|
|
1375
|
-
className: cn(
|
|
1376
|
-
"inline-flex shrink-0 items-center gap-1 whitespace-nowrap rounded-sm text-xs font-medium text-muted-foreground underline-offset-2 hover:text-foreground hover:underline focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11",
|
|
1377
|
-
className
|
|
1378
|
-
),
|
|
1379
|
-
"data-slot": "more-info",
|
|
1380
|
-
"data-testid": testId,
|
|
1381
|
-
children: [
|
|
1382
|
-
/* @__PURE__ */ jsx(Info, { className: "size-3.5", "aria-hidden": true }),
|
|
1383
|
-
label
|
|
1384
|
-
]
|
|
1385
|
-
}
|
|
1386
|
-
),
|
|
1387
|
-
/* @__PURE__ */ jsx(Dialog, { open, onOpenChange: setOpen, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", "data-testid": `${testId}-dialog`, children: [
|
|
1388
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
1389
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: title }),
|
|
1390
|
-
/* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: title })
|
|
1391
|
-
] }),
|
|
1392
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-3 text-sm leading-relaxed text-muted-foreground", children })
|
|
1393
|
-
] }) })
|
|
1394
|
-
] });
|
|
1395
|
-
}
|
|
1396
|
-
function MoreInfoList({ items }) {
|
|
1397
|
-
return /* @__PURE__ */ jsx("ul", { className: "space-y-2", "data-slot": "more-info-list", children: items.map((item, i) => /* @__PURE__ */ jsxs("li", { children: [
|
|
1398
|
-
item.term && /* @__PURE__ */ jsxs("span", { className: "font-medium text-foreground", children: [
|
|
1399
|
-
item.term,
|
|
1400
|
-
". "
|
|
1401
|
-
] }),
|
|
1402
|
-
item.text
|
|
1403
|
-
] }, item.term ?? i)) });
|
|
1404
|
-
}
|
|
1405
|
-
var barColor = (pct) => pct >= 100 ? "bg-red-500" : pct >= 50 ? "bg-yellow-500" : "bg-primary";
|
|
1406
|
-
var valueColor2 = (pct) => pct >= 100 ? "text-red-text" : pct >= 80 ? "text-yellow-text" : "text-muted-foreground";
|
|
1407
|
-
function QuotaMeter({
|
|
1408
|
-
items,
|
|
1409
|
-
size = "sm",
|
|
1410
|
-
showTooltips = true,
|
|
1411
|
-
showBars = true,
|
|
1412
|
-
showPercent = true,
|
|
1413
|
-
className,
|
|
1414
|
-
testIds
|
|
1415
|
-
}) {
|
|
1416
|
-
if (size === "lg") {
|
|
1417
|
-
return /* @__PURE__ */ jsx(
|
|
1418
|
-
"div",
|
|
1419
|
-
{
|
|
1420
|
-
"data-slot": "quota-meter",
|
|
1421
|
-
className: cn("flex flex-wrap gap-3", className),
|
|
1422
|
-
"data-testid": testIdOr(testIds?.root, { testId: "quota-badges-lg" }),
|
|
1423
|
-
children: items.map(({ key, icon: Icon, label, usedOfLimit, pct }) => /* @__PURE__ */ jsxs(
|
|
1424
|
-
"div",
|
|
1425
|
-
{
|
|
1426
|
-
className: "min-w-[8rem] flex-1 rounded-lg bg-muted p-3",
|
|
1427
|
-
"data-testid": prefixedTestId(testIds?.badge, key, { testId: `quota-badge-${key}` }),
|
|
1428
|
-
children: [
|
|
1429
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
1430
|
-
/* @__PURE__ */ jsx(Icon, { className: "h-3.5 w-3.5 flex-shrink-0" }),
|
|
1431
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: label })
|
|
1432
|
-
] }),
|
|
1433
|
-
/* @__PURE__ */ jsx("div", { className: "mt-1 text-lg font-semibold tabular-nums text-foreground", children: usedOfLimit }),
|
|
1434
|
-
/* @__PURE__ */ jsx("div", { className: "mt-2 h-1.5 overflow-hidden rounded-full bg-background", children: /* @__PURE__ */ jsx(
|
|
1435
|
-
"div",
|
|
1436
|
-
{
|
|
1437
|
-
className: cn("h-full rounded-full", barColor(pct)),
|
|
1438
|
-
style: { width: `${Math.min(pct, 100)}%` },
|
|
1439
|
-
"data-testid": prefixedTestId(
|
|
1440
|
-
testIds?.badge,
|
|
1441
|
-
key,
|
|
1442
|
-
{ testId: `quota-badge-${key}-fill` },
|
|
1443
|
-
"-fill"
|
|
1444
|
-
)
|
|
1445
|
-
}
|
|
1446
|
-
) })
|
|
1447
|
-
]
|
|
1448
|
-
},
|
|
1449
|
-
key
|
|
1450
|
-
))
|
|
1451
|
-
}
|
|
1452
|
-
);
|
|
1453
|
-
}
|
|
1454
|
-
return /* @__PURE__ */ jsx(
|
|
1455
|
-
"div",
|
|
1456
|
-
{
|
|
1457
|
-
"data-slot": "quota-meter",
|
|
1458
|
-
className: cn("flex flex-shrink-0 items-center gap-3 text-sm tabular-nums", className),
|
|
1459
|
-
"data-testid": testIdOr(testIds?.root, { testId: "quota-badges-sm" }),
|
|
1460
|
-
children: items.map(({ key, icon: Icon, label, used, usedOfLimit, pct }) => {
|
|
1461
|
-
const badge = /* @__PURE__ */ jsxs(
|
|
1462
|
-
"span",
|
|
1463
|
-
{
|
|
1464
|
-
className: "inline-flex items-center gap-1",
|
|
1465
|
-
"data-testid": prefixedTestId(testIds?.badge, key, { testId: `quota-badge-${key}` }),
|
|
1466
|
-
children: [
|
|
1467
|
-
/* @__PURE__ */ jsx(Icon, { className: "h-4 w-4 flex-shrink-0 text-muted-foreground" }),
|
|
1468
|
-
/* @__PURE__ */ jsx("span", { className: showBars ? valueColor2(pct) : "text-muted-foreground", children: showBars && showPercent ? `${used} (${Math.round(pct)}%)` : used })
|
|
1469
|
-
]
|
|
1470
|
-
}
|
|
1471
|
-
);
|
|
1472
|
-
return showTooltips ? /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
1473
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: badge }),
|
|
1474
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: `${usedOfLimit} ${label}` })
|
|
1475
|
-
] }, key) : /* @__PURE__ */ jsx(Fragment$1, { children: badge }, key);
|
|
1476
|
-
})
|
|
1477
|
-
}
|
|
1478
|
-
);
|
|
1479
|
-
}
|
|
1480
|
-
var DEFAULT_PLAN_CARD_LABELS = {
|
|
1481
|
-
currentPlan: "Current plan",
|
|
1482
|
-
popular: "Popular",
|
|
1483
|
-
noMonthlyCost: "\xA30",
|
|
1484
|
-
perMonth: "/mo",
|
|
1485
|
-
current: "Current",
|
|
1486
|
-
monthly: "Monthly",
|
|
1487
|
-
annual: "Annual",
|
|
1488
|
-
annualBilling: "Annual billing",
|
|
1489
|
-
save: (percent) => `Save ${percent}%`,
|
|
1490
|
-
havePromoCode: "Have a promo code?",
|
|
1491
|
-
promoCode: "Promo Code",
|
|
1492
|
-
enterCode: "Enter code",
|
|
1493
|
-
pricingExplainer: "How pricing works",
|
|
1494
|
-
explainerTiers: [
|
|
1495
|
-
"AI usage and storage are shared by everyone in the project. AI usage resets monthly.",
|
|
1496
|
-
"Need more? Add \xA325 of AI usage or 25 GB at a time, at checkout or later. Add-ons renew with the plan until you reduce them.",
|
|
1497
|
-
"Automatic top-ups add one more step when you run low, up to your monthly usage cap (\xA3100 by default; \xA30 = none; or no limit). Adding by hand is never capped.",
|
|
1498
|
-
"Add-ons start now: AI usage is charged in full, storage only for the rest of the period. Downgrades, billing switches and reductions start at the end of the period. No refunds.",
|
|
1499
|
-
"Annual plans are 25% off, add-ons included.",
|
|
1500
|
-
"Prices are shown + VAT; the total for your country is shown before you pay."
|
|
1501
|
-
],
|
|
1502
|
-
explainerAiUsage: "About 1p of AI usage buys one moderately complex request, or reading ~25 documents, on a Standard model. Premium models can cost 10\u2013100\xD7 more.",
|
|
1503
|
-
seeModelList: "AI model prices \u2192"
|
|
1504
|
-
};
|
|
1505
|
-
function PlanCard({ plan, onSelect, labels }) {
|
|
1506
|
-
const l = useMemo(() => ({ ...DEFAULT_PLAN_CARD_LABELS, ...labels }), [labels]);
|
|
1507
|
-
const { id, name, isFree, isCurrent, isSelected, isPopular, price, features } = plan;
|
|
1508
|
-
return /* @__PURE__ */ jsxs(
|
|
1509
|
-
"button",
|
|
1510
|
-
{
|
|
1511
|
-
type: "button",
|
|
1512
|
-
disabled: isCurrent,
|
|
1513
|
-
"aria-pressed": !!isSelected,
|
|
1514
|
-
onClick: () => !isCurrent && onSelect(id),
|
|
1515
|
-
"data-slot": "plan-card",
|
|
1516
|
-
"data-testid": `tier-card-${id}`,
|
|
1517
|
-
className: cn(
|
|
1518
|
-
"relative flex flex-col justify-start rounded-lg p-4 text-left transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
1519
|
-
isCurrent ? "cursor-default bg-blue-bg" : isSelected ? "bg-accent ring-1 ring-primary/50" : "bg-muted hover:bg-muted/70"
|
|
1520
|
-
),
|
|
1521
|
-
children: [
|
|
1522
|
-
isCurrent && /* @__PURE__ */ jsx("span", { className: "absolute -top-3 left-1/2 -translate-x-1/2 whitespace-nowrap rounded-full bg-blue-bg px-3 py-1 text-xs font-semibold leading-none text-blue-text", children: l.currentPlan }),
|
|
1523
|
-
isPopular && !isCurrent && /* @__PURE__ */ jsx("span", { className: "absolute -top-3 left-1/2 -translate-x-1/2 whitespace-nowrap rounded-full bg-primary px-3 py-1 text-xs font-semibold leading-none text-primary-foreground", children: l.popular }),
|
|
1524
|
-
/* @__PURE__ */ jsx("div", { className: "mb-3 flex items-baseline gap-2", children: /* @__PURE__ */ jsx(
|
|
1525
|
-
"span",
|
|
1526
|
-
{
|
|
1527
|
-
className: cn(
|
|
1528
|
-
"text-lg font-semibold leading-none tracking-tight",
|
|
1529
|
-
isCurrent ? "text-blue-text" : "text-foreground"
|
|
1530
|
-
),
|
|
1531
|
-
children: name
|
|
1532
|
-
}
|
|
1533
|
-
) }),
|
|
1534
|
-
isFree ? /* @__PURE__ */ jsxs("div", { className: "text-2xl font-semibold leading-none tabular-nums text-foreground", children: [
|
|
1535
|
-
l.noMonthlyCost,
|
|
1536
|
-
/* @__PURE__ */ jsx("span", { className: "ml-0.5 text-sm font-medium text-muted-foreground", children: l.perMonth })
|
|
1537
|
-
] }) : price && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1", children: [
|
|
1538
|
-
price.annual && price.yearlyTotal && /* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-x-2 whitespace-nowrap text-base tabular-nums", children: [
|
|
1539
|
-
price.yearlyStrike && /* @__PURE__ */ jsx("span", { className: "font-medium text-muted-foreground line-through decoration-muted-foreground/70 decoration-1", children: price.yearlyStrike }),
|
|
1540
|
-
/* @__PURE__ */ jsxs("span", { className: "text-lg font-semibold text-foreground", children: [
|
|
1541
|
-
price.yearlyTotal,
|
|
1542
|
-
/* @__PURE__ */ jsx("span", { className: "ml-0.5 text-xs font-semibold text-muted-foreground", children: price.intervalLabel })
|
|
1543
|
-
] })
|
|
1544
|
-
] }),
|
|
1545
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-baseline gap-x-1.5 whitespace-nowrap", children: [
|
|
1546
|
-
price.annual && /* @__PURE__ */ jsx("span", { className: "text-xl font-semibold leading-none text-muted-foreground", children: "=" }),
|
|
1547
|
-
price.monthlyStrike && /* @__PURE__ */ jsx("span", { className: "text-base font-medium tabular-nums text-muted-foreground line-through decoration-muted-foreground/70 decoration-1", children: price.monthlyStrike }),
|
|
1548
|
-
/* @__PURE__ */ jsxs("span", { className: "text-2xl font-semibold leading-none tabular-nums text-foreground", children: [
|
|
1549
|
-
price.monthly,
|
|
1550
|
-
/* @__PURE__ */ jsxs("span", { className: "ml-0.5 text-sm font-medium text-muted-foreground", children: [
|
|
1551
|
-
l.perMonth,
|
|
1552
|
-
price.taxLabel && ` ${price.taxLabel}`
|
|
1553
|
-
] })
|
|
1554
|
-
] })
|
|
1555
|
-
] }),
|
|
1556
|
-
price.note && /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", "data-slot": "plan-card-price-note", children: price.note })
|
|
1557
|
-
] }),
|
|
1558
|
-
/* @__PURE__ */ jsx("ul", { className: "mt-4 space-y-1 border-t border-border pt-4 text-sm text-foreground", children: features.map((feature) => /* @__PURE__ */ jsx("li", { children: feature }, feature)) })
|
|
1559
|
-
]
|
|
1560
|
-
}
|
|
1561
|
-
);
|
|
1562
|
-
}
|
|
1563
|
-
function PlanCardGrid({
|
|
1564
|
-
plans,
|
|
1565
|
-
onSelect,
|
|
1566
|
-
labels
|
|
1567
|
-
}) {
|
|
1568
|
-
return /* @__PURE__ */ jsx("div", { className: "@container space-y-2", "data-slot": "plan-card-grid", children: /* @__PURE__ */ jsx(
|
|
1569
|
-
"div",
|
|
1570
|
-
{
|
|
1571
|
-
className: cn(
|
|
1572
|
-
"grid gap-2",
|
|
1573
|
-
plans.length === 4 ? "grid-cols-1 @xl:grid-cols-2 @4xl:grid-cols-4" : plans.length === 2 ? "grid-cols-1 @xl:grid-cols-2" : "grid-cols-1 @2xl:grid-cols-3"
|
|
1574
|
-
),
|
|
1575
|
-
children: plans.map((plan) => /* @__PURE__ */ jsx(PlanCard, { plan, onSelect, labels }, plan.id))
|
|
1576
|
-
}
|
|
1577
|
-
) });
|
|
1578
|
-
}
|
|
1579
|
-
function PlanTierOption({
|
|
1580
|
-
option,
|
|
1581
|
-
onSelect,
|
|
1582
|
-
labels
|
|
1583
|
-
}) {
|
|
1584
|
-
const l = useMemo(() => ({ ...DEFAULT_PLAN_CARD_LABELS, ...labels }), [labels]);
|
|
1585
|
-
return /* @__PURE__ */ jsxs(
|
|
1586
|
-
"button",
|
|
1587
|
-
{
|
|
1588
|
-
type: "button",
|
|
1589
|
-
onClick: () => onSelect(option.id),
|
|
1590
|
-
"aria-pressed": option.isSelected,
|
|
1591
|
-
"data-slot": "plan-tier-option",
|
|
1592
|
-
"data-testid": `tier-option-${option.id}`,
|
|
1593
|
-
className: cn(
|
|
1594
|
-
"flex w-full items-center justify-between rounded-lg p-3 text-left transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11",
|
|
1595
|
-
option.isSelected ? "bg-accent ring-1 ring-primary/50" : "bg-muted hover:bg-muted/70"
|
|
1596
|
-
),
|
|
1597
|
-
children: [
|
|
1598
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
1599
|
-
/* @__PURE__ */ jsx("span", { className: "text-base font-semibold text-foreground", children: option.name }),
|
|
1600
|
-
option.isCurrent && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-background px-1.5 py-0.5 text-xs font-medium text-muted-foreground", children: l.current }),
|
|
1601
|
-
option.isSelected && /* @__PURE__ */ jsx(Check, { className: "h-4 w-4 text-primary" })
|
|
1602
|
-
] }),
|
|
1603
|
-
/* @__PURE__ */ jsxs("div", { className: "text-right", children: [
|
|
1604
|
-
option.total && /* @__PURE__ */ jsxs("div", { className: "font-semibold tabular-nums", children: [
|
|
1605
|
-
option.total,
|
|
1606
|
-
/* @__PURE__ */ jsx("span", { className: "text-xs font-normal text-muted-foreground", children: option.intervalLabel })
|
|
1607
|
-
] }),
|
|
1608
|
-
/* @__PURE__ */ jsx("div", { className: "text-xs tabular-nums text-muted-foreground", children: option.summary })
|
|
1609
|
-
] })
|
|
1610
|
-
]
|
|
1611
|
-
}
|
|
1612
|
-
);
|
|
1613
|
-
}
|
|
1614
|
-
function PricingToggle({
|
|
1615
|
-
isAnnual,
|
|
1616
|
-
onToggle,
|
|
1617
|
-
savingsPercent,
|
|
1618
|
-
labels
|
|
1619
|
-
}) {
|
|
1620
|
-
const l = useMemo(() => ({ ...DEFAULT_PLAN_CARD_LABELS, ...labels }), [labels]);
|
|
1621
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm", children: [
|
|
1622
|
-
/* @__PURE__ */ jsx("span", { className: isAnnual ? "text-muted-foreground" : "font-medium", children: l.monthly }),
|
|
1623
|
-
/* @__PURE__ */ jsx(
|
|
1624
|
-
"button",
|
|
1625
|
-
{
|
|
1626
|
-
type: "button",
|
|
1627
|
-
role: "switch",
|
|
1628
|
-
"aria-checked": isAnnual,
|
|
1629
|
-
"aria-label": l.annualBilling,
|
|
1630
|
-
onClick: onToggle,
|
|
1631
|
-
className: cn(
|
|
1632
|
-
"relative inline-flex h-5 w-9 items-center rounded-full transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring",
|
|
1633
|
-
isAnnual ? "bg-primary" : "bg-muted"
|
|
1634
|
-
),
|
|
1635
|
-
children: /* @__PURE__ */ jsx(
|
|
1636
|
-
"span",
|
|
1637
|
-
{
|
|
1638
|
-
className: cn(
|
|
1639
|
-
"inline-block h-3 w-3 transform rounded-full bg-card transition-transform",
|
|
1640
|
-
isAnnual ? "translate-x-5" : "translate-x-1"
|
|
1641
|
-
)
|
|
1642
|
-
}
|
|
1643
|
-
)
|
|
1644
|
-
}
|
|
1645
|
-
),
|
|
1646
|
-
/* @__PURE__ */ jsx("span", { className: isAnnual ? "font-medium" : "text-muted-foreground", children: l.annual }),
|
|
1647
|
-
savingsPercent != null && savingsPercent > 0 && /* @__PURE__ */ jsx("span", { className: "rounded-full bg-green-bg px-1.5 py-0.5 text-sm font-semibold leading-none text-green-text", children: l.save(savingsPercent) })
|
|
1648
|
-
] });
|
|
1649
|
-
}
|
|
1650
|
-
function PromoCodeInput({
|
|
1651
|
-
value,
|
|
1652
|
-
onChange,
|
|
1653
|
-
labels
|
|
1654
|
-
}) {
|
|
1655
|
-
const l = useMemo(() => ({ ...DEFAULT_PLAN_CARD_LABELS, ...labels }), [labels]);
|
|
1656
|
-
const [expanded, setExpanded] = useState(false);
|
|
1657
|
-
if (!expanded) {
|
|
1658
|
-
return /* @__PURE__ */ jsxs(
|
|
1659
|
-
"button",
|
|
1660
|
-
{
|
|
1661
|
-
type: "button",
|
|
1662
|
-
onClick: () => setExpanded(true),
|
|
1663
|
-
className: "flex items-center gap-1.5 text-sm text-muted-foreground transition-colors hover:text-foreground pointer-coarse:min-h-11",
|
|
1664
|
-
children: [
|
|
1665
|
-
/* @__PURE__ */ jsx(Tag, { className: "h-3 w-3" }),
|
|
1666
|
-
/* @__PURE__ */ jsx("span", { children: l.havePromoCode })
|
|
1667
|
-
]
|
|
1668
|
-
}
|
|
1669
|
-
);
|
|
1670
|
-
}
|
|
1671
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
1672
|
-
/* @__PURE__ */ jsx(Label, { className: "text-sm text-muted-foreground", children: l.promoCode }),
|
|
1673
|
-
/* @__PURE__ */ jsx(
|
|
1674
|
-
Input,
|
|
1675
|
-
{
|
|
1676
|
-
value,
|
|
1677
|
-
onChange: (e) => onChange(e.target.value),
|
|
1678
|
-
placeholder: l.enterCode,
|
|
1679
|
-
className: "h-8 text-sm",
|
|
1680
|
-
autoFocus: true
|
|
1681
|
-
}
|
|
1682
|
-
)
|
|
1683
|
-
] });
|
|
1684
|
-
}
|
|
1685
|
-
function PlanInfoPopover({
|
|
1686
|
-
onOpenModelList,
|
|
1687
|
-
labels
|
|
1688
|
-
}) {
|
|
1689
|
-
const l = useMemo(() => ({ ...DEFAULT_PLAN_CARD_LABELS, ...labels }), [labels]);
|
|
1690
|
-
return /* @__PURE__ */ jsxs(MoreInfo, { title: l.pricingExplainer, label: l.pricingExplainer, testId: "pricing-explainer", children: [
|
|
1691
|
-
/* @__PURE__ */ jsx(MoreInfoList, { items: l.explainerTiers.map((text) => ({ text })) }),
|
|
1692
|
-
/* @__PURE__ */ jsxs("p", { children: [
|
|
1693
|
-
l.explainerAiUsage,
|
|
1694
|
-
" ",
|
|
1695
|
-
/* @__PURE__ */ jsx(
|
|
1696
|
-
"button",
|
|
1697
|
-
{
|
|
1698
|
-
type: "button",
|
|
1699
|
-
onClick: onOpenModelList,
|
|
1700
|
-
className: "font-medium text-foreground underline underline-offset-2 hover:text-primary/80",
|
|
1701
|
-
children: l.seeModelList
|
|
1702
|
-
}
|
|
1703
|
-
)
|
|
1704
|
-
] })
|
|
1705
|
-
] });
|
|
1706
|
-
}
|
|
1707
|
-
var DEFAULT_REFERRAL_REWARD_LABELS = {
|
|
1708
|
-
badgeTitle: "Reward \u2014 automatically applied to your invoice period",
|
|
1709
|
-
badge: (amount) => `${amount} reward`,
|
|
1710
|
-
subtotal: "Subtotal",
|
|
1711
|
-
reward: "Reward",
|
|
1712
|
-
youPayNow: "You pay now",
|
|
1713
|
-
rollover: (amount) => `${amount} reward rolls over to your next invoice.`,
|
|
1714
|
-
applied: (amount) => `${amount} reward applied automatically to your invoice period.`,
|
|
1715
|
-
note: (amount) => `Your ${amount} reward applies to your invoice period.`
|
|
1716
|
-
};
|
|
1717
|
-
function ReferralRewardBadge({
|
|
1718
|
-
amountLabel,
|
|
1719
|
-
labels,
|
|
1720
|
-
testId
|
|
1721
|
-
}) {
|
|
1722
|
-
const l = useMemo(() => ({ ...DEFAULT_REFERRAL_REWARD_LABELS, ...labels }), [labels]);
|
|
1723
|
-
return /* @__PURE__ */ jsxs(
|
|
1724
|
-
"span",
|
|
1725
|
-
{
|
|
1726
|
-
className: "flex h-8 items-center gap-1.5 rounded-full bg-green-bg px-2.5 text-sm font-medium text-green-text",
|
|
1727
|
-
title: l.badgeTitle,
|
|
1728
|
-
"data-testid": testIdOr(testId, { testId: "referral-reward-badge" }),
|
|
1729
|
-
children: [
|
|
1730
|
-
/* @__PURE__ */ jsx(Gift, { className: "h-3.5 w-3.5" }),
|
|
1731
|
-
l.badge(amountLabel)
|
|
1732
|
-
]
|
|
1733
|
-
}
|
|
1734
|
-
);
|
|
1735
|
-
}
|
|
1736
|
-
function ReferralRewardSummary({
|
|
1737
|
-
amountLabel,
|
|
1738
|
-
breakdown,
|
|
1739
|
-
labels,
|
|
1740
|
-
testId,
|
|
1741
|
-
testIds
|
|
1742
|
-
}) {
|
|
1743
|
-
const l = useMemo(() => ({ ...DEFAULT_REFERRAL_REWARD_LABELS, ...labels }), [labels]);
|
|
1744
|
-
return /* @__PURE__ */ jsx(
|
|
1745
|
-
"div",
|
|
1746
|
-
{
|
|
1747
|
-
className: "rounded-lg bg-green-bg/60 p-3 text-sm",
|
|
1748
|
-
"data-testid": testIdOr(testId, { testId: "referral-reward-summary" }),
|
|
1749
|
-
children: breakdown ? /* @__PURE__ */ jsxs("dl", { className: "space-y-1 tabular-nums", children: [
|
|
1750
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-muted-foreground", children: [
|
|
1751
|
-
/* @__PURE__ */ jsx("dt", { children: l.subtotal }),
|
|
1752
|
-
/* @__PURE__ */ jsx("dd", { children: breakdown.subtotal })
|
|
1753
|
-
] }),
|
|
1754
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-green-text", children: [
|
|
1755
|
-
/* @__PURE__ */ jsxs("dt", { className: "flex items-center gap-1.5", children: [
|
|
1756
|
-
/* @__PURE__ */ jsx(Gift, { className: "h-3.5 w-3.5" }),
|
|
1757
|
-
l.reward
|
|
1758
|
-
] }),
|
|
1759
|
-
/* @__PURE__ */ jsxs("dd", { "data-testid": testIdOr(testIds?.applied, { testId: "referral-reward-applied" }), children: [
|
|
1760
|
-
"\u2212",
|
|
1761
|
-
breakdown.reward
|
|
1762
|
-
] })
|
|
1763
|
-
] }),
|
|
1764
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-t border-green-border pt-1 font-semibold text-foreground", children: [
|
|
1765
|
-
/* @__PURE__ */ jsx("dt", { children: l.youPayNow }),
|
|
1766
|
-
/* @__PURE__ */ jsx("dd", { "data-testid": testIdOr(testIds?.youPay, { testId: "referral-reward-you-pay" }), children: breakdown.youPay })
|
|
1767
|
-
] }),
|
|
1768
|
-
breakdown.rollover && /* @__PURE__ */ jsx("p", { className: "pt-0.5 text-xs font-normal text-muted-foreground", children: l.rollover(breakdown.rollover) })
|
|
1769
|
-
] }) : /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-1.5 font-medium text-green-text", children: [
|
|
1770
|
-
/* @__PURE__ */ jsx(Gift, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
1771
|
-
l.applied(amountLabel)
|
|
1772
|
-
] })
|
|
1773
|
-
}
|
|
1774
|
-
);
|
|
1775
|
-
}
|
|
1776
|
-
function ReferralRewardNote({
|
|
1777
|
-
amountLabel,
|
|
1778
|
-
labels,
|
|
1779
|
-
testId
|
|
1780
|
-
}) {
|
|
1781
|
-
const l = useMemo(() => ({ ...DEFAULT_REFERRAL_REWARD_LABELS, ...labels }), [labels]);
|
|
1782
|
-
return /* @__PURE__ */ jsxs(
|
|
1783
|
-
"p",
|
|
1784
|
-
{
|
|
1785
|
-
className: "flex items-center gap-1.5 text-sm text-green-text",
|
|
1786
|
-
"data-testid": testIdOr(testId, { testId: "referral-reward-note" }),
|
|
1787
|
-
children: [
|
|
1788
|
-
/* @__PURE__ */ jsx(Gift, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
1789
|
-
l.note(amountLabel)
|
|
1790
|
-
]
|
|
1791
|
-
}
|
|
1792
|
-
);
|
|
1793
|
-
}
|
|
1794
|
-
var DEFAULT_CONNECTION_CARD_LABELS = {
|
|
1795
|
-
connectedAs: (identity) => `Connected as ${identity}`,
|
|
1796
|
-
justConnected: "Just connected \u2713",
|
|
1797
|
-
connected: "Connected",
|
|
1798
|
-
disconnect: "Disconnect",
|
|
1799
|
-
connect: "Connect",
|
|
1800
|
-
organisationAccount: "Organisation account",
|
|
1801
|
-
readOnlyLead: "Read-only.",
|
|
1802
|
-
readOnlyBody: " ARBI only imports a copy of your email and files. It can\u2019t modify or delete anything in your account, and deleting an imported document here never affects the original."
|
|
1803
|
-
};
|
|
1804
|
-
function ConnectionCard({
|
|
1805
|
-
connection,
|
|
1806
|
-
onConnect,
|
|
1807
|
-
onDisconnect,
|
|
1808
|
-
labels
|
|
1809
|
-
}) {
|
|
1810
|
-
const l = useMemo(() => ({ ...DEFAULT_CONNECTION_CARD_LABELS, ...labels }), [labels]);
|
|
1811
|
-
const { id, status } = connection;
|
|
1812
|
-
const isConnected = status === "connected";
|
|
1813
|
-
return /* @__PURE__ */ jsxs(
|
|
1814
|
-
"div",
|
|
1815
|
-
{
|
|
1816
|
-
"data-slot": "connection-card",
|
|
1817
|
-
className: "rounded-lg bg-background px-5 py-4",
|
|
1818
|
-
"data-testid": `connector-card-${id}`,
|
|
1819
|
-
children: [
|
|
1820
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-4", children: [
|
|
1821
|
-
/* @__PURE__ */ jsx("div", { className: "mt-0.5 flex h-10 w-10 shrink-0 items-center justify-center rounded-lg bg-muted text-muted-foreground", children: connection.iconUrl ? /* @__PURE__ */ jsx(
|
|
1822
|
-
"img",
|
|
1823
|
-
{
|
|
1824
|
-
src: connection.iconUrl,
|
|
1825
|
-
alt: connection.iconAlt ?? connection.title,
|
|
1826
|
-
className: "h-6 w-6 rounded object-contain"
|
|
1827
|
-
}
|
|
1828
|
-
) : /* @__PURE__ */ jsx(PlugIcon, { className: "h-5 w-5" }) }),
|
|
1829
|
-
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
1830
|
-
/* @__PURE__ */ jsx("span", { className: "font-heading text-sm font-semibold text-foreground", children: connection.title }),
|
|
1831
|
-
connection.description && /* @__PURE__ */ jsx("p", { className: "mt-0.5 text-sm text-muted-foreground", children: connection.description }),
|
|
1832
|
-
isConnected && connection.identity && /* @__PURE__ */ jsx(
|
|
1833
|
-
"p",
|
|
1834
|
-
{
|
|
1835
|
-
className: "mt-1 text-xs text-muted-foreground",
|
|
1836
|
-
"data-testid": `connector-identity-${id}`,
|
|
1837
|
-
children: l.connectedAs(connection.identity)
|
|
1838
|
-
}
|
|
1839
|
-
),
|
|
1840
|
-
connection.warning && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-yellow-text", children: connection.warning }),
|
|
1841
|
-
connection.note && /* @__PURE__ */ jsx("p", { className: "mt-1 text-xs text-muted-foreground", children: connection.note })
|
|
1842
|
-
] }),
|
|
1843
|
-
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col items-end gap-2", children: [
|
|
1844
|
-
(isConnected || connection.justConnected) && /* @__PURE__ */ jsx(
|
|
1845
|
-
ToneBadge,
|
|
1846
|
-
{
|
|
1847
|
-
tone: "success",
|
|
1848
|
-
icon: /* @__PURE__ */ jsx(CheckCircle2, { className: "h-3 w-3", "aria-hidden": "true" }),
|
|
1849
|
-
children: connection.justConnected ? l.justConnected : l.connected
|
|
1850
|
-
}
|
|
1851
|
-
),
|
|
1852
|
-
isConnected ? /* @__PURE__ */ jsxs(
|
|
1853
|
-
Button,
|
|
1854
|
-
{
|
|
1855
|
-
variant: "outline",
|
|
1856
|
-
size: "sm",
|
|
1857
|
-
onClick: () => onDisconnect(id),
|
|
1858
|
-
disabled: connection.isDisconnecting,
|
|
1859
|
-
className: "text-destructive hover:bg-destructive/10 hover:text-destructive",
|
|
1860
|
-
"data-testid": `connector-disconnect-${id}`,
|
|
1861
|
-
children: [
|
|
1862
|
-
connection.isDisconnecting && /* @__PURE__ */ jsx(Loader2, { className: "mr-1.5 h-3.5 w-3.5 animate-spin" }),
|
|
1863
|
-
l.disconnect
|
|
1864
|
-
]
|
|
1865
|
-
}
|
|
1866
|
-
) : status === "available" ? /* @__PURE__ */ jsxs(
|
|
1867
|
-
Button,
|
|
1868
|
-
{
|
|
1869
|
-
variant: "outline",
|
|
1870
|
-
size: "sm",
|
|
1871
|
-
onClick: () => onConnect(id),
|
|
1872
|
-
className: "gap-1.5",
|
|
1873
|
-
"data-testid": `connector-connect-${id}`,
|
|
1874
|
-
children: [
|
|
1875
|
-
/* @__PURE__ */ jsx(ExternalLink, { className: "h-3.5 w-3.5" }),
|
|
1876
|
-
l.connect
|
|
1877
|
-
]
|
|
1878
|
-
}
|
|
1879
|
-
) : /* @__PURE__ */ jsx(Badge, { variant: "outline", className: "text-muted-foreground", children: l.organisationAccount })
|
|
1880
|
-
] })
|
|
1881
|
-
] }),
|
|
1882
|
-
connection.showReadOnlyNotice && isConnected && /* @__PURE__ */ jsxs("div", { className: "mt-2 flex items-start gap-2 rounded-md bg-blue-bg px-3 py-2 text-xs text-blue-text", children: [
|
|
1883
|
-
/* @__PURE__ */ jsx(ShieldCheck, { className: "mt-0.5 h-4 w-4 shrink-0" }),
|
|
1884
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
1885
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium", children: l.readOnlyLead }),
|
|
1886
|
-
l.readOnlyBody
|
|
1887
|
-
] })
|
|
1888
|
-
] })
|
|
1889
|
-
]
|
|
1890
|
-
}
|
|
1891
|
-
);
|
|
1892
|
-
}
|
|
1893
|
-
function ConnectionsEmpty({ message }) {
|
|
1894
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center gap-2 py-8 text-center", children: [
|
|
1895
|
-
/* @__PURE__ */ jsx(Plug, { className: "h-8 w-8 text-muted-foreground/40" }),
|
|
1896
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: message })
|
|
1897
|
-
] });
|
|
1898
|
-
}
|
|
1899
|
-
function ConnectionsLoading({ message }) {
|
|
1900
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 py-12 text-muted-foreground", children: [
|
|
1901
|
-
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
1902
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm", children: message })
|
|
1903
|
-
] });
|
|
1904
|
-
}
|
|
1905
|
-
function ConnectionsError({ message }) {
|
|
1906
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg bg-destructive/10 px-4 py-3 text-sm text-destructive", children: [
|
|
1907
|
-
/* @__PURE__ */ jsx(AlertCircle, { className: "h-4 w-4 shrink-0" }),
|
|
1908
|
-
/* @__PURE__ */ jsx("span", { children: message })
|
|
1909
|
-
] });
|
|
1910
|
-
}
|
|
1911
|
-
var DEFAULT_PROJECT_LIST_LABELS = {
|
|
1912
|
-
loading: "Loading projects...",
|
|
1913
|
-
empty: "No projects yet. Create one to get started.",
|
|
1914
|
-
filteredOut: "No projects match the filter."
|
|
1915
|
-
};
|
|
1916
|
-
var DEFAULT_SHARED_PROJECTS_SECTION_LABELS = {
|
|
1917
|
-
title: "Shared with you"
|
|
1918
|
-
};
|
|
1919
|
-
var DEFAULT_PROJECT_DETAIL_HEADER_LABELS = {
|
|
1920
|
-
renameProject: "Rename project"
|
|
1921
|
-
};
|
|
1922
|
-
var DEFAULT_RENAME_DIALOG_LABELS = {
|
|
1923
|
-
title: "Rename project",
|
|
1924
|
-
description: "Enter a new name.",
|
|
1925
|
-
cancel: "Cancel",
|
|
1926
|
-
save: "Save"
|
|
1927
|
-
};
|
|
1928
|
-
function ProjectRow({ testId, onOpen, identity, summary, usage, actions }) {
|
|
1929
|
-
const handleKeyDown = (e) => {
|
|
1930
|
-
if (e.key === "Enter" || e.key === " ") {
|
|
1931
|
-
e.preventDefault();
|
|
1932
|
-
onOpen();
|
|
1933
|
-
}
|
|
1934
|
-
};
|
|
1935
|
-
return /* @__PURE__ */ jsxs(
|
|
1936
|
-
"div",
|
|
1937
|
-
{
|
|
1938
|
-
role: "button",
|
|
1939
|
-
tabIndex: 0,
|
|
1940
|
-
onClick: onOpen,
|
|
1941
|
-
onKeyDown: handleKeyDown,
|
|
1942
|
-
"data-slot": "project-row",
|
|
1943
|
-
"data-testid": testId,
|
|
1944
|
-
className: "group flex cursor-pointer flex-wrap items-center gap-x-3 gap-y-3 px-3 py-3 transition-colors hover:bg-muted/50 focus:bg-muted/50 focus:outline-none pointer-coarse:min-h-11",
|
|
1945
|
-
children: [
|
|
1946
|
-
/* @__PURE__ */ jsx("div", { className: "flex min-w-0 items-center", children: identity }),
|
|
1947
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
1948
|
-
summary && /* @__PURE__ */ jsx("div", { className: "hidden items-center gap-3 md:flex", children: summary }),
|
|
1949
|
-
actions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-0.5", onClick: (e) => e.stopPropagation(), children: actions }),
|
|
1950
|
-
usage && /* @__PURE__ */ jsx("div", { className: "basis-full", children: usage })
|
|
1951
|
-
]
|
|
1952
|
-
}
|
|
1953
|
-
);
|
|
1954
|
-
}
|
|
1955
|
-
function ProjectList({
|
|
1956
|
-
isLoading,
|
|
1957
|
-
isEmpty,
|
|
1958
|
-
isFilteredOut,
|
|
1959
|
-
children,
|
|
1960
|
-
testId = "projects-list",
|
|
1961
|
-
labels
|
|
1962
|
-
}) {
|
|
1963
|
-
const l = useMemo(() => ({ ...DEFAULT_PROJECT_LIST_LABELS, ...labels }), [labels]);
|
|
1964
|
-
const message = isLoading ? l.loading : isEmpty ? l.empty : isFilteredOut ? l.filteredOut : null;
|
|
1965
|
-
return /* @__PURE__ */ jsx("div", { "data-testid": testId, children: isLoading ? /* @__PURE__ */ jsxs("div", { className: "space-y-3 px-3 py-4", "aria-busy": "true", children: [
|
|
1966
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children: message }),
|
|
1967
|
-
[0, 1].map((i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", "aria-hidden": "true", children: [
|
|
1968
|
-
/* @__PURE__ */ jsx("div", { className: "h-5 w-40 animate-pulse rounded-md bg-muted" }),
|
|
1969
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
1970
|
-
/* @__PURE__ */ jsx("div", { className: "h-5 w-48 animate-pulse rounded-md bg-muted" })
|
|
1971
|
-
] }, i))
|
|
1972
|
-
] }) : message ? /* @__PURE__ */ jsx("p", { className: "px-3 py-6 text-sm text-muted-foreground", children: message }) : /* @__PURE__ */ jsx("div", { className: "divide-y divide-border", children }) });
|
|
1973
|
-
}
|
|
1974
|
-
function SharedProjectsSection({
|
|
1975
|
-
title,
|
|
1976
|
-
footnote,
|
|
1977
|
-
children,
|
|
1978
|
-
testId = "shared-projects",
|
|
1979
|
-
labels
|
|
1980
|
-
}) {
|
|
1981
|
-
const l = useMemo(() => ({ ...DEFAULT_SHARED_PROJECTS_SECTION_LABELS, ...labels }), [labels]);
|
|
1982
|
-
return /* @__PURE__ */ jsxs("section", { className: "space-y-2", "data-testid": testId, children: [
|
|
1983
|
-
/* @__PURE__ */ jsx("h3", { className: "px-1 text-sm font-semibold text-foreground", children: title ?? l.title }),
|
|
1984
|
-
/* @__PURE__ */ jsx("div", { className: "divide-y divide-border", children }),
|
|
1985
|
-
footnote && /* @__PURE__ */ jsx("p", { className: "px-1 text-xs text-muted-foreground", children: footnote })
|
|
1986
|
-
] });
|
|
1987
|
-
}
|
|
1988
|
-
function SharedProjectRow({
|
|
1989
|
-
testId,
|
|
1990
|
-
identity,
|
|
1991
|
-
allowance
|
|
1992
|
-
}) {
|
|
1993
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-4 px-3 py-2.5", "data-testid": testId, children: [
|
|
1994
|
-
identity,
|
|
1995
|
-
/* @__PURE__ */ jsx("div", { className: "ml-auto w-44", children: allowance })
|
|
1996
|
-
] });
|
|
1997
|
-
}
|
|
1998
|
-
function ProjectDetailHeader({
|
|
1999
|
-
icon,
|
|
2000
|
-
name,
|
|
2001
|
-
badge,
|
|
2002
|
-
onRename,
|
|
2003
|
-
action,
|
|
2004
|
-
labels
|
|
2005
|
-
}) {
|
|
2006
|
-
const l = useMemo(() => ({ ...DEFAULT_PROJECT_DETAIL_HEADER_LABELS, ...labels }), [labels]);
|
|
2007
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-3", children: [
|
|
2008
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-3", children: [
|
|
2009
|
-
/* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-primary [&>svg]:h-8 [&>svg]:w-8", children: icon }),
|
|
2010
|
-
/* @__PURE__ */ jsx("div", { className: "min-w-0", children: /* @__PURE__ */ jsxs("div", { className: "group flex items-center gap-2", children: [
|
|
2011
|
-
/* @__PURE__ */ jsx("h2", { className: "truncate text-xl font-semibold text-foreground", title: name, children: name }),
|
|
2012
|
-
/* @__PURE__ */ jsx(
|
|
2013
|
-
Button,
|
|
2014
|
-
{
|
|
2015
|
-
variant: "ghost",
|
|
2016
|
-
size: "icon",
|
|
2017
|
-
className: "h-6 w-6 shrink-0 text-muted-foreground opacity-0 transition-opacity hover:text-primary focus-visible:opacity-100 [.group:hover_&]:opacity-100 [@media(hover:none)]:opacity-100",
|
|
2018
|
-
title: l.renameProject,
|
|
2019
|
-
"aria-label": l.renameProject,
|
|
2020
|
-
"data-testid": "project-detail-rename",
|
|
2021
|
-
onClick: onRename,
|
|
2022
|
-
children: /* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" })
|
|
2023
|
-
}
|
|
2024
|
-
),
|
|
2025
|
-
badge
|
|
2026
|
-
] }) })
|
|
2027
|
-
] }),
|
|
2028
|
-
action && /* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: action })
|
|
2029
|
-
] });
|
|
2030
|
-
}
|
|
2031
|
-
function ProjectDetailSection({
|
|
2032
|
-
title,
|
|
2033
|
-
className,
|
|
2034
|
-
children
|
|
2035
|
-
}) {
|
|
2036
|
-
return /* @__PURE__ */ jsxs("section", { className: cn("rounded-lg border border-border bg-card shadow-xs p-5", className), children: [
|
|
2037
|
-
/* @__PURE__ */ jsx("h3", { className: "mb-4 text-base font-semibold text-foreground", children: title }),
|
|
2038
|
-
children
|
|
2039
|
-
] });
|
|
2040
|
-
}
|
|
2041
|
-
function RenameDialog({
|
|
2042
|
-
open,
|
|
2043
|
-
onClose,
|
|
2044
|
-
title,
|
|
2045
|
-
value,
|
|
2046
|
-
onChange,
|
|
2047
|
-
onSave,
|
|
2048
|
-
isSaving,
|
|
2049
|
-
testId,
|
|
2050
|
-
dialogTestId,
|
|
2051
|
-
fieldLabel,
|
|
2052
|
-
placeholder,
|
|
2053
|
-
canSave = true,
|
|
2054
|
-
labels
|
|
2055
|
-
}) {
|
|
2056
|
-
const renameInputId = useId();
|
|
2057
|
-
const l = useMemo(() => ({ ...DEFAULT_RENAME_DIALOG_LABELS, ...labels }), [labels]);
|
|
2058
|
-
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (next) => !next && onClose(), children: /* @__PURE__ */ jsxs(DialogContent, { presentation: "sheet", "data-testid": dialogTestId, children: [
|
|
2059
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
2060
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: title ?? l.title }),
|
|
2061
|
-
/* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: l.description })
|
|
2062
|
-
] }),
|
|
2063
|
-
fieldLabel && /* @__PURE__ */ jsx("label", { htmlFor: renameInputId, className: "block text-sm font-medium", children: fieldLabel }),
|
|
2064
|
-
/* @__PURE__ */ jsx(
|
|
2065
|
-
Input,
|
|
2066
|
-
{
|
|
2067
|
-
id: renameInputId,
|
|
2068
|
-
value,
|
|
2069
|
-
onChange: (e) => onChange(e.target.value),
|
|
2070
|
-
placeholder,
|
|
2071
|
-
autoFocus: true,
|
|
2072
|
-
onKeyDown: (e) => {
|
|
2073
|
-
if (e.key === "Enter") onSave();
|
|
2074
|
-
if (e.key === "Escape") onClose();
|
|
2075
|
-
},
|
|
2076
|
-
"data-testid": testId
|
|
2077
|
-
}
|
|
2078
|
-
),
|
|
2079
|
-
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
2080
|
-
/* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onClose, children: l.cancel }),
|
|
2081
|
-
/* @__PURE__ */ jsx(Button, { onClick: onSave, disabled: isSaving || !canSave, children: l.save })
|
|
2082
|
-
] })
|
|
2083
|
-
] }) });
|
|
2084
|
-
}
|
|
2085
|
-
var DEFAULT_SUPPORT_PANEL_LABELS = {
|
|
2086
|
-
support: "Support",
|
|
2087
|
-
userGuide: "User Guide"
|
|
2088
|
-
};
|
|
2089
|
-
function SupportPanel({
|
|
2090
|
-
activeTab,
|
|
2091
|
-
onTabChange,
|
|
2092
|
-
buildInfo = [],
|
|
2093
|
-
modeSwitcher,
|
|
2094
|
-
feedback,
|
|
2095
|
-
isFeedbackLoading,
|
|
2096
|
-
loadingIndicator,
|
|
2097
|
-
guide,
|
|
2098
|
-
testId = "feedback-modal",
|
|
2099
|
-
labels
|
|
2100
|
-
}) {
|
|
2101
|
-
const l = useMemo(() => ({ ...DEFAULT_SUPPORT_PANEL_LABELS, ...labels }), [labels]);
|
|
2102
|
-
const tabs = useMemo(
|
|
2103
|
-
() => [
|
|
2104
|
-
{
|
|
2105
|
-
id: "feedback",
|
|
2106
|
-
label: l.support,
|
|
2107
|
-
icon: /* @__PURE__ */ jsx(MessageCircleQuestionMark, { className: "h-4 w-4" }),
|
|
2108
|
-
tooltip: l.support
|
|
2109
|
-
},
|
|
2110
|
-
{
|
|
2111
|
-
id: "guide",
|
|
2112
|
-
label: l.userGuide,
|
|
2113
|
-
icon: /* @__PURE__ */ jsx(BookOpen, { className: "h-4 w-4" }),
|
|
2114
|
-
tooltip: l.userGuide
|
|
2115
|
-
}
|
|
2116
|
-
],
|
|
2117
|
-
[l]
|
|
2118
|
-
);
|
|
2119
|
-
return /* @__PURE__ */ jsxs(
|
|
2120
|
-
"div",
|
|
2121
|
-
{
|
|
2122
|
-
className: "@container flex h-full flex-col bg-background",
|
|
2123
|
-
"data-testid": testId,
|
|
2124
|
-
"data-slot": "support-panel",
|
|
2125
|
-
children: [
|
|
2126
|
-
/* @__PURE__ */ jsx("div", { className: "flex-shrink-0", children: /* @__PURE__ */ jsx(
|
|
2127
|
-
TabHeader,
|
|
2128
|
-
{
|
|
2129
|
-
tabs,
|
|
2130
|
-
activeTabId: activeTab,
|
|
2131
|
-
onTabChange: (id) => onTabChange(id),
|
|
2132
|
-
rightContent: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2133
|
-
buildInfo.length > 0 && /* @__PURE__ */ jsx("div", { className: "hidden text-right font-mono text-xs leading-tight text-muted-foreground/70 @2xl:block", children: buildInfo.map((line) => /* @__PURE__ */ jsx("div", { children: line }, line)) }),
|
|
2134
|
-
modeSwitcher
|
|
2135
|
-
] }),
|
|
2136
|
-
compactBreakpoint: 360
|
|
2137
|
-
}
|
|
2138
|
-
) }),
|
|
2139
|
-
activeTab === "feedback" && /* @__PURE__ */ jsxs("div", { className: "relative min-h-0 flex-1", children: [
|
|
2140
|
-
isFeedbackLoading && /* @__PURE__ */ jsx("div", { className: "absolute inset-0 z-10 flex items-center justify-center bg-background", children: loadingIndicator }),
|
|
2141
|
-
feedback
|
|
2142
|
-
] }),
|
|
2143
|
-
activeTab === "guide" && /* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto p-4", children: guide })
|
|
2144
|
-
]
|
|
2145
|
-
}
|
|
2146
|
-
);
|
|
2147
|
-
}
|
|
2148
|
-
function SupportUnavailable({ title, message }) {
|
|
2149
|
-
return /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center p-8 text-center", children: /* @__PURE__ */ jsxs("div", { children: [
|
|
2150
|
-
/* @__PURE__ */ jsx("h3", { className: "mb-2 text-lg font-semibold", children: title }),
|
|
2151
|
-
/* @__PURE__ */ jsx("p", { className: "text-muted-foreground", children: message })
|
|
2152
|
-
] }) });
|
|
2153
|
-
}
|
|
2154
|
-
var DEFAULT_WELCOME_DIALOG_LABELS = {
|
|
2155
|
-
welcome: (firstName) => `Welcome${firstName ? `, ${firstName}` : ""}!`,
|
|
2156
|
-
description: "Your plan, usage and rewards at a glance.",
|
|
2157
|
-
currentPlan: "Current plan",
|
|
2158
|
-
seeUpgradeOptions: "See upgrade options",
|
|
2159
|
-
referralBefore: "Get ",
|
|
2160
|
-
referralAfter: " for every invited contact who goes Pro.",
|
|
2161
|
-
inviteContact: "Invite contact",
|
|
2162
|
-
currentRewards: "Current rewards: ",
|
|
2163
|
-
continue: "Continue"
|
|
2164
|
-
};
|
|
2165
|
-
var DEFAULT_INVITE_CONTACTS_DIALOG_LABELS = {
|
|
2166
|
-
title: "Invite contacts",
|
|
2167
|
-
description: "Invite contacts by email and earn the referral reward."
|
|
2168
|
-
};
|
|
2169
|
-
function WelcomeDialog({
|
|
2170
|
-
open,
|
|
2171
|
-
onClose,
|
|
2172
|
-
firstName,
|
|
2173
|
-
hasReward,
|
|
2174
|
-
projectPicker,
|
|
2175
|
-
planBadge,
|
|
2176
|
-
quotas,
|
|
2177
|
-
onSeePlans,
|
|
2178
|
-
referralOfferLabel,
|
|
2179
|
-
onInvite,
|
|
2180
|
-
rewardBalanceLabel,
|
|
2181
|
-
labels,
|
|
2182
|
-
testId,
|
|
2183
|
-
testIds
|
|
2184
|
-
}) {
|
|
2185
|
-
const l = useMemo(() => ({ ...DEFAULT_WELCOME_DIALOG_LABELS, ...labels }), [labels]);
|
|
2186
|
-
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (next) => !next && onClose(), children: /* @__PURE__ */ jsxs(
|
|
2187
|
-
DialogContent,
|
|
2188
|
-
{
|
|
2189
|
-
className: "sm:max-w-md",
|
|
2190
|
-
"data-testid": testIdOr(testId, { testId: "welcome-modal" }),
|
|
2191
|
-
hideCloseButton: true,
|
|
2192
|
-
children: [
|
|
2193
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
2194
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-wrap items-start justify-between gap-2", children: [
|
|
2195
|
-
/* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
|
|
2196
|
-
hasReward ? /* @__PURE__ */ jsx(Gift, { className: "h-5 w-5 text-green-text" }) : /* @__PURE__ */ jsx(Sparkles, { className: "h-5 w-5 text-yellow-text" }),
|
|
2197
|
-
l.welcome(firstName)
|
|
2198
|
-
] }),
|
|
2199
|
-
projectPicker
|
|
2200
|
-
] }),
|
|
2201
|
-
/* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: l.description })
|
|
2202
|
-
] }),
|
|
2203
|
-
/* @__PURE__ */ jsxs(
|
|
2204
|
-
ModalSection,
|
|
2205
|
-
{
|
|
2206
|
-
className: "space-y-4",
|
|
2207
|
-
"data-testid": testIdOr(testIds?.copy, { testId: "welcome-modal-copy" }),
|
|
2208
|
-
children: [
|
|
2209
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between", children: [
|
|
2210
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: l.currentPlan }),
|
|
2211
|
-
planBadge
|
|
2212
|
-
] }),
|
|
2213
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-3", children: quotas.map((quota) => /* @__PURE__ */ jsx(
|
|
2214
|
-
UsageMeter,
|
|
2215
|
-
{
|
|
2216
|
-
icon: quota.icon,
|
|
2217
|
-
label: quota.label,
|
|
2218
|
-
value: quota.value,
|
|
2219
|
-
pct: quota.pct,
|
|
2220
|
-
hint: quota.hint,
|
|
2221
|
-
testId: prefixedTestId(testIds?.quota, quota.key, {
|
|
2222
|
-
testId: `welcome-modal-quota-${quota.key}`
|
|
2223
|
-
})
|
|
2224
|
-
},
|
|
2225
|
-
quota.key
|
|
2226
|
-
)) }),
|
|
2227
|
-
/* @__PURE__ */ jsx(
|
|
2228
|
-
Button,
|
|
2229
|
-
{
|
|
2230
|
-
variant: "outline",
|
|
2231
|
-
className: "w-full",
|
|
2232
|
-
onClick: onSeePlans,
|
|
2233
|
-
"data-testid": testIdOr(testIds?.showPlans, { testId: "welcome-modal-show-plans" }),
|
|
2234
|
-
children: l.seeUpgradeOptions
|
|
2235
|
-
}
|
|
2236
|
-
)
|
|
2237
|
-
]
|
|
2238
|
-
}
|
|
2239
|
-
),
|
|
2240
|
-
/* @__PURE__ */ jsxs(ModalSection, { className: "space-y-2.5", children: [
|
|
2241
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
2242
|
-
/* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
2243
|
-
l.referralBefore,
|
|
2244
|
-
/* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: referralOfferLabel }),
|
|
2245
|
-
l.referralAfter
|
|
2246
|
-
] }),
|
|
2247
|
-
/* @__PURE__ */ jsxs(
|
|
2248
|
-
Button,
|
|
2249
|
-
{
|
|
2250
|
-
variant: "outline",
|
|
2251
|
-
size: "sm",
|
|
2252
|
-
className: "shrink-0 gap-1.5",
|
|
2253
|
-
onClick: onInvite,
|
|
2254
|
-
"data-testid": testIdOr(testIds?.earn, { testId: "welcome-modal-earn" }),
|
|
2255
|
-
children: [
|
|
2256
|
-
/* @__PURE__ */ jsx(UserPlus, { className: "h-3.5 w-3.5" }),
|
|
2257
|
-
l.inviteContact
|
|
2258
|
-
]
|
|
2259
|
-
}
|
|
2260
|
-
)
|
|
2261
|
-
] }),
|
|
2262
|
-
rewardBalanceLabel && // A statement, not a door: the balance applies itself to the next invoice.
|
|
2263
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 rounded-md bg-green-bg px-3 py-2 text-sm text-green-text", children: [
|
|
2264
|
-
/* @__PURE__ */ jsx(Gift, { className: "h-4 w-4 shrink-0" }),
|
|
2265
|
-
/* @__PURE__ */ jsxs("span", { className: "truncate", children: [
|
|
2266
|
-
l.currentRewards,
|
|
2267
|
-
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: rewardBalanceLabel })
|
|
2268
|
-
] })
|
|
2269
|
-
] })
|
|
2270
|
-
] }),
|
|
2271
|
-
/* @__PURE__ */ jsx(DialogFooter, { children: /* @__PURE__ */ jsx(
|
|
2272
|
-
Button,
|
|
2273
|
-
{
|
|
2274
|
-
className: "w-full",
|
|
2275
|
-
onClick: onClose,
|
|
2276
|
-
"data-testid": testIdOr(testIds?.dismiss, { testId: "welcome-modal-dismiss" }),
|
|
2277
|
-
children: l.continue
|
|
2278
|
-
}
|
|
2279
|
-
) })
|
|
2280
|
-
]
|
|
2281
|
-
}
|
|
2282
|
-
) });
|
|
2283
|
-
}
|
|
2284
|
-
function InviteContactsDialog({
|
|
2285
|
-
open,
|
|
2286
|
-
onClose,
|
|
2287
|
-
children,
|
|
2288
|
-
testId = "welcome-modal-invite",
|
|
2289
|
-
labels
|
|
2290
|
-
}) {
|
|
2291
|
-
const l = useMemo(() => ({ ...DEFAULT_INVITE_CONTACTS_DIALOG_LABELS, ...labels }), [labels]);
|
|
2292
|
-
return /* @__PURE__ */ jsx(
|
|
2293
|
-
ModalScaffold,
|
|
2294
|
-
{
|
|
2295
|
-
open,
|
|
2296
|
-
onOpenChange: (next) => !next && onClose(),
|
|
2297
|
-
title: l.title,
|
|
2298
|
-
description: l.description,
|
|
2299
|
-
icon: /* @__PURE__ */ jsx(UserPlus, { className: "h-5 w-5 text-primary" }),
|
|
2300
|
-
size: "lg",
|
|
2301
|
-
className: "sm:max-w-lg",
|
|
2302
|
-
testId,
|
|
2303
|
-
children: /* @__PURE__ */ jsx(ModalSection, { children })
|
|
2304
|
-
}
|
|
2305
|
-
);
|
|
2306
|
-
}
|
|
2307
|
-
var SERIES_STYLES = [
|
|
2308
|
-
{ bg: "bg-blue-500", stroke: "stroke-blue-500" },
|
|
2309
|
-
{ bg: "bg-purple-500", stroke: "stroke-purple-500" },
|
|
2310
|
-
{ bg: "bg-emerald-500", stroke: "stroke-emerald-500" },
|
|
2311
|
-
{ bg: "bg-amber-500", stroke: "stroke-amber-500" },
|
|
2312
|
-
{ bg: "bg-rose-500", stroke: "stroke-rose-500" },
|
|
2313
|
-
{ bg: "bg-cyan-500", stroke: "stroke-cyan-500" },
|
|
2314
|
-
{ bg: "bg-indigo-500", stroke: "stroke-indigo-500" },
|
|
2315
|
-
{ bg: "bg-orange-500", stroke: "stroke-orange-500" }
|
|
2316
|
-
];
|
|
2317
|
-
var styleAt = (index) => SERIES_STYLES[index % SERIES_STYLES.length];
|
|
2318
|
-
var DEFAULT_USAGE_LINE_CHART_LABELS = {
|
|
2319
|
-
noDailyData: "No daily data"
|
|
2320
|
-
};
|
|
2321
|
-
var DEFAULT_USAGE_PROPORTION_BAR_LABELS = {
|
|
2322
|
-
tokens: (formatted) => `${formatted} tokens`,
|
|
2323
|
-
gbp: (formatted) => formatted,
|
|
2324
|
-
tokensShort: (formatted) => `${formatted} tok`
|
|
2325
|
-
};
|
|
2326
|
-
var DEFAULT_USAGE_PANEL_LABELS = {
|
|
2327
|
-
empty: "No usage yet.",
|
|
2328
|
-
error: "Failed to load usage data"
|
|
2329
|
-
};
|
|
2330
|
-
var CHART_W = 440;
|
|
2331
|
-
var CHART_H = 120;
|
|
2332
|
-
var PAD = { top: 8, right: 8, bottom: 20, left: 40 };
|
|
2333
|
-
function UsageLineChart({
|
|
2334
|
-
dates,
|
|
2335
|
-
series,
|
|
2336
|
-
formatDate,
|
|
2337
|
-
formatValue: formatValue2,
|
|
2338
|
-
emptyLabel,
|
|
2339
|
-
labels
|
|
2340
|
-
}) {
|
|
2341
|
-
const l = useMemo(() => ({ ...DEFAULT_USAGE_LINE_CHART_LABELS, ...labels }), [labels]);
|
|
2342
|
-
const [hoverIdx, setHoverIdx] = useState(null);
|
|
2343
|
-
if (!dates.length || !series.length) {
|
|
2344
|
-
return /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: emptyLabel ?? l.noDailyData });
|
|
2345
|
-
}
|
|
2346
|
-
const maxVal = Math.max(...series.flatMap((s) => s.values), 1);
|
|
2347
|
-
const plotW = CHART_W - PAD.left - PAD.right;
|
|
2348
|
-
const plotH = CHART_H - PAD.top - PAD.bottom;
|
|
2349
|
-
const xStep = dates.length > 1 ? plotW / (dates.length - 1) : plotW;
|
|
2350
|
-
const yScale = (v) => PAD.top + plotH - v / maxVal * plotH;
|
|
2351
|
-
const yTicks = [0, maxVal / 2, maxVal].map((v) => ({
|
|
2352
|
-
v,
|
|
2353
|
-
y: yScale(v),
|
|
2354
|
-
label: v >= 1e3 ? `${Math.round(v / 1e3)}k` : String(Math.round(v * 100) / 100)
|
|
2355
|
-
}));
|
|
2356
|
-
const labelCount = Math.min(dates.length, 5);
|
|
2357
|
-
const labelStep = Math.max(1, Math.floor((dates.length - 1) / (labelCount - 1)));
|
|
2358
|
-
return /* @__PURE__ */ jsxs("div", { className: "relative", "data-slot": "usage-line-chart", children: [
|
|
2359
|
-
/* @__PURE__ */ jsxs(
|
|
2360
|
-
"svg",
|
|
2361
|
-
{
|
|
2362
|
-
viewBox: `0 0 ${CHART_W} ${CHART_H}`,
|
|
2363
|
-
className: "h-auto w-full",
|
|
2364
|
-
preserveAspectRatio: "xMidYMid meet",
|
|
2365
|
-
onMouseLeave: () => setHoverIdx(null),
|
|
2366
|
-
children: [
|
|
2367
|
-
yTicks.map((t) => /* @__PURE__ */ jsxs("g", { children: [
|
|
2368
|
-
/* @__PURE__ */ jsx(
|
|
2369
|
-
"line",
|
|
2370
|
-
{
|
|
2371
|
-
x1: PAD.left,
|
|
2372
|
-
x2: CHART_W - PAD.right,
|
|
2373
|
-
y1: t.y,
|
|
2374
|
-
y2: t.y,
|
|
2375
|
-
className: "stroke-border",
|
|
2376
|
-
strokeDasharray: "2,2"
|
|
2377
|
-
}
|
|
2378
|
-
),
|
|
2379
|
-
/* @__PURE__ */ jsx(
|
|
2380
|
-
"text",
|
|
2381
|
-
{
|
|
2382
|
-
x: PAD.left - 4,
|
|
2383
|
-
y: t.y + 3,
|
|
2384
|
-
textAnchor: "end",
|
|
2385
|
-
className: "fill-muted-foreground text-xs",
|
|
2386
|
-
children: t.label
|
|
2387
|
-
}
|
|
2388
|
-
)
|
|
2389
|
-
] }, t.v)),
|
|
2390
|
-
series.map((s, si) => /* @__PURE__ */ jsx(
|
|
2391
|
-
"polyline",
|
|
2392
|
-
{
|
|
2393
|
-
points: s.values.map((v, i) => `${PAD.left + i * xStep},${yScale(v)}`).join(" "),
|
|
2394
|
-
fill: "none",
|
|
2395
|
-
className: styleAt(si).stroke,
|
|
2396
|
-
strokeWidth: 1.5,
|
|
2397
|
-
strokeLinejoin: "round"
|
|
2398
|
-
},
|
|
2399
|
-
s.key
|
|
2400
|
-
)),
|
|
2401
|
-
dates.map((date, i) => /* @__PURE__ */ jsx(
|
|
2402
|
-
"rect",
|
|
2403
|
-
{
|
|
2404
|
-
x: PAD.left + i * xStep - xStep / 2,
|
|
2405
|
-
y: PAD.top,
|
|
2406
|
-
width: xStep,
|
|
2407
|
-
height: plotH,
|
|
2408
|
-
fill: "transparent",
|
|
2409
|
-
onMouseEnter: () => setHoverIdx(i),
|
|
2410
|
-
onClick: () => setHoverIdx(i)
|
|
2411
|
-
},
|
|
2412
|
-
date
|
|
2413
|
-
)),
|
|
2414
|
-
hoverIdx !== null && /* @__PURE__ */ jsx(
|
|
2415
|
-
"line",
|
|
2416
|
-
{
|
|
2417
|
-
x1: PAD.left + hoverIdx * xStep,
|
|
2418
|
-
x2: PAD.left + hoverIdx * xStep,
|
|
2419
|
-
y1: PAD.top,
|
|
2420
|
-
y2: PAD.top + plotH,
|
|
2421
|
-
className: "stroke-muted-foreground",
|
|
2422
|
-
strokeDasharray: "3,3"
|
|
2423
|
-
}
|
|
2424
|
-
),
|
|
2425
|
-
dates.map((d, i) => {
|
|
2426
|
-
const isLast = i === dates.length - 1;
|
|
2427
|
-
if (!isLast && (i % labelStep !== 0 || dates.length - 1 - i < labelStep / 2)) return null;
|
|
2428
|
-
return /* @__PURE__ */ jsx(
|
|
2429
|
-
"text",
|
|
2430
|
-
{
|
|
2431
|
-
x: PAD.left + i * xStep,
|
|
2432
|
-
y: CHART_H - 2,
|
|
2433
|
-
textAnchor: i === 0 ? "start" : isLast ? "end" : "middle",
|
|
2434
|
-
className: "fill-muted-foreground text-xs",
|
|
2435
|
-
children: formatDate(d)
|
|
2436
|
-
},
|
|
2437
|
-
d
|
|
2438
|
-
);
|
|
2439
|
-
})
|
|
2440
|
-
]
|
|
2441
|
-
}
|
|
2442
|
-
),
|
|
2443
|
-
hoverIdx !== null && /* @__PURE__ */ jsxs("div", { className: "pointer-events-none absolute right-0 top-0 rounded-md border bg-card/90 px-2 py-1 text-sm shadow-lg", children: [
|
|
2444
|
-
/* @__PURE__ */ jsx("div", { className: "font-medium", children: dates[hoverIdx] }),
|
|
2445
|
-
series.map((s, si) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1", children: [
|
|
2446
|
-
/* @__PURE__ */ jsx("span", { className: cn("inline-block h-2 w-2 rounded-full", styleAt(si).bg) }),
|
|
2447
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
2448
|
-
s.key,
|
|
2449
|
-
":"
|
|
2450
|
-
] }),
|
|
2451
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium tabular-nums", children: formatValue2(s.values[hoverIdx]) })
|
|
2452
|
-
] }, s.key))
|
|
2453
|
-
] })
|
|
2454
|
-
] });
|
|
2455
|
-
}
|
|
2456
|
-
function UsageLegend({ series }) {
|
|
2457
|
-
if (series.length <= 1 && series[0]?.key === "Total") return null;
|
|
2458
|
-
return /* @__PURE__ */ jsx("div", { className: "flex flex-wrap gap-x-3 gap-y-1", children: series.map((s, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 text-sm", children: [
|
|
2459
|
-
/* @__PURE__ */ jsx("span", { className: cn("inline-block h-2.5 w-2.5 rounded-full", styleAt(i).bg) }),
|
|
2460
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: s.key })
|
|
2461
|
-
] }, s.key)) });
|
|
2462
|
-
}
|
|
2463
|
-
function UsageProportionBar({
|
|
2464
|
-
items,
|
|
2465
|
-
metric,
|
|
2466
|
-
labels
|
|
2467
|
-
}) {
|
|
2468
|
-
const l = useMemo(() => ({ ...DEFAULT_USAGE_PROPORTION_BAR_LABELS, ...labels }), [labels]);
|
|
2469
|
-
const total = items.reduce((sum, item) => sum + item.amount, 0);
|
|
2470
|
-
if (!items.length || total === 0) return null;
|
|
2471
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
2472
|
-
/* @__PURE__ */ jsx("div", { className: "flex h-3 w-full overflow-hidden rounded-full bg-muted", children: items.map((item, i) => {
|
|
2473
|
-
const pct = item.amount / total * 100;
|
|
2474
|
-
if (pct < 0.5) return null;
|
|
2475
|
-
return /* @__PURE__ */ jsx(
|
|
2476
|
-
"div",
|
|
2477
|
-
{
|
|
2478
|
-
className: cn("h-full first:rounded-l-full last:rounded-r-full", styleAt(i).bg),
|
|
2479
|
-
style: { width: `${pct}%` },
|
|
2480
|
-
title: `${item.label}: ${metric === "tokens" ? l.tokens(item.tokens) : l.gbp(item.gbp)}`
|
|
2481
|
-
},
|
|
2482
|
-
item.label
|
|
2483
|
-
);
|
|
2484
|
-
}) }),
|
|
2485
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-1.5", children: items.map((item, i) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm", children: [
|
|
2486
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
2487
|
-
/* @__PURE__ */ jsx(
|
|
2488
|
-
"span",
|
|
2489
|
-
{
|
|
2490
|
-
className: cn("inline-block h-2.5 w-2.5 flex-shrink-0 rounded-full", styleAt(i).bg)
|
|
2491
|
-
}
|
|
2492
|
-
),
|
|
2493
|
-
/* @__PURE__ */ jsx("span", { className: "truncate", children: item.label })
|
|
2494
|
-
] }),
|
|
2495
|
-
/* @__PURE__ */ jsxs("div", { className: "ml-2 flex flex-shrink-0 items-center gap-2 tabular-nums", children: [
|
|
2496
|
-
/* @__PURE__ */ jsx(
|
|
2497
|
-
"span",
|
|
2498
|
-
{
|
|
2499
|
-
className: cn(
|
|
2500
|
-
"flex items-center gap-0.5",
|
|
2501
|
-
metric === "gbp" ? "font-medium text-muted-foreground" : "text-muted-foreground/60"
|
|
2502
|
-
),
|
|
2503
|
-
children: item.gbp
|
|
2504
|
-
}
|
|
2505
|
-
),
|
|
2506
|
-
/* @__PURE__ */ jsx(
|
|
2507
|
-
"span",
|
|
2508
|
-
{
|
|
2509
|
-
className: metric === "tokens" ? "font-medium text-muted-foreground" : "text-muted-foreground/60",
|
|
2510
|
-
children: l.tokensShort(item.tokens)
|
|
2511
|
-
}
|
|
2512
|
-
),
|
|
2513
|
-
/* @__PURE__ */ jsxs("span", { className: "w-8 text-right text-muted-foreground/40", children: [
|
|
2514
|
-
(item.amount / total * 100).toFixed(0),
|
|
2515
|
-
"%"
|
|
2516
|
-
] })
|
|
2517
|
-
] })
|
|
2518
|
-
] }, item.label)) })
|
|
2519
|
-
] });
|
|
2520
|
-
}
|
|
2521
|
-
function UsageSummary({ stats }) {
|
|
2522
|
-
return /* @__PURE__ */ jsx("div", { className: "grid grid-cols-3 gap-2 text-center", children: stats.map((stat) => /* @__PURE__ */ jsxs("div", { className: "rounded-lg bg-muted p-3", children: [
|
|
2523
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center justify-center gap-1 text-base font-semibold tabular-nums", children: stat.value }),
|
|
2524
|
-
/* @__PURE__ */ jsx("div", { className: "text-sm text-muted-foreground", children: stat.label })
|
|
2525
|
-
] }, stat.key)) });
|
|
2526
|
-
}
|
|
2527
|
-
function UsageToggle({
|
|
2528
|
-
value,
|
|
2529
|
-
onChange,
|
|
2530
|
-
options,
|
|
2531
|
-
ariaLabel,
|
|
2532
|
-
size = "compact"
|
|
2533
|
-
}) {
|
|
2534
|
-
return /* @__PURE__ */ jsx(
|
|
2535
|
-
RadioGroupPrimitive.Root,
|
|
2536
|
-
{
|
|
2537
|
-
"aria-label": ariaLabel,
|
|
2538
|
-
value,
|
|
2539
|
-
onValueChange: (next) => onChange(next),
|
|
2540
|
-
orientation: "horizontal",
|
|
2541
|
-
className: "flex gap-1 rounded-md border border-border bg-background p-0.5 print:hidden",
|
|
2542
|
-
children: options.map((option) => /* @__PURE__ */ jsx(
|
|
2543
|
-
RadioGroupPrimitive.Item,
|
|
2544
|
-
{
|
|
2545
|
-
value: option.value,
|
|
2546
|
-
className: cn(
|
|
2547
|
-
"rounded-md px-3 py-1 text-sm transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:py-2.5",
|
|
2548
|
-
size === "fill" && "flex-1 px-2 py-1.5",
|
|
2549
|
-
option.value === value ? "bg-accent font-medium text-accent-foreground" : "text-muted-foreground hover:text-foreground"
|
|
2550
|
-
),
|
|
2551
|
-
children: option.label
|
|
2552
|
-
},
|
|
2553
|
-
option.value
|
|
2554
|
-
))
|
|
2555
|
-
}
|
|
2556
|
-
);
|
|
2557
|
-
}
|
|
2558
|
-
function UsagePanel({
|
|
2559
|
-
state,
|
|
2560
|
-
period,
|
|
2561
|
-
actions,
|
|
2562
|
-
dateRange,
|
|
2563
|
-
emptyMessage,
|
|
2564
|
-
errorMessage,
|
|
2565
|
-
labels,
|
|
2566
|
-
children
|
|
2567
|
-
}) {
|
|
2568
|
-
const l = useMemo(() => ({ ...DEFAULT_USAGE_PANEL_LABELS, ...labels }), [labels]);
|
|
2569
|
-
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", "data-slot": "usage-panel", children: [
|
|
2570
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
2571
|
-
period,
|
|
2572
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-1", children: actions })
|
|
2573
|
-
] }),
|
|
2574
|
-
dateRange && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: dateRange }),
|
|
2575
|
-
state === "loading" && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx(Loader2, { className: "h-5 w-5 animate-spin text-muted-foreground" }) }),
|
|
2576
|
-
state === "error" && /* @__PURE__ */ jsx("p", { className: "py-4 text-sm text-destructive", children: errorMessage ?? l.error }),
|
|
2577
|
-
state === "empty" && /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center gap-2 py-10 text-center", children: [
|
|
2578
|
-
/* @__PURE__ */ jsx(ChartNoAxesColumn, { className: "h-8 w-8 text-muted-foreground/40" }),
|
|
2579
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: emptyMessage ?? l.empty })
|
|
2580
|
-
] }),
|
|
2581
|
-
state === "ready" && /* @__PURE__ */ jsx("div", { className: "space-y-4", children })
|
|
2582
|
-
] });
|
|
2583
|
-
}
|
|
2584
|
-
var DEFAULT_INVOICES_DIALOG_LABELS = {
|
|
2585
|
-
title: (projectName) => `Receipts \xB7 ${projectName}`,
|
|
2586
|
-
description: (projectName) => `Receipts for ${projectName}`,
|
|
2587
|
-
noReceipts: "No receipts yet.",
|
|
2588
|
-
paid: "Paid"
|
|
2589
|
-
};
|
|
2590
|
-
var DEFAULT_DAILY_CAP_FIELD_LABELS = {
|
|
2591
|
-
noLimit: "No limit",
|
|
2592
|
-
ariaLabel: "Daily AI usage limit per collaborator (\xA3)",
|
|
2593
|
-
unit: "\xA3 / user / day",
|
|
2594
|
-
save: "Save"
|
|
2595
|
-
};
|
|
2596
|
-
var DEFAULT_MEMBER_PROJECT_ROW_LABELS = {
|
|
2597
|
-
noDailyLimit: "No daily limit"
|
|
2598
|
-
};
|
|
2599
|
-
var DEFAULT_INLINE_NAME_EDITOR_LABELS = {
|
|
2600
|
-
saveName: "Save name",
|
|
2601
|
-
cancelRename: "Cancel rename"
|
|
2602
|
-
};
|
|
2603
|
-
var DEFAULT_PROJECT_CARD_VIEW_LABELS = {
|
|
2604
|
-
collapseProject: "Collapse project",
|
|
2605
|
-
expandProject: "Expand project"
|
|
2606
|
-
};
|
|
2607
|
-
function InvoicesDialog({
|
|
2608
|
-
open,
|
|
2609
|
-
onOpenChange,
|
|
2610
|
-
projectName,
|
|
2611
|
-
isLoading,
|
|
2612
|
-
invoices,
|
|
2613
|
-
labels
|
|
2614
|
-
}) {
|
|
2615
|
-
const l = useMemo(() => ({ ...DEFAULT_INVOICES_DIALOG_LABELS, ...labels }), [labels]);
|
|
2616
|
-
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { presentation: "sheet", className: "max-w-lg", children: [
|
|
2617
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
2618
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: l.title(projectName) }),
|
|
2619
|
-
/* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: l.description(projectName) })
|
|
2620
|
-
] }),
|
|
2621
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
2622
|
-
isLoading && /* @__PURE__ */ jsx("div", { className: "flex items-center justify-center py-8", children: /* @__PURE__ */ jsx(Loader2, { className: "h-5 w-5 animate-spin text-muted-foreground" }) }),
|
|
2623
|
-
!isLoading && invoices.length === 0 && /* @__PURE__ */ jsx("p", { className: "py-4 text-center text-sm text-muted-foreground", children: l.noReceipts }),
|
|
2624
|
-
!isLoading && invoices.map((invoice) => /* @__PURE__ */ jsxs(
|
|
2625
|
-
"div",
|
|
2626
|
-
{
|
|
2627
|
-
className: "flex items-center justify-between border-b py-2 text-sm last:border-0",
|
|
2628
|
-
children: [
|
|
2629
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-0.5", children: [
|
|
2630
|
-
/* @__PURE__ */ jsx("span", { className: "tabular-nums text-muted-foreground", children: invoice.date }),
|
|
2631
|
-
invoice.kind && /* @__PURE__ */ jsx("span", { className: "text-foreground", children: invoice.kind }),
|
|
2632
|
-
/* @__PURE__ */ jsx("span", { className: "font-medium tabular-nums", children: invoice.amount }),
|
|
2633
|
-
invoice.amountNote && /* @__PURE__ */ jsx("span", { className: "text-xs tabular-nums text-muted-foreground", children: invoice.amountNote }),
|
|
2634
|
-
/* @__PURE__ */ jsx(
|
|
2635
|
-
Badge,
|
|
2636
|
-
{
|
|
2637
|
-
variant: "outline",
|
|
2638
|
-
className: cn(
|
|
2639
|
-
"h-4 px-1.5 py-0 text-sm",
|
|
2640
|
-
invoice.isPaid && "border-green-border text-green-text"
|
|
2641
|
-
),
|
|
2642
|
-
children: invoice.isPaid ? l.paid : invoice.status
|
|
2643
|
-
}
|
|
2644
|
-
)
|
|
2645
|
-
] }),
|
|
2646
|
-
invoice.href && /* @__PURE__ */ jsxs(
|
|
2647
|
-
"a",
|
|
2648
|
-
{
|
|
2649
|
-
href: invoice.href,
|
|
2650
|
-
target: "_blank",
|
|
2651
|
-
rel: "noopener noreferrer",
|
|
2652
|
-
className: "flex items-center gap-1 text-sm text-muted-foreground hover:text-foreground",
|
|
2653
|
-
children: [
|
|
2654
|
-
invoice.linkLabel,
|
|
2655
|
-
" ",
|
|
2656
|
-
/* @__PURE__ */ jsx(FileText, { className: "h-3 w-3" })
|
|
2657
|
-
]
|
|
2658
|
-
}
|
|
2659
|
-
)
|
|
2660
|
-
]
|
|
2661
|
-
},
|
|
2662
|
-
invoice.key
|
|
2663
|
-
))
|
|
2664
|
-
] })
|
|
2665
|
-
] }) });
|
|
2666
|
-
}
|
|
2667
|
-
function DailyCapField({
|
|
2668
|
-
value,
|
|
2669
|
-
onChange,
|
|
2670
|
-
onSave,
|
|
2671
|
-
canSave,
|
|
2672
|
-
isSaving,
|
|
2673
|
-
labels
|
|
2674
|
-
}) {
|
|
2675
|
-
const l = useMemo(() => ({ ...DEFAULT_DAILY_CAP_FIELD_LABELS, ...labels }), [labels]);
|
|
2676
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
2677
|
-
/* @__PURE__ */ jsx(
|
|
2678
|
-
Input,
|
|
2679
|
-
{
|
|
2680
|
-
type: "number",
|
|
2681
|
-
min: 0,
|
|
2682
|
-
step: 0.01,
|
|
2683
|
-
value,
|
|
2684
|
-
onChange: (e) => onChange(e.target.value),
|
|
2685
|
-
onKeyDown: (e) => {
|
|
2686
|
-
if (e.key === "Enter") onSave();
|
|
2687
|
-
},
|
|
2688
|
-
placeholder: l.noLimit,
|
|
2689
|
-
className: "h-9 w-40",
|
|
2690
|
-
"aria-label": l.ariaLabel
|
|
2691
|
-
}
|
|
2692
|
-
),
|
|
2693
|
-
/* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: l.unit }),
|
|
2694
|
-
/* @__PURE__ */ jsx(Button, { size: "sm", className: "h-9 px-4", disabled: !canSave || isSaving, onClick: onSave, children: l.save })
|
|
2695
|
-
] });
|
|
2696
|
-
}
|
|
2697
|
-
function MemberProjectRow({ icon, name, owner, allowance, labels }) {
|
|
2698
|
-
const l = useMemo(() => ({ ...DEFAULT_MEMBER_PROJECT_ROW_LABELS, ...labels }), [labels]);
|
|
2699
|
-
const barColor2 = allowance && allowance.pct >= 100 ? "bg-red-500" : allowance && allowance.pct >= 90 ? "bg-yellow-500" : "bg-primary";
|
|
2700
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 rounded-lg bg-muted p-3", children: [
|
|
2701
|
-
/* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-muted-foreground", children: icon }),
|
|
2702
|
-
/* @__PURE__ */ jsx("div", { className: "min-w-0 flex-1", children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
2703
|
-
/* @__PURE__ */ jsx("span", { className: "truncate text-sm font-medium", children: name }),
|
|
2704
|
-
owner
|
|
2705
|
-
] }) }),
|
|
2706
|
-
allowance === null ? /* @__PURE__ */ jsx("span", { className: "flex-shrink-0 text-sm text-muted-foreground", children: l.noDailyLimit }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-shrink-0 flex-col items-end gap-0.5 text-sm tabular-nums", children: [
|
|
2707
|
-
/* @__PURE__ */ jsx("span", { className: "text-muted-foreground", children: allowance.text }),
|
|
2708
|
-
/* @__PURE__ */ jsx("span", { className: "h-1 w-24 overflow-hidden rounded-full bg-background", children: /* @__PURE__ */ jsx(
|
|
2709
|
-
"span",
|
|
2710
|
-
{
|
|
2711
|
-
className: cn("block h-full rounded-full", barColor2),
|
|
2712
|
-
style: { width: `${allowance.pct}%` }
|
|
2713
|
-
}
|
|
2714
|
-
) })
|
|
2715
|
-
] })
|
|
2716
|
-
] });
|
|
2717
|
-
}
|
|
2718
|
-
function InlineNameEditor({
|
|
2719
|
-
value,
|
|
2720
|
-
onChange,
|
|
2721
|
-
onSave,
|
|
2722
|
-
onCancel,
|
|
2723
|
-
labels
|
|
2724
|
-
}) {
|
|
2725
|
-
const l = useMemo(() => ({ ...DEFAULT_INLINE_NAME_EDITOR_LABELS, ...labels }), [labels]);
|
|
2726
|
-
return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-1", children: [
|
|
2727
|
-
/* @__PURE__ */ jsx(
|
|
2728
|
-
Input,
|
|
2729
|
-
{
|
|
2730
|
-
value,
|
|
2731
|
-
onChange: (e) => onChange(e.target.value),
|
|
2732
|
-
className: "h-7 text-sm",
|
|
2733
|
-
autoFocus: true,
|
|
2734
|
-
onKeyDown: (e) => {
|
|
2735
|
-
if (e.key === "Enter") onSave();
|
|
2736
|
-
if (e.key === "Escape") onCancel();
|
|
2737
|
-
}
|
|
2738
|
-
}
|
|
2739
|
-
),
|
|
2740
|
-
/* @__PURE__ */ jsx(
|
|
2741
|
-
Button,
|
|
2742
|
-
{
|
|
2743
|
-
variant: "ghost",
|
|
2744
|
-
size: "icon",
|
|
2745
|
-
className: "h-6 w-6",
|
|
2746
|
-
"aria-label": l.saveName,
|
|
2747
|
-
onClick: onSave,
|
|
2748
|
-
children: /* @__PURE__ */ jsx(Check, { className: "h-3.5 w-3.5" })
|
|
2749
|
-
}
|
|
2750
|
-
),
|
|
2751
|
-
/* @__PURE__ */ jsx(
|
|
2752
|
-
Button,
|
|
2753
|
-
{
|
|
2754
|
-
variant: "ghost",
|
|
2755
|
-
size: "icon",
|
|
2756
|
-
className: "h-6 w-6",
|
|
2757
|
-
"aria-label": l.cancelRename,
|
|
2758
|
-
onClick: onCancel,
|
|
2759
|
-
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
|
|
2760
|
-
}
|
|
2761
|
-
)
|
|
2762
|
-
] });
|
|
2763
|
-
}
|
|
2764
|
-
function ProjectCardView({
|
|
2765
|
-
expanded,
|
|
2766
|
-
onToggleExpanded,
|
|
2767
|
-
rowRef,
|
|
2768
|
-
icon,
|
|
2769
|
-
identity,
|
|
2770
|
-
actions,
|
|
2771
|
-
badge,
|
|
2772
|
-
buttons,
|
|
2773
|
-
summary,
|
|
2774
|
-
children,
|
|
2775
|
-
overlays,
|
|
2776
|
-
labels
|
|
2777
|
-
}) {
|
|
2778
|
-
const l = useMemo(() => ({ ...DEFAULT_PROJECT_CARD_VIEW_LABELS, ...labels }), [labels]);
|
|
2779
|
-
return /* @__PURE__ */ jsxs(
|
|
2780
|
-
"div",
|
|
2781
|
-
{
|
|
2782
|
-
"data-slot": "project-card",
|
|
2783
|
-
className: cn("rounded-lg bg-muted transition-colors", expanded && "ring-1 ring-primary/40"),
|
|
2784
|
-
children: [
|
|
2785
|
-
/* @__PURE__ */ jsxs(
|
|
2786
|
-
"div",
|
|
2787
|
-
{
|
|
2788
|
-
ref: rowRef,
|
|
2789
|
-
className: cn(
|
|
2790
|
-
"flex items-center gap-2 p-3 transition-colors",
|
|
2791
|
-
expanded ? "bg-blue-bg/60" : "hover:bg-muted/50"
|
|
2792
|
-
),
|
|
2793
|
-
children: [
|
|
2794
|
-
icon,
|
|
2795
|
-
identity,
|
|
2796
|
-
actions,
|
|
2797
|
-
badge,
|
|
2798
|
-
buttons,
|
|
2799
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1" }),
|
|
2800
|
-
summary,
|
|
2801
|
-
/* @__PURE__ */ jsx(
|
|
2802
|
-
"button",
|
|
2803
|
-
{
|
|
2804
|
-
type: "button",
|
|
2805
|
-
onClick: onToggleExpanded,
|
|
2806
|
-
"aria-expanded": expanded,
|
|
2807
|
-
"aria-label": expanded ? l.collapseProject : l.expandProject,
|
|
2808
|
-
className: "flex-shrink-0 rounded p-1 hover:bg-muted pointer-coarse:p-3",
|
|
2809
|
-
children: expanded ? /* @__PURE__ */ jsx(ChevronDown, { className: "h-4 w-4 text-muted-foreground" }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-4 w-4 text-muted-foreground" })
|
|
2810
|
-
}
|
|
2811
|
-
)
|
|
2812
|
-
]
|
|
2813
|
-
}
|
|
2814
|
-
),
|
|
2815
|
-
expanded && /* @__PURE__ */ jsx("div", { className: "space-y-4 border-t px-4 py-3", children }),
|
|
2816
|
-
overlays
|
|
2817
|
-
]
|
|
2818
|
-
}
|
|
2819
|
-
);
|
|
2820
|
-
}
|
|
2821
|
-
var DEFAULT_EMAIL_WORKSPACE_DIALOG_LABELS = {
|
|
2822
|
-
title: "Email this workspace",
|
|
2823
|
-
description: "Send documents and questions here from your registered email address \u2014 your Assistant reads the email and replies.",
|
|
2824
|
-
compose: "Compose email",
|
|
2825
|
-
paHintBefore: "Don\u2019t need this specific workspace? Send general questions to ",
|
|
2826
|
-
paHintAfter: " instead.",
|
|
2827
|
-
checking: "Checking your Assistant\u2019s access\u2026",
|
|
2828
|
-
noAssistant: "You don\u2019t have a default Assistant yet \u2014 one is created automatically the first time you email a workspace.",
|
|
2829
|
-
authorizedExpires: (ttl) => `Authorized \u2014 expires in ${ttl}`,
|
|
2830
|
-
end: "End",
|
|
2831
|
-
authorizePrompt: (ttl) => `Authorize your Assistant to act in this workspace${ttl ? ` for ${ttl}` : ""}, so it\u2019s ready as soon as it wakes.`,
|
|
2832
|
-
authorize: "Authorize",
|
|
2833
|
-
authorizing: "Authorizing\u2026",
|
|
2834
|
-
advanced: "Advanced",
|
|
2835
|
-
alreadyGranted: "Your Assistant already has standing access to this workspace.",
|
|
2836
|
-
standingWarning: "Standing access never expires and doesn\u2019t need re-authorizing \u2014 only use it if you trust the Assistant\u2019s environment long-term.",
|
|
2837
|
-
grant: "Grant standing access",
|
|
2838
|
-
granting: "Granting\u2026"
|
|
2839
|
-
};
|
|
2840
|
-
function EmailWorkspaceDialogView({
|
|
2841
|
-
open,
|
|
2842
|
-
onOpenChange,
|
|
2843
|
-
email,
|
|
2844
|
-
mailtoHref,
|
|
2845
|
-
paDomain,
|
|
2846
|
-
copyButton,
|
|
2847
|
-
access,
|
|
2848
|
-
standing,
|
|
2849
|
-
labels
|
|
2850
|
-
}) {
|
|
2851
|
-
const l = useMemo(() => ({ ...DEFAULT_EMAIL_WORKSPACE_DIALOG_LABELS, ...labels }), [labels]);
|
|
2852
|
-
const [advancedOpen, setAdvancedOpen] = useState(false);
|
|
2853
|
-
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-md", "data-testid": "email-workspace-dialog", children: [
|
|
2854
|
-
/* @__PURE__ */ jsxs(DialogHeader, { className: "-m-6 mb-4 bg-muted p-6 pb-4", children: [
|
|
2855
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3", children: [
|
|
2856
|
-
/* @__PURE__ */ jsx(Mail, { className: "size-6" }),
|
|
2857
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: l.title })
|
|
2858
|
-
] }),
|
|
2859
|
-
/* @__PURE__ */ jsx(DialogDescription, { children: l.description })
|
|
2860
|
-
] }),
|
|
2861
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 rounded-lg border border-border bg-muted/30 px-3 py-2", children: [
|
|
2862
|
-
/* @__PURE__ */ jsx("code", { className: "flex-1 truncate font-mono text-sm", "data-testid": "email-workspace-address", children: email }),
|
|
2863
|
-
copyButton
|
|
2864
|
-
] }),
|
|
2865
|
-
/* @__PURE__ */ jsx(Button, { asChild: true, "data-testid": "email-workspace-compose-button", children: /* @__PURE__ */ jsxs("a", { href: mailtoHref, children: [
|
|
2866
|
-
/* @__PURE__ */ jsx(Send, { className: "mr-1.5 size-4" }),
|
|
2867
|
-
l.compose
|
|
2868
|
-
] }) }),
|
|
2869
|
-
/* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", "data-testid": "email-workspace-pa-hint", children: [
|
|
2870
|
-
l.paHintBefore,
|
|
2871
|
-
/* @__PURE__ */ jsxs("code", { className: "font-mono", children: [
|
|
2872
|
-
"pa@",
|
|
2873
|
-
paDomain
|
|
2874
|
-
] }),
|
|
2875
|
-
l.paHintAfter
|
|
2876
|
-
] }),
|
|
2877
|
-
access && /* @__PURE__ */ jsxs("div", { className: "space-y-2 rounded-md border border-border bg-muted/30 p-3", children: [
|
|
2878
|
-
access.kind === "loading" ? /* @__PURE__ */ jsx(
|
|
2879
|
-
"p",
|
|
2880
|
-
{
|
|
2881
|
-
className: "text-xs text-muted-foreground",
|
|
2882
|
-
"data-testid": "email-workspace-authorize-loading",
|
|
2883
|
-
children: l.checking
|
|
2884
|
-
}
|
|
2885
|
-
) : access.kind === "none" ? /* @__PURE__ */ jsx(
|
|
2886
|
-
"p",
|
|
2887
|
-
{
|
|
2888
|
-
className: "text-xs text-muted-foreground",
|
|
2889
|
-
"data-testid": "email-workspace-no-assistant",
|
|
2890
|
-
children: l.noAssistant
|
|
2891
|
-
}
|
|
2892
|
-
) : access.kind === "session" ? /* @__PURE__ */ jsxs(
|
|
2893
|
-
"div",
|
|
2894
|
-
{
|
|
2895
|
-
className: "flex items-center justify-between gap-3",
|
|
2896
|
-
"data-testid": "email-workspace-active-session",
|
|
2897
|
-
children: [
|
|
2898
|
-
/* @__PURE__ */ jsxs("p", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
2899
|
-
/* @__PURE__ */ jsx(Clock, { className: "size-3.5" }),
|
|
2900
|
-
l.authorizedExpires(access.expiresIn)
|
|
2901
|
-
] }),
|
|
2902
|
-
/* @__PURE__ */ jsxs(
|
|
2903
|
-
Button,
|
|
2904
|
-
{
|
|
2905
|
-
variant: "ghost",
|
|
2906
|
-
size: "sm",
|
|
2907
|
-
onClick: access.onEnd,
|
|
2908
|
-
disabled: access.isEnding,
|
|
2909
|
-
className: "h-7 shrink-0 gap-1 px-2 text-xs text-destructive hover:bg-destructive/10 hover:text-destructive pointer-coarse:h-11",
|
|
2910
|
-
"data-testid": "email-workspace-end-session-button",
|
|
2911
|
-
children: [
|
|
2912
|
-
/* @__PURE__ */ jsx(X, { className: "size-3" }),
|
|
2913
|
-
l.end
|
|
2914
|
-
]
|
|
2915
|
-
}
|
|
2916
|
-
)
|
|
2917
|
-
]
|
|
2918
|
-
}
|
|
2919
|
-
) : /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-3", children: [
|
|
2920
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: l.authorizePrompt(access.defaultTtl) }),
|
|
2921
|
-
/* @__PURE__ */ jsxs(
|
|
2922
|
-
Button,
|
|
2923
|
-
{
|
|
2924
|
-
variant: "outline",
|
|
2925
|
-
size: "sm",
|
|
2926
|
-
onClick: access.onAuthorize,
|
|
2927
|
-
disabled: access.isAuthorizing,
|
|
2928
|
-
className: "shrink-0 gap-1.5",
|
|
2929
|
-
"data-testid": "email-workspace-authorize-button",
|
|
2930
|
-
children: [
|
|
2931
|
-
/* @__PURE__ */ jsx(Clock, { className: "size-3.5" }),
|
|
2932
|
-
access.isAuthorizing ? l.authorizing : l.authorize
|
|
2933
|
-
]
|
|
2934
|
-
}
|
|
2935
|
-
)
|
|
2936
|
-
] }),
|
|
2937
|
-
/* @__PURE__ */ jsx(
|
|
2938
|
-
"button",
|
|
2939
|
-
{
|
|
2940
|
-
type: "button",
|
|
2941
|
-
onClick: () => setAdvancedOpen((o) => !o),
|
|
2942
|
-
"aria-expanded": advancedOpen,
|
|
2943
|
-
className: "text-xs font-semibold uppercase tracking-wide text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring pointer-coarse:min-h-11",
|
|
2944
|
-
"data-testid": "email-workspace-advanced-toggle",
|
|
2945
|
-
children: l.advanced
|
|
2946
|
-
}
|
|
2947
|
-
),
|
|
2948
|
-
advancedOpen && standing && (standing.alreadyGranted ? /* @__PURE__ */ jsxs("p", { className: "flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
2949
|
-
/* @__PURE__ */ jsx(Check, { className: "size-3.5 text-green-solid" }),
|
|
2950
|
-
l.alreadyGranted
|
|
2951
|
-
] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
2952
|
-
/* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: l.standingWarning }),
|
|
2953
|
-
/* @__PURE__ */ jsxs(
|
|
2954
|
-
Button,
|
|
2955
|
-
{
|
|
2956
|
-
variant: "outline",
|
|
2957
|
-
size: "sm",
|
|
2958
|
-
onClick: standing.onGrant,
|
|
2959
|
-
disabled: standing.isGranting,
|
|
2960
|
-
className: "gap-1.5",
|
|
2961
|
-
"data-testid": "email-workspace-grant-access-button",
|
|
2962
|
-
children: [
|
|
2963
|
-
/* @__PURE__ */ jsx(Infinity, { className: "size-3.5" }),
|
|
2964
|
-
standing.isGranting ? l.granting : l.grant
|
|
2965
|
-
]
|
|
2966
|
-
}
|
|
2967
|
-
)
|
|
2968
|
-
] }))
|
|
2969
|
-
] })
|
|
2970
|
-
] }) });
|
|
2971
|
-
}
|
|
2972
|
-
function PlanNotice({
|
|
2973
|
-
tone = "muted",
|
|
2974
|
-
className,
|
|
2975
|
-
testId,
|
|
2976
|
-
children
|
|
2977
|
-
}) {
|
|
2978
|
-
return /* @__PURE__ */ jsx(
|
|
2979
|
-
"p",
|
|
2980
|
-
{
|
|
2981
|
-
"data-slot": "plan-notice",
|
|
2982
|
-
"data-testid": testId,
|
|
2983
|
-
className: cn(
|
|
2984
|
-
"text-sm",
|
|
2985
|
-
tone === "error" ? "text-destructive" : "text-muted-foreground",
|
|
2986
|
-
className
|
|
2987
|
-
),
|
|
2988
|
-
children
|
|
2989
|
-
}
|
|
2990
|
-
);
|
|
2991
|
-
}
|
|
2992
|
-
function PlanStack({
|
|
2993
|
-
gap = 3,
|
|
2994
|
-
testId,
|
|
2995
|
-
className,
|
|
2996
|
-
children
|
|
2997
|
-
}) {
|
|
2998
|
-
const GAP = { 2: "space-y-2", 3: "space-y-3", 4: "space-y-4", 5: "space-y-5 pt-2" };
|
|
2999
|
-
return /* @__PURE__ */ jsx("div", { "data-slot": "plan-stack", "data-testid": testId, className: cn(GAP[gap], className), children });
|
|
3000
|
-
}
|
|
3001
|
-
function PlanTransition({ from, to }) {
|
|
3002
|
-
return /* @__PURE__ */ jsxs("div", { "data-slot": "plan-transition", className: "flex flex-wrap items-center gap-2 text-sm", children: [
|
|
3003
|
-
/* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full bg-muted px-2 py-0.5 text-xs font-semibold text-muted-foreground", children: from }),
|
|
3004
|
-
/* @__PURE__ */ jsx(ArrowRight, { className: "size-4 text-muted-foreground", "aria-hidden": true }),
|
|
3005
|
-
/* @__PURE__ */ jsx("span", { className: "inline-flex items-center rounded-full bg-primary px-2 py-0.5 text-xs font-semibold text-white", children: to })
|
|
3006
|
-
] });
|
|
3007
|
-
}
|
|
3008
|
-
function PlanPickerHeader({
|
|
3009
|
-
title,
|
|
3010
|
-
info,
|
|
3011
|
-
infoPlacement = "title",
|
|
3012
|
-
toggle,
|
|
3013
|
-
className
|
|
3014
|
-
}) {
|
|
3015
|
-
return /* @__PURE__ */ jsxs(
|
|
3016
|
-
"div",
|
|
3017
|
-
{
|
|
3018
|
-
"data-slot": "plan-picker-header",
|
|
3019
|
-
className: cn("flex flex-wrap items-center justify-between gap-x-3 gap-y-2", className),
|
|
3020
|
-
children: [
|
|
3021
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3022
|
-
/* @__PURE__ */ jsx("span", { className: "text-lg font-semibold", children: title }),
|
|
3023
|
-
infoPlacement === "title" && info
|
|
3024
|
-
] }),
|
|
3025
|
-
infoPlacement === "toggle" ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-4 gap-y-2", children: [
|
|
3026
|
-
info,
|
|
3027
|
-
toggle
|
|
3028
|
-
] }) : toggle
|
|
3029
|
-
]
|
|
3030
|
-
}
|
|
3031
|
-
);
|
|
3032
|
-
}
|
|
3033
|
-
function PlanPickerCard({ children }) {
|
|
3034
|
-
return /* @__PURE__ */ jsx(
|
|
3035
|
-
"div",
|
|
3036
|
-
{
|
|
3037
|
-
"data-slot": "plan-picker-card",
|
|
3038
|
-
className: "space-y-4 rounded-lg border border-border bg-card shadow-xs p-4",
|
|
3039
|
-
children
|
|
3040
|
-
}
|
|
3041
|
-
);
|
|
3042
|
-
}
|
|
3043
|
-
function PlanActionRow({ children }) {
|
|
3044
|
-
return /* @__PURE__ */ jsx("div", { "data-slot": "plan-action-row", className: "flex flex-col-reverse gap-2 @xl:flex-row", children });
|
|
3045
|
-
}
|
|
3046
|
-
function PlanActionButton({
|
|
3047
|
-
tone = "primary",
|
|
3048
|
-
fill,
|
|
3049
|
-
...props
|
|
3050
|
-
}) {
|
|
3051
|
-
return /* @__PURE__ */ jsx(
|
|
3052
|
-
Button,
|
|
3053
|
-
{
|
|
3054
|
-
"data-slot": "plan-action-button",
|
|
3055
|
-
variant: tone === "muted" ? "ghost" : "default",
|
|
3056
|
-
...props,
|
|
3057
|
-
className: cn(
|
|
3058
|
-
"w-full",
|
|
3059
|
-
fill && "sm:flex-1",
|
|
3060
|
-
tone === "muted" && "text-muted-foreground",
|
|
3061
|
-
props.className
|
|
3062
|
-
)
|
|
3063
|
-
}
|
|
3064
|
-
);
|
|
3065
|
-
}
|
|
3066
|
-
var DEFAULT_SUBSCRIPTION_STATUS_LABELS = {
|
|
3067
|
-
aiUsageResets: (date) => `AI usage resets ${date}`,
|
|
3068
|
-
cancelsAtPeriodEnd: "\xB7 Cancels at period end",
|
|
3069
|
-
cancelsAtEndOfBillingPeriod: "Cancels at end of billing period"
|
|
3070
|
-
};
|
|
3071
|
-
function SubscriptionStatusView({
|
|
3072
|
-
resetDate,
|
|
3073
|
-
isCanceling,
|
|
3074
|
-
meters,
|
|
3075
|
-
testIdPrefix,
|
|
3076
|
-
labels
|
|
3077
|
-
}) {
|
|
3078
|
-
const l = { ...DEFAULT_SUBSCRIPTION_STATUS_LABELS, ...labels };
|
|
3079
|
-
return /* @__PURE__ */ jsxs("div", { "data-slot": "subscription-status", className: "space-y-3", children: [
|
|
3080
|
-
resetDate && /* @__PURE__ */ jsxs("p", { className: "text-sm text-muted-foreground", children: [
|
|
3081
|
-
l.aiUsageResets(resetDate),
|
|
3082
|
-
isCanceling && /* @__PURE__ */ jsx("span", { className: "ml-2 text-yellow-text", children: l.cancelsAtPeriodEnd })
|
|
3083
|
-
] }),
|
|
3084
|
-
!resetDate && isCanceling && /* @__PURE__ */ jsx("p", { className: "text-sm text-yellow-text", children: l.cancelsAtEndOfBillingPeriod }),
|
|
3085
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-3", children: meters.map((m) => /* @__PURE__ */ jsx(
|
|
3086
|
-
UsageMeter,
|
|
3087
|
-
{
|
|
3088
|
-
icon: m.icon,
|
|
3089
|
-
label: m.label,
|
|
3090
|
-
value: m.value,
|
|
3091
|
-
pct: m.pct,
|
|
3092
|
-
testId: prefixedTestId(testIdPrefix, m.key, { testId: `project-quota-${m.key}` })
|
|
3093
|
-
},
|
|
3094
|
-
m.key
|
|
3095
|
-
)) })
|
|
3096
|
-
] });
|
|
3097
|
-
}
|
|
3098
|
-
function PlanDialogFrame({
|
|
3099
|
-
open,
|
|
3100
|
-
onOpenChange,
|
|
3101
|
-
title,
|
|
3102
|
-
description,
|
|
3103
|
-
isDescriptionHidden,
|
|
3104
|
-
projectName,
|
|
3105
|
-
projectTestId,
|
|
3106
|
-
children,
|
|
3107
|
-
labels
|
|
3108
|
-
}) {
|
|
3109
|
-
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-5xl", children: [
|
|
3110
|
-
/* @__PURE__ */ jsxs(DialogHeader, { className: "flex-row items-start justify-between gap-3 space-y-0 pr-8", children: [
|
|
3111
|
-
/* @__PURE__ */ jsxs("div", { className: "space-y-1.5", children: [
|
|
3112
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: title }),
|
|
3113
|
-
/* @__PURE__ */ jsx(DialogDescription, { className: isDescriptionHidden ? "sr-only" : void 0, children: description })
|
|
3114
|
-
] }),
|
|
3115
|
-
projectName !== void 0 && /* @__PURE__ */ jsxs(
|
|
3116
|
-
"span",
|
|
3117
|
-
{
|
|
3118
|
-
className: "shrink-0 text-sm text-muted-foreground",
|
|
3119
|
-
"data-testid": testIdOr(projectTestId, { testId: "change-plan-project" }),
|
|
3120
|
-
children: [
|
|
3121
|
-
labels?.project ?? "Project:",
|
|
3122
|
-
" ",
|
|
3123
|
-
/* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: projectName })
|
|
3124
|
-
]
|
|
3125
|
-
}
|
|
3126
|
-
)
|
|
3127
|
-
] }),
|
|
3128
|
-
children
|
|
3129
|
-
] }) });
|
|
3130
|
-
}
|
|
3131
|
-
var DEFAULT_CHECKOUT_DIALOG_LABELS = {
|
|
3132
|
-
unavailableTitle: "Stripe Not Configured",
|
|
3133
|
-
unavailableDescription: "Stripe checkout is not available. Please contact support.",
|
|
3134
|
-
title: "Payment",
|
|
3135
|
-
description: "Enter your card to start the plan",
|
|
3136
|
-
loading: "Loading\u2026",
|
|
3137
|
-
error: "Checkout didn't load. Try again."
|
|
3138
|
-
};
|
|
3139
|
-
function CheckoutDialogFrame({
|
|
3140
|
-
open,
|
|
3141
|
-
onOpenChange,
|
|
3142
|
-
isUnavailable,
|
|
3143
|
-
isLoading,
|
|
3144
|
-
hasError,
|
|
3145
|
-
children,
|
|
3146
|
-
labels
|
|
3147
|
-
}) {
|
|
3148
|
-
const l = { ...DEFAULT_CHECKOUT_DIALOG_LABELS, ...labels };
|
|
3149
|
-
if (isUnavailable) {
|
|
3150
|
-
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
3151
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: l.unavailableTitle }),
|
|
3152
|
-
/* @__PURE__ */ jsx(DialogDescription, { children: l.unavailableDescription })
|
|
3153
|
-
] }) }) });
|
|
3154
|
-
}
|
|
3155
|
-
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
|
|
3156
|
-
DialogContent,
|
|
3157
|
-
{
|
|
3158
|
-
presentation: "sheet",
|
|
3159
|
-
className: "flex max-h-[calc(100dvh-2rem)] max-w-2xl flex-col gap-0 overflow-hidden p-0",
|
|
3160
|
-
onInteractOutside: (e) => e.preventDefault(),
|
|
3161
|
-
onEscapeKeyDown: (e) => e.preventDefault(),
|
|
3162
|
-
children: [
|
|
3163
|
-
/* @__PURE__ */ jsxs(DialogHeader, { className: "flex-shrink-0 px-6 pb-3 pt-6", children: [
|
|
3164
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: l.title }),
|
|
3165
|
-
/* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: l.description })
|
|
3166
|
-
] }),
|
|
3167
|
-
/* @__PURE__ */ jsxs("div", { className: "min-h-0 flex-1 overflow-y-auto px-6 pb-6", children: [
|
|
3168
|
-
isLoading && /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-muted-foreground", children: l.loading }),
|
|
3169
|
-
hasError && /* @__PURE__ */ jsx("div", { className: "py-8 text-center text-destructive", children: l.error }),
|
|
3170
|
-
children
|
|
3171
|
-
] })
|
|
3172
|
-
]
|
|
3173
|
-
}
|
|
3174
|
-
) });
|
|
3175
|
-
}
|
|
3176
|
-
var DEFAULT_QUOTA_EXCEEDED_DIALOG_LABELS = {
|
|
3177
|
-
title: "AI usage used up",
|
|
3178
|
-
projectUsage: "Project usage",
|
|
3179
|
-
progress: "AI usage this month",
|
|
3180
|
-
project: "Project:",
|
|
3181
|
-
close: "Not now",
|
|
3182
|
-
upgrade: "Upgrade"
|
|
3183
|
-
};
|
|
3184
|
-
function QuotaExceededDialogView({
|
|
3185
|
-
open,
|
|
3186
|
-
onClose,
|
|
3187
|
-
onUpgrade,
|
|
3188
|
-
message,
|
|
3189
|
-
usage,
|
|
3190
|
-
actions,
|
|
3191
|
-
extra,
|
|
3192
|
-
labels
|
|
3193
|
-
}) {
|
|
3194
|
-
const l = { ...DEFAULT_QUOTA_EXCEEDED_DIALOG_LABELS, ...labels };
|
|
3195
|
-
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange: (o) => !o && onClose(), children: /* @__PURE__ */ jsxs(DialogContent, { className: "max-w-md", "data-testid": "quota-exceeded-modal", children: [
|
|
3196
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
3197
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: l.title }),
|
|
3198
|
-
/* @__PURE__ */ jsx(DialogDescription, { children: message })
|
|
3199
|
-
] }),
|
|
3200
|
-
usage && /* @__PURE__ */ jsxs(ModalSection, { className: "space-y-2", children: [
|
|
3201
|
-
/* @__PURE__ */ jsx(Progress, { value: usage.percent, "aria-label": l.progress }),
|
|
3202
|
-
/* @__PURE__ */ jsxs(
|
|
3203
|
-
"div",
|
|
3204
|
-
{
|
|
3205
|
-
className: "flex flex-wrap items-center justify-between gap-x-3 text-sm text-muted-foreground",
|
|
3206
|
-
"data-testid": "quota-usage-readout",
|
|
3207
|
-
children: [
|
|
3208
|
-
/* @__PURE__ */ jsx("span", { className: "tabular-nums", children: usage.readout }),
|
|
3209
|
-
usage.projectId && /* @__PURE__ */ jsx("span", { className: "truncate", children: usage.projectId })
|
|
3210
|
-
]
|
|
3211
|
-
}
|
|
3212
|
-
)
|
|
3213
|
-
] }),
|
|
3214
|
-
extra,
|
|
3215
|
-
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
3216
|
-
/* @__PURE__ */ jsx(Button, { variant: "outline", onClick: onClose, "data-testid": "quota-close-button", children: l.close }),
|
|
3217
|
-
actions ?? /* @__PURE__ */ jsx(Button, { onClick: onUpgrade, "data-testid": "quota-upgrade-button", children: l.upgrade })
|
|
3218
|
-
] })
|
|
3219
|
-
] }) });
|
|
3220
|
-
}
|
|
3221
|
-
function WelcomeProjectPicker({
|
|
3222
|
-
value,
|
|
3223
|
-
options,
|
|
3224
|
-
onChange,
|
|
3225
|
-
testId = "welcome-modal-project-select"
|
|
3226
|
-
}) {
|
|
3227
|
-
return /* @__PURE__ */ jsxs(Select, { value, onValueChange: onChange, children: [
|
|
3228
|
-
/* @__PURE__ */ jsx(
|
|
3229
|
-
SelectTrigger,
|
|
3230
|
-
{
|
|
3231
|
-
className: "h-7 w-auto max-w-[9.5rem] shrink-0 gap-1 border-none bg-muted px-2 text-xs font-medium pointer-coarse:h-11",
|
|
3232
|
-
"data-testid": testId,
|
|
3233
|
-
children: /* @__PURE__ */ jsx(SelectValue, {})
|
|
3234
|
-
}
|
|
3235
|
-
),
|
|
3236
|
-
/* @__PURE__ */ jsx(SelectContent, { align: "end", children: options.map((o) => /* @__PURE__ */ jsx(SelectItem, { value: o.id, children: o.name }, o.id)) })
|
|
3237
|
-
] });
|
|
3238
|
-
}
|
|
3239
|
-
var DEFAULT_SUBSCRIPTION_SECTION_LABELS = {
|
|
3240
|
-
loading: "Loading projects...",
|
|
3241
|
-
empty: "No projects yet \u2014 create one above."
|
|
3242
|
-
};
|
|
3243
|
-
function SubscriptionSectionView({
|
|
3244
|
-
intro,
|
|
3245
|
-
isLoading,
|
|
3246
|
-
isEmpty,
|
|
3247
|
-
children,
|
|
3248
|
-
labels
|
|
3249
|
-
}) {
|
|
3250
|
-
const l = { ...DEFAULT_SUBSCRIPTION_SECTION_LABELS, ...labels };
|
|
3251
|
-
if (isLoading) {
|
|
3252
|
-
return /* @__PURE__ */ jsx("div", { className: "py-4 text-sm text-muted-foreground", children: l.loading });
|
|
3253
|
-
}
|
|
3254
|
-
return /* @__PURE__ */ jsxs("div", { "data-slot": "subscription-section", className: "space-y-4", children: [
|
|
3255
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: intro }),
|
|
3256
|
-
isEmpty ? /* @__PURE__ */ jsx("div", { className: "rounded-lg bg-muted py-8 text-center", children: /* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: l.empty }) }) : children
|
|
3257
|
-
] });
|
|
3258
|
-
}
|
|
3259
|
-
function ProjectGroup({ children }) {
|
|
3260
|
-
return /* @__PURE__ */ jsx("div", { "data-slot": "project-group", className: "space-y-2", children });
|
|
3261
|
-
}
|
|
3262
|
-
function ProjectPlanPicker({ children }) {
|
|
3263
|
-
return /* @__PURE__ */ jsx("div", { "data-slot": "project-plan-picker", className: "border-b pb-3", children });
|
|
3264
|
-
}
|
|
3265
|
-
function ProjectNameLabel({ children }) {
|
|
3266
|
-
return /* @__PURE__ */ jsx("span", { className: "truncate text-sm font-medium", children });
|
|
3267
|
-
}
|
|
3268
|
-
function ProjectRowActions({ children }) {
|
|
3269
|
-
return /* @__PURE__ */ jsx("div", { "data-slot": "project-row-actions", className: "flex flex-shrink-0 items-center gap-0.5", children });
|
|
3270
|
-
}
|
|
3271
|
-
function RowIconAction({
|
|
3272
|
-
label,
|
|
3273
|
-
tooltip,
|
|
3274
|
-
icon,
|
|
3275
|
-
tone = "primary",
|
|
3276
|
-
disabled,
|
|
3277
|
-
onClick
|
|
3278
|
-
}) {
|
|
3279
|
-
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
3280
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx("span", { children: /* @__PURE__ */ jsx(
|
|
3281
|
-
Button,
|
|
3282
|
-
{
|
|
3283
|
-
variant: "ghost",
|
|
3284
|
-
size: "icon",
|
|
3285
|
-
className: cn(
|
|
3286
|
-
"size-6 text-muted-foreground/50 pointer-coarse:size-11",
|
|
3287
|
-
tone === "destructive" ? "hover:text-destructive" : "hover:text-primary"
|
|
3288
|
-
),
|
|
3289
|
-
"aria-label": label,
|
|
3290
|
-
disabled,
|
|
3291
|
-
onClick,
|
|
3292
|
-
children: icon
|
|
3293
|
-
}
|
|
3294
|
-
) }) }),
|
|
3295
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: tooltip ?? label })
|
|
3296
|
-
] });
|
|
3297
|
-
}
|
|
3298
|
-
function RowButton({
|
|
3299
|
-
icon,
|
|
3300
|
-
children,
|
|
3301
|
-
onClick
|
|
3302
|
-
}) {
|
|
3303
|
-
return /* @__PURE__ */ jsxs(
|
|
3304
|
-
Button,
|
|
3305
|
-
{
|
|
3306
|
-
variant: "outline",
|
|
3307
|
-
size: "sm",
|
|
3308
|
-
className: "h-7 gap-1 px-2.5 text-sm pointer-coarse:h-11",
|
|
3309
|
-
onClick,
|
|
3310
|
-
children: [
|
|
3311
|
-
icon,
|
|
3312
|
-
children
|
|
3313
|
-
]
|
|
3314
|
-
}
|
|
3315
|
-
);
|
|
3316
|
-
}
|
|
3317
|
-
function UsageActionButton({
|
|
3318
|
-
label,
|
|
3319
|
-
icon,
|
|
3320
|
-
onClick
|
|
3321
|
-
}) {
|
|
3322
|
-
return /* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
3323
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3324
|
-
Button,
|
|
3325
|
-
{
|
|
3326
|
-
variant: "ghost",
|
|
3327
|
-
size: "icon",
|
|
3328
|
-
className: "size-6 text-muted-foreground hover:text-foreground pointer-coarse:size-11",
|
|
3329
|
-
"aria-label": label,
|
|
3330
|
-
onClick,
|
|
3331
|
-
children: icon
|
|
3332
|
-
}
|
|
3333
|
-
) }),
|
|
3334
|
-
/* @__PURE__ */ jsx(TooltipContent, { children: label })
|
|
3335
|
-
] });
|
|
3336
|
-
}
|
|
3337
|
-
function UsageQuotaHint({ children }) {
|
|
3338
|
-
return /* @__PURE__ */ jsx("span", { className: "ml-1 tabular-nums", children });
|
|
3339
|
-
}
|
|
3340
|
-
function UsageSection({
|
|
3341
|
-
title,
|
|
3342
|
-
action,
|
|
3343
|
-
children,
|
|
3344
|
-
footer,
|
|
3345
|
-
gap = "sm"
|
|
3346
|
-
}) {
|
|
3347
|
-
return /* @__PURE__ */ jsxs("div", { "data-slot": "usage-section", className: gap === "md" ? "space-y-3" : void 0, children: [
|
|
3348
|
-
/* @__PURE__ */ jsxs("div", { className: cn("flex items-center justify-between", gap === "sm" && "mb-2"), children: [
|
|
3349
|
-
/* @__PURE__ */ jsx("div", { className: "text-sm font-medium text-muted-foreground", children: title }),
|
|
3350
|
-
action
|
|
3351
|
-
] }),
|
|
3352
|
-
children,
|
|
3353
|
-
footer && /* @__PURE__ */ jsx("div", { className: "mt-2", children: footer })
|
|
3354
|
-
] });
|
|
3355
|
-
}
|
|
3356
|
-
var DEFAULT_ERROR_DIALOG_LABELS = {
|
|
3357
|
-
title: "Something Went Wrong",
|
|
3358
|
-
srDescription: "Error dialog",
|
|
3359
|
-
reportHint: "Please click below to report the error to our support team if you have not done so already.",
|
|
3360
|
-
refreshHint: "Clicking Refresh Session will attempt to refresh your session, which may help resolve the error.",
|
|
3361
|
-
hideDetails: "Hide Details",
|
|
3362
|
-
viewDetails: "View Details",
|
|
3363
|
-
toggleDetailsAria: "Toggle error details",
|
|
3364
|
-
copyAria: "Copy error details",
|
|
3365
|
-
copy: "Copy error",
|
|
3366
|
-
copied: "Copied",
|
|
3367
|
-
refreshSession: "Refresh Session",
|
|
3368
|
-
logout: "Logout"
|
|
3369
|
-
};
|
|
3370
|
-
function ErrorDialogView({
|
|
3371
|
-
details,
|
|
3372
|
-
report,
|
|
3373
|
-
onRefresh,
|
|
3374
|
-
onLogout,
|
|
3375
|
-
labels
|
|
3376
|
-
}) {
|
|
3377
|
-
const l = { ...DEFAULT_ERROR_DIALOG_LABELS, ...labels };
|
|
3378
|
-
return /* @__PURE__ */ jsx(Dialog, { open: true, onOpenChange: () => {
|
|
3379
|
-
}, children: /* @__PURE__ */ jsxs(
|
|
3380
|
-
DialogContent,
|
|
3381
|
-
{
|
|
3382
|
-
presentation: "sheet",
|
|
3383
|
-
className: "flex max-h-panel w-modal max-w-modal-vw flex-col overflow-hidden p-0",
|
|
3384
|
-
"data-testid": "error-boundary-modal",
|
|
3385
|
-
hideCloseButton: true,
|
|
3386
|
-
children: [
|
|
3387
|
-
/* @__PURE__ */ jsxs(ModalHeader, { children: [
|
|
3388
|
-
/* @__PURE__ */ jsx(DialogTitle, { children: /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
3389
|
-
/* @__PURE__ */ jsx(AlertCircle, { className: "text-red-text", size: 24 }),
|
|
3390
|
-
/* @__PURE__ */ jsx("span", { children: l.title })
|
|
3391
|
-
] }) }),
|
|
3392
|
-
/* @__PURE__ */ jsx(DialogDescription, { className: "sr-only", children: l.srDescription })
|
|
3393
|
-
] }),
|
|
3394
|
-
/* @__PURE__ */ jsx("div", { className: "min-h-0 flex-1 overflow-auto px-6 pb-6", children: /* @__PURE__ */ jsxs(ModalSection, { "data-testid": "error-boundary", children: [
|
|
3395
|
-
/* @__PURE__ */ jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: l.reportHint }),
|
|
3396
|
-
/* @__PURE__ */ jsx("p", { className: "mb-4 text-sm text-muted-foreground", children: l.refreshHint }),
|
|
3397
|
-
details?.isShown && /* @__PURE__ */ jsx("div", { className: "mb-4 rounded border border-border bg-background p-3", children: /* @__PURE__ */ jsx("pre", { className: "max-h-96 overflow-auto whitespace-pre-wrap font-mono text-sm", children: details.text }) }),
|
|
3398
|
-
/* @__PURE__ */ jsxs("div", { className: "flex w-full flex-col gap-2", children: [
|
|
3399
|
-
details && /* @__PURE__ */ jsxs("div", { className: "flex w-full gap-2", children: [
|
|
3400
|
-
/* @__PURE__ */ jsxs(
|
|
3401
|
-
Button,
|
|
3402
|
-
{
|
|
3403
|
-
variant: "outline",
|
|
3404
|
-
className: "flex-1",
|
|
3405
|
-
onClick: details.onToggle,
|
|
3406
|
-
"aria-label": l.toggleDetailsAria,
|
|
3407
|
-
"data-testid": "error-boundary-view-details",
|
|
3408
|
-
children: [
|
|
3409
|
-
/* @__PURE__ */ jsx(FileText, { className: "mr-2 size-4" }),
|
|
3410
|
-
details.isShown ? l.hideDetails : l.viewDetails
|
|
3411
|
-
]
|
|
3412
|
-
}
|
|
3413
|
-
),
|
|
3414
|
-
/* @__PURE__ */ jsxs(
|
|
3415
|
-
Button,
|
|
3416
|
-
{
|
|
3417
|
-
variant: "outline",
|
|
3418
|
-
className: "flex-1",
|
|
3419
|
-
onClick: details.onCopy,
|
|
3420
|
-
"aria-label": l.copyAria,
|
|
3421
|
-
"data-testid": "error-boundary-copy-details",
|
|
3422
|
-
children: [
|
|
3423
|
-
details.isCopied ? /* @__PURE__ */ jsx(Check, { className: "mr-2 size-4 text-green-text" }) : /* @__PURE__ */ jsx(Copy, { className: "mr-2 size-4" }),
|
|
3424
|
-
details.isCopied ? l.copied : l.copy
|
|
3425
|
-
]
|
|
3426
|
-
}
|
|
3427
|
-
)
|
|
3428
|
-
] }),
|
|
3429
|
-
report,
|
|
3430
|
-
/* @__PURE__ */ jsxs(
|
|
3431
|
-
Button,
|
|
3432
|
-
{
|
|
3433
|
-
variant: "outline",
|
|
3434
|
-
className: "w-full",
|
|
3435
|
-
onClick: onRefresh,
|
|
3436
|
-
"aria-label": "Refresh session",
|
|
3437
|
-
children: [
|
|
3438
|
-
/* @__PURE__ */ jsx(RefreshCw, { className: "mr-2 size-4" }),
|
|
3439
|
-
l.refreshSession
|
|
3440
|
-
]
|
|
3441
|
-
}
|
|
3442
|
-
),
|
|
3443
|
-
/* @__PURE__ */ jsxs(Button, { variant: "outline", className: "w-full", onClick: onLogout, "aria-label": "Logout", children: [
|
|
3444
|
-
/* @__PURE__ */ jsx(LogOut, { className: "mr-2 size-4" }),
|
|
3445
|
-
l.logout
|
|
3446
|
-
] })
|
|
3447
|
-
] })
|
|
3448
|
-
] }) })
|
|
3449
|
-
]
|
|
3450
|
-
}
|
|
3451
|
-
) });
|
|
3452
|
-
}
|
|
3453
|
-
var SCHEME_OPTIONS = [
|
|
3454
|
-
{ value: "light", label: "Light", icon: /* @__PURE__ */ jsx(Sun, { className: "h-4 w-4" }) },
|
|
3455
|
-
{ value: "dark", label: "Dark", icon: /* @__PURE__ */ jsx(Moon, { className: "h-4 w-4" }) }
|
|
3456
|
-
].map((option) => ({ ...option, testId: `appearance-scheme-${option.value}` }));
|
|
3457
|
-
var TEXT_SIZE_OPTIONS = [
|
|
3458
|
-
{ value: "default", label: "Default" },
|
|
3459
|
-
{ value: "large", label: "Large" },
|
|
3460
|
-
{ value: "larger", label: "Larger" }
|
|
3461
|
-
].map((option) => ({ ...option, testId: `appearance-text-size-${option.value}` }));
|
|
3462
|
-
var DEFAULT_APPEARANCE_PAIRING_IDS = [
|
|
3463
|
-
"office",
|
|
3464
|
-
"inter",
|
|
3465
|
-
"fraunces-inter",
|
|
3466
|
-
"montserrat-nunito"
|
|
3467
|
-
];
|
|
3468
|
-
function AppearanceSettings({
|
|
3469
|
-
colorScheme,
|
|
3470
|
-
onColorSchemeChange,
|
|
3471
|
-
textSize,
|
|
3472
|
-
onTextSizeChange,
|
|
3473
|
-
pairingId,
|
|
3474
|
-
onPairingChange,
|
|
3475
|
-
pairingIds = DEFAULT_APPEARANCE_PAIRING_IDS,
|
|
3476
|
-
onReset
|
|
3477
|
-
}) {
|
|
3478
|
-
const activePairing = getFontPairing(pairingId) ?? getFontPairing(pairingIds[0]);
|
|
3479
|
-
return /* @__PURE__ */ jsxs(SettingsPanel, { testId: "settings-appearance", children: [
|
|
3480
|
-
/* @__PURE__ */ jsx(
|
|
3481
|
-
SettingsSection,
|
|
3482
|
-
{
|
|
3483
|
-
title: "Colour scheme",
|
|
3484
|
-
action: onReset && /* @__PURE__ */ jsxs(
|
|
3485
|
-
"button",
|
|
3486
|
-
{
|
|
3487
|
-
type: "button",
|
|
3488
|
-
onClick: onReset,
|
|
3489
|
-
className: "flex items-center gap-1.5 py-1 text-sm text-muted-foreground hover:text-foreground pointer-coarse:min-h-11",
|
|
3490
|
-
"data-testid": "appearance-reset",
|
|
3491
|
-
children: [
|
|
3492
|
-
/* @__PURE__ */ jsx(RotateCcw, { className: "h-3 w-3" }),
|
|
3493
|
-
"Reset"
|
|
3494
|
-
]
|
|
3495
|
-
}
|
|
3496
|
-
),
|
|
3497
|
-
children: /* @__PURE__ */ jsx(
|
|
3498
|
-
SegmentedControl,
|
|
3499
|
-
{
|
|
3500
|
-
value: colorScheme,
|
|
3501
|
-
onChange: onColorSchemeChange,
|
|
3502
|
-
options: SCHEME_OPTIONS,
|
|
3503
|
-
ariaLabel: "Colour scheme"
|
|
3504
|
-
}
|
|
3505
|
-
)
|
|
3506
|
-
}
|
|
3507
|
-
),
|
|
3508
|
-
/* @__PURE__ */ jsxs(SettingsSection, { title: "Text size", children: [
|
|
3509
|
-
/* @__PURE__ */ jsx(
|
|
3510
|
-
SegmentedControl,
|
|
3511
|
-
{
|
|
3512
|
-
value: textSize,
|
|
3513
|
-
onChange: onTextSizeChange,
|
|
3514
|
-
options: TEXT_SIZE_OPTIONS,
|
|
3515
|
-
ariaLabel: "Text size"
|
|
3516
|
-
}
|
|
3517
|
-
),
|
|
3518
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Makes all text larger, including documents in the viewer and citations. Applied straight away and remembered on this device." })
|
|
3519
|
-
] }),
|
|
3520
|
-
/* @__PURE__ */ jsxs(SettingsSection, { title: "Typeface", children: [
|
|
3521
|
-
/* @__PURE__ */ jsxs(Select, { value: pairingId, onValueChange: onPairingChange, children: [
|
|
3522
|
-
/* @__PURE__ */ jsx(SelectTrigger, { className: "w-full", "data-testid": "appearance-typeface-select", children: /* @__PURE__ */ jsx(SelectValue, { children: activePairing && /* @__PURE__ */ jsx("span", { style: { fontFamily: activePairing.display }, children: activePairing.label }) }) }),
|
|
3523
|
-
/* @__PURE__ */ jsx(SelectContent, { children: pairingIds.map((id) => {
|
|
3524
|
-
const pairing = getFontPairing(id);
|
|
3525
|
-
if (!pairing) return null;
|
|
3526
|
-
return /* @__PURE__ */ jsx(SelectItem, { value: id, "data-testid": `appearance-typeface-${id}`, children: /* @__PURE__ */ jsx("span", { style: { fontFamily: pairing.display }, children: pairing.label }) }, id);
|
|
3527
|
-
}) })
|
|
3528
|
-
] }),
|
|
3529
|
-
/* @__PURE__ */ jsx("p", { className: "text-sm text-muted-foreground", children: "Sets the headings and body text across the app. Applied straight away and remembered on this device." })
|
|
3530
|
-
] })
|
|
3531
|
-
] });
|
|
3532
|
-
}
|
|
3533
|
-
|
|
3534
|
-
export { AppearanceSettings, CONVERSATION_TITLE_MAX, CheckoutDialogFrame, ConfigSwitcherBar, ConnectionCard, ConnectionsEmpty, ConnectionsError, ConnectionsLoading, ConversationTitleSection, DEFAULT_APPEARANCE_PAIRING_IDS, DEFAULT_CHECKOUT_DIALOG_LABELS, DEFAULT_CONFIG_SWITCHER_BAR_LABELS, DEFAULT_CONNECTION_CARD_LABELS, DEFAULT_CONVERSATION_TITLE_SECTION_LABELS, DEFAULT_DAILY_CAP_FIELD_LABELS, DEFAULT_EMAIL_WORKSPACE_DIALOG_LABELS, DEFAULT_ERROR_DIALOG_LABELS, DEFAULT_INLINE_NAME_EDITOR_LABELS, DEFAULT_INVITE_CONTACTS_DIALOG_LABELS, DEFAULT_INVOICES_DIALOG_LABELS, DEFAULT_MEMBER_PROJECT_ROW_LABELS, DEFAULT_MODEL_SELECTION_SECTION_LABELS, DEFAULT_PLAN_CARD_LABELS, DEFAULT_PROJECT_CARD_VIEW_LABELS, DEFAULT_PROJECT_DETAIL_HEADER_LABELS, DEFAULT_PROJECT_LIST_LABELS, DEFAULT_QUOTA_EXCEEDED_DIALOG_LABELS, DEFAULT_REFERRAL_REWARD_LABELS, DEFAULT_RENAME_DIALOG_LABELS, DEFAULT_SHARED_PROJECTS_SECTION_LABELS, DEFAULT_SUBSCRIPTION_SECTION_LABELS, DEFAULT_SUBSCRIPTION_STATUS_LABELS, DEFAULT_SUPPORT_PANEL_LABELS, DEFAULT_SYNC_DIALOG_FOOTER_LABELS, DEFAULT_SYNC_FOLDER_ROW_LABELS, DEFAULT_TIPS_EDITOR_LABELS, DEFAULT_USAGE_LINE_CHART_LABELS, DEFAULT_USAGE_PANEL_LABELS, DEFAULT_USAGE_PROPORTION_BAR_LABELS, DEFAULT_WELCOME_DIALOG_LABELS, DailyCapField, EmailWorkspaceDialogView, ErrorDialogView, FilterChip, FloatingPanel, InlineNameEditor, InviteContactsDialog, InvoicesDialog, JsonTree, MemberProjectRow, MessageJsonTree, ModelSelectionSection, MoreInfo, MoreInfoList, PlanActionButton, PlanActionRow, PlanBadge, PlanCard, PlanCardGrid, PlanDialogFrame, PlanInfoPopover, PlanNotice, PlanPickerCard, PlanPickerHeader, PlanStack, PlanTierOption, PlanTransition, PricingToggle, ProjectCardView, ProjectDetailHeader, ProjectDetailSection, ProjectGroup, ProjectList, ProjectNameLabel, ProjectPlanPicker, ProjectRow, ProjectRowActions, PromoCodeInput, QuotaExceededDialogView, QuotaMeter, ReferralRewardBadge, ReferralRewardNote, ReferralRewardSummary, RenameDialog, RowButton, RowIconAction, SegmentedControl, SharedProjectRow, SharedProjectsSection, SubscriptionSectionView, SubscriptionStatusView, SupportPanel, SupportUnavailable, SyncCheckList, SyncDialogBody, SyncDialogFooter, SyncField, SyncFolderRow, SyncFolderStatus, SyncLinkButton, SyncLinkRow, SyncLoading, SyncNote, SyncOptionToggle, SyncOptions, SyncReconnectNotice, SyncSelect, SyncSmallNote, SyncTreeFrame, ThreadPreviewDialog, TipsEditorDialog, UsageActionButton, UsageLegend, UsageLineChart, UsagePanel, UsageProportionBar, UsageQuotaHint, UsageSection, UsageSummary, UsageToggle, WelcomeDialog, WelcomeProjectPicker };
|
|
3535
18
|
//# sourceMappingURL=index.js.map
|
|
3536
19
|
//# sourceMappingURL=index.js.map
|