@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.cjs
CHANGED
|
@@ -2724,6 +2724,91 @@ function JsonDrawer({
|
|
|
2724
2724
|
] })
|
|
2725
2725
|
] }) });
|
|
2726
2726
|
}
|
|
2727
|
+
var buttonVariants = classVarianceAuthority.cva(
|
|
2728
|
+
"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",
|
|
2729
|
+
{
|
|
2730
|
+
variants: {
|
|
2731
|
+
variant: {
|
|
2732
|
+
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
2733
|
+
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
2734
|
+
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
2735
|
+
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
2736
|
+
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
2737
|
+
link: "text-primary underline-offset-4 hover:underline"
|
|
2738
|
+
},
|
|
2739
|
+
size: {
|
|
2740
|
+
default: "h-9 px-4 py-2",
|
|
2741
|
+
sm: "h-8 rounded-md px-3 text-xs",
|
|
2742
|
+
lg: "h-10 rounded-md px-8",
|
|
2743
|
+
icon: "h-9 w-9"
|
|
2744
|
+
}
|
|
2745
|
+
},
|
|
2746
|
+
defaultVariants: {
|
|
2747
|
+
variant: "default",
|
|
2748
|
+
size: "default"
|
|
2749
|
+
}
|
|
2750
|
+
}
|
|
2751
|
+
);
|
|
2752
|
+
var Button = React__namespace.forwardRef(
|
|
2753
|
+
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
2754
|
+
const Comp = asChild ? reactSlot.Slot : "button";
|
|
2755
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
|
|
2756
|
+
}
|
|
2757
|
+
);
|
|
2758
|
+
Button.displayName = "Button";
|
|
2759
|
+
var Dialog = DialogPrimitive__namespace.Root;
|
|
2760
|
+
var DialogPortal = DialogPrimitive__namespace.Portal;
|
|
2761
|
+
var DialogOverlay = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2762
|
+
DialogPrimitive__namespace.Overlay,
|
|
2763
|
+
{
|
|
2764
|
+
ref,
|
|
2765
|
+
className: cn(
|
|
2766
|
+
"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",
|
|
2767
|
+
className
|
|
2768
|
+
),
|
|
2769
|
+
...props
|
|
2770
|
+
}
|
|
2771
|
+
));
|
|
2772
|
+
DialogOverlay.displayName = DialogPrimitive__namespace.Overlay.displayName;
|
|
2773
|
+
var DialogContent = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { children: [
|
|
2774
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
|
|
2775
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2776
|
+
DialogPrimitive__namespace.Content,
|
|
2777
|
+
{
|
|
2778
|
+
ref,
|
|
2779
|
+
className: cn(
|
|
2780
|
+
"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",
|
|
2781
|
+
className
|
|
2782
|
+
),
|
|
2783
|
+
...props,
|
|
2784
|
+
children: [
|
|
2785
|
+
children,
|
|
2786
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.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: [
|
|
2787
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }),
|
|
2788
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
|
|
2789
|
+
] })
|
|
2790
|
+
]
|
|
2791
|
+
}
|
|
2792
|
+
)
|
|
2793
|
+
] }));
|
|
2794
|
+
DialogContent.displayName = DialogPrimitive__namespace.Content.displayName;
|
|
2795
|
+
function DialogHeader({ className, ...props }) {
|
|
2796
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
|
|
2797
|
+
}
|
|
2798
|
+
function DialogFooter({ className, ...props }) {
|
|
2799
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className), ...props });
|
|
2800
|
+
}
|
|
2801
|
+
var DialogTitle = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2802
|
+
DialogPrimitive__namespace.Title,
|
|
2803
|
+
{
|
|
2804
|
+
ref,
|
|
2805
|
+
className: cn("text-lg font-semibold leading-none tracking-tight", className),
|
|
2806
|
+
...props
|
|
2807
|
+
}
|
|
2808
|
+
));
|
|
2809
|
+
DialogTitle.displayName = DialogPrimitive__namespace.Title.displayName;
|
|
2810
|
+
var DialogDescription = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
|
|
2811
|
+
DialogDescription.displayName = DialogPrimitive__namespace.Description.displayName;
|
|
2727
2812
|
var Input = React__namespace.forwardRef(
|
|
2728
2813
|
({ className, type, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2729
2814
|
"input",
|
|
@@ -2739,6 +2824,265 @@ var Input = React__namespace.forwardRef(
|
|
|
2739
2824
|
)
|
|
2740
2825
|
);
|
|
2741
2826
|
Input.displayName = "Input";
|
|
2827
|
+
var Label = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2828
|
+
LabelPrimitive__namespace.Root,
|
|
2829
|
+
{
|
|
2830
|
+
ref,
|
|
2831
|
+
className: cn("text-sm font-medium leading-none text-foreground", className),
|
|
2832
|
+
...props
|
|
2833
|
+
}
|
|
2834
|
+
));
|
|
2835
|
+
Label.displayName = LabelPrimitive__namespace.Root.displayName;
|
|
2836
|
+
function recentToResult(msg) {
|
|
2837
|
+
return {
|
|
2838
|
+
ok: true,
|
|
2839
|
+
channelId: msg.channelId,
|
|
2840
|
+
channelName: msg.channelName,
|
|
2841
|
+
ts: msg.ts,
|
|
2842
|
+
blocks: msg.blocks,
|
|
2843
|
+
editableVia: msg.editableVia ?? "bot",
|
|
2844
|
+
workspaceName: msg.workspaceName,
|
|
2845
|
+
username: msg.username,
|
|
2846
|
+
iconUrl: msg.iconUrl
|
|
2847
|
+
};
|
|
2848
|
+
}
|
|
2849
|
+
function LoadMessageDialog({
|
|
2850
|
+
open,
|
|
2851
|
+
onOpenChange,
|
|
2852
|
+
onLoadMessage,
|
|
2853
|
+
loadRecentMessages,
|
|
2854
|
+
loadChannels,
|
|
2855
|
+
onLoaded,
|
|
2856
|
+
onOpenAsNew
|
|
2857
|
+
}) {
|
|
2858
|
+
const [link, setLink] = React.useState("");
|
|
2859
|
+
const [status, setStatus] = React.useState({ kind: "idle" });
|
|
2860
|
+
const [channels, setChannels] = React.useState(null);
|
|
2861
|
+
const [channelsError, setChannelsError] = React.useState(null);
|
|
2862
|
+
const [channelId, setChannelId] = React.useState("");
|
|
2863
|
+
const [recent, setRecent] = React.useState(null);
|
|
2864
|
+
const [recentError, setRecentError] = React.useState(null);
|
|
2865
|
+
const inputRef = React.useRef(null);
|
|
2866
|
+
const onLoadMessageRef = React.useRef(onLoadMessage);
|
|
2867
|
+
const loadRecentMessagesRef = React.useRef(loadRecentMessages);
|
|
2868
|
+
const loadChannelsRef = React.useRef(loadChannels);
|
|
2869
|
+
React.useEffect(() => {
|
|
2870
|
+
onLoadMessageRef.current = onLoadMessage;
|
|
2871
|
+
loadRecentMessagesRef.current = loadRecentMessages;
|
|
2872
|
+
loadChannelsRef.current = loadChannels;
|
|
2873
|
+
});
|
|
2874
|
+
const hasRecent = !!loadRecentMessages;
|
|
2875
|
+
React.useEffect(() => {
|
|
2876
|
+
if (!open) {
|
|
2877
|
+
return;
|
|
2878
|
+
}
|
|
2879
|
+
setLink("");
|
|
2880
|
+
setStatus({ kind: "idle" });
|
|
2881
|
+
setChannelId("");
|
|
2882
|
+
setRecent(null);
|
|
2883
|
+
setRecentError(null);
|
|
2884
|
+
if (!loadRecentMessagesRef.current) {
|
|
2885
|
+
setChannels([]);
|
|
2886
|
+
setChannelsError(null);
|
|
2887
|
+
return;
|
|
2888
|
+
}
|
|
2889
|
+
setChannels(null);
|
|
2890
|
+
setChannelsError(null);
|
|
2891
|
+
let cancelled = false;
|
|
2892
|
+
loadChannelsRef.current().then((list) => {
|
|
2893
|
+
if (!cancelled) {
|
|
2894
|
+
setChannels(list);
|
|
2895
|
+
}
|
|
2896
|
+
}).catch((e) => {
|
|
2897
|
+
if (!cancelled) {
|
|
2898
|
+
setChannelsError(e instanceof Error ? e.message : "Failed to load channels");
|
|
2899
|
+
}
|
|
2900
|
+
});
|
|
2901
|
+
return () => {
|
|
2902
|
+
cancelled = true;
|
|
2903
|
+
};
|
|
2904
|
+
}, [open]);
|
|
2905
|
+
React.useEffect(() => {
|
|
2906
|
+
if (!open || !loadRecentMessagesRef.current || !channelId) {
|
|
2907
|
+
return;
|
|
2908
|
+
}
|
|
2909
|
+
setRecent(null);
|
|
2910
|
+
setRecentError(null);
|
|
2911
|
+
let cancelled = false;
|
|
2912
|
+
loadRecentMessagesRef.current(channelId).then((list) => {
|
|
2913
|
+
if (!cancelled) {
|
|
2914
|
+
setRecent(list);
|
|
2915
|
+
}
|
|
2916
|
+
}).catch((e) => {
|
|
2917
|
+
if (!cancelled) {
|
|
2918
|
+
setRecentError(e instanceof Error ? e.message : "Failed to load recent messages.");
|
|
2919
|
+
}
|
|
2920
|
+
});
|
|
2921
|
+
return () => {
|
|
2922
|
+
cancelled = true;
|
|
2923
|
+
};
|
|
2924
|
+
}, [open, channelId]);
|
|
2925
|
+
const handleLoad = async () => {
|
|
2926
|
+
const trimmed = link.trim();
|
|
2927
|
+
if (!trimmed) {
|
|
2928
|
+
setStatus({ kind: "error", error: "Paste a Slack message link first." });
|
|
2929
|
+
return;
|
|
2930
|
+
}
|
|
2931
|
+
setStatus({ kind: "loading" });
|
|
2932
|
+
try {
|
|
2933
|
+
const result = await onLoadMessageRef.current({ link: trimmed });
|
|
2934
|
+
if (result.ok) {
|
|
2935
|
+
onLoaded(result);
|
|
2936
|
+
return;
|
|
2937
|
+
}
|
|
2938
|
+
setStatus({ kind: "not-editable", reason: result.reason, blocks: result.blocks });
|
|
2939
|
+
} catch (e) {
|
|
2940
|
+
setStatus({ kind: "error", error: e instanceof Error ? e.message : "Failed to load message." });
|
|
2941
|
+
}
|
|
2942
|
+
};
|
|
2943
|
+
const notEditable = status.kind === "not-editable" ? status : null;
|
|
2944
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2945
|
+
DialogContent,
|
|
2946
|
+
{
|
|
2947
|
+
className: "w-[calc(100vw-1.5rem)] max-w-lg rounded-lg",
|
|
2948
|
+
onOpenAutoFocus: (e) => {
|
|
2949
|
+
e.preventDefault();
|
|
2950
|
+
inputRef.current?.focus();
|
|
2951
|
+
},
|
|
2952
|
+
children: [
|
|
2953
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
|
|
2954
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Edit an existing message" }),
|
|
2955
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-1.5", children: [
|
|
2956
|
+
/* @__PURE__ */ jsxRuntime.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.` }),
|
|
2957
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
2958
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2959
|
+
"button",
|
|
2960
|
+
{
|
|
2961
|
+
type: "button",
|
|
2962
|
+
"aria-label": "How to copy a message link",
|
|
2963
|
+
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",
|
|
2964
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { className: "h-3.5 w-3.5" })
|
|
2965
|
+
}
|
|
2966
|
+
) }),
|
|
2967
|
+
/* @__PURE__ */ jsxRuntime.jsxs(TooltipContent, { className: "max-w-xs leading-relaxed", children: [
|
|
2968
|
+
"In Slack, hover over the message and click the ",
|
|
2969
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "\u22EE More actions" }),
|
|
2970
|
+
" button (or right-click the message), then choose ",
|
|
2971
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Copy link" }),
|
|
2972
|
+
"."
|
|
2973
|
+
] })
|
|
2974
|
+
] })
|
|
2975
|
+
] })
|
|
2976
|
+
] }),
|
|
2977
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2978
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
2979
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "message-link", children: "Message link" }),
|
|
2980
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2981
|
+
Input,
|
|
2982
|
+
{
|
|
2983
|
+
ref: inputRef,
|
|
2984
|
+
id: "message-link",
|
|
2985
|
+
value: link,
|
|
2986
|
+
onChange: (e) => {
|
|
2987
|
+
setLink(e.target.value);
|
|
2988
|
+
if (status.kind !== "idle" && status.kind !== "loading") {
|
|
2989
|
+
setStatus({ kind: "idle" });
|
|
2990
|
+
}
|
|
2991
|
+
},
|
|
2992
|
+
onKeyDown: (e) => {
|
|
2993
|
+
if (e.key === "Enter" && status.kind !== "loading") {
|
|
2994
|
+
e.preventDefault();
|
|
2995
|
+
handleLoad();
|
|
2996
|
+
}
|
|
2997
|
+
},
|
|
2998
|
+
placeholder: "https://your-workspace.slack.com/archives/C\u2026/p\u2026",
|
|
2999
|
+
autoComplete: "off",
|
|
3000
|
+
spellCheck: false
|
|
3001
|
+
}
|
|
3002
|
+
)
|
|
3003
|
+
] }),
|
|
3004
|
+
status.kind === "error" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "rounded-md border border-destructive/30 bg-destructive/5 p-2 text-xs text-destructive", children: status.error }),
|
|
3005
|
+
notEditable && /* @__PURE__ */ jsxRuntime.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: [
|
|
3006
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
|
|
3007
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }),
|
|
3008
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: notEditable.reason })
|
|
3009
|
+
] }),
|
|
3010
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3011
|
+
Button,
|
|
3012
|
+
{
|
|
3013
|
+
type: "button",
|
|
3014
|
+
variant: "outline",
|
|
3015
|
+
size: "sm",
|
|
3016
|
+
className: "self-start",
|
|
3017
|
+
onClick: () => onOpenAsNew(notEditable.blocks),
|
|
3018
|
+
children: "Open as a new message instead"
|
|
3019
|
+
}
|
|
3020
|
+
)
|
|
3021
|
+
] }),
|
|
3022
|
+
hasRecent && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
3023
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
3024
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" }),
|
|
3025
|
+
"or pick a recent message",
|
|
3026
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" })
|
|
3027
|
+
] }),
|
|
3028
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
3029
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "recent-channel-picker", children: "Channel" }),
|
|
3030
|
+
channels === null && !channelsError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Loading channels\u2026" }),
|
|
3031
|
+
channelsError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive", children: channelsError }),
|
|
3032
|
+
channels && channels.length === 0 && !channelsError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "No public channels available." }),
|
|
3033
|
+
channels && channels.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3034
|
+
"select",
|
|
3035
|
+
{
|
|
3036
|
+
id: "recent-channel-picker",
|
|
3037
|
+
value: channelId,
|
|
3038
|
+
onChange: (e) => setChannelId(e.target.value),
|
|
3039
|
+
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",
|
|
3040
|
+
children: [
|
|
3041
|
+
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "Select a channel\u2026" }),
|
|
3042
|
+
channels.map((c) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: c.id, children: [
|
|
3043
|
+
"#",
|
|
3044
|
+
c.name
|
|
3045
|
+
] }, c.id))
|
|
3046
|
+
]
|
|
3047
|
+
}
|
|
3048
|
+
)
|
|
3049
|
+
] }),
|
|
3050
|
+
!channelId && channels && channels.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Select a channel to see recent messages." }),
|
|
3051
|
+
channelId && recent === null && !recentError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Loading recent messages\u2026" }),
|
|
3052
|
+
channelId && recentError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive", children: recentError }),
|
|
3053
|
+
channelId && recent && recent.length === 0 && !recentError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "No recent messages from this app in this channel." }),
|
|
3054
|
+
channelId && recent && recent.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex max-h-48 flex-col gap-1 overflow-y-auto", children: recent.map((m) => {
|
|
3055
|
+
const asUser = (m.editableVia ?? "bot") === "user";
|
|
3056
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3057
|
+
"button",
|
|
3058
|
+
{
|
|
3059
|
+
type: "button",
|
|
3060
|
+
onClick: () => onLoaded(recentToResult(m)),
|
|
3061
|
+
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",
|
|
3062
|
+
children: [
|
|
3063
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-baseline justify-between gap-2", children: [
|
|
3064
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-baseline gap-1.5", children: [
|
|
3065
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: m.channelName ? `#${m.channelName}` : m.channelId }),
|
|
3066
|
+
/* @__PURE__ */ jsxRuntime.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" })
|
|
3067
|
+
] }),
|
|
3068
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 font-mono text-xs text-muted-foreground", children: m.ts })
|
|
3069
|
+
] }),
|
|
3070
|
+
m.label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs text-muted-foreground", children: m.label })
|
|
3071
|
+
]
|
|
3072
|
+
},
|
|
3073
|
+
`${m.channelId}:${m.ts}`
|
|
3074
|
+
);
|
|
3075
|
+
}) })
|
|
3076
|
+
] })
|
|
3077
|
+
] }),
|
|
3078
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
|
|
3079
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
3080
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", onClick: handleLoad, disabled: status.kind === "loading" || !link.trim(), children: status.kind === "loading" ? "Loading\u2026" : "Load message" })
|
|
3081
|
+
] })
|
|
3082
|
+
]
|
|
3083
|
+
}
|
|
3084
|
+
) });
|
|
3085
|
+
}
|
|
2742
3086
|
var PALETTE_DRAG_PREFIX = "palette:";
|
|
2743
3087
|
function parsePaletteDragId(id) {
|
|
2744
3088
|
if (typeof id !== "string" || !id.startsWith(PALETTE_DRAG_PREFIX)) {
|
|
@@ -2938,100 +3282,6 @@ function PaletteItem({
|
|
|
2938
3282
|
}
|
|
2939
3283
|
);
|
|
2940
3284
|
}
|
|
2941
|
-
var buttonVariants = classVarianceAuthority.cva(
|
|
2942
|
-
"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",
|
|
2943
|
-
{
|
|
2944
|
-
variants: {
|
|
2945
|
-
variant: {
|
|
2946
|
-
default: "bg-primary text-primary-foreground shadow hover:bg-primary/90",
|
|
2947
|
-
destructive: "bg-destructive text-destructive-foreground shadow-sm hover:bg-destructive/90",
|
|
2948
|
-
outline: "border border-input bg-background shadow-sm hover:bg-accent hover:text-accent-foreground",
|
|
2949
|
-
secondary: "bg-secondary text-secondary-foreground shadow-sm hover:bg-secondary/80",
|
|
2950
|
-
ghost: "hover:bg-accent hover:text-accent-foreground",
|
|
2951
|
-
link: "text-primary underline-offset-4 hover:underline"
|
|
2952
|
-
},
|
|
2953
|
-
size: {
|
|
2954
|
-
default: "h-9 px-4 py-2",
|
|
2955
|
-
sm: "h-8 rounded-md px-3 text-xs",
|
|
2956
|
-
lg: "h-10 rounded-md px-8",
|
|
2957
|
-
icon: "h-9 w-9"
|
|
2958
|
-
}
|
|
2959
|
-
},
|
|
2960
|
-
defaultVariants: {
|
|
2961
|
-
variant: "default",
|
|
2962
|
-
size: "default"
|
|
2963
|
-
}
|
|
2964
|
-
}
|
|
2965
|
-
);
|
|
2966
|
-
var Button = React__namespace.forwardRef(
|
|
2967
|
-
({ className, variant, size, asChild = false, ...props }, ref) => {
|
|
2968
|
-
const Comp = asChild ? reactSlot.Slot : "button";
|
|
2969
|
-
return /* @__PURE__ */ jsxRuntime.jsx(Comp, { className: cn(buttonVariants({ variant, size, className })), ref, ...props });
|
|
2970
|
-
}
|
|
2971
|
-
);
|
|
2972
|
-
Button.displayName = "Button";
|
|
2973
|
-
var Dialog = DialogPrimitive__namespace.Root;
|
|
2974
|
-
var DialogPortal = DialogPrimitive__namespace.Portal;
|
|
2975
|
-
var DialogOverlay = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2976
|
-
DialogPrimitive__namespace.Overlay,
|
|
2977
|
-
{
|
|
2978
|
-
ref,
|
|
2979
|
-
className: cn(
|
|
2980
|
-
"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",
|
|
2981
|
-
className
|
|
2982
|
-
),
|
|
2983
|
-
...props
|
|
2984
|
-
}
|
|
2985
|
-
));
|
|
2986
|
-
DialogOverlay.displayName = DialogPrimitive__namespace.Overlay.displayName;
|
|
2987
|
-
var DialogContent = React__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(DialogPortal, { children: [
|
|
2988
|
-
/* @__PURE__ */ jsxRuntime.jsx(DialogOverlay, {}),
|
|
2989
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
2990
|
-
DialogPrimitive__namespace.Content,
|
|
2991
|
-
{
|
|
2992
|
-
ref,
|
|
2993
|
-
className: cn(
|
|
2994
|
-
"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",
|
|
2995
|
-
className
|
|
2996
|
-
),
|
|
2997
|
-
...props,
|
|
2998
|
-
children: [
|
|
2999
|
-
children,
|
|
3000
|
-
/* @__PURE__ */ jsxRuntime.jsxs(DialogPrimitive__namespace.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: [
|
|
3001
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-4 w-4" }),
|
|
3002
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "sr-only", children: "Close" })
|
|
3003
|
-
] })
|
|
3004
|
-
]
|
|
3005
|
-
}
|
|
3006
|
-
)
|
|
3007
|
-
] }));
|
|
3008
|
-
DialogContent.displayName = DialogPrimitive__namespace.Content.displayName;
|
|
3009
|
-
function DialogHeader({ className, ...props }) {
|
|
3010
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col space-y-1.5 text-center sm:text-left", className), ...props });
|
|
3011
|
-
}
|
|
3012
|
-
function DialogFooter({ className, ...props }) {
|
|
3013
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className), ...props });
|
|
3014
|
-
}
|
|
3015
|
-
var DialogTitle = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3016
|
-
DialogPrimitive__namespace.Title,
|
|
3017
|
-
{
|
|
3018
|
-
ref,
|
|
3019
|
-
className: cn("text-lg font-semibold leading-none tracking-tight", className),
|
|
3020
|
-
...props
|
|
3021
|
-
}
|
|
3022
|
-
));
|
|
3023
|
-
DialogTitle.displayName = DialogPrimitive__namespace.Title.displayName;
|
|
3024
|
-
var DialogDescription = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(DialogPrimitive__namespace.Description, { ref, className: cn("text-sm text-muted-foreground", className), ...props }));
|
|
3025
|
-
DialogDescription.displayName = DialogPrimitive__namespace.Description.displayName;
|
|
3026
|
-
var Label = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3027
|
-
LabelPrimitive__namespace.Root,
|
|
3028
|
-
{
|
|
3029
|
-
ref,
|
|
3030
|
-
className: cn("text-sm font-medium leading-none text-foreground", className),
|
|
3031
|
-
...props
|
|
3032
|
-
}
|
|
3033
|
-
));
|
|
3034
|
-
Label.displayName = LabelPrimitive__namespace.Root.displayName;
|
|
3035
3285
|
function SendDialog({
|
|
3036
3286
|
open,
|
|
3037
3287
|
onOpenChange,
|
|
@@ -4172,7 +4422,7 @@ function TextItemCard({
|
|
|
4172
4422
|
id: `ctx-text-${index}`,
|
|
4173
4423
|
value: element.text,
|
|
4174
4424
|
rows: 2,
|
|
4175
|
-
placeholder: "e.g. Posted by @
|
|
4425
|
+
placeholder: "e.g. Posted by @riley",
|
|
4176
4426
|
onChange: (e) => onChange({ ...element, text: e.target.value })
|
|
4177
4427
|
}
|
|
4178
4428
|
) }),
|
|
@@ -4257,7 +4507,7 @@ function ImageItemCard({
|
|
|
4257
4507
|
{
|
|
4258
4508
|
id: `ctx-img-alt-${index}`,
|
|
4259
4509
|
value: element.alt_text,
|
|
4260
|
-
placeholder: "e.g.
|
|
4510
|
+
placeholder: "e.g. Riley's avatar",
|
|
4261
4511
|
onChange: (e) => onChange({ ...element, alt_text: e.target.value })
|
|
4262
4512
|
}
|
|
4263
4513
|
) })
|
|
@@ -8590,6 +8840,8 @@ var SURFACE_DROPPABLE_ID = "builder-surface";
|
|
|
8590
8840
|
function Surface({
|
|
8591
8841
|
blocks,
|
|
8592
8842
|
workspaceName,
|
|
8843
|
+
authorName,
|
|
8844
|
+
authorIcon,
|
|
8593
8845
|
previewHooks,
|
|
8594
8846
|
previewTheme,
|
|
8595
8847
|
previewSurface = "message",
|
|
@@ -8665,16 +8917,20 @@ function Surface({
|
|
|
8665
8917
|
{
|
|
8666
8918
|
"aria-label": "Block preview",
|
|
8667
8919
|
className: cn("flex min-w-0 flex-1 flex-col overflow-y-auto bg-muted p-3 sm:p-6"),
|
|
8668
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto w-full max-w-2xl", children: previewSurface === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(ModalFrame, { isDark, children: blocksList }) : previewSurface === "app_home" ? /* @__PURE__ */ jsxRuntime.jsx(AppHomeFrame, { workspaceName, isDark, children: blocksList }) : /* @__PURE__ */ jsxRuntime.jsx(MessageFrame, { workspaceName, isDark, children: blocksList }) })
|
|
8920
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mx-auto w-full max-w-2xl", children: previewSurface === "modal" ? /* @__PURE__ */ jsxRuntime.jsx(ModalFrame, { isDark, children: blocksList }) : previewSurface === "app_home" ? /* @__PURE__ */ jsxRuntime.jsx(AppHomeFrame, { workspaceName, isDark, children: blocksList }) : /* @__PURE__ */ jsxRuntime.jsx(MessageFrame, { workspaceName, authorName, authorIcon, isDark, children: blocksList }) })
|
|
8669
8921
|
}
|
|
8670
8922
|
);
|
|
8671
8923
|
}
|
|
8672
8924
|
function MessageFrame({
|
|
8673
8925
|
workspaceName,
|
|
8926
|
+
authorName,
|
|
8927
|
+
authorIcon,
|
|
8674
8928
|
isDark,
|
|
8675
8929
|
children
|
|
8676
8930
|
}) {
|
|
8677
|
-
const
|
|
8931
|
+
const displayName = authorName ?? workspaceName ?? "Your app";
|
|
8932
|
+
const initial = displayName.slice(0, 1).toUpperCase();
|
|
8933
|
+
const safeIcon = authorIcon && isSafeImageSrc(authorIcon) ? authorIcon : null;
|
|
8678
8934
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8679
8935
|
"div",
|
|
8680
8936
|
{
|
|
@@ -8688,7 +8944,7 @@ function MessageFrame({
|
|
|
8688
8944
|
{
|
|
8689
8945
|
className: cn("flex items-center gap-2 px-5 pt-3 pb-1 text-xs", isDark ? "text-white/60" : "text-[#616061]"),
|
|
8690
8946
|
children: [
|
|
8691
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8947
|
+
safeIcon ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: safeIcon, alt: "", className: "h-7 w-7 shrink-0 rounded object-cover" }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8692
8948
|
"span",
|
|
8693
8949
|
{
|
|
8694
8950
|
className: cn(
|
|
@@ -8698,17 +8954,7 @@ function MessageFrame({
|
|
|
8698
8954
|
children: initial
|
|
8699
8955
|
}
|
|
8700
8956
|
),
|
|
8701
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-bold text-sm", isDark ? "text-white" : "text-[#1d1c1d]"), children:
|
|
8702
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8703
|
-
"span",
|
|
8704
|
-
{
|
|
8705
|
-
className: cn(
|
|
8706
|
-
"rounded px-1 text-[10px] font-semibold",
|
|
8707
|
-
isDark ? "bg-white/10 text-white/70" : "bg-[#f3f3f3] text-[#616061]"
|
|
8708
|
-
),
|
|
8709
|
-
children: "APP"
|
|
8710
|
-
}
|
|
8711
|
-
),
|
|
8957
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-bold text-sm", isDark ? "text-white" : "text-[#1d1c1d]"), children: displayName }),
|
|
8712
8958
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "10:37 AM" })
|
|
8713
8959
|
]
|
|
8714
8960
|
}
|
|
@@ -8910,6 +9156,14 @@ var SURFACE_OPTIONS = [
|
|
|
8910
9156
|
];
|
|
8911
9157
|
var DEFAULT_DOCS_HREF = "https://docs.slack.dev/reference/block-kit/blocks";
|
|
8912
9158
|
var DEFAULT_DOCS_LABEL = "Docs";
|
|
9159
|
+
function formatMessageTs(ts) {
|
|
9160
|
+
const seconds = Number.parseFloat(ts);
|
|
9161
|
+
if (!Number.isFinite(seconds)) return ts;
|
|
9162
|
+
const date = new Date(seconds * 1e3);
|
|
9163
|
+
if (Number.isNaN(date.getTime())) return ts;
|
|
9164
|
+
return date.toLocaleString(void 0, { dateStyle: "medium", timeStyle: "short" });
|
|
9165
|
+
}
|
|
9166
|
+
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";
|
|
8913
9167
|
function Toolbar2({
|
|
8914
9168
|
onClear,
|
|
8915
9169
|
onOpenJson,
|
|
@@ -8926,194 +9180,227 @@ function Toolbar2({
|
|
|
8926
9180
|
showThemeControl = true,
|
|
8927
9181
|
docsLink,
|
|
8928
9182
|
errorCount,
|
|
8929
|
-
sendButtonLabel = "
|
|
9183
|
+
sendButtonLabel = "Review & send",
|
|
9184
|
+
editingEnabled = false,
|
|
9185
|
+
editBadge,
|
|
9186
|
+
onOpenLoad,
|
|
9187
|
+
onOpenUpdate,
|
|
9188
|
+
onExitEdit,
|
|
9189
|
+
loadButtonLabel = "Load message",
|
|
9190
|
+
updateButtonLabel = "Review & update"
|
|
8930
9191
|
}) {
|
|
8931
9192
|
const activeTheme = THEME_OPTIONS.find((t) => t.value === previewTheme) ?? THEME_OPTIONS[0];
|
|
8932
|
-
const activeSurface = SURFACE_OPTIONS.find((s) => s.value === previewSurface) ?? SURFACE_OPTIONS[0];
|
|
8933
|
-
const surfaceOptions = SURFACE_OPTIONS.filter((s) => allowedSurfaces.includes(s.value));
|
|
8934
|
-
const showSurfaceControl = surfaceOptions.length > 1;
|
|
8935
|
-
const docsHref = docsLink === false ? null : docsLink?.href ?? DEFAULT_DOCS_HREF;
|
|
8936
|
-
const docsLabel = docsLink === false ? null : docsLink?.label ?? DEFAULT_DOCS_LABEL;
|
|
8937
|
-
const [surfaceMenuOpen, setSurfaceMenuOpen] = React.useState(false);
|
|
8938
|
-
const [themeMenuOpen, setThemeMenuOpen] = React.useState(false);
|
|
8939
|
-
const [
|
|
8940
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8941
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
8942
|
-
|
|
8943
|
-
Button,
|
|
8944
|
-
|
|
8945
|
-
|
|
8946
|
-
|
|
8947
|
-
|
|
8948
|
-
|
|
8949
|
-
className: "md:hidden",
|
|
8950
|
-
"aria-label": "Add a block",
|
|
8951
|
-
children: [
|
|
8952
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4" }),
|
|
8953
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Blocks" })
|
|
8954
|
-
]
|
|
8955
|
-
}
|
|
8956
|
-
) : null,
|
|
8957
|
-
showSurfaceControl ? /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: surfaceMenuOpen, onOpenChange: setSurfaceMenuOpen, children: [
|
|
8958
|
-
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": `Preview surface: ${activeSurface.label}`, children: [
|
|
8959
|
-
/* @__PURE__ */ jsxRuntime.jsx(activeSurface.Icon, { className: "h-3.5 w-3.5" }),
|
|
8960
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: activeSurface.label }),
|
|
8961
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3.5 w-3.5 opacity-60" })
|
|
8962
|
-
] }) }),
|
|
8963
|
-
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { align: "start", className: "w-36 p-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8964
|
-
Menu,
|
|
9193
|
+
const activeSurface = SURFACE_OPTIONS.find((s) => s.value === previewSurface) ?? SURFACE_OPTIONS[0];
|
|
9194
|
+
const surfaceOptions = SURFACE_OPTIONS.filter((s) => allowedSurfaces.includes(s.value));
|
|
9195
|
+
const showSurfaceControl = surfaceOptions.length > 1;
|
|
9196
|
+
const docsHref = docsLink === false ? null : docsLink?.href ?? DEFAULT_DOCS_HREF;
|
|
9197
|
+
const docsLabel = docsLink === false ? null : docsLink?.label ?? DEFAULT_DOCS_LABEL;
|
|
9198
|
+
const [surfaceMenuOpen, setSurfaceMenuOpen] = React.useState(false);
|
|
9199
|
+
const [themeMenuOpen, setThemeMenuOpen] = React.useState(false);
|
|
9200
|
+
const [sendMenuOpen, setSendMenuOpen] = React.useState(false);
|
|
9201
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9202
|
+
/* @__PURE__ */ jsxRuntime.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: [
|
|
9203
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-1 sm:gap-2", children: [
|
|
9204
|
+
editingEnabled && !editBadge ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: onOpenLoad, "aria-label": loadButtonLabel, children: [
|
|
9205
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-3.5 w-3.5" }),
|
|
9206
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: loadButtonLabel })
|
|
9207
|
+
] }) : null,
|
|
9208
|
+
onOpenPalette ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9209
|
+
Button,
|
|
8965
9210
|
{
|
|
8966
|
-
|
|
8967
|
-
|
|
8968
|
-
|
|
8969
|
-
|
|
8970
|
-
|
|
8971
|
-
|
|
9211
|
+
type: "button",
|
|
9212
|
+
variant: "ghost",
|
|
9213
|
+
size: "sm",
|
|
9214
|
+
onClick: onOpenPalette,
|
|
9215
|
+
className: "md:hidden",
|
|
9216
|
+
"aria-label": "Add a block",
|
|
9217
|
+
children: [
|
|
9218
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4" }),
|
|
9219
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Blocks" })
|
|
9220
|
+
]
|
|
9221
|
+
}
|
|
9222
|
+
) : null,
|
|
9223
|
+
showSurfaceControl ? /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: surfaceMenuOpen, onOpenChange: setSurfaceMenuOpen, children: [
|
|
9224
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": `Preview surface: ${activeSurface.label}`, children: [
|
|
9225
|
+
/* @__PURE__ */ jsxRuntime.jsx(activeSurface.Icon, { className: "h-3.5 w-3.5" }),
|
|
9226
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: activeSurface.label }),
|
|
9227
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "hidden h-3.5 w-3.5 opacity-60 md:inline" })
|
|
9228
|
+
] }) }),
|
|
9229
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { align: "start", className: "w-36 p-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9230
|
+
Menu,
|
|
9231
|
+
{
|
|
9232
|
+
ariaLabel: "Preview surface",
|
|
9233
|
+
options: surfaceOptions,
|
|
9234
|
+
value: previewSurface,
|
|
9235
|
+
onChange: (next) => {
|
|
9236
|
+
onPreviewSurfaceChange(next);
|
|
9237
|
+
setSurfaceMenuOpen(false);
|
|
9238
|
+
}
|
|
9239
|
+
}
|
|
9240
|
+
) })
|
|
9241
|
+
] }) : null,
|
|
9242
|
+
showThemeControl ? /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: themeMenuOpen, onOpenChange: setThemeMenuOpen, children: [
|
|
9243
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": `Preview theme: ${activeTheme.label}`, children: [
|
|
9244
|
+
/* @__PURE__ */ jsxRuntime.jsx(activeTheme.Icon, { className: "h-3.5 w-3.5" }),
|
|
9245
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: activeTheme.label }),
|
|
9246
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3.5 w-3.5 opacity-60" })
|
|
9247
|
+
] }) }),
|
|
9248
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { align: "start", className: "w-32 p-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9249
|
+
Menu,
|
|
9250
|
+
{
|
|
9251
|
+
ariaLabel: "Preview theme",
|
|
9252
|
+
options: THEME_OPTIONS,
|
|
9253
|
+
value: previewTheme,
|
|
9254
|
+
onChange: (next) => {
|
|
9255
|
+
onPreviewThemeChange(next);
|
|
9256
|
+
setThemeMenuOpen(false);
|
|
9257
|
+
}
|
|
8972
9258
|
}
|
|
9259
|
+
) })
|
|
9260
|
+
] }) : null,
|
|
9261
|
+
docsHref ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9262
|
+
"a",
|
|
9263
|
+
{
|
|
9264
|
+
href: docsHref,
|
|
9265
|
+
target: "_blank",
|
|
9266
|
+
rel: "noreferrer noopener",
|
|
9267
|
+
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",
|
|
9268
|
+
"aria-label": `${docsLabel} (opens in a new tab)`,
|
|
9269
|
+
children: [
|
|
9270
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BookOpen, { className: "h-3.5 w-3.5" }),
|
|
9271
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: docsLabel }),
|
|
9272
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "hidden h-3 w-3 opacity-50 md:inline" })
|
|
9273
|
+
]
|
|
8973
9274
|
}
|
|
8974
|
-
)
|
|
8975
|
-
] })
|
|
8976
|
-
|
|
8977
|
-
|
|
8978
|
-
|
|
8979
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: activeTheme.label }),
|
|
8980
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3.5 w-3.5 opacity-60" })
|
|
8981
|
-
] }) }),
|
|
8982
|
-
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { align: "start", className: "w-32 p-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8983
|
-
Menu,
|
|
9275
|
+
) : null
|
|
9276
|
+
] }),
|
|
9277
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 sm:gap-2", children: [
|
|
9278
|
+
errorCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9279
|
+
Button,
|
|
8984
9280
|
{
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
8989
|
-
|
|
8990
|
-
|
|
8991
|
-
|
|
9281
|
+
type: "button",
|
|
9282
|
+
variant: "ghost",
|
|
9283
|
+
size: "sm",
|
|
9284
|
+
onClick: onOpenIssues,
|
|
9285
|
+
className: "border border-red-200! bg-red-50 text-red-700 hover:bg-red-100 hover:text-red-700",
|
|
9286
|
+
"aria-label": `${errorCount} ${errorCount === 1 ? "issue" : "issues"}`,
|
|
9287
|
+
children: [
|
|
9288
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5" }),
|
|
9289
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
9290
|
+
errorCount,
|
|
9291
|
+
" ",
|
|
9292
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: errorCount === 1 ? "issue" : "issues" })
|
|
9293
|
+
] })
|
|
9294
|
+
]
|
|
8992
9295
|
}
|
|
8993
|
-
)
|
|
8994
|
-
|
|
8995
|
-
docsHref ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8996
|
-
"a",
|
|
8997
|
-
{
|
|
8998
|
-
href: docsHref,
|
|
8999
|
-
target: "_blank",
|
|
9000
|
-
rel: "noreferrer noopener",
|
|
9001
|
-
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",
|
|
9002
|
-
"aria-label": `${docsLabel} (opens in a new tab)`,
|
|
9003
|
-
children: [
|
|
9004
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BookOpen, { className: "h-3.5 w-3.5" }),
|
|
9005
|
-
docsLabel,
|
|
9006
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-3 w-3 opacity-50" })
|
|
9007
|
-
]
|
|
9008
|
-
}
|
|
9009
|
-
) : null
|
|
9010
|
-
] }),
|
|
9011
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 sm:gap-2", children: [
|
|
9012
|
-
errorCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9013
|
-
Button,
|
|
9014
|
-
{
|
|
9015
|
-
type: "button",
|
|
9016
|
-
variant: "ghost",
|
|
9017
|
-
size: "sm",
|
|
9018
|
-
onClick: onOpenIssues,
|
|
9019
|
-
className: "border border-red-200! bg-red-50 text-red-700 hover:bg-red-100 hover:text-red-700",
|
|
9020
|
-
"aria-label": `${errorCount} ${errorCount === 1 ? "issue" : "issues"}`,
|
|
9021
|
-
children: [
|
|
9022
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5" }),
|
|
9023
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
9024
|
-
errorCount,
|
|
9025
|
-
" ",
|
|
9026
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: errorCount === 1 ? "issue" : "issues" })
|
|
9027
|
-
] })
|
|
9028
|
-
]
|
|
9029
|
-
}
|
|
9030
|
-
) : null,
|
|
9031
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9032
|
-
Button,
|
|
9033
|
-
{
|
|
9034
|
-
type: "button",
|
|
9035
|
-
variant: "ghost",
|
|
9036
|
-
size: "sm",
|
|
9037
|
-
onClick: onClear,
|
|
9038
|
-
disabled: !canClear,
|
|
9039
|
-
className: "hidden hover:bg-destructive/10 hover:text-destructive sm:inline-flex",
|
|
9040
|
-
"aria-label": "Clear all blocks",
|
|
9041
|
-
children: [
|
|
9042
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" }),
|
|
9043
|
-
"Clear"
|
|
9044
|
-
]
|
|
9045
|
-
}
|
|
9046
|
-
),
|
|
9047
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9048
|
-
Button,
|
|
9049
|
-
{
|
|
9050
|
-
type: "button",
|
|
9051
|
-
variant: "ghost",
|
|
9052
|
-
size: "sm",
|
|
9053
|
-
onClick: onOpenJson,
|
|
9054
|
-
"aria-label": "View JSON",
|
|
9055
|
-
className: "hidden sm:inline-flex",
|
|
9056
|
-
children: [
|
|
9057
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { className: "h-3.5 w-3.5" }),
|
|
9058
|
-
"View JSON"
|
|
9059
|
-
]
|
|
9060
|
-
}
|
|
9061
|
-
),
|
|
9062
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: moreMenuOpen, onOpenChange: setMoreMenuOpen, children: [
|
|
9063
|
-
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9296
|
+
) : null,
|
|
9297
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9064
9298
|
Button,
|
|
9065
9299
|
{
|
|
9066
9300
|
type: "button",
|
|
9067
9301
|
variant: "ghost",
|
|
9068
9302
|
size: "sm",
|
|
9069
|
-
|
|
9070
|
-
|
|
9071
|
-
className: "
|
|
9072
|
-
|
|
9303
|
+
onClick: onClear,
|
|
9304
|
+
disabled: !canClear,
|
|
9305
|
+
className: "hover:bg-destructive/10 hover:text-destructive",
|
|
9306
|
+
"aria-label": "Clear all blocks",
|
|
9307
|
+
children: [
|
|
9308
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" }),
|
|
9309
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: "Clear" })
|
|
9310
|
+
]
|
|
9073
9311
|
}
|
|
9074
|
-
)
|
|
9075
|
-
/* @__PURE__ */ jsxRuntime.
|
|
9076
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9077
|
-
|
|
9078
|
-
|
|
9079
|
-
|
|
9080
|
-
|
|
9081
|
-
|
|
9082
|
-
|
|
9083
|
-
|
|
9084
|
-
|
|
9085
|
-
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
|
|
9089
|
-
|
|
9090
|
-
|
|
9091
|
-
|
|
9092
|
-
|
|
9093
|
-
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
}
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
|
|
9101
|
-
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
|
|
9105
|
-
|
|
9106
|
-
|
|
9107
|
-
|
|
9108
|
-
|
|
9109
|
-
|
|
9110
|
-
|
|
9312
|
+
),
|
|
9313
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", size: "sm", onClick: onOpenJson, "aria-label": "View JSON", children: [
|
|
9314
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { className: "h-3.5 w-3.5" }),
|
|
9315
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: "View JSON" })
|
|
9316
|
+
] }),
|
|
9317
|
+
editBadge ? (
|
|
9318
|
+
// A message is loaded: split button. Main action updates it in
|
|
9319
|
+
// place; the menu also offers posting the blocks as a new message.
|
|
9320
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-stretch", children: [
|
|
9321
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9322
|
+
Button,
|
|
9323
|
+
{
|
|
9324
|
+
type: "button",
|
|
9325
|
+
size: "sm",
|
|
9326
|
+
onClick: onOpenUpdate,
|
|
9327
|
+
disabled: !canSend,
|
|
9328
|
+
"aria-label": updateButtonLabel,
|
|
9329
|
+
className: "rounded-r-none",
|
|
9330
|
+
children: [
|
|
9331
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-3.5 w-3.5" }),
|
|
9332
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: updateButtonLabel })
|
|
9333
|
+
]
|
|
9334
|
+
}
|
|
9335
|
+
),
|
|
9336
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: sendMenuOpen, onOpenChange: setSendMenuOpen, children: [
|
|
9337
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9338
|
+
Button,
|
|
9339
|
+
{
|
|
9340
|
+
type: "button",
|
|
9341
|
+
size: "sm",
|
|
9342
|
+
"aria-label": "More message options",
|
|
9343
|
+
"aria-haspopup": "menu",
|
|
9344
|
+
className: "rounded-l-none border-l border-l-primary-foreground/30! px-1.5",
|
|
9345
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3.5 w-3.5" })
|
|
9346
|
+
}
|
|
9347
|
+
) }),
|
|
9348
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { align: "end", className: "w-56 p-1", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { role: "menu", "aria-label": "Message options", className: "flex flex-col", children: [
|
|
9349
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9350
|
+
"button",
|
|
9351
|
+
{
|
|
9352
|
+
type: "button",
|
|
9353
|
+
role: "menuitem",
|
|
9354
|
+
disabled: !canSend,
|
|
9355
|
+
onClick: () => {
|
|
9356
|
+
setSendMenuOpen(false);
|
|
9357
|
+
onOpenUpdate?.();
|
|
9358
|
+
},
|
|
9359
|
+
className: SEND_MENU_ITEM,
|
|
9360
|
+
children: [
|
|
9361
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-3.5 w-3.5" }),
|
|
9362
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "Update message" })
|
|
9363
|
+
]
|
|
9364
|
+
}
|
|
9365
|
+
),
|
|
9366
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9367
|
+
"button",
|
|
9368
|
+
{
|
|
9369
|
+
type: "button",
|
|
9370
|
+
role: "menuitem",
|
|
9371
|
+
disabled: !canSend,
|
|
9372
|
+
onClick: () => {
|
|
9373
|
+
setSendMenuOpen(false);
|
|
9374
|
+
onOpenSend();
|
|
9375
|
+
},
|
|
9376
|
+
className: SEND_MENU_ITEM,
|
|
9377
|
+
children: [
|
|
9378
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3.5 w-3.5" }),
|
|
9379
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "Send as a new message" })
|
|
9380
|
+
]
|
|
9381
|
+
}
|
|
9382
|
+
)
|
|
9383
|
+
] }) })
|
|
9384
|
+
] })
|
|
9385
|
+
] })
|
|
9386
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: onOpenSend, disabled: !canSend, "aria-label": sendButtonLabel, children: [
|
|
9387
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3.5 w-3.5" }),
|
|
9388
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: sendButtonLabel })
|
|
9389
|
+
] })
|
|
9390
|
+
] })
|
|
9391
|
+
] }),
|
|
9392
|
+
editingEnabled && editBadge ? /* @__PURE__ */ jsxRuntime.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: [
|
|
9393
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-4 w-4 shrink-0 text-primary" }),
|
|
9394
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1 text-sm", children: [
|
|
9395
|
+
"References an existing message in ",
|
|
9396
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: editBadge.channelLabel }),
|
|
9397
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-xs opacity-70", title: editBadge.ts, children: formatMessageTs(editBadge.ts) })
|
|
9111
9398
|
] }),
|
|
9112
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick:
|
|
9113
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.
|
|
9114
|
-
|
|
9399
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", size: "sm", onClick: onExitEdit, className: "shrink-0", children: [
|
|
9400
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3.5 w-3.5" }),
|
|
9401
|
+
"Switch to a new message"
|
|
9115
9402
|
] })
|
|
9116
|
-
] })
|
|
9403
|
+
] }) : null
|
|
9117
9404
|
] });
|
|
9118
9405
|
}
|
|
9119
9406
|
function Menu({
|
|
@@ -9171,52 +9458,132 @@ function Menu({
|
|
|
9171
9458
|
);
|
|
9172
9459
|
}) });
|
|
9173
9460
|
}
|
|
9174
|
-
|
|
9175
|
-
|
|
9176
|
-
|
|
9177
|
-
|
|
9178
|
-
|
|
9179
|
-
|
|
9180
|
-
|
|
9461
|
+
function UpdateDialog({
|
|
9462
|
+
open,
|
|
9463
|
+
onOpenChange,
|
|
9464
|
+
target,
|
|
9465
|
+
blocks,
|
|
9466
|
+
loadSendAsUserStatus,
|
|
9467
|
+
onUpdate,
|
|
9468
|
+
confirmUpdateLabel = "Update message",
|
|
9469
|
+
errorCount,
|
|
9470
|
+
onShowIssues
|
|
9181
9471
|
}) {
|
|
9182
|
-
|
|
9183
|
-
|
|
9184
|
-
|
|
9185
|
-
|
|
9186
|
-
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
|
|
9472
|
+
const asUser = target.editableVia === "user";
|
|
9473
|
+
const [userStatus, setUserStatus] = React.useState(null);
|
|
9474
|
+
const [status, setStatus] = React.useState({ kind: "idle" });
|
|
9475
|
+
const loadSendAsUserStatusRef = React.useRef(loadSendAsUserStatus);
|
|
9476
|
+
React.useEffect(() => {
|
|
9477
|
+
loadSendAsUserStatusRef.current = loadSendAsUserStatus;
|
|
9478
|
+
});
|
|
9479
|
+
const refreshSendAsUser = React.useCallback(() => {
|
|
9480
|
+
loadSendAsUserStatusRef.current().then(setUserStatus).catch(() => setUserStatus({ canSendAsUser: false }));
|
|
9481
|
+
}, []);
|
|
9482
|
+
React.useEffect(() => {
|
|
9483
|
+
if (!open) {
|
|
9484
|
+
return;
|
|
9194
9485
|
}
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
|
|
9199
|
-
icon,
|
|
9200
|
-
trailingIcon,
|
|
9201
|
-
children,
|
|
9202
|
-
onSelect
|
|
9203
|
-
}) {
|
|
9204
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9205
|
-
"a",
|
|
9206
|
-
{
|
|
9207
|
-
role: "menuitem",
|
|
9208
|
-
href,
|
|
9209
|
-
target: "_blank",
|
|
9210
|
-
rel: "noreferrer noopener",
|
|
9211
|
-
onClick: onSelect,
|
|
9212
|
-
className: ACTION_ITEM_BASE,
|
|
9213
|
-
children: [
|
|
9214
|
-
icon,
|
|
9215
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children }),
|
|
9216
|
-
trailingIcon
|
|
9217
|
-
]
|
|
9486
|
+
setStatus({ kind: "idle" });
|
|
9487
|
+
if (asUser) {
|
|
9488
|
+
setUserStatus(null);
|
|
9489
|
+
refreshSendAsUser();
|
|
9218
9490
|
}
|
|
9219
|
-
);
|
|
9491
|
+
}, [open, asUser, refreshSendAsUser]);
|
|
9492
|
+
React.useEffect(() => {
|
|
9493
|
+
if (!open || !asUser) {
|
|
9494
|
+
return;
|
|
9495
|
+
}
|
|
9496
|
+
const handler = () => refreshSendAsUser();
|
|
9497
|
+
window.addEventListener("focus", handler);
|
|
9498
|
+
return () => window.removeEventListener("focus", handler);
|
|
9499
|
+
}, [open, asUser, refreshSendAsUser]);
|
|
9500
|
+
const needsSignIn = asUser && userStatus !== null && !userStatus.canSendAsUser;
|
|
9501
|
+
const handleSubmit = async () => {
|
|
9502
|
+
setStatus({ kind: "updating" });
|
|
9503
|
+
try {
|
|
9504
|
+
const result = await onUpdate({
|
|
9505
|
+
channelId: target.channelId,
|
|
9506
|
+
ts: target.ts,
|
|
9507
|
+
blocks: toSlackBlocks(blocks),
|
|
9508
|
+
asUser
|
|
9509
|
+
});
|
|
9510
|
+
if (result.ok) {
|
|
9511
|
+
setStatus({ kind: "idle" });
|
|
9512
|
+
onOpenChange(false);
|
|
9513
|
+
return;
|
|
9514
|
+
}
|
|
9515
|
+
setStatus({ kind: "error", error: result.error ?? "Update failed." });
|
|
9516
|
+
} catch (e) {
|
|
9517
|
+
setStatus({ kind: "error", error: e instanceof Error ? e.message : "Update failed." });
|
|
9518
|
+
}
|
|
9519
|
+
};
|
|
9520
|
+
const channelLabel = target.channelName ? `#${target.channelName}` : target.channelId;
|
|
9521
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "w-[calc(100vw-1.5rem)] max-w-lg rounded-lg", children: [
|
|
9522
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
|
|
9523
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Update message" }),
|
|
9524
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "This replaces the message that's already posted. It stays in the same channel and can't be moved." })
|
|
9525
|
+
] }),
|
|
9526
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
9527
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
9528
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Channel" }),
|
|
9529
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "flex h-9 items-center rounded-md border border-input bg-muted px-3 text-sm text-muted-foreground", children: channelLabel })
|
|
9530
|
+
] }),
|
|
9531
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
9532
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Posting as" }),
|
|
9533
|
+
/* @__PURE__ */ jsxRuntime.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" }),
|
|
9534
|
+
needsSignIn && userStatus?.oauthUrl && isSafeHref(userStatus.oauthUrl) && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
9535
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9536
|
+
"a",
|
|
9537
|
+
{
|
|
9538
|
+
href: userStatus.oauthUrl,
|
|
9539
|
+
target: "_blank",
|
|
9540
|
+
rel: "noopener noreferrer",
|
|
9541
|
+
className: "inline-flex items-center gap-1 text-primary hover:underline",
|
|
9542
|
+
children: [
|
|
9543
|
+
"Sign in with Slack ",
|
|
9544
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-3 w-3" })
|
|
9545
|
+
]
|
|
9546
|
+
}
|
|
9547
|
+
),
|
|
9548
|
+
" ",
|
|
9549
|
+
"to update your own message."
|
|
9550
|
+
] }),
|
|
9551
|
+
needsSignIn && !userStatus?.oauthUrl && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Sign in with Slack to update your own message." })
|
|
9552
|
+
] }),
|
|
9553
|
+
errorCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9554
|
+
"button",
|
|
9555
|
+
{
|
|
9556
|
+
type: "button",
|
|
9557
|
+
onClick: onShowIssues,
|
|
9558
|
+
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",
|
|
9559
|
+
children: [
|
|
9560
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
9561
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex-1", children: [
|
|
9562
|
+
"Fix ",
|
|
9563
|
+
errorCount,
|
|
9564
|
+
" ",
|
|
9565
|
+
errorCount === 1 ? "issue" : "issues",
|
|
9566
|
+
" before updating."
|
|
9567
|
+
] }),
|
|
9568
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 underline", children: "Show issues" })
|
|
9569
|
+
]
|
|
9570
|
+
}
|
|
9571
|
+
) : null,
|
|
9572
|
+
status.kind === "error" && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "rounded-md border border-destructive/30 bg-destructive/5 p-2 text-xs text-destructive", children: status.error })
|
|
9573
|
+
] }),
|
|
9574
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
|
|
9575
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
9576
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9577
|
+
Button,
|
|
9578
|
+
{
|
|
9579
|
+
type: "button",
|
|
9580
|
+
onClick: handleSubmit,
|
|
9581
|
+
disabled: status.kind === "updating" || blocks.length === 0 || errorCount > 0 || needsSignIn,
|
|
9582
|
+
children: status.kind === "updating" ? "Updating\u2026" : confirmUpdateLabel
|
|
9583
|
+
}
|
|
9584
|
+
)
|
|
9585
|
+
] })
|
|
9586
|
+
] }) });
|
|
9220
9587
|
}
|
|
9221
9588
|
function BlockKitchen(props) {
|
|
9222
9589
|
const {
|
|
@@ -9228,6 +9595,10 @@ function BlockKitchen(props) {
|
|
|
9228
9595
|
loadChannels,
|
|
9229
9596
|
loadSendAsUserStatus,
|
|
9230
9597
|
onSend,
|
|
9598
|
+
editing,
|
|
9599
|
+
loadButtonLabel,
|
|
9600
|
+
updateButtonLabel,
|
|
9601
|
+
confirmUpdateLabel,
|
|
9231
9602
|
palette,
|
|
9232
9603
|
disabledBlockTypes,
|
|
9233
9604
|
showPaletteSearch,
|
|
@@ -9273,6 +9644,10 @@ function BlockKitchen(props) {
|
|
|
9273
9644
|
}, [blocks]);
|
|
9274
9645
|
const [jsonOpen, setJsonOpen] = React.useState(false);
|
|
9275
9646
|
const [sendOpen, setSendOpen] = React.useState(false);
|
|
9647
|
+
const [updateOpen, setUpdateOpen] = React.useState(false);
|
|
9648
|
+
const [loadOpen, setLoadOpen] = React.useState(false);
|
|
9649
|
+
const [editTarget, setEditTarget] = React.useState(null);
|
|
9650
|
+
const activeEditTarget = editing ? editTarget : null;
|
|
9276
9651
|
const [issuesOpen, setIssuesOpen] = React.useState(false);
|
|
9277
9652
|
const [paletteOpen, setPaletteOpen] = React.useState(false);
|
|
9278
9653
|
const [openBlockId, setOpenBlockId] = React.useState(null);
|
|
@@ -9393,7 +9768,21 @@ function BlockKitchen(props) {
|
|
|
9393
9768
|
allowedSurfaces,
|
|
9394
9769
|
showThemeControl: isPreviewThemeControlled ? false : showThemeControl,
|
|
9395
9770
|
docsLink,
|
|
9396
|
-
sendButtonLabel
|
|
9771
|
+
sendButtonLabel,
|
|
9772
|
+
editingEnabled: !!editing,
|
|
9773
|
+
editBadge: activeEditTarget ? {
|
|
9774
|
+
channelLabel: activeEditTarget.channelName ? `#${activeEditTarget.channelName}` : activeEditTarget.channelId,
|
|
9775
|
+
ts: activeEditTarget.ts
|
|
9776
|
+
} : null,
|
|
9777
|
+
onOpenLoad: () => setLoadOpen(true),
|
|
9778
|
+
onOpenUpdate: () => setUpdateOpen(true),
|
|
9779
|
+
onExitEdit: () => {
|
|
9780
|
+
setEditTarget(null);
|
|
9781
|
+
replaceAll([]);
|
|
9782
|
+
setLoadOpen(true);
|
|
9783
|
+
},
|
|
9784
|
+
loadButtonLabel,
|
|
9785
|
+
updateButtonLabel
|
|
9397
9786
|
}
|
|
9398
9787
|
),
|
|
9399
9788
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 items-stretch", children: [
|
|
@@ -9412,6 +9801,8 @@ function BlockKitchen(props) {
|
|
|
9412
9801
|
{
|
|
9413
9802
|
blocks,
|
|
9414
9803
|
workspaceName,
|
|
9804
|
+
authorName: activeEditTarget?.username,
|
|
9805
|
+
authorIcon: activeEditTarget?.iconUrl,
|
|
9415
9806
|
previewHooks: mergedPreviewHooks,
|
|
9416
9807
|
previewTheme,
|
|
9417
9808
|
previewSurface,
|
|
@@ -9477,6 +9868,53 @@ function BlockKitchen(props) {
|
|
|
9477
9868
|
}
|
|
9478
9869
|
}
|
|
9479
9870
|
),
|
|
9871
|
+
activeEditTarget && editing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
9872
|
+
UpdateDialog,
|
|
9873
|
+
{
|
|
9874
|
+
open: updateOpen,
|
|
9875
|
+
onOpenChange: setUpdateOpen,
|
|
9876
|
+
target: activeEditTarget,
|
|
9877
|
+
blocks: blockPayloads,
|
|
9878
|
+
loadSendAsUserStatus,
|
|
9879
|
+
onUpdate: editing.onUpdate,
|
|
9880
|
+
confirmUpdateLabel,
|
|
9881
|
+
errorCount: validation.total,
|
|
9882
|
+
onShowIssues: () => {
|
|
9883
|
+
setUpdateOpen(false);
|
|
9884
|
+
setIssuesOpen(true);
|
|
9885
|
+
}
|
|
9886
|
+
}
|
|
9887
|
+
) : null,
|
|
9888
|
+
editing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
9889
|
+
LoadMessageDialog,
|
|
9890
|
+
{
|
|
9891
|
+
open: loadOpen,
|
|
9892
|
+
onOpenChange: setLoadOpen,
|
|
9893
|
+
onLoadMessage: editing.onLoadMessage,
|
|
9894
|
+
loadRecentMessages: editing.loadRecentMessages,
|
|
9895
|
+
loadChannels,
|
|
9896
|
+
onLoaded: (result) => {
|
|
9897
|
+
replaceAll(result.blocks);
|
|
9898
|
+
setEditTarget({
|
|
9899
|
+
channelId: result.channelId,
|
|
9900
|
+
channelName: result.channelName,
|
|
9901
|
+
ts: result.ts,
|
|
9902
|
+
editableVia: result.editableVia,
|
|
9903
|
+
workspaceName: result.workspaceName,
|
|
9904
|
+
username: result.username,
|
|
9905
|
+
iconUrl: result.iconUrl
|
|
9906
|
+
});
|
|
9907
|
+
setLoadOpen(false);
|
|
9908
|
+
},
|
|
9909
|
+
onOpenAsNew: (loadedBlocks) => {
|
|
9910
|
+
if (loadedBlocks) {
|
|
9911
|
+
replaceAll(loadedBlocks);
|
|
9912
|
+
}
|
|
9913
|
+
setEditTarget(null);
|
|
9914
|
+
setLoadOpen(false);
|
|
9915
|
+
}
|
|
9916
|
+
}
|
|
9917
|
+
) : null,
|
|
9480
9918
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9481
9919
|
IssuesSheet,
|
|
9482
9920
|
{
|