@tightknitai/block-kitchen 0.10.3 → 0.10.5
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/README.md +20 -7
- package/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.cjs +495 -272
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +495 -272
- package/dist/index.js.map +1 -1
- package/dist/{palette-TGNFqyja.d.cts → palette-Sz27861i.d.cts} +9 -6
- package/dist/{palette-TGNFqyja.d.ts → palette-Sz27861i.d.ts} +9 -6
- package/dist/palette.d.cts +1 -1
- package/dist/palette.d.ts +1 -1
- package/dist/styles.css +2 -2
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -13,14 +13,14 @@ import { nanoid } from 'nanoid';
|
|
|
13
13
|
import { Slot } from '@radix-ui/react-slot';
|
|
14
14
|
import { cva } from 'class-variance-authority';
|
|
15
15
|
import * as LabelPrimitive from '@radix-ui/react-label';
|
|
16
|
+
import 'slack-blocks-to-jsx/dist/style.css';
|
|
17
|
+
import { Message } from 'slack-blocks-to-jsx';
|
|
16
18
|
import { CSS } from '@dnd-kit/utilities';
|
|
17
19
|
import * as PopoverPrimitive from '@radix-ui/react-popover';
|
|
18
20
|
import * as RadioGroupPrimitive from '@radix-ui/react-radio-group';
|
|
19
21
|
import Link from '@tiptap/extension-link';
|
|
20
22
|
import { Node, ReactNodeViewRenderer, mergeAttributes, NodeViewWrapper, useEditor, EditorContent } from '@tiptap/react';
|
|
21
23
|
import StarterKit from '@tiptap/starter-kit';
|
|
22
|
-
import 'slack-blocks-to-jsx/dist/style.css';
|
|
23
|
-
import { Message } from 'slack-blocks-to-jsx';
|
|
24
24
|
|
|
25
25
|
// src/components/block-kitchen.tsx
|
|
26
26
|
|
|
@@ -3024,6 +3024,128 @@ var Label = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ j
|
|
|
3024
3024
|
}
|
|
3025
3025
|
));
|
|
3026
3026
|
Label.displayName = LabelPrimitive.Root.displayName;
|
|
3027
|
+
function SlackBlockPreview({
|
|
3028
|
+
block,
|
|
3029
|
+
hooks,
|
|
3030
|
+
theme = "light"
|
|
3031
|
+
}) {
|
|
3032
|
+
const rootRef = useRef(null);
|
|
3033
|
+
const safeBlock = useMemo(() => sanitizeBlock(block), [block]);
|
|
3034
|
+
useEffect(() => {
|
|
3035
|
+
const root = rootRef.current;
|
|
3036
|
+
if (!root) return;
|
|
3037
|
+
for (const wrapper of root.querySelectorAll(
|
|
3038
|
+
".slack_blocks_to_jsx__image_media_trigger, .slack_blocks_to_jsx__video_title"
|
|
3039
|
+
)) {
|
|
3040
|
+
for (const btn of wrapper.querySelectorAll("button:not([aria-label])")) {
|
|
3041
|
+
const title = wrapper.querySelector(".slack_blocks_to_jsx__image_title")?.textContent?.trim();
|
|
3042
|
+
btn.setAttribute("aria-label", title ? `Toggle ${title}` : "Toggle media");
|
|
3043
|
+
}
|
|
3044
|
+
}
|
|
3045
|
+
for (const a of root.querySelectorAll("a[href]")) {
|
|
3046
|
+
const href = a.getAttribute("href");
|
|
3047
|
+
if (!isSafeHref(href)) {
|
|
3048
|
+
a.setAttribute("href", "#");
|
|
3049
|
+
a.setAttribute("data-bk-blocked-href", "1");
|
|
3050
|
+
}
|
|
3051
|
+
}
|
|
3052
|
+
for (const img of root.querySelectorAll("img[src]")) {
|
|
3053
|
+
const src = img.getAttribute("src");
|
|
3054
|
+
if (!isSafeImageSrc(src)) {
|
|
3055
|
+
img.removeAttribute("src");
|
|
3056
|
+
img.setAttribute("data-bk-blocked-src", "1");
|
|
3057
|
+
}
|
|
3058
|
+
}
|
|
3059
|
+
});
|
|
3060
|
+
return (
|
|
3061
|
+
// The library scopes all of its CSS under `#slack_blocks_to_jsx` and
|
|
3062
|
+
// depends on the `slack_blocks_to_jsx styles_enabled` classes plus the
|
|
3063
|
+
// `data-theme` attribute for its button / mention / divider styling
|
|
3064
|
+
// (e.g. button reset + `bg-green-primary` for primary). `<Message
|
|
3065
|
+
// withoutWrapper>` skips that wrapper entirely, so we re-create it
|
|
3066
|
+
// here without the avatar / timestamp chrome.
|
|
3067
|
+
/* @__PURE__ */ jsx("div", { ref: rootRef, id: "slack_blocks_to_jsx", "data-theme": theme, className: "slack_blocks_to_jsx styles_enabled", children: /* @__PURE__ */ jsx(
|
|
3068
|
+
Message,
|
|
3069
|
+
{
|
|
3070
|
+
time: /* @__PURE__ */ new Date(),
|
|
3071
|
+
name: "",
|
|
3072
|
+
logo: "",
|
|
3073
|
+
withoutWrapper: true,
|
|
3074
|
+
theme,
|
|
3075
|
+
blocks: [safeBlock],
|
|
3076
|
+
hooks
|
|
3077
|
+
}
|
|
3078
|
+
) })
|
|
3079
|
+
);
|
|
3080
|
+
}
|
|
3081
|
+
var PLACEHOLDER_TIME = "10:37 AM";
|
|
3082
|
+
function SlackMessageFrame({
|
|
3083
|
+
workspaceName,
|
|
3084
|
+
authorName,
|
|
3085
|
+
authorIcon,
|
|
3086
|
+
time = PLACEHOLDER_TIME,
|
|
3087
|
+
isDark,
|
|
3088
|
+
children
|
|
3089
|
+
}) {
|
|
3090
|
+
const displayName = authorName ?? workspaceName ?? "Your app";
|
|
3091
|
+
const initial = displayName.slice(0, 1).toUpperCase();
|
|
3092
|
+
const safeIcon = authorIcon && isSafeImageSrc(authorIcon) ? authorIcon : null;
|
|
3093
|
+
return /* @__PURE__ */ jsxs(
|
|
3094
|
+
"div",
|
|
3095
|
+
{
|
|
3096
|
+
className: cn(
|
|
3097
|
+
"flex flex-col overflow-hidden rounded-md border",
|
|
3098
|
+
isDark ? "border-[#2c2d30] bg-[#1a1d21]" : "border-[#e8e8e8] bg-white"
|
|
3099
|
+
),
|
|
3100
|
+
children: [
|
|
3101
|
+
/* @__PURE__ */ jsxs(
|
|
3102
|
+
"div",
|
|
3103
|
+
{
|
|
3104
|
+
className: cn("flex items-center gap-2 px-5 pt-3 pb-1 text-xs", isDark ? "text-white/60" : "text-[#616061]"),
|
|
3105
|
+
children: [
|
|
3106
|
+
safeIcon ? /* @__PURE__ */ jsx("img", { src: safeIcon, alt: "", className: "h-7 w-7 shrink-0 rounded object-cover" }) : /* @__PURE__ */ jsx(
|
|
3107
|
+
"span",
|
|
3108
|
+
{
|
|
3109
|
+
className: cn(
|
|
3110
|
+
"inline-flex h-7 w-7 items-center justify-center rounded text-[12px] font-semibold",
|
|
3111
|
+
isDark ? "bg-white/10 text-white" : "bg-[#4a154b]/10 text-[#1d1c1d]"
|
|
3112
|
+
),
|
|
3113
|
+
children: initial
|
|
3114
|
+
}
|
|
3115
|
+
),
|
|
3116
|
+
/* @__PURE__ */ jsx("span", { className: cn("font-bold text-sm", isDark ? "text-white" : "text-[#1d1c1d]"), children: displayName }),
|
|
3117
|
+
time ? /* @__PURE__ */ jsx("span", { children: time }) : null
|
|
3118
|
+
]
|
|
3119
|
+
}
|
|
3120
|
+
),
|
|
3121
|
+
children
|
|
3122
|
+
]
|
|
3123
|
+
}
|
|
3124
|
+
);
|
|
3125
|
+
}
|
|
3126
|
+
function SlackMessagePreview({
|
|
3127
|
+
blocks,
|
|
3128
|
+
hooks,
|
|
3129
|
+
theme = "light",
|
|
3130
|
+
workspaceName,
|
|
3131
|
+
authorName,
|
|
3132
|
+
authorIcon,
|
|
3133
|
+
time,
|
|
3134
|
+
emptyLabel = "This message has no blocks to preview."
|
|
3135
|
+
}) {
|
|
3136
|
+
const isDark = theme === "dark";
|
|
3137
|
+
return /* @__PURE__ */ jsx(
|
|
3138
|
+
SlackMessageFrame,
|
|
3139
|
+
{
|
|
3140
|
+
workspaceName,
|
|
3141
|
+
authorName,
|
|
3142
|
+
authorIcon,
|
|
3143
|
+
time,
|
|
3144
|
+
isDark,
|
|
3145
|
+
children: /* @__PURE__ */ jsx("div", { className: cn("flex min-w-0 flex-col gap-1 px-5 pb-3", isDark ? "bg-[#1a1d21]" : "bg-white"), children: blocks.length === 0 ? /* @__PURE__ */ jsx("p", { className: cn("py-1 text-sm", isDark ? "text-white/60" : "text-[#616061]"), children: emptyLabel }) : blocks.map((block, index) => /* @__PURE__ */ jsx(SlackBlockPreview, { block, hooks, theme }, `${block.type}-${index}`)) })
|
|
3146
|
+
}
|
|
3147
|
+
);
|
|
3148
|
+
}
|
|
3027
3149
|
var POLL_INTERVAL_MS = 2500;
|
|
3028
3150
|
var MAX_POLLS = 24;
|
|
3029
3151
|
function useSlackSignIn(loadStatus, { open, enabled }) {
|
|
@@ -3097,6 +3219,13 @@ function SlackSignInButton({ onClick, polling }) {
|
|
|
3097
3219
|
/* @__PURE__ */ jsx(ExternalLink, {})
|
|
3098
3220
|
] }) });
|
|
3099
3221
|
}
|
|
3222
|
+
var LINK_DEBOUNCE_MS = 400;
|
|
3223
|
+
var LINK_HELP_TEXT = 'Click the \u2807menu while hovering over the message in Slack (or right-click), and select "Copy Link".';
|
|
3224
|
+
var LINK_HELP_LABEL = "Where to find a message link";
|
|
3225
|
+
var TABS = [
|
|
3226
|
+
{ id: "recent", label: "Pick from Recent" },
|
|
3227
|
+
{ id: "link", label: "Direct Link" }
|
|
3228
|
+
];
|
|
3100
3229
|
function recentToResult(msg) {
|
|
3101
3230
|
return {
|
|
3102
3231
|
ok: true,
|
|
@@ -3121,6 +3250,16 @@ function previewText(m) {
|
|
|
3121
3250
|
}
|
|
3122
3251
|
return `${m.blocks.length} block${m.blocks.length === 1 ? "" : "s"}`;
|
|
3123
3252
|
}
|
|
3253
|
+
function formatTs(ts) {
|
|
3254
|
+
const seconds = Number(ts);
|
|
3255
|
+
if (!ts || !Number.isFinite(seconds) || seconds <= 0) {
|
|
3256
|
+
return "";
|
|
3257
|
+
}
|
|
3258
|
+
return new Date(seconds * 1e3).toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" });
|
|
3259
|
+
}
|
|
3260
|
+
function editableLabel(editableVia) {
|
|
3261
|
+
return editableVia === "user" ? "You" : "Bot";
|
|
3262
|
+
}
|
|
3124
3263
|
function LoadMessageDialog({
|
|
3125
3264
|
open,
|
|
3126
3265
|
onOpenChange,
|
|
@@ -3128,10 +3267,14 @@ function LoadMessageDialog({
|
|
|
3128
3267
|
loadRecentMessages,
|
|
3129
3268
|
loadChannels,
|
|
3130
3269
|
onLoaded,
|
|
3131
|
-
onOpenAsNew
|
|
3270
|
+
onOpenAsNew,
|
|
3271
|
+
previewHooks,
|
|
3272
|
+
previewTheme = "light"
|
|
3132
3273
|
}) {
|
|
3133
3274
|
const [link, setLink] = useState("");
|
|
3134
|
-
const [
|
|
3275
|
+
const [linkStatus, setLinkStatus] = useState({ kind: "idle" });
|
|
3276
|
+
const [emptyLinkError, setEmptyLinkError] = useState(null);
|
|
3277
|
+
const [committing, setCommitting] = useState(false);
|
|
3135
3278
|
const [channels, setChannels] = useState(null);
|
|
3136
3279
|
const [channelsError, setChannelsError] = useState(null);
|
|
3137
3280
|
const [channelId, setChannelId] = useState("");
|
|
@@ -3139,8 +3282,14 @@ function LoadMessageDialog({
|
|
|
3139
3282
|
const [recentError, setRecentError] = useState(null);
|
|
3140
3283
|
const [selectedRecent, setSelectedRecent] = useState(null);
|
|
3141
3284
|
const [signInPolling, setSignInPolling] = useState(false);
|
|
3285
|
+
const [tab, setTab] = useState("recent");
|
|
3142
3286
|
const inputRef = useRef(null);
|
|
3143
3287
|
const signInPollRef = useRef(null);
|
|
3288
|
+
const resolvedLinkRef = useRef(null);
|
|
3289
|
+
const linkRequestRef = useRef(0);
|
|
3290
|
+
const domId = useId();
|
|
3291
|
+
const tabDomId = (id) => `${domId}-${id}-tab`;
|
|
3292
|
+
const panelDomId = (id) => `${domId}-${id}-panel`;
|
|
3144
3293
|
const onLoadMessageRef = useRef(onLoadMessage);
|
|
3145
3294
|
const loadRecentMessagesRef = useRef(loadRecentMessages);
|
|
3146
3295
|
const loadChannelsRef = useRef(loadChannels);
|
|
@@ -3150,16 +3299,22 @@ function LoadMessageDialog({
|
|
|
3150
3299
|
loadChannelsRef.current = loadChannels;
|
|
3151
3300
|
});
|
|
3152
3301
|
const hasRecent = !!loadRecentMessages && !!loadChannels;
|
|
3302
|
+
const activeTab = hasRecent ? tab : "link";
|
|
3153
3303
|
useEffect(() => {
|
|
3154
3304
|
if (!open) {
|
|
3155
3305
|
return;
|
|
3156
3306
|
}
|
|
3157
3307
|
setLink("");
|
|
3158
|
-
|
|
3308
|
+
setLinkStatus({ kind: "idle" });
|
|
3309
|
+
setEmptyLinkError(null);
|
|
3310
|
+
setCommitting(false);
|
|
3159
3311
|
setChannelId("");
|
|
3160
3312
|
setRecent(null);
|
|
3161
3313
|
setRecentError(null);
|
|
3162
3314
|
setSelectedRecent(null);
|
|
3315
|
+
setTab("recent");
|
|
3316
|
+
resolvedLinkRef.current = null;
|
|
3317
|
+
linkRequestRef.current += 1;
|
|
3163
3318
|
}, [open]);
|
|
3164
3319
|
useEffect(() => {
|
|
3165
3320
|
const load = loadChannelsRef.current;
|
|
@@ -3218,27 +3373,71 @@ function LoadMessageDialog({
|
|
|
3218
3373
|
}
|
|
3219
3374
|
return stopSignInPoll;
|
|
3220
3375
|
}, [open, stopSignInPoll]);
|
|
3376
|
+
const resolveLink = useCallback(async (trimmed) => {
|
|
3377
|
+
const requestId = ++linkRequestRef.current;
|
|
3378
|
+
setLinkStatus({ kind: "loading" });
|
|
3379
|
+
try {
|
|
3380
|
+
const result = await onLoadMessageRef.current({ link: trimmed });
|
|
3381
|
+
if (linkRequestRef.current !== requestId) {
|
|
3382
|
+
return null;
|
|
3383
|
+
}
|
|
3384
|
+
resolvedLinkRef.current = trimmed;
|
|
3385
|
+
setLinkStatus(
|
|
3386
|
+
result.ok ? { kind: "ready", result } : { kind: "not-editable", reason: result.reason, blocks: result.blocks, oauthUrl: result.oauthUrl }
|
|
3387
|
+
);
|
|
3388
|
+
return result;
|
|
3389
|
+
} catch (e) {
|
|
3390
|
+
if (linkRequestRef.current !== requestId) {
|
|
3391
|
+
return null;
|
|
3392
|
+
}
|
|
3393
|
+
resolvedLinkRef.current = trimmed;
|
|
3394
|
+
setLinkStatus({ kind: "error", error: e instanceof Error ? e.message : "Failed to load message." });
|
|
3395
|
+
return null;
|
|
3396
|
+
}
|
|
3397
|
+
}, []);
|
|
3398
|
+
useEffect(() => {
|
|
3399
|
+
if (!open) {
|
|
3400
|
+
return;
|
|
3401
|
+
}
|
|
3402
|
+
const trimmed = link.trim();
|
|
3403
|
+
if (!trimmed) {
|
|
3404
|
+
linkRequestRef.current += 1;
|
|
3405
|
+
resolvedLinkRef.current = null;
|
|
3406
|
+
setLinkStatus({ kind: "idle" });
|
|
3407
|
+
return;
|
|
3408
|
+
}
|
|
3409
|
+
if (resolvedLinkRef.current === trimmed) {
|
|
3410
|
+
return;
|
|
3411
|
+
}
|
|
3412
|
+
const timer = setTimeout(() => {
|
|
3413
|
+
if (resolvedLinkRef.current !== trimmed) {
|
|
3414
|
+
void resolveLink(trimmed);
|
|
3415
|
+
}
|
|
3416
|
+
}, LINK_DEBOUNCE_MS);
|
|
3417
|
+
return () => clearTimeout(timer);
|
|
3418
|
+
}, [open, link, resolveLink]);
|
|
3221
3419
|
const handleLoad = async () => {
|
|
3222
3420
|
stopSignInPoll();
|
|
3223
|
-
if (
|
|
3224
|
-
|
|
3421
|
+
if (activeTab === "recent") {
|
|
3422
|
+
if (selectedRecent) {
|
|
3423
|
+
onLoaded(recentToResult(selectedRecent));
|
|
3424
|
+
}
|
|
3225
3425
|
return;
|
|
3226
3426
|
}
|
|
3227
3427
|
const trimmed = link.trim();
|
|
3228
3428
|
if (!trimmed) {
|
|
3229
|
-
|
|
3429
|
+
setEmptyLinkError("Paste a Slack message link first.");
|
|
3230
3430
|
return;
|
|
3231
3431
|
}
|
|
3232
|
-
|
|
3233
|
-
|
|
3234
|
-
|
|
3235
|
-
|
|
3236
|
-
|
|
3237
|
-
|
|
3238
|
-
|
|
3239
|
-
|
|
3240
|
-
|
|
3241
|
-
setStatus({ kind: "error", error: e instanceof Error ? e.message : "Failed to load message." });
|
|
3432
|
+
if (linkStatus.kind === "ready" && resolvedLinkRef.current === trimmed) {
|
|
3433
|
+
onLoaded(linkStatus.result);
|
|
3434
|
+
return;
|
|
3435
|
+
}
|
|
3436
|
+
setCommitting(true);
|
|
3437
|
+
const result = await resolveLink(trimmed);
|
|
3438
|
+
setCommitting(false);
|
|
3439
|
+
if (result?.ok) {
|
|
3440
|
+
onLoaded(result);
|
|
3242
3441
|
}
|
|
3243
3442
|
};
|
|
3244
3443
|
const startFindSignIn = (oauthUrl) => {
|
|
@@ -3270,191 +3469,301 @@ function LoadMessageDialog({
|
|
|
3270
3469
|
});
|
|
3271
3470
|
}, POLL_INTERVAL_MS2);
|
|
3272
3471
|
};
|
|
3273
|
-
const
|
|
3274
|
-
const
|
|
3472
|
+
const preview = activeTab === "recent" ? selectedRecent ? { kind: "ready", target: { ...selectedRecent, editableVia: selectedRecent.editableVia ?? "bot" } } : { kind: "empty" } : linkStatus.kind === "idle" ? { kind: "empty" } : linkStatus.kind === "ready" ? { kind: "ready", target: linkStatus.result } : linkStatus;
|
|
3473
|
+
const canLoad = activeTab === "recent" ? !!selectedRecent : !!link.trim();
|
|
3474
|
+
const panelProps = (id) => hasRecent ? { role: "tabpanel", id: panelDomId(id), "aria-labelledby": tabDomId(id) } : {};
|
|
3275
3475
|
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
|
|
3276
3476
|
DialogContent,
|
|
3277
3477
|
{
|
|
3278
|
-
className: "w-[calc(100vw-1.5rem)] max-w-
|
|
3478
|
+
className: "flex max-h-[85svh] w-[calc(100vw-1.5rem)] max-w-4xl flex-col rounded-lg max-lg:max-w-lg",
|
|
3279
3479
|
onOpenAutoFocus: (e) => {
|
|
3480
|
+
if (hasRecent) {
|
|
3481
|
+
return;
|
|
3482
|
+
}
|
|
3280
3483
|
e.preventDefault();
|
|
3281
3484
|
inputRef.current?.focus();
|
|
3282
3485
|
},
|
|
3283
3486
|
children: [
|
|
3284
|
-
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
3487
|
+
/* @__PURE__ */ jsxs(DialogHeader, { className: "shrink-0", children: [
|
|
3285
3488
|
/* @__PURE__ */ jsx(DialogTitle, { children: "Find an existing message" }),
|
|
3286
|
-
/* @__PURE__ */
|
|
3287
|
-
/* @__PURE__ */ jsx(DialogDescription, { children: hasRecent ? "Paste a Slack message link, or pick a recent message your app posted." : `Paste a Slack message link (Slack's "Copy link") to load its blocks for editing.` }),
|
|
3288
|
-
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
3289
|
-
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3290
|
-
"button",
|
|
3291
|
-
{
|
|
3292
|
-
type: "button",
|
|
3293
|
-
"aria-label": "How to copy a message link",
|
|
3294
|
-
className: "mt-0.5 shrink-0 rounded text-muted-foreground transition-colors hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
3295
|
-
children: /* @__PURE__ */ jsx(Info, { className: "h-3.5 w-3.5" })
|
|
3296
|
-
}
|
|
3297
|
-
) }),
|
|
3298
|
-
/* @__PURE__ */ jsxs(TooltipContent, { className: "max-w-xs leading-relaxed", children: [
|
|
3299
|
-
"In Slack, hover over the message and click the ",
|
|
3300
|
-
/* @__PURE__ */ jsx("strong", { children: "\u22EE More actions" }),
|
|
3301
|
-
" button (or right-click the message), then choose ",
|
|
3302
|
-
/* @__PURE__ */ jsx("strong", { children: "Copy link" }),
|
|
3303
|
-
"."
|
|
3304
|
-
] })
|
|
3305
|
-
] })
|
|
3306
|
-
] })
|
|
3489
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: hasRecent ? "Pick a recent message your app posted, or paste a Slack message link. Preview it before loading." : `Paste a Slack message link (Slack's "Copy link") to preview it and load its blocks for editing.` })
|
|
3307
3490
|
] }),
|
|
3308
|
-
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-col gap-4", children: [
|
|
3309
|
-
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-
|
|
3310
|
-
/* @__PURE__ */ jsx(
|
|
3311
|
-
/* @__PURE__ */
|
|
3312
|
-
|
|
3491
|
+
/* @__PURE__ */ jsxs("div", { className: "-mx-1 flex min-h-0 min-w-0 flex-1 px-1 max-lg:flex-col max-lg:gap-4 max-lg:overflow-y-auto lg:flex-row lg:gap-5 lg:overflow-hidden", children: [
|
|
3492
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 shrink-0 flex-col gap-3 lg:min-h-0 lg:w-[19rem]", children: [
|
|
3493
|
+
hasRecent && /* @__PURE__ */ jsx(TabStrip, { activeTab, onSelect: setTab, tabDomId, panelDomId }),
|
|
3494
|
+
activeTab === "recent" ? /* @__PURE__ */ jsxs(
|
|
3495
|
+
"div",
|
|
3313
3496
|
{
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3497
|
+
...panelProps("recent"),
|
|
3498
|
+
className: "-mx-1 flex min-w-0 flex-col gap-2 px-1 lg:min-h-0 lg:flex-1 lg:overflow-hidden",
|
|
3499
|
+
children: [
|
|
3500
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col gap-1.5", children: [
|
|
3501
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "recent-channel-picker", children: "Channel" }),
|
|
3502
|
+
channels === null && !channelsError && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Loading channels\u2026" }),
|
|
3503
|
+
channelsError && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: channelsError }),
|
|
3504
|
+
channels && channels.length === 0 && !channelsError && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "No public channels available." }),
|
|
3505
|
+
channels && channels.length > 0 && /* @__PURE__ */ jsxs(
|
|
3506
|
+
"select",
|
|
3507
|
+
{
|
|
3508
|
+
id: "recent-channel-picker",
|
|
3509
|
+
value: channelId,
|
|
3510
|
+
onChange: (e) => setChannelId(e.target.value),
|
|
3511
|
+
className: "flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
3512
|
+
children: [
|
|
3513
|
+
/* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Select a channel\u2026" }),
|
|
3514
|
+
channels.map((c) => /* @__PURE__ */ jsxs("option", { value: c.id, children: [
|
|
3515
|
+
"#",
|
|
3516
|
+
c.name
|
|
3517
|
+
] }, c.id))
|
|
3518
|
+
]
|
|
3519
|
+
}
|
|
3520
|
+
)
|
|
3521
|
+
] }),
|
|
3522
|
+
!channelId && channels && channels.length > 0 && /* @__PURE__ */ jsx("p", { className: "shrink-0 text-xs text-muted-foreground", children: "Select a channel to see recent messages." }),
|
|
3523
|
+
channelId && recent === null && !recentError && /* @__PURE__ */ jsx("p", { className: "shrink-0 text-xs text-muted-foreground", children: "Loading recent messages\u2026" }),
|
|
3524
|
+
channelId && recentError && /* @__PURE__ */ jsx("p", { className: "shrink-0 text-xs text-destructive", children: recentError }),
|
|
3525
|
+
channelId && recent && recent.length === 0 && !recentError && /* @__PURE__ */ jsx("p", { className: "shrink-0 text-xs text-muted-foreground", children: "No recent messages from this app in this channel." }),
|
|
3526
|
+
channelId && recent && recent.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex min-h-0 min-w-0 flex-col gap-1 overflow-y-auto max-lg:max-h-60 lg:flex-1", children: recent.map((m) => {
|
|
3527
|
+
const asUser = (m.editableVia ?? "bot") === "user";
|
|
3528
|
+
const authorName = m.username || (asUser ? "You" : "App bot");
|
|
3529
|
+
const safeIcon = isSafeImageSrc(m.iconUrl) ? m.iconUrl : void 0;
|
|
3530
|
+
const isSelected = selectedRecent?.channelId === m.channelId && selectedRecent?.ts === m.ts;
|
|
3531
|
+
return /* @__PURE__ */ jsxs(
|
|
3532
|
+
"button",
|
|
3533
|
+
{
|
|
3534
|
+
type: "button",
|
|
3535
|
+
"aria-pressed": isSelected,
|
|
3536
|
+
onClick: () => {
|
|
3537
|
+
setSelectedRecent(m);
|
|
3538
|
+
},
|
|
3539
|
+
className: cn(
|
|
3540
|
+
// Inset rings so the scroll container's overflow clip
|
|
3541
|
+
// can't shave the corners off the selected outline.
|
|
3542
|
+
"flex min-w-0 items-start gap-2.5 rounded-md border border-input bg-background px-3 py-2 text-left hover:bg-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring",
|
|
3543
|
+
isSelected && "border-primary! bg-accent ring-1 ring-inset ring-primary"
|
|
3544
|
+
),
|
|
3545
|
+
children: [
|
|
3546
|
+
safeIcon ? /* @__PURE__ */ jsx("img", { src: safeIcon, alt: "", className: "h-9 w-9 shrink-0 rounded-md object-cover" }) : /* @__PURE__ */ jsx(
|
|
3547
|
+
"span",
|
|
3548
|
+
{
|
|
3549
|
+
"aria-hidden": true,
|
|
3550
|
+
className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-muted text-sm font-semibold text-muted-foreground",
|
|
3551
|
+
children: authorName.charAt(0).toUpperCase()
|
|
3552
|
+
}
|
|
3553
|
+
),
|
|
3554
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
|
|
3555
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
3556
|
+
/* @__PURE__ */ jsx("span", { className: "truncate text-sm font-semibold text-foreground", children: authorName }),
|
|
3557
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 rounded border px-1 py-px text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: asUser ? "You" : "Bot" })
|
|
3558
|
+
] }),
|
|
3559
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
3560
|
+
new Date(Number(m.ts) * 1e3).toLocaleString(),
|
|
3561
|
+
" ",
|
|
3562
|
+
/* @__PURE__ */ jsxs("span", { className: "font-mono", children: [
|
|
3563
|
+
"(",
|
|
3564
|
+
m.ts,
|
|
3565
|
+
")"
|
|
3566
|
+
] })
|
|
3567
|
+
] }),
|
|
3568
|
+
/* @__PURE__ */ jsx("span", { className: "line-clamp-2 text-sm text-foreground", children: previewText(m) })
|
|
3569
|
+
] })
|
|
3570
|
+
]
|
|
3571
|
+
},
|
|
3572
|
+
`${m.channelId}:${m.ts}`
|
|
3573
|
+
);
|
|
3574
|
+
}) })
|
|
3575
|
+
]
|
|
3576
|
+
}
|
|
3577
|
+
) : /* @__PURE__ */ jsxs(
|
|
3578
|
+
"div",
|
|
3579
|
+
{
|
|
3580
|
+
...panelProps("link"),
|
|
3581
|
+
className: "-mx-1 flex min-w-0 flex-col gap-2 px-1 lg:min-h-0 lg:flex-1 lg:overflow-y-auto",
|
|
3582
|
+
children: [
|
|
3583
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
3584
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3585
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "message-link", children: "Message link" }),
|
|
3586
|
+
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
3587
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
3588
|
+
"button",
|
|
3589
|
+
{
|
|
3590
|
+
type: "button",
|
|
3591
|
+
"aria-label": LINK_HELP_LABEL,
|
|
3592
|
+
className: "flex h-4 w-4 items-center justify-center rounded-full text-muted-foreground hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
3593
|
+
children: /* @__PURE__ */ jsx(Info, { className: "h-3.5 w-3.5" })
|
|
3594
|
+
}
|
|
3595
|
+
) }),
|
|
3596
|
+
/* @__PURE__ */ jsx(TooltipContent, { side: "right", children: LINK_HELP_TEXT })
|
|
3597
|
+
] })
|
|
3598
|
+
] }),
|
|
3599
|
+
/* @__PURE__ */ jsx(
|
|
3600
|
+
Input,
|
|
3601
|
+
{
|
|
3602
|
+
ref: inputRef,
|
|
3603
|
+
id: "message-link",
|
|
3604
|
+
value: link,
|
|
3605
|
+
onChange: (e) => {
|
|
3606
|
+
setLink(e.target.value);
|
|
3607
|
+
setEmptyLinkError(null);
|
|
3608
|
+
stopSignInPoll();
|
|
3609
|
+
},
|
|
3610
|
+
onKeyDown: (e) => {
|
|
3611
|
+
if (e.key === "Enter" && !committing) {
|
|
3612
|
+
e.preventDefault();
|
|
3613
|
+
handleLoad();
|
|
3614
|
+
}
|
|
3615
|
+
},
|
|
3616
|
+
placeholder: "https://your-workspace.slack.com/archives/C\u2026/p\u2026",
|
|
3617
|
+
autoComplete: "off",
|
|
3618
|
+
spellCheck: false
|
|
3619
|
+
}
|
|
3620
|
+
)
|
|
3621
|
+
] }),
|
|
3622
|
+
emptyLinkError && /* @__PURE__ */ jsx("p", { className: "rounded-md border border-destructive/30 bg-destructive/5 p-2 text-xs text-destructive", children: emptyLinkError })
|
|
3623
|
+
]
|
|
3334
3624
|
}
|
|
3335
3625
|
)
|
|
3336
3626
|
] }),
|
|
3337
|
-
|
|
3338
|
-
|
|
3627
|
+
/* @__PURE__ */ jsx(
|
|
3628
|
+
PreviewPane,
|
|
3629
|
+
{
|
|
3630
|
+
state: preview,
|
|
3631
|
+
hooks: previewHooks,
|
|
3632
|
+
theme: previewTheme,
|
|
3633
|
+
emptyHint: activeTab === "recent" ? "Select a recent message to preview it here." : "Paste a message link to preview it here.",
|
|
3634
|
+
signInPolling,
|
|
3635
|
+
onSignIn: startFindSignIn,
|
|
3636
|
+
onOpenAsNew
|
|
3637
|
+
}
|
|
3638
|
+
)
|
|
3639
|
+
] }),
|
|
3640
|
+
/* @__PURE__ */ jsxs(DialogFooter, { className: "shrink-0", children: [
|
|
3641
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
3642
|
+
/* @__PURE__ */ jsx(Button, { type: "button", onClick: handleLoad, disabled: committing || !canLoad, children: committing ? "Loading\u2026" : "Load message" })
|
|
3643
|
+
] })
|
|
3644
|
+
]
|
|
3645
|
+
}
|
|
3646
|
+
) });
|
|
3647
|
+
}
|
|
3648
|
+
function TabStrip({
|
|
3649
|
+
activeTab,
|
|
3650
|
+
onSelect,
|
|
3651
|
+
tabDomId,
|
|
3652
|
+
panelDomId
|
|
3653
|
+
}) {
|
|
3654
|
+
const tabRefs = useRef({});
|
|
3655
|
+
const moveTo = (next) => {
|
|
3656
|
+
onSelect(next);
|
|
3657
|
+
tabRefs.current[next]?.focus();
|
|
3658
|
+
};
|
|
3659
|
+
return /* @__PURE__ */ jsx("div", { role: "tablist", "aria-label": "Message source", className: "flex shrink-0 gap-1 rounded-md bg-muted p-1", children: TABS.map((entry, index) => {
|
|
3660
|
+
const selected = entry.id === activeTab;
|
|
3661
|
+
return /* @__PURE__ */ jsx(
|
|
3662
|
+
"button",
|
|
3663
|
+
{
|
|
3664
|
+
ref: (node) => {
|
|
3665
|
+
tabRefs.current[entry.id] = node;
|
|
3666
|
+
},
|
|
3667
|
+
type: "button",
|
|
3668
|
+
role: "tab",
|
|
3669
|
+
id: tabDomId(entry.id),
|
|
3670
|
+
"aria-selected": selected,
|
|
3671
|
+
"aria-controls": panelDomId(entry.id),
|
|
3672
|
+
tabIndex: selected ? 0 : -1,
|
|
3673
|
+
onClick: () => onSelect(entry.id),
|
|
3674
|
+
onKeyDown: (e) => {
|
|
3675
|
+
if (e.key === "ArrowRight" || e.key === "ArrowLeft") {
|
|
3676
|
+
e.preventDefault();
|
|
3677
|
+
const delta = e.key === "ArrowRight" ? 1 : -1;
|
|
3678
|
+
moveTo(TABS[(index + delta + TABS.length) % TABS.length].id);
|
|
3679
|
+
} else if (e.key === "Home") {
|
|
3680
|
+
e.preventDefault();
|
|
3681
|
+
moveTo(TABS[0].id);
|
|
3682
|
+
} else if (e.key === "End") {
|
|
3683
|
+
e.preventDefault();
|
|
3684
|
+
moveTo(TABS[TABS.length - 1].id);
|
|
3685
|
+
}
|
|
3686
|
+
},
|
|
3687
|
+
className: cn(
|
|
3688
|
+
"flex-1 rounded-sm px-3 py-1.5 text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
3689
|
+
selected ? "bg-background text-foreground shadow-sm" : "text-muted-foreground hover:text-foreground"
|
|
3690
|
+
),
|
|
3691
|
+
children: entry.label
|
|
3692
|
+
},
|
|
3693
|
+
entry.id
|
|
3694
|
+
);
|
|
3695
|
+
}) });
|
|
3696
|
+
}
|
|
3697
|
+
function PreviewPane({
|
|
3698
|
+
state,
|
|
3699
|
+
hooks,
|
|
3700
|
+
theme,
|
|
3701
|
+
emptyHint,
|
|
3702
|
+
signInPolling,
|
|
3703
|
+
onSignIn,
|
|
3704
|
+
onOpenAsNew
|
|
3705
|
+
}) {
|
|
3706
|
+
const target = state.kind === "ready" ? state.target : null;
|
|
3707
|
+
const signInUrl = state.kind === "not-editable" && state.oauthUrl && isSafeHref(state.oauthUrl) ? state.oauthUrl : null;
|
|
3708
|
+
const verdictBlocks = state.kind === "not-editable" ? state.blocks : void 0;
|
|
3709
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex min-w-0 shrink-0 flex-col gap-2 lg:min-h-0 lg:flex-1", children: [
|
|
3710
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-wrap items-center gap-2", children: [
|
|
3711
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "Preview" }),
|
|
3712
|
+
target?.channelName || target?.channelId ? /* @__PURE__ */ jsx("span", { className: "rounded border px-1.5 py-px text-[10px] font-medium text-muted-foreground", children: target.channelName ? `#${target.channelName}` : target.channelId }) : null,
|
|
3713
|
+
target?.editableVia ? /* @__PURE__ */ jsxs("span", { className: "rounded border px-1.5 py-px text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: [
|
|
3714
|
+
"Editable as ",
|
|
3715
|
+
editableLabel(target.editableVia)
|
|
3716
|
+
] }) : null
|
|
3717
|
+
] }),
|
|
3718
|
+
/* @__PURE__ */ jsxs(
|
|
3719
|
+
"div",
|
|
3720
|
+
{
|
|
3721
|
+
role: "region",
|
|
3722
|
+
"aria-label": "Message preview",
|
|
3723
|
+
tabIndex: 0,
|
|
3724
|
+
className: "flex flex-1 flex-col gap-3 overflow-y-auto rounded-md border bg-muted/40 p-3 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring max-lg:max-h-72 max-lg:min-h-32 lg:min-h-0",
|
|
3725
|
+
children: [
|
|
3726
|
+
state.kind === "not-editable" && /* @__PURE__ */ jsxs("div", { className: "flex shrink-0 flex-col gap-2 rounded-md border border-amber-200! bg-amber-50 p-3 text-xs text-amber-800", children: [
|
|
3339
3727
|
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
3340
3728
|
/* @__PURE__ */ jsx(AlertTriangle, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }),
|
|
3341
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1", children:
|
|
3729
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1", children: state.reason })
|
|
3342
3730
|
] }),
|
|
3343
|
-
signInUrl && /* @__PURE__ */ jsx(SlackSignInButton, { onClick: () =>
|
|
3344
|
-
|
|
3731
|
+
signInUrl && /* @__PURE__ */ jsx(SlackSignInButton, { onClick: () => onSignIn(signInUrl), polling: signInPolling }),
|
|
3732
|
+
verdictBlocks && verdictBlocks.length > 0 && /* @__PURE__ */ jsx(
|
|
3345
3733
|
Button,
|
|
3346
3734
|
{
|
|
3347
3735
|
type: "button",
|
|
3348
3736
|
variant: "outline",
|
|
3349
3737
|
size: "sm",
|
|
3350
3738
|
className: "self-start",
|
|
3351
|
-
onClick: () => onOpenAsNew(
|
|
3739
|
+
onClick: () => onOpenAsNew(verdictBlocks),
|
|
3352
3740
|
children: "Open as a new message instead"
|
|
3353
3741
|
}
|
|
3354
3742
|
)
|
|
3355
3743
|
] }),
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
channels === null && !channelsError && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Loading channels\u2026" }),
|
|
3365
|
-
channelsError && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: channelsError }),
|
|
3366
|
-
channels && channels.length === 0 && !channelsError && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "No public channels available." }),
|
|
3367
|
-
channels && channels.length > 0 && /* @__PURE__ */ jsxs(
|
|
3368
|
-
"select",
|
|
3369
|
-
{
|
|
3370
|
-
id: "recent-channel-picker",
|
|
3371
|
-
value: channelId,
|
|
3372
|
-
onChange: (e) => setChannelId(e.target.value),
|
|
3373
|
-
className: "flex h-9 w-full rounded-md border border-input bg-background px-3 py-1 text-sm shadow-sm focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
3374
|
-
children: [
|
|
3375
|
-
/* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Select a channel\u2026" }),
|
|
3376
|
-
channels.map((c) => /* @__PURE__ */ jsxs("option", { value: c.id, children: [
|
|
3377
|
-
"#",
|
|
3378
|
-
c.name
|
|
3379
|
-
] }, c.id))
|
|
3380
|
-
]
|
|
3381
|
-
}
|
|
3382
|
-
)
|
|
3383
|
-
] }),
|
|
3384
|
-
!channelId && channels && channels.length > 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Select a channel to see recent messages." }),
|
|
3385
|
-
channelId && recent === null && !recentError && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Loading recent messages\u2026" }),
|
|
3386
|
-
channelId && recentError && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: recentError }),
|
|
3387
|
-
channelId && recent && recent.length === 0 && !recentError && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "No recent messages from this app in this channel." }),
|
|
3388
|
-
channelId && recent && recent.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex max-h-48 min-w-0 flex-col gap-1 overflow-y-auto", children: recent.map((m) => {
|
|
3389
|
-
const asUser = (m.editableVia ?? "bot") === "user";
|
|
3390
|
-
const authorName = m.username || (asUser ? "You" : "App bot");
|
|
3391
|
-
const safeIcon = isSafeImageSrc(m.iconUrl) ? m.iconUrl : void 0;
|
|
3392
|
-
const isSelected = selectedRecent?.channelId === m.channelId && selectedRecent?.ts === m.ts;
|
|
3393
|
-
return /* @__PURE__ */ jsxs(
|
|
3394
|
-
"button",
|
|
3395
|
-
{
|
|
3396
|
-
type: "button",
|
|
3397
|
-
"aria-pressed": isSelected,
|
|
3398
|
-
onClick: () => {
|
|
3399
|
-
setSelectedRecent(m);
|
|
3400
|
-
setLink("");
|
|
3401
|
-
if (status.kind !== "idle" && status.kind !== "loading") {
|
|
3402
|
-
setStatus({ kind: "idle" });
|
|
3403
|
-
}
|
|
3404
|
-
},
|
|
3405
|
-
className: cn(
|
|
3406
|
-
// Inset rings so the scroll container's overflow clip
|
|
3407
|
-
// can't shave the corners off the selected outline.
|
|
3408
|
-
"flex min-w-0 items-start gap-2.5 rounded-md border border-input bg-background px-3 py-2 text-left hover:bg-accent focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-inset focus-visible:ring-ring",
|
|
3409
|
-
isSelected && "border-primary! bg-accent ring-1 ring-inset ring-primary"
|
|
3410
|
-
),
|
|
3411
|
-
children: [
|
|
3412
|
-
safeIcon ? /* @__PURE__ */ jsx("img", { src: safeIcon, alt: "", className: "h-9 w-9 shrink-0 rounded-md object-cover" }) : /* @__PURE__ */ jsx(
|
|
3413
|
-
"span",
|
|
3414
|
-
{
|
|
3415
|
-
"aria-hidden": true,
|
|
3416
|
-
className: "flex h-9 w-9 shrink-0 items-center justify-center rounded-md bg-muted text-sm font-semibold text-muted-foreground",
|
|
3417
|
-
children: authorName.charAt(0).toUpperCase()
|
|
3418
|
-
}
|
|
3419
|
-
),
|
|
3420
|
-
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col gap-0.5", children: [
|
|
3421
|
-
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
3422
|
-
/* @__PURE__ */ jsx("span", { className: "truncate text-sm font-semibold text-foreground", children: authorName }),
|
|
3423
|
-
/* @__PURE__ */ jsx("span", { className: "shrink-0 rounded border px-1 py-px text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: asUser ? "You" : "Bot" })
|
|
3424
|
-
] }),
|
|
3425
|
-
/* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground", children: [
|
|
3426
|
-
new Date(Number(m.ts) * 1e3).toLocaleString(),
|
|
3427
|
-
" ",
|
|
3428
|
-
/* @__PURE__ */ jsxs("span", { className: "font-mono", children: [
|
|
3429
|
-
"(",
|
|
3430
|
-
m.ts,
|
|
3431
|
-
")"
|
|
3432
|
-
] })
|
|
3433
|
-
] }),
|
|
3434
|
-
/* @__PURE__ */ jsx("span", { className: "line-clamp-2 text-sm text-foreground", children: previewText(m) })
|
|
3435
|
-
] })
|
|
3436
|
-
]
|
|
3437
|
-
},
|
|
3438
|
-
`${m.channelId}:${m.ts}`
|
|
3439
|
-
);
|
|
3440
|
-
}) })
|
|
3441
|
-
] })
|
|
3442
|
-
] }),
|
|
3443
|
-
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
3444
|
-
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
3445
|
-
/* @__PURE__ */ jsx(
|
|
3446
|
-
Button,
|
|
3744
|
+
state.kind === "error" && /* @__PURE__ */ jsx("p", { className: "shrink-0 rounded-md border border-destructive/30 bg-destructive/5 p-2 text-xs text-destructive", children: state.error }),
|
|
3745
|
+
state.kind === "loading" && /* @__PURE__ */ jsxs("p", { className: "m-auto flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
3746
|
+
/* @__PURE__ */ jsx(Loader2, { className: "h-4 w-4 animate-spin" }),
|
|
3747
|
+
"Looking up that message\u2026"
|
|
3748
|
+
] }),
|
|
3749
|
+
state.kind === "empty" && /* @__PURE__ */ jsx("p", { className: "m-auto px-4 text-center text-sm text-muted-foreground", children: emptyHint }),
|
|
3750
|
+
target && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: /* @__PURE__ */ jsx(
|
|
3751
|
+
SlackMessagePreview,
|
|
3447
3752
|
{
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3753
|
+
blocks: target.blocks,
|
|
3754
|
+
hooks,
|
|
3755
|
+
theme,
|
|
3756
|
+
workspaceName: target.workspaceName,
|
|
3757
|
+
authorName: target.username,
|
|
3758
|
+
authorIcon: target.iconUrl,
|
|
3759
|
+
time: formatTs(target.ts)
|
|
3452
3760
|
}
|
|
3453
|
-
)
|
|
3454
|
-
|
|
3455
|
-
|
|
3456
|
-
|
|
3457
|
-
|
|
3761
|
+
) }),
|
|
3762
|
+
verdictBlocks && verdictBlocks.length > 0 && /* @__PURE__ */ jsx("div", { className: "shrink-0", children: /* @__PURE__ */ jsx(SlackMessagePreview, { blocks: verdictBlocks, hooks, theme, time: "" }) })
|
|
3763
|
+
]
|
|
3764
|
+
}
|
|
3765
|
+
)
|
|
3766
|
+
] });
|
|
3458
3767
|
}
|
|
3459
3768
|
var PALETTE_DRAG_PREFIX = "palette:";
|
|
3460
3769
|
function parsePaletteDragId(id) {
|
|
@@ -8677,60 +8986,6 @@ function dispatch(block, onChange) {
|
|
|
8677
8986
|
return null;
|
|
8678
8987
|
}
|
|
8679
8988
|
}
|
|
8680
|
-
function SlackBlockPreview({
|
|
8681
|
-
block,
|
|
8682
|
-
hooks,
|
|
8683
|
-
theme = "light"
|
|
8684
|
-
}) {
|
|
8685
|
-
const rootRef = useRef(null);
|
|
8686
|
-
const safeBlock = useMemo(() => sanitizeBlock(block), [block]);
|
|
8687
|
-
useEffect(() => {
|
|
8688
|
-
const root = rootRef.current;
|
|
8689
|
-
if (!root) return;
|
|
8690
|
-
for (const wrapper of root.querySelectorAll(
|
|
8691
|
-
".slack_blocks_to_jsx__image_media_trigger, .slack_blocks_to_jsx__video_title"
|
|
8692
|
-
)) {
|
|
8693
|
-
for (const btn of wrapper.querySelectorAll("button:not([aria-label])")) {
|
|
8694
|
-
const title = wrapper.querySelector(".slack_blocks_to_jsx__image_title")?.textContent?.trim();
|
|
8695
|
-
btn.setAttribute("aria-label", title ? `Toggle ${title}` : "Toggle media");
|
|
8696
|
-
}
|
|
8697
|
-
}
|
|
8698
|
-
for (const a of root.querySelectorAll("a[href]")) {
|
|
8699
|
-
const href = a.getAttribute("href");
|
|
8700
|
-
if (!isSafeHref(href)) {
|
|
8701
|
-
a.setAttribute("href", "#");
|
|
8702
|
-
a.setAttribute("data-bk-blocked-href", "1");
|
|
8703
|
-
}
|
|
8704
|
-
}
|
|
8705
|
-
for (const img of root.querySelectorAll("img[src]")) {
|
|
8706
|
-
const src = img.getAttribute("src");
|
|
8707
|
-
if (!isSafeImageSrc(src)) {
|
|
8708
|
-
img.removeAttribute("src");
|
|
8709
|
-
img.setAttribute("data-bk-blocked-src", "1");
|
|
8710
|
-
}
|
|
8711
|
-
}
|
|
8712
|
-
});
|
|
8713
|
-
return (
|
|
8714
|
-
// The library scopes all of its CSS under `#slack_blocks_to_jsx` and
|
|
8715
|
-
// depends on the `slack_blocks_to_jsx styles_enabled` classes plus the
|
|
8716
|
-
// `data-theme` attribute for its button / mention / divider styling
|
|
8717
|
-
// (e.g. button reset + `bg-green-primary` for primary). `<Message
|
|
8718
|
-
// withoutWrapper>` skips that wrapper entirely, so we re-create it
|
|
8719
|
-
// here without the avatar / timestamp chrome.
|
|
8720
|
-
/* @__PURE__ */ jsx("div", { ref: rootRef, id: "slack_blocks_to_jsx", "data-theme": theme, className: "slack_blocks_to_jsx styles_enabled", children: /* @__PURE__ */ jsx(
|
|
8721
|
-
Message,
|
|
8722
|
-
{
|
|
8723
|
-
time: /* @__PURE__ */ new Date(),
|
|
8724
|
-
name: "",
|
|
8725
|
-
logo: "",
|
|
8726
|
-
withoutWrapper: true,
|
|
8727
|
-
theme,
|
|
8728
|
-
blocks: [safeBlock],
|
|
8729
|
-
hooks
|
|
8730
|
-
}
|
|
8731
|
-
) })
|
|
8732
|
-
);
|
|
8733
|
-
}
|
|
8734
8989
|
var BLOCK_TYPE_LABELS = {
|
|
8735
8990
|
section: "Section",
|
|
8736
8991
|
header: "Header",
|
|
@@ -9353,50 +9608,16 @@ function Surface({
|
|
|
9353
9608
|
{
|
|
9354
9609
|
"aria-label": "Block preview",
|
|
9355
9610
|
className: cn("flex min-w-0 flex-1 flex-col overflow-y-auto bg-muted p-3 sm:p-6"),
|
|
9356
|
-
children: /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-2xl", children: previewSurface === "modal" ? /* @__PURE__ */ jsx(ModalFrame, { isDark, children: blocksList }) : previewSurface === "app_home" ? /* @__PURE__ */ jsx(AppHomeFrame, { workspaceName, isDark, children: blocksList }) : /* @__PURE__ */ jsx(
|
|
9357
|
-
|
|
9358
|
-
|
|
9359
|
-
|
|
9360
|
-
|
|
9361
|
-
|
|
9362
|
-
|
|
9363
|
-
|
|
9364
|
-
|
|
9365
|
-
|
|
9366
|
-
}) {
|
|
9367
|
-
const displayName = authorName ?? workspaceName ?? "Your app";
|
|
9368
|
-
const initial = displayName.slice(0, 1).toUpperCase();
|
|
9369
|
-
const safeIcon = authorIcon && isSafeImageSrc(authorIcon) ? authorIcon : null;
|
|
9370
|
-
return /* @__PURE__ */ jsxs(
|
|
9371
|
-
"div",
|
|
9372
|
-
{
|
|
9373
|
-
className: cn(
|
|
9374
|
-
"flex flex-col overflow-hidden rounded-md border",
|
|
9375
|
-
isDark ? "border-[#2c2d30] bg-[#1a1d21]" : "border-[#e8e8e8] bg-white"
|
|
9376
|
-
),
|
|
9377
|
-
children: [
|
|
9378
|
-
/* @__PURE__ */ jsxs(
|
|
9379
|
-
"div",
|
|
9380
|
-
{
|
|
9381
|
-
className: cn("flex items-center gap-2 px-5 pt-3 pb-1 text-xs", isDark ? "text-white/60" : "text-[#616061]"),
|
|
9382
|
-
children: [
|
|
9383
|
-
safeIcon ? /* @__PURE__ */ jsx("img", { src: safeIcon, alt: "", className: "h-7 w-7 shrink-0 rounded object-cover" }) : /* @__PURE__ */ jsx(
|
|
9384
|
-
"span",
|
|
9385
|
-
{
|
|
9386
|
-
className: cn(
|
|
9387
|
-
"inline-flex h-7 w-7 items-center justify-center rounded text-[12px] font-semibold",
|
|
9388
|
-
isDark ? "bg-white/10 text-white" : "bg-[#4a154b]/10 text-[#1d1c1d]"
|
|
9389
|
-
),
|
|
9390
|
-
children: initial
|
|
9391
|
-
}
|
|
9392
|
-
),
|
|
9393
|
-
/* @__PURE__ */ jsx("span", { className: cn("font-bold text-sm", isDark ? "text-white" : "text-[#1d1c1d]"), children: displayName }),
|
|
9394
|
-
/* @__PURE__ */ jsx("span", { children: "10:37 AM" })
|
|
9395
|
-
]
|
|
9396
|
-
}
|
|
9397
|
-
),
|
|
9398
|
-
children
|
|
9399
|
-
]
|
|
9611
|
+
children: /* @__PURE__ */ jsx("div", { className: "mx-auto w-full max-w-2xl", children: previewSurface === "modal" ? /* @__PURE__ */ jsx(ModalFrame, { isDark, children: blocksList }) : previewSurface === "app_home" ? /* @__PURE__ */ jsx(AppHomeFrame, { workspaceName, isDark, children: blocksList }) : /* @__PURE__ */ jsx(
|
|
9612
|
+
SlackMessageFrame,
|
|
9613
|
+
{
|
|
9614
|
+
workspaceName,
|
|
9615
|
+
authorName,
|
|
9616
|
+
authorIcon,
|
|
9617
|
+
isDark,
|
|
9618
|
+
children: blocksList
|
|
9619
|
+
}
|
|
9620
|
+
) })
|
|
9400
9621
|
}
|
|
9401
9622
|
);
|
|
9402
9623
|
}
|
|
@@ -10485,6 +10706,8 @@ function BlockKitchen(props) {
|
|
|
10485
10706
|
onLoadMessage: loading.onLoadMessage,
|
|
10486
10707
|
loadRecentMessages: loading.loadRecentMessages,
|
|
10487
10708
|
loadChannels: recentChannelSource,
|
|
10709
|
+
previewHooks: mergedPreviewHooks,
|
|
10710
|
+
previewTheme,
|
|
10488
10711
|
onLoaded: (result) => {
|
|
10489
10712
|
resetAll(result.blocks);
|
|
10490
10713
|
setEditTarget(toLoadedMessage(result));
|