@tightknitai/block-kitchen 0.8.10 → 0.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +67 -1
- package/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.cjs +765 -327
- 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 +766 -328
- package/dist/index.js.map +1 -1
- package/dist/{palette-DBTHRygt.d.cts → palette-DIbvAzRA.d.cts} +156 -4
- package/dist/{palette-DBTHRygt.d.ts → palette-DIbvAzRA.d.ts} +156 -4
- package/dist/palette.d.cts +1 -1
- package/dist/palette.d.ts +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useSensors, useSensor, PointerSensor, TouchSensor, KeyboardSensor, pointerWithin, closestCenter, DndContext, DragOverlay, useDroppable, useDraggable } from '@dnd-kit/core';
|
|
2
2
|
import { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, useSortable } from '@dnd-kit/sortable';
|
|
3
|
-
import { X, Circle, Sparkles, FileText, AlignLeft, MousePointerClick, TextCursorInput, LayoutTemplate, Bell, Pilcrow, Image, Video, GalleryHorizontal, Table, ChartColumnBig, Container, GripVertical, Sun, Moon, MessageSquare, AppWindow, Home, Plus, ChevronDown, BookOpen, ExternalLink, AlertTriangle, Trash2, Code2,
|
|
3
|
+
import { X, Circle, Sparkles, FileText, AlignLeft, MousePointerClick, TextCursorInput, LayoutTemplate, Bell, Pilcrow, Image, Video, GalleryHorizontal, Table, ChartColumnBig, Container, GripVertical, Sun, Moon, MessageSquare, AppWindow, Home, Pencil, Plus, ChevronDown, BookOpen, ExternalLink, AlertTriangle, Trash2, Code2, Send, Search, Info, CheckCircle2, Check, ChevronRight, LayoutGrid, ArrowUp, ArrowDown, Copy, Type, Bold, Italic, Strikethrough, Underline, Code, List, ListOrdered, Quote, Undo2, Redo2, Smile, Link as Link$1 } from 'lucide-react';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { createContext, useMemo, useState, useCallback, useRef, useEffect, useId, useContext } from 'react';
|
|
6
6
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
@@ -2694,6 +2694,91 @@ function JsonDrawer({
|
|
|
2694
2694
|
] })
|
|
2695
2695
|
] }) });
|
|
2696
2696
|
}
|
|
2697
|
+
var buttonVariants = cva(
|
|
2698
|
+
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
2699
|
+
{
|
|
2700
|
+
variants: {
|
|
2701
|
+
variant: {
|
|
2702
|
+
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
2703
|
+
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
2704
|
+
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
2705
|
+
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
2706
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
2707
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
2708
|
+
},
|
|
2709
|
+
size: {
|
|
2710
|
+
default: "h-9 px-4 py-2",
|
|
2711
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
2712
|
+
lg: "h-10 rounded-md px-8",
|
|
2713
|
+
icon: "h-9 w-9"
|
|
2714
|
+
}
|
|
2715
|
+
},
|
|
2716
|
+
defaultVariants: {
|
|
2717
|
+
variant: "default",
|
|
2718
|
+
size: "default"
|
|
2719
|
+
}
|
|
2720
|
+
}
|
|
2721
|
+
);
|
|
2722
|
+
var Button = React.forwardRef(
|
|
2723
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
2724
|
+
const Comp = asChild ? Slot : "button";
|
|
2725
|
+
return /* @__PURE__ */ jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
|
|
2726
|
+
}
|
|
2727
|
+
);
|
|
2728
|
+
Button.displayName = "Button";
|
|
2729
|
+
var Dialog = DialogPrimitive.Root;
|
|
2730
|
+
var DialogPortal = DialogPrimitive.Portal;
|
|
2731
|
+
var DialogOverlay = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2732
|
+
DialogPrimitive.Overlay,
|
|
2733
|
+
{
|
|
2734
|
+
ref,
|
|
2735
|
+
className: cn(
|
|
2736
|
+
"bk-portal-content fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
2737
|
+
className
|
|
2738
|
+
),
|
|
2739
|
+
...props
|
|
2740
|
+
}
|
|
2741
|
+
));
|
|
2742
|
+
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
2743
|
+
var DialogContent = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
|
|
2744
|
+
/* @__PURE__ */ jsx(DialogOverlay, {}),
|
|
2745
|
+
/* @__PURE__ */ jsxs(
|
|
2746
|
+
DialogPrimitive.Content,
|
|
2747
|
+
{
|
|
2748
|
+
ref,
|
|
2749
|
+
className: cn(
|
|
2750
|
+
"bk-portal-content fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg duration-200 sm:rounded-lg",
|
|
2751
|
+
className
|
|
2752
|
+
),
|
|
2753
|
+
...props,
|
|
2754
|
+
children: [
|
|
2755
|
+
children,
|
|
2756
|
+
/* @__PURE__ */ jsxs(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-1 focus:ring-ring", children: [
|
|
2757
|
+
/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }),
|
|
2758
|
+
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
2759
|
+
] })
|
|
2760
|
+
]
|
|
2761
|
+
}
|
|
2762
|
+
)
|
|
2763
|
+
] }));
|
|
2764
|
+
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
2765
|
+
function DialogHeader({ className, ...props }) {
|
|
2766
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
|
|
2767
|
+
}
|
|
2768
|
+
function DialogFooter({ className, ...props }) {
|
|
2769
|
+
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className), ...props });
|
|
2770
|
+
}
|
|
2771
|
+
var DialogTitle = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2772
|
+
DialogPrimitive.Title,
|
|
2773
|
+
{
|
|
2774
|
+
ref,
|
|
2775
|
+
className: cn("text-lg font-semibold leading-none tracking-tight", className),
|
|
2776
|
+
...props
|
|
2777
|
+
}
|
|
2778
|
+
));
|
|
2779
|
+
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
2780
|
+
var DialogDescription = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
|
|
2781
|
+
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
2697
2782
|
var Input = React.forwardRef(
|
|
2698
2783
|
({ className, type, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2699
2784
|
"input",
|
|
@@ -2709,6 +2794,265 @@ var Input = React.forwardRef(
|
|
|
2709
2794
|
)
|
|
2710
2795
|
);
|
|
2711
2796
|
Input.displayName = "Input";
|
|
2797
|
+
var Label = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2798
|
+
LabelPrimitive.Root,
|
|
2799
|
+
{
|
|
2800
|
+
ref,
|
|
2801
|
+
className: cn("text-sm font-medium leading-none text-foreground", className),
|
|
2802
|
+
...props
|
|
2803
|
+
}
|
|
2804
|
+
));
|
|
2805
|
+
Label.displayName = LabelPrimitive.Root.displayName;
|
|
2806
|
+
function recentToResult(msg) {
|
|
2807
|
+
return {
|
|
2808
|
+
ok: true,
|
|
2809
|
+
channelId: msg.channelId,
|
|
2810
|
+
channelName: msg.channelName,
|
|
2811
|
+
ts: msg.ts,
|
|
2812
|
+
blocks: msg.blocks,
|
|
2813
|
+
editableVia: msg.editableVia ?? "bot",
|
|
2814
|
+
workspaceName: msg.workspaceName,
|
|
2815
|
+
username: msg.username,
|
|
2816
|
+
iconUrl: msg.iconUrl
|
|
2817
|
+
};
|
|
2818
|
+
}
|
|
2819
|
+
function LoadMessageDialog({
|
|
2820
|
+
open,
|
|
2821
|
+
onOpenChange,
|
|
2822
|
+
onLoadMessage,
|
|
2823
|
+
loadRecentMessages,
|
|
2824
|
+
loadChannels,
|
|
2825
|
+
onLoaded,
|
|
2826
|
+
onOpenAsNew
|
|
2827
|
+
}) {
|
|
2828
|
+
const [link, setLink] = useState("");
|
|
2829
|
+
const [status, setStatus] = useState({ kind: "idle" });
|
|
2830
|
+
const [channels, setChannels] = useState(null);
|
|
2831
|
+
const [channelsError, setChannelsError] = useState(null);
|
|
2832
|
+
const [channelId, setChannelId] = useState("");
|
|
2833
|
+
const [recent, setRecent] = useState(null);
|
|
2834
|
+
const [recentError, setRecentError] = useState(null);
|
|
2835
|
+
const inputRef = useRef(null);
|
|
2836
|
+
const onLoadMessageRef = useRef(onLoadMessage);
|
|
2837
|
+
const loadRecentMessagesRef = useRef(loadRecentMessages);
|
|
2838
|
+
const loadChannelsRef = useRef(loadChannels);
|
|
2839
|
+
useEffect(() => {
|
|
2840
|
+
onLoadMessageRef.current = onLoadMessage;
|
|
2841
|
+
loadRecentMessagesRef.current = loadRecentMessages;
|
|
2842
|
+
loadChannelsRef.current = loadChannels;
|
|
2843
|
+
});
|
|
2844
|
+
const hasRecent = !!loadRecentMessages;
|
|
2845
|
+
useEffect(() => {
|
|
2846
|
+
if (!open) {
|
|
2847
|
+
return;
|
|
2848
|
+
}
|
|
2849
|
+
setLink("");
|
|
2850
|
+
setStatus({ kind: "idle" });
|
|
2851
|
+
setChannelId("");
|
|
2852
|
+
setRecent(null);
|
|
2853
|
+
setRecentError(null);
|
|
2854
|
+
if (!loadRecentMessagesRef.current) {
|
|
2855
|
+
setChannels([]);
|
|
2856
|
+
setChannelsError(null);
|
|
2857
|
+
return;
|
|
2858
|
+
}
|
|
2859
|
+
setChannels(null);
|
|
2860
|
+
setChannelsError(null);
|
|
2861
|
+
let cancelled = false;
|
|
2862
|
+
loadChannelsRef.current().then((list) => {
|
|
2863
|
+
if (!cancelled) {
|
|
2864
|
+
setChannels(list);
|
|
2865
|
+
}
|
|
2866
|
+
}).catch((e) => {
|
|
2867
|
+
if (!cancelled) {
|
|
2868
|
+
setChannelsError(e instanceof Error ? e.message : "Failed to load channels");
|
|
2869
|
+
}
|
|
2870
|
+
});
|
|
2871
|
+
return () => {
|
|
2872
|
+
cancelled = true;
|
|
2873
|
+
};
|
|
2874
|
+
}, [open]);
|
|
2875
|
+
useEffect(() => {
|
|
2876
|
+
if (!open || !loadRecentMessagesRef.current || !channelId) {
|
|
2877
|
+
return;
|
|
2878
|
+
}
|
|
2879
|
+
setRecent(null);
|
|
2880
|
+
setRecentError(null);
|
|
2881
|
+
let cancelled = false;
|
|
2882
|
+
loadRecentMessagesRef.current(channelId).then((list) => {
|
|
2883
|
+
if (!cancelled) {
|
|
2884
|
+
setRecent(list);
|
|
2885
|
+
}
|
|
2886
|
+
}).catch((e) => {
|
|
2887
|
+
if (!cancelled) {
|
|
2888
|
+
setRecentError(e instanceof Error ? e.message : "Failed to load recent messages.");
|
|
2889
|
+
}
|
|
2890
|
+
});
|
|
2891
|
+
return () => {
|
|
2892
|
+
cancelled = true;
|
|
2893
|
+
};
|
|
2894
|
+
}, [open, channelId]);
|
|
2895
|
+
const handleLoad = async () => {
|
|
2896
|
+
const trimmed = link.trim();
|
|
2897
|
+
if (!trimmed) {
|
|
2898
|
+
setStatus({ kind: "error", error: "Paste a Slack message link first." });
|
|
2899
|
+
return;
|
|
2900
|
+
}
|
|
2901
|
+
setStatus({ kind: "loading" });
|
|
2902
|
+
try {
|
|
2903
|
+
const result = await onLoadMessageRef.current({ link: trimmed });
|
|
2904
|
+
if (result.ok) {
|
|
2905
|
+
onLoaded(result);
|
|
2906
|
+
return;
|
|
2907
|
+
}
|
|
2908
|
+
setStatus({ kind: "not-editable", reason: result.reason, blocks: result.blocks });
|
|
2909
|
+
} catch (e) {
|
|
2910
|
+
setStatus({ kind: "error", error: e instanceof Error ? e.message : "Failed to load message." });
|
|
2911
|
+
}
|
|
2912
|
+
};
|
|
2913
|
+
const notEditable = status.kind === "not-editable" ? status : null;
|
|
2914
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
|
|
2915
|
+
DialogContent,
|
|
2916
|
+
{
|
|
2917
|
+
className: "w-[calc(100vw-1.5rem)] max-w-lg rounded-lg",
|
|
2918
|
+
onOpenAutoFocus: (e) => {
|
|
2919
|
+
e.preventDefault();
|
|
2920
|
+
inputRef.current?.focus();
|
|
2921
|
+
},
|
|
2922
|
+
children: [
|
|
2923
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
2924
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: "Edit an existing message" }),
|
|
2925
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1.5", children: [
|
|
2926
|
+
/* @__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.` }),
|
|
2927
|
+
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
2928
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
2929
|
+
"button",
|
|
2930
|
+
{
|
|
2931
|
+
type: "button",
|
|
2932
|
+
"aria-label": "How to copy a message link",
|
|
2933
|
+
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",
|
|
2934
|
+
children: /* @__PURE__ */ jsx(Info, { className: "h-3.5 w-3.5" })
|
|
2935
|
+
}
|
|
2936
|
+
) }),
|
|
2937
|
+
/* @__PURE__ */ jsxs(TooltipContent, { className: "max-w-xs leading-relaxed", children: [
|
|
2938
|
+
"In Slack, hover over the message and click the ",
|
|
2939
|
+
/* @__PURE__ */ jsx("strong", { children: "\u22EE More actions" }),
|
|
2940
|
+
" button (or right-click the message), then choose ",
|
|
2941
|
+
/* @__PURE__ */ jsx("strong", { children: "Copy link" }),
|
|
2942
|
+
"."
|
|
2943
|
+
] })
|
|
2944
|
+
] })
|
|
2945
|
+
] })
|
|
2946
|
+
] }),
|
|
2947
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2948
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
2949
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "message-link", children: "Message link" }),
|
|
2950
|
+
/* @__PURE__ */ jsx(
|
|
2951
|
+
Input,
|
|
2952
|
+
{
|
|
2953
|
+
ref: inputRef,
|
|
2954
|
+
id: "message-link",
|
|
2955
|
+
value: link,
|
|
2956
|
+
onChange: (e) => {
|
|
2957
|
+
setLink(e.target.value);
|
|
2958
|
+
if (status.kind !== "idle" && status.kind !== "loading") {
|
|
2959
|
+
setStatus({ kind: "idle" });
|
|
2960
|
+
}
|
|
2961
|
+
},
|
|
2962
|
+
onKeyDown: (e) => {
|
|
2963
|
+
if (e.key === "Enter" && status.kind !== "loading") {
|
|
2964
|
+
e.preventDefault();
|
|
2965
|
+
handleLoad();
|
|
2966
|
+
}
|
|
2967
|
+
},
|
|
2968
|
+
placeholder: "https://your-workspace.slack.com/archives/C\u2026/p\u2026",
|
|
2969
|
+
autoComplete: "off",
|
|
2970
|
+
spellCheck: false
|
|
2971
|
+
}
|
|
2972
|
+
)
|
|
2973
|
+
] }),
|
|
2974
|
+
status.kind === "error" && /* @__PURE__ */ jsx("p", { className: "rounded-md border border-destructive/30 bg-destructive/5 p-2 text-xs text-destructive", children: status.error }),
|
|
2975
|
+
notEditable && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 rounded-md border border-amber-200! bg-amber-50 p-3 text-xs text-amber-800", children: [
|
|
2976
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
2977
|
+
/* @__PURE__ */ jsx(AlertTriangle, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }),
|
|
2978
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1", children: notEditable.reason })
|
|
2979
|
+
] }),
|
|
2980
|
+
/* @__PURE__ */ jsx(
|
|
2981
|
+
Button,
|
|
2982
|
+
{
|
|
2983
|
+
type: "button",
|
|
2984
|
+
variant: "outline",
|
|
2985
|
+
size: "sm",
|
|
2986
|
+
className: "self-start",
|
|
2987
|
+
onClick: () => onOpenAsNew(notEditable.blocks),
|
|
2988
|
+
children: "Open as a new message instead"
|
|
2989
|
+
}
|
|
2990
|
+
)
|
|
2991
|
+
] }),
|
|
2992
|
+
hasRecent && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
2993
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
2994
|
+
/* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" }),
|
|
2995
|
+
"or pick a recent message",
|
|
2996
|
+
/* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" })
|
|
2997
|
+
] }),
|
|
2998
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
2999
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "recent-channel-picker", children: "Channel" }),
|
|
3000
|
+
channels === null && !channelsError && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Loading channels\u2026" }),
|
|
3001
|
+
channelsError && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: channelsError }),
|
|
3002
|
+
channels && channels.length === 0 && !channelsError && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "No public channels available." }),
|
|
3003
|
+
channels && channels.length > 0 && /* @__PURE__ */ jsxs(
|
|
3004
|
+
"select",
|
|
3005
|
+
{
|
|
3006
|
+
id: "recent-channel-picker",
|
|
3007
|
+
value: channelId,
|
|
3008
|
+
onChange: (e) => setChannelId(e.target.value),
|
|
3009
|
+
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",
|
|
3010
|
+
children: [
|
|
3011
|
+
/* @__PURE__ */ jsx("option", { value: "", disabled: true, children: "Select a channel\u2026" }),
|
|
3012
|
+
channels.map((c) => /* @__PURE__ */ jsxs("option", { value: c.id, children: [
|
|
3013
|
+
"#",
|
|
3014
|
+
c.name
|
|
3015
|
+
] }, c.id))
|
|
3016
|
+
]
|
|
3017
|
+
}
|
|
3018
|
+
)
|
|
3019
|
+
] }),
|
|
3020
|
+
!channelId && channels && channels.length > 0 && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Select a channel to see recent messages." }),
|
|
3021
|
+
channelId && recent === null && !recentError && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Loading recent messages\u2026" }),
|
|
3022
|
+
channelId && recentError && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: recentError }),
|
|
3023
|
+
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." }),
|
|
3024
|
+
channelId && recent && recent.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex max-h-48 flex-col gap-1 overflow-y-auto", children: recent.map((m) => {
|
|
3025
|
+
const asUser = (m.editableVia ?? "bot") === "user";
|
|
3026
|
+
return /* @__PURE__ */ jsxs(
|
|
3027
|
+
"button",
|
|
3028
|
+
{
|
|
3029
|
+
type: "button",
|
|
3030
|
+
onClick: () => onLoaded(recentToResult(m)),
|
|
3031
|
+
className: "flex flex-col gap-0.5 rounded-md border border-input bg-background px-3 py-2 text-left text-sm hover:bg-accent hover:text-accent-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
3032
|
+
children: [
|
|
3033
|
+
/* @__PURE__ */ jsxs("span", { className: "flex items-baseline justify-between gap-2", children: [
|
|
3034
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-baseline gap-1.5", children: [
|
|
3035
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: m.channelName ? `#${m.channelName}` : m.channelId }),
|
|
3036
|
+
/* @__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" })
|
|
3037
|
+
] }),
|
|
3038
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 font-mono text-xs text-muted-foreground", children: m.ts })
|
|
3039
|
+
] }),
|
|
3040
|
+
m.label && /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: m.label })
|
|
3041
|
+
]
|
|
3042
|
+
},
|
|
3043
|
+
`${m.channelId}:${m.ts}`
|
|
3044
|
+
);
|
|
3045
|
+
}) })
|
|
3046
|
+
] })
|
|
3047
|
+
] }),
|
|
3048
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
3049
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
3050
|
+
/* @__PURE__ */ jsx(Button, { type: "button", onClick: handleLoad, disabled: status.kind === "loading" || !link.trim(), children: status.kind === "loading" ? "Loading\u2026" : "Load message" })
|
|
3051
|
+
] })
|
|
3052
|
+
]
|
|
3053
|
+
}
|
|
3054
|
+
) });
|
|
3055
|
+
}
|
|
2712
3056
|
var PALETTE_DRAG_PREFIX = "palette:";
|
|
2713
3057
|
function parsePaletteDragId(id) {
|
|
2714
3058
|
if (typeof id !== "string" || !id.startsWith(PALETTE_DRAG_PREFIX)) {
|
|
@@ -2908,100 +3252,6 @@ function PaletteItem({
|
|
|
2908
3252
|
}
|
|
2909
3253
|
);
|
|
2910
3254
|
}
|
|
2911
|
-
var buttonVariants = cva(
|
|
2912
|
-
"inline-flex items-center justify-center gap-2 whitespace-nowrap rounded-md text-sm font-medium cursor-pointer transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0",
|
|
2913
|
-
{
|
|
2914
|
-
variants: {
|
|
2915
|
-
variant: {
|
|
2916
|
-
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
2917
|
-
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
2918
|
-
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
2919
|
-
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
2920
|
-
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
2921
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
2922
|
-
},
|
|
2923
|
-
size: {
|
|
2924
|
-
default: "h-9 px-4 py-2",
|
|
2925
|
-
sm: "h-8 rounded-md px-3 text-xs",
|
|
2926
|
-
lg: "h-10 rounded-md px-8",
|
|
2927
|
-
icon: "h-9 w-9"
|
|
2928
|
-
}
|
|
2929
|
-
},
|
|
2930
|
-
defaultVariants: {
|
|
2931
|
-
variant: "default",
|
|
2932
|
-
size: "default"
|
|
2933
|
-
}
|
|
2934
|
-
}
|
|
2935
|
-
);
|
|
2936
|
-
var Button = React.forwardRef(
|
|
2937
|
-
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
2938
|
-
const Comp = asChild ? Slot : "button";
|
|
2939
|
-
return /* @__PURE__ */ jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
|
|
2940
|
-
}
|
|
2941
|
-
);
|
|
2942
|
-
Button.displayName = "Button";
|
|
2943
|
-
var Dialog = DialogPrimitive.Root;
|
|
2944
|
-
var DialogPortal = DialogPrimitive.Portal;
|
|
2945
|
-
var DialogOverlay = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2946
|
-
DialogPrimitive.Overlay,
|
|
2947
|
-
{
|
|
2948
|
-
ref,
|
|
2949
|
-
className: cn(
|
|
2950
|
-
"bk-portal-content fixed inset-0 z-50 bg-black/50 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
2951
|
-
className
|
|
2952
|
-
),
|
|
2953
|
-
...props
|
|
2954
|
-
}
|
|
2955
|
-
));
|
|
2956
|
-
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName;
|
|
2957
|
-
var DialogContent = React.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(DialogPortal, { children: [
|
|
2958
|
-
/* @__PURE__ */ jsx(DialogOverlay, {}),
|
|
2959
|
-
/* @__PURE__ */ jsxs(
|
|
2960
|
-
DialogPrimitive.Content,
|
|
2961
|
-
{
|
|
2962
|
-
ref,
|
|
2963
|
-
className: cn(
|
|
2964
|
-
"bk-portal-content fixed left-1/2 top-1/2 z-50 grid w-full max-w-lg -translate-x-1/2 -translate-y-1/2 gap-4 border bg-background p-6 shadow-lg duration-200 sm:rounded-lg",
|
|
2965
|
-
className
|
|
2966
|
-
),
|
|
2967
|
-
...props,
|
|
2968
|
-
children: [
|
|
2969
|
-
children,
|
|
2970
|
-
/* @__PURE__ */ jsxs(DialogPrimitive.Close, { className: "absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-1 focus:ring-ring", children: [
|
|
2971
|
-
/* @__PURE__ */ jsx(X, { className: "h-4 w-4" }),
|
|
2972
|
-
/* @__PURE__ */ jsx("span", { className: "sr-only", children: "Close" })
|
|
2973
|
-
] })
|
|
2974
|
-
]
|
|
2975
|
-
}
|
|
2976
|
-
)
|
|
2977
|
-
] }));
|
|
2978
|
-
DialogContent.displayName = DialogPrimitive.Content.displayName;
|
|
2979
|
-
function DialogHeader({ className, ...props }) {
|
|
2980
|
-
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
|
|
2981
|
-
}
|
|
2982
|
-
function DialogFooter({ className, ...props }) {
|
|
2983
|
-
return /* @__PURE__ */ jsx("div", { className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className), ...props });
|
|
2984
|
-
}
|
|
2985
|
-
var DialogTitle = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2986
|
-
DialogPrimitive.Title,
|
|
2987
|
-
{
|
|
2988
|
-
ref,
|
|
2989
|
-
className: cn("text-lg font-semibold leading-none tracking-tight", className),
|
|
2990
|
-
...props
|
|
2991
|
-
}
|
|
2992
|
-
));
|
|
2993
|
-
DialogTitle.displayName = DialogPrimitive.Title.displayName;
|
|
2994
|
-
var DialogDescription = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(DialogPrimitive.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
|
|
2995
|
-
DialogDescription.displayName = DialogPrimitive.Description.displayName;
|
|
2996
|
-
var Label = React.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsx(
|
|
2997
|
-
LabelPrimitive.Root,
|
|
2998
|
-
{
|
|
2999
|
-
ref,
|
|
3000
|
-
className: cn("text-sm font-medium leading-none text-foreground", className),
|
|
3001
|
-
...props
|
|
3002
|
-
}
|
|
3003
|
-
));
|
|
3004
|
-
Label.displayName = LabelPrimitive.Root.displayName;
|
|
3005
3255
|
function SendDialog({
|
|
3006
3256
|
open,
|
|
3007
3257
|
onOpenChange,
|
|
@@ -4142,7 +4392,7 @@ function TextItemCard({
|
|
|
4142
4392
|
id: `ctx-text-${index}`,
|
|
4143
4393
|
value: element.text,
|
|
4144
4394
|
rows: 2,
|
|
4145
|
-
placeholder: "e.g. Posted by @
|
|
4395
|
+
placeholder: "e.g. Posted by @riley",
|
|
4146
4396
|
onChange: (e) => onChange({ ...element, text: e.target.value })
|
|
4147
4397
|
}
|
|
4148
4398
|
) }),
|
|
@@ -4227,7 +4477,7 @@ function ImageItemCard({
|
|
|
4227
4477
|
{
|
|
4228
4478
|
id: `ctx-img-alt-${index}`,
|
|
4229
4479
|
value: element.alt_text,
|
|
4230
|
-
placeholder: "e.g.
|
|
4480
|
+
placeholder: "e.g. Riley's avatar",
|
|
4231
4481
|
onChange: (e) => onChange({ ...element, alt_text: e.target.value })
|
|
4232
4482
|
}
|
|
4233
4483
|
) })
|
|
@@ -8560,6 +8810,8 @@ var SURFACE_DROPPABLE_ID = "builder-surface";
|
|
|
8560
8810
|
function Surface({
|
|
8561
8811
|
blocks,
|
|
8562
8812
|
workspaceName,
|
|
8813
|
+
authorName,
|
|
8814
|
+
authorIcon,
|
|
8563
8815
|
previewHooks,
|
|
8564
8816
|
previewTheme,
|
|
8565
8817
|
previewSurface = "message",
|
|
@@ -8635,16 +8887,20 @@ function Surface({
|
|
|
8635
8887
|
{
|
|
8636
8888
|
"aria-label": "Block preview",
|
|
8637
8889
|
className: cn("flex min-w-0 flex-1 flex-col overflow-y-auto bg-muted p-3 sm:p-6"),
|
|
8638
|
-
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(MessageFrame, { workspaceName, isDark, children: blocksList }) })
|
|
8890
|
+
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(MessageFrame, { workspaceName, authorName, authorIcon, isDark, children: blocksList }) })
|
|
8639
8891
|
}
|
|
8640
8892
|
);
|
|
8641
8893
|
}
|
|
8642
8894
|
function MessageFrame({
|
|
8643
8895
|
workspaceName,
|
|
8896
|
+
authorName,
|
|
8897
|
+
authorIcon,
|
|
8644
8898
|
isDark,
|
|
8645
8899
|
children
|
|
8646
8900
|
}) {
|
|
8647
|
-
const
|
|
8901
|
+
const displayName = authorName ?? workspaceName ?? "Your app";
|
|
8902
|
+
const initial = displayName.slice(0, 1).toUpperCase();
|
|
8903
|
+
const safeIcon = authorIcon && isSafeImageSrc(authorIcon) ? authorIcon : null;
|
|
8648
8904
|
return /* @__PURE__ */ jsxs(
|
|
8649
8905
|
"div",
|
|
8650
8906
|
{
|
|
@@ -8658,7 +8914,7 @@ function MessageFrame({
|
|
|
8658
8914
|
{
|
|
8659
8915
|
className: cn("flex items-center gap-2 px-5 pt-3 pb-1 text-xs", isDark ? "text-white/60" : "text-[#616061]"),
|
|
8660
8916
|
children: [
|
|
8661
|
-
/* @__PURE__ */ jsx(
|
|
8917
|
+
safeIcon ? /* @__PURE__ */ jsx("img", { src: safeIcon, alt: "", className: "h-7 w-7 shrink-0 rounded object-cover" }) : /* @__PURE__ */ jsx(
|
|
8662
8918
|
"span",
|
|
8663
8919
|
{
|
|
8664
8920
|
className: cn(
|
|
@@ -8668,17 +8924,7 @@ function MessageFrame({
|
|
|
8668
8924
|
children: initial
|
|
8669
8925
|
}
|
|
8670
8926
|
),
|
|
8671
|
-
/* @__PURE__ */ jsx("span", { className: cn("font-bold text-sm", isDark ? "text-white" : "text-[#1d1c1d]"), children:
|
|
8672
|
-
/* @__PURE__ */ jsx(
|
|
8673
|
-
"span",
|
|
8674
|
-
{
|
|
8675
|
-
className: cn(
|
|
8676
|
-
"rounded px-1 text-[10px] font-semibold",
|
|
8677
|
-
isDark ? "bg-white/10 text-white/70" : "bg-[#f3f3f3] text-[#616061]"
|
|
8678
|
-
),
|
|
8679
|
-
children: "APP"
|
|
8680
|
-
}
|
|
8681
|
-
),
|
|
8927
|
+
/* @__PURE__ */ jsx("span", { className: cn("font-bold text-sm", isDark ? "text-white" : "text-[#1d1c1d]"), children: displayName }),
|
|
8682
8928
|
/* @__PURE__ */ jsx("span", { children: "10:37 AM" })
|
|
8683
8929
|
]
|
|
8684
8930
|
}
|
|
@@ -8880,6 +9126,14 @@ var SURFACE_OPTIONS = [
|
|
|
8880
9126
|
];
|
|
8881
9127
|
var DEFAULT_DOCS_HREF = "https://docs.slack.dev/reference/block-kit/blocks";
|
|
8882
9128
|
var DEFAULT_DOCS_LABEL = "Docs";
|
|
9129
|
+
function formatMessageTs(ts) {
|
|
9130
|
+
const seconds = Number.parseFloat(ts);
|
|
9131
|
+
if (!Number.isFinite(seconds)) return ts;
|
|
9132
|
+
const date = new Date(seconds * 1e3);
|
|
9133
|
+
if (Number.isNaN(date.getTime())) return ts;
|
|
9134
|
+
return date.toLocaleString(void 0, { dateStyle: "medium", timeStyle: "short" });
|
|
9135
|
+
}
|
|
9136
|
+
var SEND_MENU_ITEM = "flex w-full cursor-pointer items-center gap-2 rounded px-2 py-1.5 text-left text-sm text-foreground transition-colors hover:bg-accent hover:text-accent-foreground focus-visible:bg-accent focus-visible:text-accent-foreground focus-visible:outline-none disabled:pointer-events-none disabled:opacity-50";
|
|
8883
9137
|
function Toolbar2({
|
|
8884
9138
|
onClear,
|
|
8885
9139
|
onOpenJson,
|
|
@@ -8896,194 +9150,227 @@ function Toolbar2({
|
|
|
8896
9150
|
showThemeControl = true,
|
|
8897
9151
|
docsLink,
|
|
8898
9152
|
errorCount,
|
|
8899
|
-
sendButtonLabel = "
|
|
9153
|
+
sendButtonLabel = "Review & send",
|
|
9154
|
+
editingEnabled = false,
|
|
9155
|
+
editBadge,
|
|
9156
|
+
onOpenLoad,
|
|
9157
|
+
onOpenUpdate,
|
|
9158
|
+
onExitEdit,
|
|
9159
|
+
loadButtonLabel = "Load message",
|
|
9160
|
+
updateButtonLabel = "Review & update"
|
|
8900
9161
|
}) {
|
|
8901
9162
|
const activeTheme = THEME_OPTIONS.find((t) => t.value === previewTheme) ?? THEME_OPTIONS[0];
|
|
8902
|
-
const activeSurface = SURFACE_OPTIONS.find((s) => s.value === previewSurface) ?? SURFACE_OPTIONS[0];
|
|
8903
|
-
const surfaceOptions = SURFACE_OPTIONS.filter((s) => allowedSurfaces.includes(s.value));
|
|
8904
|
-
const showSurfaceControl = surfaceOptions.length > 1;
|
|
8905
|
-
const docsHref = docsLink === false ? null : docsLink?.href ?? DEFAULT_DOCS_HREF;
|
|
8906
|
-
const docsLabel = docsLink === false ? null : docsLink?.label ?? DEFAULT_DOCS_LABEL;
|
|
8907
|
-
const [surfaceMenuOpen, setSurfaceMenuOpen] = useState(false);
|
|
8908
|
-
const [themeMenuOpen, setThemeMenuOpen] = useState(false);
|
|
8909
|
-
const [
|
|
8910
|
-
return /* @__PURE__ */ jsxs(
|
|
8911
|
-
/* @__PURE__ */ jsxs("div", { className: "flex
|
|
8912
|
-
|
|
8913
|
-
Button,
|
|
8914
|
-
|
|
8915
|
-
|
|
8916
|
-
|
|
8917
|
-
|
|
8918
|
-
|
|
8919
|
-
className: "md:hidden",
|
|
8920
|
-
"aria-label": "Add a block",
|
|
8921
|
-
children: [
|
|
8922
|
-
/* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
|
|
8923
|
-
/* @__PURE__ */ jsx("span", { children: "Blocks" })
|
|
8924
|
-
]
|
|
8925
|
-
}
|
|
8926
|
-
) : null,
|
|
8927
|
-
showSurfaceControl ? /* @__PURE__ */ jsxs(Popover, { open: surfaceMenuOpen, onOpenChange: setSurfaceMenuOpen, children: [
|
|
8928
|
-
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": `Preview surface: ${activeSurface.label}`, children: [
|
|
8929
|
-
/* @__PURE__ */ jsx(activeSurface.Icon, { className: "h-3.5 w-3.5" }),
|
|
8930
|
-
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: activeSurface.label }),
|
|
8931
|
-
/* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5 opacity-60" })
|
|
8932
|
-
] }) }),
|
|
8933
|
-
/* @__PURE__ */ jsx(PopoverContent, { align: "start", className: "w-36 p-1", children: /* @__PURE__ */ jsx(
|
|
8934
|
-
Menu,
|
|
9163
|
+
const activeSurface = SURFACE_OPTIONS.find((s) => s.value === previewSurface) ?? SURFACE_OPTIONS[0];
|
|
9164
|
+
const surfaceOptions = SURFACE_OPTIONS.filter((s) => allowedSurfaces.includes(s.value));
|
|
9165
|
+
const showSurfaceControl = surfaceOptions.length > 1;
|
|
9166
|
+
const docsHref = docsLink === false ? null : docsLink?.href ?? DEFAULT_DOCS_HREF;
|
|
9167
|
+
const docsLabel = docsLink === false ? null : docsLink?.label ?? DEFAULT_DOCS_LABEL;
|
|
9168
|
+
const [surfaceMenuOpen, setSurfaceMenuOpen] = useState(false);
|
|
9169
|
+
const [themeMenuOpen, setThemeMenuOpen] = useState(false);
|
|
9170
|
+
const [sendMenuOpen, setSendMenuOpen] = useState(false);
|
|
9171
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9172
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center justify-between gap-x-2 gap-y-1 border-b bg-background px-2 py-1.5 sm:px-3 sm:py-2", children: [
|
|
9173
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-1 sm:gap-2", children: [
|
|
9174
|
+
editingEnabled && !editBadge ? /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", onClick: onOpenLoad, "aria-label": loadButtonLabel, children: [
|
|
9175
|
+
/* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" }),
|
|
9176
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: loadButtonLabel })
|
|
9177
|
+
] }) : null,
|
|
9178
|
+
onOpenPalette ? /* @__PURE__ */ jsxs(
|
|
9179
|
+
Button,
|
|
8935
9180
|
{
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
|
|
9181
|
+
type: "button",
|
|
9182
|
+
variant: "ghost",
|
|
9183
|
+
size: "sm",
|
|
9184
|
+
onClick: onOpenPalette,
|
|
9185
|
+
className: "md:hidden",
|
|
9186
|
+
"aria-label": "Add a block",
|
|
9187
|
+
children: [
|
|
9188
|
+
/* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
|
|
9189
|
+
/* @__PURE__ */ jsx("span", { children: "Blocks" })
|
|
9190
|
+
]
|
|
9191
|
+
}
|
|
9192
|
+
) : null,
|
|
9193
|
+
showSurfaceControl ? /* @__PURE__ */ jsxs(Popover, { open: surfaceMenuOpen, onOpenChange: setSurfaceMenuOpen, children: [
|
|
9194
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": `Preview surface: ${activeSurface.label}`, children: [
|
|
9195
|
+
/* @__PURE__ */ jsx(activeSurface.Icon, { className: "h-3.5 w-3.5" }),
|
|
9196
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: activeSurface.label }),
|
|
9197
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "hidden h-3.5 w-3.5 opacity-60 md:inline" })
|
|
9198
|
+
] }) }),
|
|
9199
|
+
/* @__PURE__ */ jsx(PopoverContent, { align: "start", className: "w-36 p-1", children: /* @__PURE__ */ jsx(
|
|
9200
|
+
Menu,
|
|
9201
|
+
{
|
|
9202
|
+
ariaLabel: "Preview surface",
|
|
9203
|
+
options: surfaceOptions,
|
|
9204
|
+
value: previewSurface,
|
|
9205
|
+
onChange: (next) => {
|
|
9206
|
+
onPreviewSurfaceChange(next);
|
|
9207
|
+
setSurfaceMenuOpen(false);
|
|
9208
|
+
}
|
|
9209
|
+
}
|
|
9210
|
+
) })
|
|
9211
|
+
] }) : null,
|
|
9212
|
+
showThemeControl ? /* @__PURE__ */ jsxs(Popover, { open: themeMenuOpen, onOpenChange: setThemeMenuOpen, children: [
|
|
9213
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": `Preview theme: ${activeTheme.label}`, children: [
|
|
9214
|
+
/* @__PURE__ */ jsx(activeTheme.Icon, { className: "h-3.5 w-3.5" }),
|
|
9215
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: activeTheme.label }),
|
|
9216
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5 opacity-60" })
|
|
9217
|
+
] }) }),
|
|
9218
|
+
/* @__PURE__ */ jsx(PopoverContent, { align: "start", className: "w-32 p-1", children: /* @__PURE__ */ jsx(
|
|
9219
|
+
Menu,
|
|
9220
|
+
{
|
|
9221
|
+
ariaLabel: "Preview theme",
|
|
9222
|
+
options: THEME_OPTIONS,
|
|
9223
|
+
value: previewTheme,
|
|
9224
|
+
onChange: (next) => {
|
|
9225
|
+
onPreviewThemeChange(next);
|
|
9226
|
+
setThemeMenuOpen(false);
|
|
9227
|
+
}
|
|
8942
9228
|
}
|
|
9229
|
+
) })
|
|
9230
|
+
] }) : null,
|
|
9231
|
+
docsHref ? /* @__PURE__ */ jsxs(
|
|
9232
|
+
"a",
|
|
9233
|
+
{
|
|
9234
|
+
href: docsHref,
|
|
9235
|
+
target: "_blank",
|
|
9236
|
+
rel: "noreferrer noopener",
|
|
9237
|
+
className: "inline-flex h-8 items-center gap-1.5 rounded-md px-2 text-xs font-medium text-muted-foreground no-underline transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
9238
|
+
"aria-label": `${docsLabel} (opens in a new tab)`,
|
|
9239
|
+
children: [
|
|
9240
|
+
/* @__PURE__ */ jsx(BookOpen, { className: "h-3.5 w-3.5" }),
|
|
9241
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: docsLabel }),
|
|
9242
|
+
/* @__PURE__ */ jsx(ExternalLink, { className: "hidden h-3 w-3 opacity-50 md:inline" })
|
|
9243
|
+
]
|
|
8943
9244
|
}
|
|
8944
|
-
)
|
|
8945
|
-
] })
|
|
8946
|
-
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: activeTheme.label }),
|
|
8950
|
-
/* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5 opacity-60" })
|
|
8951
|
-
] }) }),
|
|
8952
|
-
/* @__PURE__ */ jsx(PopoverContent, { align: "start", className: "w-32 p-1", children: /* @__PURE__ */ jsx(
|
|
8953
|
-
Menu,
|
|
9245
|
+
) : null
|
|
9246
|
+
] }),
|
|
9247
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 sm:gap-2", children: [
|
|
9248
|
+
errorCount > 0 ? /* @__PURE__ */ jsxs(
|
|
9249
|
+
Button,
|
|
8954
9250
|
{
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
9251
|
+
type: "button",
|
|
9252
|
+
variant: "ghost",
|
|
9253
|
+
size: "sm",
|
|
9254
|
+
onClick: onOpenIssues,
|
|
9255
|
+
className: "border border-red-200! bg-red-50 text-red-700 hover:bg-red-100 hover:text-red-700",
|
|
9256
|
+
"aria-label": `${errorCount} ${errorCount === 1 ? "issue" : "issues"}`,
|
|
9257
|
+
children: [
|
|
9258
|
+
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-3.5 w-3.5" }),
|
|
9259
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
9260
|
+
errorCount,
|
|
9261
|
+
" ",
|
|
9262
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: errorCount === 1 ? "issue" : "issues" })
|
|
9263
|
+
] })
|
|
9264
|
+
]
|
|
8962
9265
|
}
|
|
8963
|
-
)
|
|
8964
|
-
|
|
8965
|
-
docsHref ? /* @__PURE__ */ jsxs(
|
|
8966
|
-
"a",
|
|
8967
|
-
{
|
|
8968
|
-
href: docsHref,
|
|
8969
|
-
target: "_blank",
|
|
8970
|
-
rel: "noreferrer noopener",
|
|
8971
|
-
className: "hidden h-8 items-center gap-1.5 rounded-md px-2 py-1 text-sm text-muted-foreground no-underline transition-colors hover:bg-accent hover:text-foreground focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring sm:inline-flex",
|
|
8972
|
-
"aria-label": `${docsLabel} (opens in a new tab)`,
|
|
8973
|
-
children: [
|
|
8974
|
-
/* @__PURE__ */ jsx(BookOpen, { className: "h-3.5 w-3.5" }),
|
|
8975
|
-
docsLabel,
|
|
8976
|
-
/* @__PURE__ */ jsx(ExternalLink, { className: "h-3 w-3 opacity-50" })
|
|
8977
|
-
]
|
|
8978
|
-
}
|
|
8979
|
-
) : null
|
|
8980
|
-
] }),
|
|
8981
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 sm:gap-2", children: [
|
|
8982
|
-
errorCount > 0 ? /* @__PURE__ */ jsxs(
|
|
8983
|
-
Button,
|
|
8984
|
-
{
|
|
8985
|
-
type: "button",
|
|
8986
|
-
variant: "ghost",
|
|
8987
|
-
size: "sm",
|
|
8988
|
-
onClick: onOpenIssues,
|
|
8989
|
-
className: "border border-red-200! bg-red-50 text-red-700 hover:bg-red-100 hover:text-red-700",
|
|
8990
|
-
"aria-label": `${errorCount} ${errorCount === 1 ? "issue" : "issues"}`,
|
|
8991
|
-
children: [
|
|
8992
|
-
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-3.5 w-3.5" }),
|
|
8993
|
-
/* @__PURE__ */ jsxs("span", { children: [
|
|
8994
|
-
errorCount,
|
|
8995
|
-
" ",
|
|
8996
|
-
/* @__PURE__ */ jsx("span", { className: "hidden sm:inline", children: errorCount === 1 ? "issue" : "issues" })
|
|
8997
|
-
] })
|
|
8998
|
-
]
|
|
8999
|
-
}
|
|
9000
|
-
) : null,
|
|
9001
|
-
/* @__PURE__ */ jsxs(
|
|
9002
|
-
Button,
|
|
9003
|
-
{
|
|
9004
|
-
type: "button",
|
|
9005
|
-
variant: "ghost",
|
|
9006
|
-
size: "sm",
|
|
9007
|
-
onClick: onClear,
|
|
9008
|
-
disabled: !canClear,
|
|
9009
|
-
className: "hidden hover:bg-destructive/10 hover:text-destructive sm:inline-flex",
|
|
9010
|
-
"aria-label": "Clear all blocks",
|
|
9011
|
-
children: [
|
|
9012
|
-
/* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" }),
|
|
9013
|
-
"Clear"
|
|
9014
|
-
]
|
|
9015
|
-
}
|
|
9016
|
-
),
|
|
9017
|
-
/* @__PURE__ */ jsxs(
|
|
9018
|
-
Button,
|
|
9019
|
-
{
|
|
9020
|
-
type: "button",
|
|
9021
|
-
variant: "ghost",
|
|
9022
|
-
size: "sm",
|
|
9023
|
-
onClick: onOpenJson,
|
|
9024
|
-
"aria-label": "View JSON",
|
|
9025
|
-
className: "hidden sm:inline-flex",
|
|
9026
|
-
children: [
|
|
9027
|
-
/* @__PURE__ */ jsx(Code2, { className: "h-3.5 w-3.5" }),
|
|
9028
|
-
"View JSON"
|
|
9029
|
-
]
|
|
9030
|
-
}
|
|
9031
|
-
),
|
|
9032
|
-
/* @__PURE__ */ jsxs(Popover, { open: moreMenuOpen, onOpenChange: setMoreMenuOpen, children: [
|
|
9033
|
-
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
9266
|
+
) : null,
|
|
9267
|
+
/* @__PURE__ */ jsxs(
|
|
9034
9268
|
Button,
|
|
9035
9269
|
{
|
|
9036
9270
|
type: "button",
|
|
9037
9271
|
variant: "ghost",
|
|
9038
9272
|
size: "sm",
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
className: "
|
|
9042
|
-
|
|
9273
|
+
onClick: onClear,
|
|
9274
|
+
disabled: !canClear,
|
|
9275
|
+
className: "hover:bg-destructive/10 hover:text-destructive",
|
|
9276
|
+
"aria-label": "Clear all blocks",
|
|
9277
|
+
children: [
|
|
9278
|
+
/* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" }),
|
|
9279
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: "Clear" })
|
|
9280
|
+
]
|
|
9043
9281
|
}
|
|
9044
|
-
)
|
|
9045
|
-
/* @__PURE__ */
|
|
9046
|
-
/* @__PURE__ */ jsx(
|
|
9047
|
-
|
|
9048
|
-
|
|
9049
|
-
|
|
9050
|
-
|
|
9051
|
-
|
|
9052
|
-
|
|
9053
|
-
|
|
9054
|
-
|
|
9055
|
-
|
|
9056
|
-
|
|
9057
|
-
|
|
9058
|
-
|
|
9059
|
-
|
|
9060
|
-
|
|
9061
|
-
|
|
9062
|
-
|
|
9063
|
-
|
|
9064
|
-
|
|
9065
|
-
|
|
9066
|
-
}
|
|
9067
|
-
|
|
9068
|
-
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
|
|
9072
|
-
|
|
9073
|
-
|
|
9074
|
-
|
|
9075
|
-
|
|
9076
|
-
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9282
|
+
),
|
|
9283
|
+
/* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", onClick: onOpenJson, "aria-label": "View JSON", children: [
|
|
9284
|
+
/* @__PURE__ */ jsx(Code2, { className: "h-3.5 w-3.5" }),
|
|
9285
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: "View JSON" })
|
|
9286
|
+
] }),
|
|
9287
|
+
editBadge ? (
|
|
9288
|
+
// A message is loaded: split button. Main action updates it in
|
|
9289
|
+
// place; the menu also offers posting the blocks as a new message.
|
|
9290
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-stretch", children: [
|
|
9291
|
+
/* @__PURE__ */ jsxs(
|
|
9292
|
+
Button,
|
|
9293
|
+
{
|
|
9294
|
+
type: "button",
|
|
9295
|
+
size: "sm",
|
|
9296
|
+
onClick: onOpenUpdate,
|
|
9297
|
+
disabled: !canSend,
|
|
9298
|
+
"aria-label": updateButtonLabel,
|
|
9299
|
+
className: "rounded-r-none",
|
|
9300
|
+
children: [
|
|
9301
|
+
/* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" }),
|
|
9302
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: updateButtonLabel })
|
|
9303
|
+
]
|
|
9304
|
+
}
|
|
9305
|
+
),
|
|
9306
|
+
/* @__PURE__ */ jsxs(Popover, { open: sendMenuOpen, onOpenChange: setSendMenuOpen, children: [
|
|
9307
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
9308
|
+
Button,
|
|
9309
|
+
{
|
|
9310
|
+
type: "button",
|
|
9311
|
+
size: "sm",
|
|
9312
|
+
"aria-label": "More message options",
|
|
9313
|
+
"aria-haspopup": "menu",
|
|
9314
|
+
className: "rounded-l-none border-l border-l-primary-foreground/30! px-1.5",
|
|
9315
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5" })
|
|
9316
|
+
}
|
|
9317
|
+
) }),
|
|
9318
|
+
/* @__PURE__ */ jsx(PopoverContent, { align: "end", className: "w-56 p-1", children: /* @__PURE__ */ jsxs("div", { role: "menu", "aria-label": "Message options", className: "flex flex-col", children: [
|
|
9319
|
+
/* @__PURE__ */ jsxs(
|
|
9320
|
+
"button",
|
|
9321
|
+
{
|
|
9322
|
+
type: "button",
|
|
9323
|
+
role: "menuitem",
|
|
9324
|
+
disabled: !canSend,
|
|
9325
|
+
onClick: () => {
|
|
9326
|
+
setSendMenuOpen(false);
|
|
9327
|
+
onOpenUpdate?.();
|
|
9328
|
+
},
|
|
9329
|
+
className: SEND_MENU_ITEM,
|
|
9330
|
+
children: [
|
|
9331
|
+
/* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" }),
|
|
9332
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1", children: "Update message" })
|
|
9333
|
+
]
|
|
9334
|
+
}
|
|
9335
|
+
),
|
|
9336
|
+
/* @__PURE__ */ jsxs(
|
|
9337
|
+
"button",
|
|
9338
|
+
{
|
|
9339
|
+
type: "button",
|
|
9340
|
+
role: "menuitem",
|
|
9341
|
+
disabled: !canSend,
|
|
9342
|
+
onClick: () => {
|
|
9343
|
+
setSendMenuOpen(false);
|
|
9344
|
+
onOpenSend();
|
|
9345
|
+
},
|
|
9346
|
+
className: SEND_MENU_ITEM,
|
|
9347
|
+
children: [
|
|
9348
|
+
/* @__PURE__ */ jsx(Send, { className: "h-3.5 w-3.5" }),
|
|
9349
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1", children: "Send as a new message" })
|
|
9350
|
+
]
|
|
9351
|
+
}
|
|
9352
|
+
)
|
|
9353
|
+
] }) })
|
|
9354
|
+
] })
|
|
9355
|
+
] })
|
|
9356
|
+
) : /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", onClick: onOpenSend, disabled: !canSend, "aria-label": sendButtonLabel, children: [
|
|
9357
|
+
/* @__PURE__ */ jsx(Send, { className: "h-3.5 w-3.5" }),
|
|
9358
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: sendButtonLabel })
|
|
9359
|
+
] })
|
|
9360
|
+
] })
|
|
9361
|
+
] }),
|
|
9362
|
+
editingEnabled && editBadge ? /* @__PURE__ */ jsxs("div", { className: "flex flex-wrap items-center gap-x-3 gap-y-1 border-b bg-muted px-2 py-2 text-foreground sm:px-3", children: [
|
|
9363
|
+
/* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4 shrink-0 text-primary" }),
|
|
9364
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 text-sm", children: [
|
|
9365
|
+
"References an existing message in ",
|
|
9366
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: editBadge.channelLabel }),
|
|
9367
|
+
/* @__PURE__ */ jsx("span", { className: "ml-1 text-xs opacity-70", title: editBadge.ts, children: formatMessageTs(editBadge.ts) })
|
|
9081
9368
|
] }),
|
|
9082
|
-
/* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", onClick:
|
|
9083
|
-
/* @__PURE__ */ jsx(
|
|
9084
|
-
|
|
9369
|
+
/* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", onClick: onExitEdit, className: "shrink-0", children: [
|
|
9370
|
+
/* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" }),
|
|
9371
|
+
"Switch to a new message"
|
|
9085
9372
|
] })
|
|
9086
|
-
] })
|
|
9373
|
+
] }) : null
|
|
9087
9374
|
] });
|
|
9088
9375
|
}
|
|
9089
9376
|
function Menu({
|
|
@@ -9141,52 +9428,132 @@ function Menu({
|
|
|
9141
9428
|
);
|
|
9142
9429
|
}) });
|
|
9143
9430
|
}
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9431
|
+
function UpdateDialog({
|
|
9432
|
+
open,
|
|
9433
|
+
onOpenChange,
|
|
9434
|
+
target,
|
|
9435
|
+
blocks,
|
|
9436
|
+
loadSendAsUserStatus,
|
|
9437
|
+
onUpdate,
|
|
9438
|
+
confirmUpdateLabel = "Update message",
|
|
9439
|
+
errorCount,
|
|
9440
|
+
onShowIssues
|
|
9151
9441
|
}) {
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9442
|
+
const asUser = target.editableVia === "user";
|
|
9443
|
+
const [userStatus, setUserStatus] = useState(null);
|
|
9444
|
+
const [status, setStatus] = useState({ kind: "idle" });
|
|
9445
|
+
const loadSendAsUserStatusRef = useRef(loadSendAsUserStatus);
|
|
9446
|
+
useEffect(() => {
|
|
9447
|
+
loadSendAsUserStatusRef.current = loadSendAsUserStatus;
|
|
9448
|
+
});
|
|
9449
|
+
const refreshSendAsUser = useCallback(() => {
|
|
9450
|
+
loadSendAsUserStatusRef.current().then(setUserStatus).catch(() => setUserStatus({ canSendAsUser: false }));
|
|
9451
|
+
}, []);
|
|
9452
|
+
useEffect(() => {
|
|
9453
|
+
if (!open) {
|
|
9454
|
+
return;
|
|
9164
9455
|
}
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
icon,
|
|
9170
|
-
trailingIcon,
|
|
9171
|
-
children,
|
|
9172
|
-
onSelect
|
|
9173
|
-
}) {
|
|
9174
|
-
return /* @__PURE__ */ jsxs(
|
|
9175
|
-
"a",
|
|
9176
|
-
{
|
|
9177
|
-
role: "menuitem",
|
|
9178
|
-
href,
|
|
9179
|
-
target: "_blank",
|
|
9180
|
-
rel: "noreferrer noopener",
|
|
9181
|
-
onClick: onSelect,
|
|
9182
|
-
className: ACTION_ITEM_BASE,
|
|
9183
|
-
children: [
|
|
9184
|
-
icon,
|
|
9185
|
-
/* @__PURE__ */ jsx("span", { className: "flex-1", children }),
|
|
9186
|
-
trailingIcon
|
|
9187
|
-
]
|
|
9456
|
+
setStatus({ kind: "idle" });
|
|
9457
|
+
if (asUser) {
|
|
9458
|
+
setUserStatus(null);
|
|
9459
|
+
refreshSendAsUser();
|
|
9188
9460
|
}
|
|
9189
|
-
);
|
|
9461
|
+
}, [open, asUser, refreshSendAsUser]);
|
|
9462
|
+
useEffect(() => {
|
|
9463
|
+
if (!open || !asUser) {
|
|
9464
|
+
return;
|
|
9465
|
+
}
|
|
9466
|
+
const handler = () => refreshSendAsUser();
|
|
9467
|
+
window.addEventListener("focus", handler);
|
|
9468
|
+
return () => window.removeEventListener("focus", handler);
|
|
9469
|
+
}, [open, asUser, refreshSendAsUser]);
|
|
9470
|
+
const needsSignIn = asUser && userStatus !== null && !userStatus.canSendAsUser;
|
|
9471
|
+
const handleSubmit = async () => {
|
|
9472
|
+
setStatus({ kind: "updating" });
|
|
9473
|
+
try {
|
|
9474
|
+
const result = await onUpdate({
|
|
9475
|
+
channelId: target.channelId,
|
|
9476
|
+
ts: target.ts,
|
|
9477
|
+
blocks: toSlackBlocks(blocks),
|
|
9478
|
+
asUser
|
|
9479
|
+
});
|
|
9480
|
+
if (result.ok) {
|
|
9481
|
+
setStatus({ kind: "idle" });
|
|
9482
|
+
onOpenChange(false);
|
|
9483
|
+
return;
|
|
9484
|
+
}
|
|
9485
|
+
setStatus({ kind: "error", error: result.error ?? "Update failed." });
|
|
9486
|
+
} catch (e) {
|
|
9487
|
+
setStatus({ kind: "error", error: e instanceof Error ? e.message : "Update failed." });
|
|
9488
|
+
}
|
|
9489
|
+
};
|
|
9490
|
+
const channelLabel = target.channelName ? `#${target.channelName}` : target.channelId;
|
|
9491
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "w-[calc(100vw-1.5rem)] max-w-lg rounded-lg", children: [
|
|
9492
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
9493
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: "Update message" }),
|
|
9494
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: "This replaces the message that's already posted. It stays in the same channel and can't be moved." })
|
|
9495
|
+
] }),
|
|
9496
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
9497
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
9498
|
+
/* @__PURE__ */ jsx(Label, { children: "Channel" }),
|
|
9499
|
+
/* @__PURE__ */ jsx("p", { className: "flex h-9 items-center rounded-md border border-input bg-muted px-3 text-sm text-muted-foreground", children: channelLabel })
|
|
9500
|
+
] }),
|
|
9501
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
9502
|
+
/* @__PURE__ */ jsx(Label, { children: "Posting as" }),
|
|
9503
|
+
/* @__PURE__ */ jsx("p", { className: "flex h-9 items-center rounded-md border border-input bg-muted px-3 text-sm text-muted-foreground", children: asUser ? "Your account" : "App bot" }),
|
|
9504
|
+
needsSignIn && userStatus?.oauthUrl && isSafeHref(userStatus.oauthUrl) && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
9505
|
+
/* @__PURE__ */ jsxs(
|
|
9506
|
+
"a",
|
|
9507
|
+
{
|
|
9508
|
+
href: userStatus.oauthUrl,
|
|
9509
|
+
target: "_blank",
|
|
9510
|
+
rel: "noopener noreferrer",
|
|
9511
|
+
className: "inline-flex items-center gap-1 text-primary hover:underline",
|
|
9512
|
+
children: [
|
|
9513
|
+
"Sign in with Slack ",
|
|
9514
|
+
/* @__PURE__ */ jsx(ExternalLink, { className: "h-3 w-3" })
|
|
9515
|
+
]
|
|
9516
|
+
}
|
|
9517
|
+
),
|
|
9518
|
+
" ",
|
|
9519
|
+
"to update your own message."
|
|
9520
|
+
] }),
|
|
9521
|
+
needsSignIn && !userStatus?.oauthUrl && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Sign in with Slack to update your own message." })
|
|
9522
|
+
] }),
|
|
9523
|
+
errorCount > 0 ? /* @__PURE__ */ jsxs(
|
|
9524
|
+
"button",
|
|
9525
|
+
{
|
|
9526
|
+
type: "button",
|
|
9527
|
+
onClick: onShowIssues,
|
|
9528
|
+
className: "flex items-center gap-2 rounded-md border border-destructive/30 bg-destructive/5 p-2 text-left text-xs text-destructive hover:bg-destructive/10",
|
|
9529
|
+
children: [
|
|
9530
|
+
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
9531
|
+
/* @__PURE__ */ jsxs("span", { className: "flex-1", children: [
|
|
9532
|
+
"Fix ",
|
|
9533
|
+
errorCount,
|
|
9534
|
+
" ",
|
|
9535
|
+
errorCount === 1 ? "issue" : "issues",
|
|
9536
|
+
" before updating."
|
|
9537
|
+
] }),
|
|
9538
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 underline", children: "Show issues" })
|
|
9539
|
+
]
|
|
9540
|
+
}
|
|
9541
|
+
) : null,
|
|
9542
|
+
status.kind === "error" && /* @__PURE__ */ jsx("p", { className: "rounded-md border border-destructive/30 bg-destructive/5 p-2 text-xs text-destructive", children: status.error })
|
|
9543
|
+
] }),
|
|
9544
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
9545
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
9546
|
+
/* @__PURE__ */ jsx(
|
|
9547
|
+
Button,
|
|
9548
|
+
{
|
|
9549
|
+
type: "button",
|
|
9550
|
+
onClick: handleSubmit,
|
|
9551
|
+
disabled: status.kind === "updating" || blocks.length === 0 || errorCount > 0 || needsSignIn,
|
|
9552
|
+
children: status.kind === "updating" ? "Updating\u2026" : confirmUpdateLabel
|
|
9553
|
+
}
|
|
9554
|
+
)
|
|
9555
|
+
] })
|
|
9556
|
+
] }) });
|
|
9190
9557
|
}
|
|
9191
9558
|
function BlockKitchen(props) {
|
|
9192
9559
|
const {
|
|
@@ -9198,6 +9565,10 @@ function BlockKitchen(props) {
|
|
|
9198
9565
|
loadChannels,
|
|
9199
9566
|
loadSendAsUserStatus,
|
|
9200
9567
|
onSend,
|
|
9568
|
+
editing,
|
|
9569
|
+
loadButtonLabel,
|
|
9570
|
+
updateButtonLabel,
|
|
9571
|
+
confirmUpdateLabel,
|
|
9201
9572
|
palette,
|
|
9202
9573
|
disabledBlockTypes,
|
|
9203
9574
|
showPaletteSearch,
|
|
@@ -9243,6 +9614,10 @@ function BlockKitchen(props) {
|
|
|
9243
9614
|
}, [blocks]);
|
|
9244
9615
|
const [jsonOpen, setJsonOpen] = useState(false);
|
|
9245
9616
|
const [sendOpen, setSendOpen] = useState(false);
|
|
9617
|
+
const [updateOpen, setUpdateOpen] = useState(false);
|
|
9618
|
+
const [loadOpen, setLoadOpen] = useState(false);
|
|
9619
|
+
const [editTarget, setEditTarget] = useState(null);
|
|
9620
|
+
const activeEditTarget = editing ? editTarget : null;
|
|
9246
9621
|
const [issuesOpen, setIssuesOpen] = useState(false);
|
|
9247
9622
|
const [paletteOpen, setPaletteOpen] = useState(false);
|
|
9248
9623
|
const [openBlockId, setOpenBlockId] = useState(null);
|
|
@@ -9363,7 +9738,21 @@ function BlockKitchen(props) {
|
|
|
9363
9738
|
allowedSurfaces,
|
|
9364
9739
|
showThemeControl: isPreviewThemeControlled ? false : showThemeControl,
|
|
9365
9740
|
docsLink,
|
|
9366
|
-
sendButtonLabel
|
|
9741
|
+
sendButtonLabel,
|
|
9742
|
+
editingEnabled: !!editing,
|
|
9743
|
+
editBadge: activeEditTarget ? {
|
|
9744
|
+
channelLabel: activeEditTarget.channelName ? `#${activeEditTarget.channelName}` : activeEditTarget.channelId,
|
|
9745
|
+
ts: activeEditTarget.ts
|
|
9746
|
+
} : null,
|
|
9747
|
+
onOpenLoad: () => setLoadOpen(true),
|
|
9748
|
+
onOpenUpdate: () => setUpdateOpen(true),
|
|
9749
|
+
onExitEdit: () => {
|
|
9750
|
+
setEditTarget(null);
|
|
9751
|
+
replaceAll([]);
|
|
9752
|
+
setLoadOpen(true);
|
|
9753
|
+
},
|
|
9754
|
+
loadButtonLabel,
|
|
9755
|
+
updateButtonLabel
|
|
9367
9756
|
}
|
|
9368
9757
|
),
|
|
9369
9758
|
/* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 items-stretch", children: [
|
|
@@ -9382,6 +9771,8 @@ function BlockKitchen(props) {
|
|
|
9382
9771
|
{
|
|
9383
9772
|
blocks,
|
|
9384
9773
|
workspaceName,
|
|
9774
|
+
authorName: activeEditTarget?.username,
|
|
9775
|
+
authorIcon: activeEditTarget?.iconUrl,
|
|
9385
9776
|
previewHooks: mergedPreviewHooks,
|
|
9386
9777
|
previewTheme,
|
|
9387
9778
|
previewSurface,
|
|
@@ -9447,6 +9838,53 @@ function BlockKitchen(props) {
|
|
|
9447
9838
|
}
|
|
9448
9839
|
}
|
|
9449
9840
|
),
|
|
9841
|
+
activeEditTarget && editing ? /* @__PURE__ */ jsx(
|
|
9842
|
+
UpdateDialog,
|
|
9843
|
+
{
|
|
9844
|
+
open: updateOpen,
|
|
9845
|
+
onOpenChange: setUpdateOpen,
|
|
9846
|
+
target: activeEditTarget,
|
|
9847
|
+
blocks: blockPayloads,
|
|
9848
|
+
loadSendAsUserStatus,
|
|
9849
|
+
onUpdate: editing.onUpdate,
|
|
9850
|
+
confirmUpdateLabel,
|
|
9851
|
+
errorCount: validation.total,
|
|
9852
|
+
onShowIssues: () => {
|
|
9853
|
+
setUpdateOpen(false);
|
|
9854
|
+
setIssuesOpen(true);
|
|
9855
|
+
}
|
|
9856
|
+
}
|
|
9857
|
+
) : null,
|
|
9858
|
+
editing ? /* @__PURE__ */ jsx(
|
|
9859
|
+
LoadMessageDialog,
|
|
9860
|
+
{
|
|
9861
|
+
open: loadOpen,
|
|
9862
|
+
onOpenChange: setLoadOpen,
|
|
9863
|
+
onLoadMessage: editing.onLoadMessage,
|
|
9864
|
+
loadRecentMessages: editing.loadRecentMessages,
|
|
9865
|
+
loadChannels,
|
|
9866
|
+
onLoaded: (result) => {
|
|
9867
|
+
replaceAll(result.blocks);
|
|
9868
|
+
setEditTarget({
|
|
9869
|
+
channelId: result.channelId,
|
|
9870
|
+
channelName: result.channelName,
|
|
9871
|
+
ts: result.ts,
|
|
9872
|
+
editableVia: result.editableVia,
|
|
9873
|
+
workspaceName: result.workspaceName,
|
|
9874
|
+
username: result.username,
|
|
9875
|
+
iconUrl: result.iconUrl
|
|
9876
|
+
});
|
|
9877
|
+
setLoadOpen(false);
|
|
9878
|
+
},
|
|
9879
|
+
onOpenAsNew: (loadedBlocks) => {
|
|
9880
|
+
if (loadedBlocks) {
|
|
9881
|
+
replaceAll(loadedBlocks);
|
|
9882
|
+
}
|
|
9883
|
+
setEditTarget(null);
|
|
9884
|
+
setLoadOpen(false);
|
|
9885
|
+
}
|
|
9886
|
+
}
|
|
9887
|
+
) : null,
|
|
9450
9888
|
/* @__PURE__ */ jsx(
|
|
9451
9889
|
IssuesSheet,
|
|
9452
9890
|
{
|