@tightknitai/block-kitchen 0.8.10 → 0.8.11
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 +65 -1
- package/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.cjs +705 -320
- 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 +706 -321
- package/dist/index.js.map +1 -1
- package/dist/{palette-DBTHRygt.d.cts → palette-Bup05opK.d.cts} +152 -4
- package/dist/{palette-DBTHRygt.d.ts → palette-Bup05opK.d.ts} +152 -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,213 @@ 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
|
+
onLoaded,
|
|
2825
|
+
onOpenAsNew
|
|
2826
|
+
}) {
|
|
2827
|
+
const [link, setLink] = useState("");
|
|
2828
|
+
const [status, setStatus] = useState({ kind: "idle" });
|
|
2829
|
+
const [recent, setRecent] = useState(null);
|
|
2830
|
+
const [recentError, setRecentError] = useState(null);
|
|
2831
|
+
const inputRef = useRef(null);
|
|
2832
|
+
const onLoadMessageRef = useRef(onLoadMessage);
|
|
2833
|
+
const loadRecentMessagesRef = useRef(loadRecentMessages);
|
|
2834
|
+
useEffect(() => {
|
|
2835
|
+
onLoadMessageRef.current = onLoadMessage;
|
|
2836
|
+
loadRecentMessagesRef.current = loadRecentMessages;
|
|
2837
|
+
});
|
|
2838
|
+
const hasRecent = !!loadRecentMessages;
|
|
2839
|
+
useEffect(() => {
|
|
2840
|
+
if (!open) {
|
|
2841
|
+
return;
|
|
2842
|
+
}
|
|
2843
|
+
setLink("");
|
|
2844
|
+
setStatus({ kind: "idle" });
|
|
2845
|
+
if (!loadRecentMessagesRef.current) {
|
|
2846
|
+
setRecent([]);
|
|
2847
|
+
setRecentError(null);
|
|
2848
|
+
return;
|
|
2849
|
+
}
|
|
2850
|
+
setRecent(null);
|
|
2851
|
+
setRecentError(null);
|
|
2852
|
+
let cancelled = false;
|
|
2853
|
+
loadRecentMessagesRef.current().then((list) => {
|
|
2854
|
+
if (!cancelled) {
|
|
2855
|
+
setRecent(list);
|
|
2856
|
+
}
|
|
2857
|
+
}).catch((e) => {
|
|
2858
|
+
if (!cancelled) {
|
|
2859
|
+
setRecentError(e instanceof Error ? e.message : "Failed to load recent messages.");
|
|
2860
|
+
}
|
|
2861
|
+
});
|
|
2862
|
+
return () => {
|
|
2863
|
+
cancelled = true;
|
|
2864
|
+
};
|
|
2865
|
+
}, [open]);
|
|
2866
|
+
const handleLoad = async () => {
|
|
2867
|
+
const trimmed = link.trim();
|
|
2868
|
+
if (!trimmed) {
|
|
2869
|
+
setStatus({ kind: "error", error: "Paste a Slack message link first." });
|
|
2870
|
+
return;
|
|
2871
|
+
}
|
|
2872
|
+
setStatus({ kind: "loading" });
|
|
2873
|
+
try {
|
|
2874
|
+
const result = await onLoadMessageRef.current({ link: trimmed });
|
|
2875
|
+
if (result.ok) {
|
|
2876
|
+
onLoaded(result);
|
|
2877
|
+
return;
|
|
2878
|
+
}
|
|
2879
|
+
setStatus({ kind: "not-editable", reason: result.reason, blocks: result.blocks });
|
|
2880
|
+
} catch (e) {
|
|
2881
|
+
setStatus({ kind: "error", error: e instanceof Error ? e.message : "Failed to load message." });
|
|
2882
|
+
}
|
|
2883
|
+
};
|
|
2884
|
+
const notEditable = status.kind === "not-editable" ? status : null;
|
|
2885
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(
|
|
2886
|
+
DialogContent,
|
|
2887
|
+
{
|
|
2888
|
+
className: "w-[calc(100vw-1.5rem)] max-w-lg rounded-lg",
|
|
2889
|
+
onOpenAutoFocus: (e) => {
|
|
2890
|
+
e.preventDefault();
|
|
2891
|
+
inputRef.current?.focus();
|
|
2892
|
+
},
|
|
2893
|
+
children: [
|
|
2894
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
2895
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: "Edit an existing message" }),
|
|
2896
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-1.5", children: [
|
|
2897
|
+
/* @__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.` }),
|
|
2898
|
+
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
2899
|
+
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
2900
|
+
"button",
|
|
2901
|
+
{
|
|
2902
|
+
type: "button",
|
|
2903
|
+
"aria-label": "How to copy a message link",
|
|
2904
|
+
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",
|
|
2905
|
+
children: /* @__PURE__ */ jsx(Info, { className: "h-3.5 w-3.5" })
|
|
2906
|
+
}
|
|
2907
|
+
) }),
|
|
2908
|
+
/* @__PURE__ */ jsxs(TooltipContent, { className: "max-w-xs leading-relaxed", children: [
|
|
2909
|
+
"In Slack, hover over the message and click the ",
|
|
2910
|
+
/* @__PURE__ */ jsx("strong", { children: "\u22EE More actions" }),
|
|
2911
|
+
" button (or right-click the message), then choose ",
|
|
2912
|
+
/* @__PURE__ */ jsx("strong", { children: "Copy link" }),
|
|
2913
|
+
"."
|
|
2914
|
+
] })
|
|
2915
|
+
] })
|
|
2916
|
+
] })
|
|
2917
|
+
] }),
|
|
2918
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2919
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
2920
|
+
/* @__PURE__ */ jsx(Label, { htmlFor: "message-link", children: "Message link" }),
|
|
2921
|
+
/* @__PURE__ */ jsx(
|
|
2922
|
+
Input,
|
|
2923
|
+
{
|
|
2924
|
+
ref: inputRef,
|
|
2925
|
+
id: "message-link",
|
|
2926
|
+
value: link,
|
|
2927
|
+
onChange: (e) => {
|
|
2928
|
+
setLink(e.target.value);
|
|
2929
|
+
if (status.kind !== "idle" && status.kind !== "loading") {
|
|
2930
|
+
setStatus({ kind: "idle" });
|
|
2931
|
+
}
|
|
2932
|
+
},
|
|
2933
|
+
onKeyDown: (e) => {
|
|
2934
|
+
if (e.key === "Enter" && status.kind !== "loading") {
|
|
2935
|
+
e.preventDefault();
|
|
2936
|
+
handleLoad();
|
|
2937
|
+
}
|
|
2938
|
+
},
|
|
2939
|
+
placeholder: "https://your-workspace.slack.com/archives/C\u2026/p\u2026",
|
|
2940
|
+
autoComplete: "off",
|
|
2941
|
+
spellCheck: false
|
|
2942
|
+
}
|
|
2943
|
+
)
|
|
2944
|
+
] }),
|
|
2945
|
+
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 }),
|
|
2946
|
+
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: [
|
|
2947
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-start gap-2", children: [
|
|
2948
|
+
/* @__PURE__ */ jsx(AlertTriangle, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }),
|
|
2949
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1", children: notEditable.reason })
|
|
2950
|
+
] }),
|
|
2951
|
+
/* @__PURE__ */ jsx(
|
|
2952
|
+
Button,
|
|
2953
|
+
{
|
|
2954
|
+
type: "button",
|
|
2955
|
+
variant: "outline",
|
|
2956
|
+
size: "sm",
|
|
2957
|
+
className: "self-start",
|
|
2958
|
+
onClick: () => onOpenAsNew(notEditable.blocks),
|
|
2959
|
+
children: "Open as a new message instead"
|
|
2960
|
+
}
|
|
2961
|
+
)
|
|
2962
|
+
] }),
|
|
2963
|
+
hasRecent && /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
2964
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
2965
|
+
/* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" }),
|
|
2966
|
+
"or pick a recent message",
|
|
2967
|
+
/* @__PURE__ */ jsx("span", { className: "h-px flex-1 bg-border" })
|
|
2968
|
+
] }),
|
|
2969
|
+
recent === null && !recentError && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Loading recent messages\u2026" }),
|
|
2970
|
+
recentError && /* @__PURE__ */ jsx("p", { className: "text-xs text-destructive", children: recentError }),
|
|
2971
|
+
recent && recent.length === 0 && !recentError && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "No recent messages from this app." }),
|
|
2972
|
+
recent && recent.length > 0 && /* @__PURE__ */ jsx("div", { className: "flex max-h-48 flex-col gap-1 overflow-y-auto", children: recent.map((m) => {
|
|
2973
|
+
const asUser = (m.editableVia ?? "bot") === "user";
|
|
2974
|
+
return /* @__PURE__ */ jsxs(
|
|
2975
|
+
"button",
|
|
2976
|
+
{
|
|
2977
|
+
type: "button",
|
|
2978
|
+
onClick: () => onLoaded(recentToResult(m)),
|
|
2979
|
+
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",
|
|
2980
|
+
children: [
|
|
2981
|
+
/* @__PURE__ */ jsxs("span", { className: "flex items-baseline justify-between gap-2", children: [
|
|
2982
|
+
/* @__PURE__ */ jsxs("span", { className: "flex min-w-0 items-baseline gap-1.5", children: [
|
|
2983
|
+
/* @__PURE__ */ jsx("span", { className: "truncate font-medium", children: m.channelName ? `#${m.channelName}` : m.channelId }),
|
|
2984
|
+
/* @__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" })
|
|
2985
|
+
] }),
|
|
2986
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 font-mono text-xs text-muted-foreground", children: m.ts })
|
|
2987
|
+
] }),
|
|
2988
|
+
m.label && /* @__PURE__ */ jsx("span", { className: "truncate text-xs text-muted-foreground", children: m.label })
|
|
2989
|
+
]
|
|
2990
|
+
},
|
|
2991
|
+
`${m.channelId}:${m.ts}`
|
|
2992
|
+
);
|
|
2993
|
+
}) })
|
|
2994
|
+
] })
|
|
2995
|
+
] }),
|
|
2996
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
2997
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
2998
|
+
/* @__PURE__ */ jsx(Button, { type: "button", onClick: handleLoad, disabled: status.kind === "loading" || !link.trim(), children: status.kind === "loading" ? "Loading\u2026" : "Load message" })
|
|
2999
|
+
] })
|
|
3000
|
+
]
|
|
3001
|
+
}
|
|
3002
|
+
) });
|
|
3003
|
+
}
|
|
2712
3004
|
var PALETTE_DRAG_PREFIX = "palette:";
|
|
2713
3005
|
function parsePaletteDragId(id) {
|
|
2714
3006
|
if (typeof id !== "string" || !id.startsWith(PALETTE_DRAG_PREFIX)) {
|
|
@@ -2908,100 +3200,6 @@ function PaletteItem({
|
|
|
2908
3200
|
}
|
|
2909
3201
|
);
|
|
2910
3202
|
}
|
|
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
3203
|
function SendDialog({
|
|
3006
3204
|
open,
|
|
3007
3205
|
onOpenChange,
|
|
@@ -4142,7 +4340,7 @@ function TextItemCard({
|
|
|
4142
4340
|
id: `ctx-text-${index}`,
|
|
4143
4341
|
value: element.text,
|
|
4144
4342
|
rows: 2,
|
|
4145
|
-
placeholder: "e.g. Posted by @
|
|
4343
|
+
placeholder: "e.g. Posted by @riley",
|
|
4146
4344
|
onChange: (e) => onChange({ ...element, text: e.target.value })
|
|
4147
4345
|
}
|
|
4148
4346
|
) }),
|
|
@@ -4227,7 +4425,7 @@ function ImageItemCard({
|
|
|
4227
4425
|
{
|
|
4228
4426
|
id: `ctx-img-alt-${index}`,
|
|
4229
4427
|
value: element.alt_text,
|
|
4230
|
-
placeholder: "e.g.
|
|
4428
|
+
placeholder: "e.g. Riley's avatar",
|
|
4231
4429
|
onChange: (e) => onChange({ ...element, alt_text: e.target.value })
|
|
4232
4430
|
}
|
|
4233
4431
|
) })
|
|
@@ -8560,6 +8758,8 @@ var SURFACE_DROPPABLE_ID = "builder-surface";
|
|
|
8560
8758
|
function Surface({
|
|
8561
8759
|
blocks,
|
|
8562
8760
|
workspaceName,
|
|
8761
|
+
authorName,
|
|
8762
|
+
authorIcon,
|
|
8563
8763
|
previewHooks,
|
|
8564
8764
|
previewTheme,
|
|
8565
8765
|
previewSurface = "message",
|
|
@@ -8635,16 +8835,20 @@ function Surface({
|
|
|
8635
8835
|
{
|
|
8636
8836
|
"aria-label": "Block preview",
|
|
8637
8837
|
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 }) })
|
|
8838
|
+
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
8839
|
}
|
|
8640
8840
|
);
|
|
8641
8841
|
}
|
|
8642
8842
|
function MessageFrame({
|
|
8643
8843
|
workspaceName,
|
|
8844
|
+
authorName,
|
|
8845
|
+
authorIcon,
|
|
8644
8846
|
isDark,
|
|
8645
8847
|
children
|
|
8646
8848
|
}) {
|
|
8647
|
-
const
|
|
8849
|
+
const displayName = authorName ?? workspaceName ?? "Your app";
|
|
8850
|
+
const initial = displayName.slice(0, 1).toUpperCase();
|
|
8851
|
+
const safeIcon = authorIcon && isSafeImageSrc(authorIcon) ? authorIcon : null;
|
|
8648
8852
|
return /* @__PURE__ */ jsxs(
|
|
8649
8853
|
"div",
|
|
8650
8854
|
{
|
|
@@ -8658,7 +8862,7 @@ function MessageFrame({
|
|
|
8658
8862
|
{
|
|
8659
8863
|
className: cn("flex items-center gap-2 px-5 pt-3 pb-1 text-xs", isDark ? "text-white/60" : "text-[#616061]"),
|
|
8660
8864
|
children: [
|
|
8661
|
-
/* @__PURE__ */ jsx(
|
|
8865
|
+
safeIcon ? /* @__PURE__ */ jsx("img", { src: safeIcon, alt: "", className: "h-7 w-7 shrink-0 rounded object-cover" }) : /* @__PURE__ */ jsx(
|
|
8662
8866
|
"span",
|
|
8663
8867
|
{
|
|
8664
8868
|
className: cn(
|
|
@@ -8668,17 +8872,7 @@ function MessageFrame({
|
|
|
8668
8872
|
children: initial
|
|
8669
8873
|
}
|
|
8670
8874
|
),
|
|
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
|
-
),
|
|
8875
|
+
/* @__PURE__ */ jsx("span", { className: cn("font-bold text-sm", isDark ? "text-white" : "text-[#1d1c1d]"), children: displayName }),
|
|
8682
8876
|
/* @__PURE__ */ jsx("span", { children: "10:37 AM" })
|
|
8683
8877
|
]
|
|
8684
8878
|
}
|
|
@@ -8880,6 +9074,14 @@ var SURFACE_OPTIONS = [
|
|
|
8880
9074
|
];
|
|
8881
9075
|
var DEFAULT_DOCS_HREF = "https://docs.slack.dev/reference/block-kit/blocks";
|
|
8882
9076
|
var DEFAULT_DOCS_LABEL = "Docs";
|
|
9077
|
+
function formatMessageTs(ts) {
|
|
9078
|
+
const seconds = Number.parseFloat(ts);
|
|
9079
|
+
if (!Number.isFinite(seconds)) return ts;
|
|
9080
|
+
const date = new Date(seconds * 1e3);
|
|
9081
|
+
if (Number.isNaN(date.getTime())) return ts;
|
|
9082
|
+
return date.toLocaleString(void 0, { dateStyle: "medium", timeStyle: "short" });
|
|
9083
|
+
}
|
|
9084
|
+
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
9085
|
function Toolbar2({
|
|
8884
9086
|
onClear,
|
|
8885
9087
|
onOpenJson,
|
|
@@ -8896,7 +9098,14 @@ function Toolbar2({
|
|
|
8896
9098
|
showThemeControl = true,
|
|
8897
9099
|
docsLink,
|
|
8898
9100
|
errorCount,
|
|
8899
|
-
sendButtonLabel = "
|
|
9101
|
+
sendButtonLabel = "Review & send",
|
|
9102
|
+
editingEnabled = false,
|
|
9103
|
+
editBadge,
|
|
9104
|
+
onOpenLoad,
|
|
9105
|
+
onOpenUpdate,
|
|
9106
|
+
onExitEdit,
|
|
9107
|
+
loadButtonLabel = "Load message",
|
|
9108
|
+
updateButtonLabel = "Review & update"
|
|
8900
9109
|
}) {
|
|
8901
9110
|
const activeTheme = THEME_OPTIONS.find((t) => t.value === previewTheme) ?? THEME_OPTIONS[0];
|
|
8902
9111
|
const activeSurface = SURFACE_OPTIONS.find((s) => s.value === previewSurface) ?? SURFACE_OPTIONS[0];
|
|
@@ -8906,184 +9115,210 @@ function Toolbar2({
|
|
|
8906
9115
|
const docsLabel = docsLink === false ? null : docsLink?.label ?? DEFAULT_DOCS_LABEL;
|
|
8907
9116
|
const [surfaceMenuOpen, setSurfaceMenuOpen] = useState(false);
|
|
8908
9117
|
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,
|
|
9118
|
+
const [sendMenuOpen, setSendMenuOpen] = useState(false);
|
|
9119
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9120
|
+
/* @__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: [
|
|
9121
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-1 sm:gap-2", children: [
|
|
9122
|
+
editingEnabled && !editBadge ? /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", onClick: onOpenLoad, "aria-label": loadButtonLabel, children: [
|
|
9123
|
+
/* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" }),
|
|
9124
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: loadButtonLabel })
|
|
9125
|
+
] }) : null,
|
|
9126
|
+
onOpenPalette ? /* @__PURE__ */ jsxs(
|
|
9127
|
+
Button,
|
|
8935
9128
|
{
|
|
8936
|
-
|
|
8937
|
-
|
|
8938
|
-
|
|
8939
|
-
|
|
8940
|
-
|
|
8941
|
-
|
|
9129
|
+
type: "button",
|
|
9130
|
+
variant: "ghost",
|
|
9131
|
+
size: "sm",
|
|
9132
|
+
onClick: onOpenPalette,
|
|
9133
|
+
className: "md:hidden",
|
|
9134
|
+
"aria-label": "Add a block",
|
|
9135
|
+
children: [
|
|
9136
|
+
/* @__PURE__ */ jsx(Plus, { className: "h-4 w-4" }),
|
|
9137
|
+
/* @__PURE__ */ jsx("span", { children: "Blocks" })
|
|
9138
|
+
]
|
|
9139
|
+
}
|
|
9140
|
+
) : null,
|
|
9141
|
+
showSurfaceControl ? /* @__PURE__ */ jsxs(Popover, { open: surfaceMenuOpen, onOpenChange: setSurfaceMenuOpen, children: [
|
|
9142
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": `Preview surface: ${activeSurface.label}`, children: [
|
|
9143
|
+
/* @__PURE__ */ jsx(activeSurface.Icon, { className: "h-3.5 w-3.5" }),
|
|
9144
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: activeSurface.label }),
|
|
9145
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "hidden h-3.5 w-3.5 opacity-60 md:inline" })
|
|
9146
|
+
] }) }),
|
|
9147
|
+
/* @__PURE__ */ jsx(PopoverContent, { align: "start", className: "w-36 p-1", children: /* @__PURE__ */ jsx(
|
|
9148
|
+
Menu,
|
|
9149
|
+
{
|
|
9150
|
+
ariaLabel: "Preview surface",
|
|
9151
|
+
options: surfaceOptions,
|
|
9152
|
+
value: previewSurface,
|
|
9153
|
+
onChange: (next) => {
|
|
9154
|
+
onPreviewSurfaceChange(next);
|
|
9155
|
+
setSurfaceMenuOpen(false);
|
|
9156
|
+
}
|
|
9157
|
+
}
|
|
9158
|
+
) })
|
|
9159
|
+
] }) : null,
|
|
9160
|
+
showThemeControl ? /* @__PURE__ */ jsxs(Popover, { open: themeMenuOpen, onOpenChange: setThemeMenuOpen, children: [
|
|
9161
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": `Preview theme: ${activeTheme.label}`, children: [
|
|
9162
|
+
/* @__PURE__ */ jsx(activeTheme.Icon, { className: "h-3.5 w-3.5" }),
|
|
9163
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: activeTheme.label }),
|
|
9164
|
+
/* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5 opacity-60" })
|
|
9165
|
+
] }) }),
|
|
9166
|
+
/* @__PURE__ */ jsx(PopoverContent, { align: "start", className: "w-32 p-1", children: /* @__PURE__ */ jsx(
|
|
9167
|
+
Menu,
|
|
9168
|
+
{
|
|
9169
|
+
ariaLabel: "Preview theme",
|
|
9170
|
+
options: THEME_OPTIONS,
|
|
9171
|
+
value: previewTheme,
|
|
9172
|
+
onChange: (next) => {
|
|
9173
|
+
onPreviewThemeChange(next);
|
|
9174
|
+
setThemeMenuOpen(false);
|
|
9175
|
+
}
|
|
8942
9176
|
}
|
|
9177
|
+
) })
|
|
9178
|
+
] }) : null,
|
|
9179
|
+
docsHref ? /* @__PURE__ */ jsxs(
|
|
9180
|
+
"a",
|
|
9181
|
+
{
|
|
9182
|
+
href: docsHref,
|
|
9183
|
+
target: "_blank",
|
|
9184
|
+
rel: "noreferrer noopener",
|
|
9185
|
+
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",
|
|
9186
|
+
"aria-label": `${docsLabel} (opens in a new tab)`,
|
|
9187
|
+
children: [
|
|
9188
|
+
/* @__PURE__ */ jsx(BookOpen, { className: "h-3.5 w-3.5" }),
|
|
9189
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: docsLabel }),
|
|
9190
|
+
/* @__PURE__ */ jsx(ExternalLink, { className: "hidden h-3 w-3 opacity-50 md:inline" })
|
|
9191
|
+
]
|
|
8943
9192
|
}
|
|
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,
|
|
9193
|
+
) : null
|
|
9194
|
+
] }),
|
|
9195
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1 sm:gap-2", children: [
|
|
9196
|
+
errorCount > 0 ? /* @__PURE__ */ jsxs(
|
|
9197
|
+
Button,
|
|
8954
9198
|
{
|
|
8955
|
-
|
|
8956
|
-
|
|
8957
|
-
|
|
8958
|
-
|
|
8959
|
-
|
|
8960
|
-
|
|
8961
|
-
|
|
9199
|
+
type: "button",
|
|
9200
|
+
variant: "ghost",
|
|
9201
|
+
size: "sm",
|
|
9202
|
+
onClick: onOpenIssues,
|
|
9203
|
+
className: "border border-red-200! bg-red-50 text-red-700 hover:bg-red-100 hover:text-red-700",
|
|
9204
|
+
"aria-label": `${errorCount} ${errorCount === 1 ? "issue" : "issues"}`,
|
|
9205
|
+
children: [
|
|
9206
|
+
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-3.5 w-3.5" }),
|
|
9207
|
+
/* @__PURE__ */ jsxs("span", { children: [
|
|
9208
|
+
errorCount,
|
|
9209
|
+
" ",
|
|
9210
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: errorCount === 1 ? "issue" : "issues" })
|
|
9211
|
+
] })
|
|
9212
|
+
]
|
|
8962
9213
|
}
|
|
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(
|
|
9214
|
+
) : null,
|
|
9215
|
+
/* @__PURE__ */ jsxs(
|
|
9034
9216
|
Button,
|
|
9035
9217
|
{
|
|
9036
9218
|
type: "button",
|
|
9037
9219
|
variant: "ghost",
|
|
9038
9220
|
size: "sm",
|
|
9039
|
-
|
|
9040
|
-
|
|
9041
|
-
className: "
|
|
9042
|
-
|
|
9221
|
+
onClick: onClear,
|
|
9222
|
+
disabled: !canClear,
|
|
9223
|
+
className: "hover:bg-destructive/10 hover:text-destructive",
|
|
9224
|
+
"aria-label": "Clear all blocks",
|
|
9225
|
+
children: [
|
|
9226
|
+
/* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" }),
|
|
9227
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: "Clear" })
|
|
9228
|
+
]
|
|
9043
9229
|
}
|
|
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
|
-
|
|
9230
|
+
),
|
|
9231
|
+
/* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", onClick: onOpenJson, "aria-label": "View JSON", children: [
|
|
9232
|
+
/* @__PURE__ */ jsx(Code2, { className: "h-3.5 w-3.5" }),
|
|
9233
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: "View JSON" })
|
|
9234
|
+
] }),
|
|
9235
|
+
editBadge ? (
|
|
9236
|
+
// A message is loaded: split button. Main action updates it in
|
|
9237
|
+
// place; the menu also offers posting the blocks as a new message.
|
|
9238
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-stretch", children: [
|
|
9239
|
+
/* @__PURE__ */ jsxs(
|
|
9240
|
+
Button,
|
|
9241
|
+
{
|
|
9242
|
+
type: "button",
|
|
9243
|
+
size: "sm",
|
|
9244
|
+
onClick: onOpenUpdate,
|
|
9245
|
+
disabled: !canSend,
|
|
9246
|
+
"aria-label": updateButtonLabel,
|
|
9247
|
+
className: "rounded-r-none",
|
|
9248
|
+
children: [
|
|
9249
|
+
/* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" }),
|
|
9250
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: updateButtonLabel })
|
|
9251
|
+
]
|
|
9252
|
+
}
|
|
9253
|
+
),
|
|
9254
|
+
/* @__PURE__ */ jsxs(Popover, { open: sendMenuOpen, onOpenChange: setSendMenuOpen, children: [
|
|
9255
|
+
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
9256
|
+
Button,
|
|
9257
|
+
{
|
|
9258
|
+
type: "button",
|
|
9259
|
+
size: "sm",
|
|
9260
|
+
"aria-label": "More message options",
|
|
9261
|
+
"aria-haspopup": "menu",
|
|
9262
|
+
className: "rounded-l-none border-l border-l-primary-foreground/30! px-1.5",
|
|
9263
|
+
children: /* @__PURE__ */ jsx(ChevronDown, { className: "h-3.5 w-3.5" })
|
|
9264
|
+
}
|
|
9265
|
+
) }),
|
|
9266
|
+
/* @__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: [
|
|
9267
|
+
/* @__PURE__ */ jsxs(
|
|
9268
|
+
"button",
|
|
9269
|
+
{
|
|
9270
|
+
type: "button",
|
|
9271
|
+
role: "menuitem",
|
|
9272
|
+
disabled: !canSend,
|
|
9273
|
+
onClick: () => {
|
|
9274
|
+
setSendMenuOpen(false);
|
|
9275
|
+
onOpenUpdate?.();
|
|
9276
|
+
},
|
|
9277
|
+
className: SEND_MENU_ITEM,
|
|
9278
|
+
children: [
|
|
9279
|
+
/* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" }),
|
|
9280
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1", children: "Update message" })
|
|
9281
|
+
]
|
|
9282
|
+
}
|
|
9283
|
+
),
|
|
9284
|
+
/* @__PURE__ */ jsxs(
|
|
9285
|
+
"button",
|
|
9286
|
+
{
|
|
9287
|
+
type: "button",
|
|
9288
|
+
role: "menuitem",
|
|
9289
|
+
disabled: !canSend,
|
|
9290
|
+
onClick: () => {
|
|
9291
|
+
setSendMenuOpen(false);
|
|
9292
|
+
onOpenSend();
|
|
9293
|
+
},
|
|
9294
|
+
className: SEND_MENU_ITEM,
|
|
9295
|
+
children: [
|
|
9296
|
+
/* @__PURE__ */ jsx(Send, { className: "h-3.5 w-3.5" }),
|
|
9297
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1", children: "Send as a new message" })
|
|
9298
|
+
]
|
|
9299
|
+
}
|
|
9300
|
+
)
|
|
9301
|
+
] }) })
|
|
9302
|
+
] })
|
|
9303
|
+
] })
|
|
9304
|
+
) : /* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", onClick: onOpenSend, disabled: !canSend, "aria-label": sendButtonLabel, children: [
|
|
9305
|
+
/* @__PURE__ */ jsx(Send, { className: "h-3.5 w-3.5" }),
|
|
9306
|
+
/* @__PURE__ */ jsx("span", { className: "hidden md:inline", children: sendButtonLabel })
|
|
9307
|
+
] })
|
|
9308
|
+
] })
|
|
9309
|
+
] }),
|
|
9310
|
+
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: [
|
|
9311
|
+
/* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4 shrink-0 text-primary" }),
|
|
9312
|
+
/* @__PURE__ */ jsxs("span", { className: "min-w-0 flex-1 text-sm", children: [
|
|
9313
|
+
"References an existing message in ",
|
|
9314
|
+
/* @__PURE__ */ jsx("span", { className: "font-semibold", children: editBadge.channelLabel }),
|
|
9315
|
+
/* @__PURE__ */ jsx("span", { className: "ml-1 text-xs opacity-70", title: editBadge.ts, children: formatMessageTs(editBadge.ts) })
|
|
9081
9316
|
] }),
|
|
9082
|
-
/* @__PURE__ */ jsxs(Button, { type: "button", size: "sm", onClick:
|
|
9083
|
-
/* @__PURE__ */ jsx(
|
|
9084
|
-
|
|
9317
|
+
/* @__PURE__ */ jsxs(Button, { type: "button", variant: "ghost", size: "sm", onClick: onExitEdit, className: "shrink-0", children: [
|
|
9318
|
+
/* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" }),
|
|
9319
|
+
"Switch to a new message"
|
|
9085
9320
|
] })
|
|
9086
|
-
] })
|
|
9321
|
+
] }) : null
|
|
9087
9322
|
] });
|
|
9088
9323
|
}
|
|
9089
9324
|
function Menu({
|
|
@@ -9141,52 +9376,132 @@ function Menu({
|
|
|
9141
9376
|
);
|
|
9142
9377
|
}) });
|
|
9143
9378
|
}
|
|
9144
|
-
|
|
9145
|
-
|
|
9146
|
-
|
|
9147
|
-
|
|
9148
|
-
|
|
9149
|
-
|
|
9150
|
-
|
|
9379
|
+
function UpdateDialog({
|
|
9380
|
+
open,
|
|
9381
|
+
onOpenChange,
|
|
9382
|
+
target,
|
|
9383
|
+
blocks,
|
|
9384
|
+
loadSendAsUserStatus,
|
|
9385
|
+
onUpdate,
|
|
9386
|
+
confirmUpdateLabel = "Update message",
|
|
9387
|
+
errorCount,
|
|
9388
|
+
onShowIssues
|
|
9151
9389
|
}) {
|
|
9152
|
-
|
|
9153
|
-
|
|
9154
|
-
|
|
9155
|
-
|
|
9156
|
-
|
|
9157
|
-
|
|
9158
|
-
|
|
9159
|
-
|
|
9160
|
-
|
|
9161
|
-
|
|
9162
|
-
|
|
9163
|
-
|
|
9390
|
+
const asUser = target.editableVia === "user";
|
|
9391
|
+
const [userStatus, setUserStatus] = useState(null);
|
|
9392
|
+
const [status, setStatus] = useState({ kind: "idle" });
|
|
9393
|
+
const loadSendAsUserStatusRef = useRef(loadSendAsUserStatus);
|
|
9394
|
+
useEffect(() => {
|
|
9395
|
+
loadSendAsUserStatusRef.current = loadSendAsUserStatus;
|
|
9396
|
+
});
|
|
9397
|
+
const refreshSendAsUser = useCallback(() => {
|
|
9398
|
+
loadSendAsUserStatusRef.current().then(setUserStatus).catch(() => setUserStatus({ canSendAsUser: false }));
|
|
9399
|
+
}, []);
|
|
9400
|
+
useEffect(() => {
|
|
9401
|
+
if (!open) {
|
|
9402
|
+
return;
|
|
9164
9403
|
}
|
|
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
|
-
]
|
|
9404
|
+
setStatus({ kind: "idle" });
|
|
9405
|
+
if (asUser) {
|
|
9406
|
+
setUserStatus(null);
|
|
9407
|
+
refreshSendAsUser();
|
|
9188
9408
|
}
|
|
9189
|
-
);
|
|
9409
|
+
}, [open, asUser, refreshSendAsUser]);
|
|
9410
|
+
useEffect(() => {
|
|
9411
|
+
if (!open || !asUser) {
|
|
9412
|
+
return;
|
|
9413
|
+
}
|
|
9414
|
+
const handler = () => refreshSendAsUser();
|
|
9415
|
+
window.addEventListener("focus", handler);
|
|
9416
|
+
return () => window.removeEventListener("focus", handler);
|
|
9417
|
+
}, [open, asUser, refreshSendAsUser]);
|
|
9418
|
+
const needsSignIn = asUser && userStatus !== null && !userStatus.canSendAsUser;
|
|
9419
|
+
const handleSubmit = async () => {
|
|
9420
|
+
setStatus({ kind: "updating" });
|
|
9421
|
+
try {
|
|
9422
|
+
const result = await onUpdate({
|
|
9423
|
+
channelId: target.channelId,
|
|
9424
|
+
ts: target.ts,
|
|
9425
|
+
blocks: toSlackBlocks(blocks),
|
|
9426
|
+
asUser
|
|
9427
|
+
});
|
|
9428
|
+
if (result.ok) {
|
|
9429
|
+
setStatus({ kind: "idle" });
|
|
9430
|
+
onOpenChange(false);
|
|
9431
|
+
return;
|
|
9432
|
+
}
|
|
9433
|
+
setStatus({ kind: "error", error: result.error ?? "Update failed." });
|
|
9434
|
+
} catch (e) {
|
|
9435
|
+
setStatus({ kind: "error", error: e instanceof Error ? e.message : "Update failed." });
|
|
9436
|
+
}
|
|
9437
|
+
};
|
|
9438
|
+
const channelLabel = target.channelName ? `#${target.channelName}` : target.channelId;
|
|
9439
|
+
return /* @__PURE__ */ jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxs(DialogContent, { className: "w-[calc(100vw-1.5rem)] max-w-lg rounded-lg", children: [
|
|
9440
|
+
/* @__PURE__ */ jsxs(DialogHeader, { children: [
|
|
9441
|
+
/* @__PURE__ */ jsx(DialogTitle, { children: "Update message" }),
|
|
9442
|
+
/* @__PURE__ */ jsx(DialogDescription, { children: "This replaces the message that's already posted. It stays in the same channel and can't be moved." })
|
|
9443
|
+
] }),
|
|
9444
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
9445
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
9446
|
+
/* @__PURE__ */ jsx(Label, { children: "Channel" }),
|
|
9447
|
+
/* @__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 })
|
|
9448
|
+
] }),
|
|
9449
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
9450
|
+
/* @__PURE__ */ jsx(Label, { children: "Posting as" }),
|
|
9451
|
+
/* @__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" }),
|
|
9452
|
+
needsSignIn && userStatus?.oauthUrl && isSafeHref(userStatus.oauthUrl) && /* @__PURE__ */ jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
9453
|
+
/* @__PURE__ */ jsxs(
|
|
9454
|
+
"a",
|
|
9455
|
+
{
|
|
9456
|
+
href: userStatus.oauthUrl,
|
|
9457
|
+
target: "_blank",
|
|
9458
|
+
rel: "noopener noreferrer",
|
|
9459
|
+
className: "inline-flex items-center gap-1 text-primary hover:underline",
|
|
9460
|
+
children: [
|
|
9461
|
+
"Sign in with Slack ",
|
|
9462
|
+
/* @__PURE__ */ jsx(ExternalLink, { className: "h-3 w-3" })
|
|
9463
|
+
]
|
|
9464
|
+
}
|
|
9465
|
+
),
|
|
9466
|
+
" ",
|
|
9467
|
+
"to update your own message."
|
|
9468
|
+
] }),
|
|
9469
|
+
needsSignIn && !userStatus?.oauthUrl && /* @__PURE__ */ jsx("p", { className: "text-xs text-muted-foreground", children: "Sign in with Slack to update your own message." })
|
|
9470
|
+
] }),
|
|
9471
|
+
errorCount > 0 ? /* @__PURE__ */ jsxs(
|
|
9472
|
+
"button",
|
|
9473
|
+
{
|
|
9474
|
+
type: "button",
|
|
9475
|
+
onClick: onShowIssues,
|
|
9476
|
+
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",
|
|
9477
|
+
children: [
|
|
9478
|
+
/* @__PURE__ */ jsx(AlertTriangle, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
9479
|
+
/* @__PURE__ */ jsxs("span", { className: "flex-1", children: [
|
|
9480
|
+
"Fix ",
|
|
9481
|
+
errorCount,
|
|
9482
|
+
" ",
|
|
9483
|
+
errorCount === 1 ? "issue" : "issues",
|
|
9484
|
+
" before updating."
|
|
9485
|
+
] }),
|
|
9486
|
+
/* @__PURE__ */ jsx("span", { className: "shrink-0 underline", children: "Show issues" })
|
|
9487
|
+
]
|
|
9488
|
+
}
|
|
9489
|
+
) : null,
|
|
9490
|
+
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 })
|
|
9491
|
+
] }),
|
|
9492
|
+
/* @__PURE__ */ jsxs(DialogFooter, { children: [
|
|
9493
|
+
/* @__PURE__ */ jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
9494
|
+
/* @__PURE__ */ jsx(
|
|
9495
|
+
Button,
|
|
9496
|
+
{
|
|
9497
|
+
type: "button",
|
|
9498
|
+
onClick: handleSubmit,
|
|
9499
|
+
disabled: status.kind === "updating" || blocks.length === 0 || errorCount > 0 || needsSignIn,
|
|
9500
|
+
children: status.kind === "updating" ? "Updating\u2026" : confirmUpdateLabel
|
|
9501
|
+
}
|
|
9502
|
+
)
|
|
9503
|
+
] })
|
|
9504
|
+
] }) });
|
|
9190
9505
|
}
|
|
9191
9506
|
function BlockKitchen(props) {
|
|
9192
9507
|
const {
|
|
@@ -9198,6 +9513,10 @@ function BlockKitchen(props) {
|
|
|
9198
9513
|
loadChannels,
|
|
9199
9514
|
loadSendAsUserStatus,
|
|
9200
9515
|
onSend,
|
|
9516
|
+
editing,
|
|
9517
|
+
loadButtonLabel,
|
|
9518
|
+
updateButtonLabel,
|
|
9519
|
+
confirmUpdateLabel,
|
|
9201
9520
|
palette,
|
|
9202
9521
|
disabledBlockTypes,
|
|
9203
9522
|
showPaletteSearch,
|
|
@@ -9243,6 +9562,10 @@ function BlockKitchen(props) {
|
|
|
9243
9562
|
}, [blocks]);
|
|
9244
9563
|
const [jsonOpen, setJsonOpen] = useState(false);
|
|
9245
9564
|
const [sendOpen, setSendOpen] = useState(false);
|
|
9565
|
+
const [updateOpen, setUpdateOpen] = useState(false);
|
|
9566
|
+
const [loadOpen, setLoadOpen] = useState(false);
|
|
9567
|
+
const [editTarget, setEditTarget] = useState(null);
|
|
9568
|
+
const activeEditTarget = editing ? editTarget : null;
|
|
9246
9569
|
const [issuesOpen, setIssuesOpen] = useState(false);
|
|
9247
9570
|
const [paletteOpen, setPaletteOpen] = useState(false);
|
|
9248
9571
|
const [openBlockId, setOpenBlockId] = useState(null);
|
|
@@ -9363,7 +9686,21 @@ function BlockKitchen(props) {
|
|
|
9363
9686
|
allowedSurfaces,
|
|
9364
9687
|
showThemeControl: isPreviewThemeControlled ? false : showThemeControl,
|
|
9365
9688
|
docsLink,
|
|
9366
|
-
sendButtonLabel
|
|
9689
|
+
sendButtonLabel,
|
|
9690
|
+
editingEnabled: !!editing,
|
|
9691
|
+
editBadge: activeEditTarget ? {
|
|
9692
|
+
channelLabel: activeEditTarget.channelName ? `#${activeEditTarget.channelName}` : activeEditTarget.channelId,
|
|
9693
|
+
ts: activeEditTarget.ts
|
|
9694
|
+
} : null,
|
|
9695
|
+
onOpenLoad: () => setLoadOpen(true),
|
|
9696
|
+
onOpenUpdate: () => setUpdateOpen(true),
|
|
9697
|
+
onExitEdit: () => {
|
|
9698
|
+
setEditTarget(null);
|
|
9699
|
+
replaceAll([]);
|
|
9700
|
+
setLoadOpen(true);
|
|
9701
|
+
},
|
|
9702
|
+
loadButtonLabel,
|
|
9703
|
+
updateButtonLabel
|
|
9367
9704
|
}
|
|
9368
9705
|
),
|
|
9369
9706
|
/* @__PURE__ */ jsxs("div", { className: "flex min-h-0 flex-1 items-stretch", children: [
|
|
@@ -9382,6 +9719,8 @@ function BlockKitchen(props) {
|
|
|
9382
9719
|
{
|
|
9383
9720
|
blocks,
|
|
9384
9721
|
workspaceName,
|
|
9722
|
+
authorName: activeEditTarget?.username,
|
|
9723
|
+
authorIcon: activeEditTarget?.iconUrl,
|
|
9385
9724
|
previewHooks: mergedPreviewHooks,
|
|
9386
9725
|
previewTheme,
|
|
9387
9726
|
previewSurface,
|
|
@@ -9447,6 +9786,52 @@ function BlockKitchen(props) {
|
|
|
9447
9786
|
}
|
|
9448
9787
|
}
|
|
9449
9788
|
),
|
|
9789
|
+
activeEditTarget && editing ? /* @__PURE__ */ jsx(
|
|
9790
|
+
UpdateDialog,
|
|
9791
|
+
{
|
|
9792
|
+
open: updateOpen,
|
|
9793
|
+
onOpenChange: setUpdateOpen,
|
|
9794
|
+
target: activeEditTarget,
|
|
9795
|
+
blocks: blockPayloads,
|
|
9796
|
+
loadSendAsUserStatus,
|
|
9797
|
+
onUpdate: editing.onUpdate,
|
|
9798
|
+
confirmUpdateLabel,
|
|
9799
|
+
errorCount: validation.total,
|
|
9800
|
+
onShowIssues: () => {
|
|
9801
|
+
setUpdateOpen(false);
|
|
9802
|
+
setIssuesOpen(true);
|
|
9803
|
+
}
|
|
9804
|
+
}
|
|
9805
|
+
) : null,
|
|
9806
|
+
editing ? /* @__PURE__ */ jsx(
|
|
9807
|
+
LoadMessageDialog,
|
|
9808
|
+
{
|
|
9809
|
+
open: loadOpen,
|
|
9810
|
+
onOpenChange: setLoadOpen,
|
|
9811
|
+
onLoadMessage: editing.onLoadMessage,
|
|
9812
|
+
loadRecentMessages: editing.loadRecentMessages,
|
|
9813
|
+
onLoaded: (result) => {
|
|
9814
|
+
replaceAll(result.blocks);
|
|
9815
|
+
setEditTarget({
|
|
9816
|
+
channelId: result.channelId,
|
|
9817
|
+
channelName: result.channelName,
|
|
9818
|
+
ts: result.ts,
|
|
9819
|
+
editableVia: result.editableVia,
|
|
9820
|
+
workspaceName: result.workspaceName,
|
|
9821
|
+
username: result.username,
|
|
9822
|
+
iconUrl: result.iconUrl
|
|
9823
|
+
});
|
|
9824
|
+
setLoadOpen(false);
|
|
9825
|
+
},
|
|
9826
|
+
onOpenAsNew: (loadedBlocks) => {
|
|
9827
|
+
if (loadedBlocks) {
|
|
9828
|
+
replaceAll(loadedBlocks);
|
|
9829
|
+
}
|
|
9830
|
+
setEditTarget(null);
|
|
9831
|
+
setLoadOpen(false);
|
|
9832
|
+
}
|
|
9833
|
+
}
|
|
9834
|
+
) : null,
|
|
9450
9835
|
/* @__PURE__ */ jsx(
|
|
9451
9836
|
IssuesSheet,
|
|
9452
9837
|
{
|