@tightknitai/block-kitchen 0.8.9 → 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 +733 -365
- 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 +734 -366
- 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.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,213 @@ 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
|
+
onLoaded,
|
|
2855
|
+
onOpenAsNew
|
|
2856
|
+
}) {
|
|
2857
|
+
const [link, setLink] = React.useState("");
|
|
2858
|
+
const [status, setStatus] = React.useState({ kind: "idle" });
|
|
2859
|
+
const [recent, setRecent] = React.useState(null);
|
|
2860
|
+
const [recentError, setRecentError] = React.useState(null);
|
|
2861
|
+
const inputRef = React.useRef(null);
|
|
2862
|
+
const onLoadMessageRef = React.useRef(onLoadMessage);
|
|
2863
|
+
const loadRecentMessagesRef = React.useRef(loadRecentMessages);
|
|
2864
|
+
React.useEffect(() => {
|
|
2865
|
+
onLoadMessageRef.current = onLoadMessage;
|
|
2866
|
+
loadRecentMessagesRef.current = loadRecentMessages;
|
|
2867
|
+
});
|
|
2868
|
+
const hasRecent = !!loadRecentMessages;
|
|
2869
|
+
React.useEffect(() => {
|
|
2870
|
+
if (!open) {
|
|
2871
|
+
return;
|
|
2872
|
+
}
|
|
2873
|
+
setLink("");
|
|
2874
|
+
setStatus({ kind: "idle" });
|
|
2875
|
+
if (!loadRecentMessagesRef.current) {
|
|
2876
|
+
setRecent([]);
|
|
2877
|
+
setRecentError(null);
|
|
2878
|
+
return;
|
|
2879
|
+
}
|
|
2880
|
+
setRecent(null);
|
|
2881
|
+
setRecentError(null);
|
|
2882
|
+
let cancelled = false;
|
|
2883
|
+
loadRecentMessagesRef.current().then((list) => {
|
|
2884
|
+
if (!cancelled) {
|
|
2885
|
+
setRecent(list);
|
|
2886
|
+
}
|
|
2887
|
+
}).catch((e) => {
|
|
2888
|
+
if (!cancelled) {
|
|
2889
|
+
setRecentError(e instanceof Error ? e.message : "Failed to load recent messages.");
|
|
2890
|
+
}
|
|
2891
|
+
});
|
|
2892
|
+
return () => {
|
|
2893
|
+
cancelled = true;
|
|
2894
|
+
};
|
|
2895
|
+
}, [open]);
|
|
2896
|
+
const handleLoad = async () => {
|
|
2897
|
+
const trimmed = link.trim();
|
|
2898
|
+
if (!trimmed) {
|
|
2899
|
+
setStatus({ kind: "error", error: "Paste a Slack message link first." });
|
|
2900
|
+
return;
|
|
2901
|
+
}
|
|
2902
|
+
setStatus({ kind: "loading" });
|
|
2903
|
+
try {
|
|
2904
|
+
const result = await onLoadMessageRef.current({ link: trimmed });
|
|
2905
|
+
if (result.ok) {
|
|
2906
|
+
onLoaded(result);
|
|
2907
|
+
return;
|
|
2908
|
+
}
|
|
2909
|
+
setStatus({ kind: "not-editable", reason: result.reason, blocks: result.blocks });
|
|
2910
|
+
} catch (e) {
|
|
2911
|
+
setStatus({ kind: "error", error: e instanceof Error ? e.message : "Failed to load message." });
|
|
2912
|
+
}
|
|
2913
|
+
};
|
|
2914
|
+
const notEditable = status.kind === "not-editable" ? status : null;
|
|
2915
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2916
|
+
DialogContent,
|
|
2917
|
+
{
|
|
2918
|
+
className: "w-[calc(100vw-1.5rem)] max-w-lg rounded-lg",
|
|
2919
|
+
onOpenAutoFocus: (e) => {
|
|
2920
|
+
e.preventDefault();
|
|
2921
|
+
inputRef.current?.focus();
|
|
2922
|
+
},
|
|
2923
|
+
children: [
|
|
2924
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
|
|
2925
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Edit an existing message" }),
|
|
2926
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-1.5", children: [
|
|
2927
|
+
/* @__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.` }),
|
|
2928
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Tooltip, { children: [
|
|
2929
|
+
/* @__PURE__ */ jsxRuntime.jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2930
|
+
"button",
|
|
2931
|
+
{
|
|
2932
|
+
type: "button",
|
|
2933
|
+
"aria-label": "How to copy a message link",
|
|
2934
|
+
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",
|
|
2935
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Info, { className: "h-3.5 w-3.5" })
|
|
2936
|
+
}
|
|
2937
|
+
) }),
|
|
2938
|
+
/* @__PURE__ */ jsxRuntime.jsxs(TooltipContent, { className: "max-w-xs leading-relaxed", children: [
|
|
2939
|
+
"In Slack, hover over the message and click the ",
|
|
2940
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "\u22EE More actions" }),
|
|
2941
|
+
" button (or right-click the message), then choose ",
|
|
2942
|
+
/* @__PURE__ */ jsxRuntime.jsx("strong", { children: "Copy link" }),
|
|
2943
|
+
"."
|
|
2944
|
+
] })
|
|
2945
|
+
] })
|
|
2946
|
+
] })
|
|
2947
|
+
] }),
|
|
2948
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
2949
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
2950
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: "message-link", children: "Message link" }),
|
|
2951
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2952
|
+
Input,
|
|
2953
|
+
{
|
|
2954
|
+
ref: inputRef,
|
|
2955
|
+
id: "message-link",
|
|
2956
|
+
value: link,
|
|
2957
|
+
onChange: (e) => {
|
|
2958
|
+
setLink(e.target.value);
|
|
2959
|
+
if (status.kind !== "idle" && status.kind !== "loading") {
|
|
2960
|
+
setStatus({ kind: "idle" });
|
|
2961
|
+
}
|
|
2962
|
+
},
|
|
2963
|
+
onKeyDown: (e) => {
|
|
2964
|
+
if (e.key === "Enter" && status.kind !== "loading") {
|
|
2965
|
+
e.preventDefault();
|
|
2966
|
+
handleLoad();
|
|
2967
|
+
}
|
|
2968
|
+
},
|
|
2969
|
+
placeholder: "https://your-workspace.slack.com/archives/C\u2026/p\u2026",
|
|
2970
|
+
autoComplete: "off",
|
|
2971
|
+
spellCheck: false
|
|
2972
|
+
}
|
|
2973
|
+
)
|
|
2974
|
+
] }),
|
|
2975
|
+
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 }),
|
|
2976
|
+
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: [
|
|
2977
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start gap-2", children: [
|
|
2978
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "mt-0.5 h-3.5 w-3.5 shrink-0" }),
|
|
2979
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: notEditable.reason })
|
|
2980
|
+
] }),
|
|
2981
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2982
|
+
Button,
|
|
2983
|
+
{
|
|
2984
|
+
type: "button",
|
|
2985
|
+
variant: "outline",
|
|
2986
|
+
size: "sm",
|
|
2987
|
+
className: "self-start",
|
|
2988
|
+
onClick: () => onOpenAsNew(notEditable.blocks),
|
|
2989
|
+
children: "Open as a new message instead"
|
|
2990
|
+
}
|
|
2991
|
+
)
|
|
2992
|
+
] }),
|
|
2993
|
+
hasRecent && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-2", children: [
|
|
2994
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
2995
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" }),
|
|
2996
|
+
"or pick a recent message",
|
|
2997
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "h-px flex-1 bg-border" })
|
|
2998
|
+
] }),
|
|
2999
|
+
recent === null && !recentError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Loading recent messages\u2026" }),
|
|
3000
|
+
recentError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive", children: recentError }),
|
|
3001
|
+
recent && recent.length === 0 && !recentError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "No recent messages from this app." }),
|
|
3002
|
+
recent && recent.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex max-h-48 flex-col gap-1 overflow-y-auto", children: recent.map((m) => {
|
|
3003
|
+
const asUser = (m.editableVia ?? "bot") === "user";
|
|
3004
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3005
|
+
"button",
|
|
3006
|
+
{
|
|
3007
|
+
type: "button",
|
|
3008
|
+
onClick: () => onLoaded(recentToResult(m)),
|
|
3009
|
+
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",
|
|
3010
|
+
children: [
|
|
3011
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex items-baseline justify-between gap-2", children: [
|
|
3012
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex min-w-0 items-baseline gap-1.5", children: [
|
|
3013
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate font-medium", children: m.channelName ? `#${m.channelName}` : m.channelId }),
|
|
3014
|
+
/* @__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" })
|
|
3015
|
+
] }),
|
|
3016
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 font-mono text-xs text-muted-foreground", children: m.ts })
|
|
3017
|
+
] }),
|
|
3018
|
+
m.label && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate text-xs text-muted-foreground", children: m.label })
|
|
3019
|
+
]
|
|
3020
|
+
},
|
|
3021
|
+
`${m.channelId}:${m.ts}`
|
|
3022
|
+
);
|
|
3023
|
+
}) })
|
|
3024
|
+
] })
|
|
3025
|
+
] }),
|
|
3026
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
|
|
3027
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
3028
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", onClick: handleLoad, disabled: status.kind === "loading" || !link.trim(), children: status.kind === "loading" ? "Loading\u2026" : "Load message" })
|
|
3029
|
+
] })
|
|
3030
|
+
]
|
|
3031
|
+
}
|
|
3032
|
+
) });
|
|
3033
|
+
}
|
|
2742
3034
|
var PALETTE_DRAG_PREFIX = "palette:";
|
|
2743
3035
|
function parsePaletteDragId(id) {
|
|
2744
3036
|
if (typeof id !== "string" || !id.startsWith(PALETTE_DRAG_PREFIX)) {
|
|
@@ -2938,100 +3230,6 @@ function PaletteItem({
|
|
|
2938
3230
|
}
|
|
2939
3231
|
);
|
|
2940
3232
|
}
|
|
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
3233
|
function SendDialog({
|
|
3036
3234
|
open,
|
|
3037
3235
|
onOpenChange,
|
|
@@ -3425,12 +3623,16 @@ function AlertEditor({ block, onChange }) {
|
|
|
3425
3623
|
) })
|
|
3426
3624
|
] });
|
|
3427
3625
|
}
|
|
3428
|
-
function CardEditor({
|
|
3626
|
+
function CardEditor({
|
|
3627
|
+
block,
|
|
3628
|
+
onChange,
|
|
3629
|
+
idPrefix = "card"
|
|
3630
|
+
}) {
|
|
3429
3631
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
3430
|
-
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Title", help: "Up to 150 characters. Supports mrkdwn formatting.", htmlFor:
|
|
3632
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Title", help: "Up to 150 characters. Supports mrkdwn formatting.", htmlFor: `${idPrefix}-title`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3431
3633
|
Input,
|
|
3432
3634
|
{
|
|
3433
|
-
id:
|
|
3635
|
+
id: `${idPrefix}-title`,
|
|
3434
3636
|
value: block.title?.text ?? "",
|
|
3435
3637
|
maxLength: 150,
|
|
3436
3638
|
placeholder: "e.g. New launch update",
|
|
@@ -3440,10 +3642,10 @@ function CardEditor({ block, onChange }) {
|
|
|
3440
3642
|
})
|
|
3441
3643
|
}
|
|
3442
3644
|
) }),
|
|
3443
|
-
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Subtitle", help: "Up to 150 characters.", htmlFor:
|
|
3645
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Subtitle", help: "Up to 150 characters.", htmlFor: `${idPrefix}-subtitle`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3444
3646
|
Input,
|
|
3445
3647
|
{
|
|
3446
|
-
id:
|
|
3648
|
+
id: `${idPrefix}-subtitle`,
|
|
3447
3649
|
value: block.subtitle?.text ?? "",
|
|
3448
3650
|
maxLength: 150,
|
|
3449
3651
|
placeholder: "e.g. Released April 28",
|
|
@@ -3453,10 +3655,10 @@ function CardEditor({ block, onChange }) {
|
|
|
3453
3655
|
})
|
|
3454
3656
|
}
|
|
3455
3657
|
) }),
|
|
3456
|
-
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Body", help: "Up to 200 characters. Supports mrkdwn formatting.", htmlFor:
|
|
3658
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Body", help: "Up to 200 characters. Supports mrkdwn formatting.", htmlFor: `${idPrefix}-body`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3457
3659
|
Textarea,
|
|
3458
3660
|
{
|
|
3459
|
-
id:
|
|
3661
|
+
id: `${idPrefix}-body`,
|
|
3460
3662
|
value: block.body?.text ?? "",
|
|
3461
3663
|
maxLength: 200,
|
|
3462
3664
|
rows: 3,
|
|
@@ -3472,7 +3674,7 @@ function CardEditor({ block, onChange }) {
|
|
|
3472
3674
|
{
|
|
3473
3675
|
label: "Hero image",
|
|
3474
3676
|
help: "Wide image displayed at the top of the card.",
|
|
3475
|
-
idPrefix:
|
|
3677
|
+
idPrefix: `${idPrefix}-hero`,
|
|
3476
3678
|
image: block.hero_image,
|
|
3477
3679
|
onChange: (next) => onChange({ ...block, hero_image: next })
|
|
3478
3680
|
}
|
|
@@ -3482,7 +3684,7 @@ function CardEditor({ block, onChange }) {
|
|
|
3482
3684
|
{
|
|
3483
3685
|
label: "Icon",
|
|
3484
3686
|
help: "Small image shown next to the title.",
|
|
3485
|
-
idPrefix:
|
|
3687
|
+
idPrefix: `${idPrefix}-icon`,
|
|
3486
3688
|
image: block.icon,
|
|
3487
3689
|
onChange: (next) => onChange({ ...block, icon: next })
|
|
3488
3690
|
}
|
|
@@ -3490,6 +3692,7 @@ function CardEditor({ block, onChange }) {
|
|
|
3490
3692
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3491
3693
|
ButtonsField,
|
|
3492
3694
|
{
|
|
3695
|
+
idPrefix,
|
|
3493
3696
|
buttons: block.actions ?? [],
|
|
3494
3697
|
onChange: (next) => onChange({ ...block, actions: next.length > 0 ? next : void 0 })
|
|
3495
3698
|
}
|
|
@@ -3546,7 +3749,11 @@ function ImageFields({
|
|
|
3546
3749
|
) })
|
|
3547
3750
|
] });
|
|
3548
3751
|
}
|
|
3549
|
-
function ButtonsField({
|
|
3752
|
+
function ButtonsField({
|
|
3753
|
+
buttons,
|
|
3754
|
+
onChange,
|
|
3755
|
+
idPrefix = "card"
|
|
3756
|
+
}) {
|
|
3550
3757
|
const update = (idx, change) => {
|
|
3551
3758
|
onChange(buttons.map((b, i) => i === idx ? { ...b, ...change } : b));
|
|
3552
3759
|
};
|
|
@@ -3589,10 +3796,10 @@ function ButtonsField({ buttons, onChange }) {
|
|
|
3589
3796
|
}
|
|
3590
3797
|
)
|
|
3591
3798
|
] }),
|
|
3592
|
-
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Label", htmlFor:
|
|
3799
|
+
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Label", htmlFor: `${idPrefix}-btn-label-${idx}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3593
3800
|
Input,
|
|
3594
3801
|
{
|
|
3595
|
-
id:
|
|
3802
|
+
id: `${idPrefix}-btn-label-${idx}`,
|
|
3596
3803
|
value: label,
|
|
3597
3804
|
placeholder: "e.g. Open",
|
|
3598
3805
|
onChange: (e) => update(idx, {
|
|
@@ -3609,11 +3816,11 @@ function ButtonsField({ buttons, onChange }) {
|
|
|
3609
3816
|
{
|
|
3610
3817
|
label: "Link URL",
|
|
3611
3818
|
help: "Optional. If set, the button opens this link.",
|
|
3612
|
-
htmlFor:
|
|
3819
|
+
htmlFor: `${idPrefix}-btn-url-${idx}`,
|
|
3613
3820
|
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3614
3821
|
Input,
|
|
3615
3822
|
{
|
|
3616
|
-
id:
|
|
3823
|
+
id: `${idPrefix}-btn-url-${idx}`,
|
|
3617
3824
|
type: "url",
|
|
3618
3825
|
value: url,
|
|
3619
3826
|
placeholder: "e.g. https://example.com",
|
|
@@ -3632,8 +3839,8 @@ function ButtonsField({ buttons, onChange }) {
|
|
|
3632
3839
|
},
|
|
3633
3840
|
className: "flex flex-row gap-3",
|
|
3634
3841
|
children: ["default", "primary", "danger"].map((s) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
3635
|
-
/* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: s, id:
|
|
3636
|
-
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor:
|
|
3842
|
+
/* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value: s, id: `${idPrefix}-btn-style-${idx}-${s}` }),
|
|
3843
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: `${idPrefix}-btn-style-${idx}-${s}`, className: "text-xs capitalize", children: s })
|
|
3637
3844
|
] }, s))
|
|
3638
3845
|
}
|
|
3639
3846
|
) })
|
|
@@ -3682,8 +3889,8 @@ function CarouselEditor({ block, onChange }) {
|
|
|
3682
3889
|
});
|
|
3683
3890
|
};
|
|
3684
3891
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
3685
|
-
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "Carousels hold 1-10 cards.
|
|
3686
|
-
elements.map((card, idx) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-
|
|
3892
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "Carousels hold 1-10 cards." }),
|
|
3893
|
+
elements.map((card, idx) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3 rounded-md border bg-muted/20 p-3", children: [
|
|
3687
3894
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between", children: [
|
|
3688
3895
|
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-medium text-foreground", children: [
|
|
3689
3896
|
"Card ",
|
|
@@ -3701,33 +3908,7 @@ function CarouselEditor({ block, onChange }) {
|
|
|
3701
3908
|
}
|
|
3702
3909
|
)
|
|
3703
3910
|
] }),
|
|
3704
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3705
|
-
Input,
|
|
3706
|
-
{
|
|
3707
|
-
id: `carousel-card-title-${idx}`,
|
|
3708
|
-
value: card.title?.text ?? "",
|
|
3709
|
-
maxLength: 150,
|
|
3710
|
-
placeholder: "e.g. Card title",
|
|
3711
|
-
onChange: (e) => updateCard(idx, {
|
|
3712
|
-
...card,
|
|
3713
|
-
title: e.target.value ? { type: "mrkdwn", text: e.target.value } : void 0
|
|
3714
|
-
})
|
|
3715
|
-
}
|
|
3716
|
-
) }),
|
|
3717
|
-
/* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Body", htmlFor: `carousel-card-body-${idx}`, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3718
|
-
Textarea,
|
|
3719
|
-
{
|
|
3720
|
-
id: `carousel-card-body-${idx}`,
|
|
3721
|
-
value: card.body?.text ?? "",
|
|
3722
|
-
maxLength: 200,
|
|
3723
|
-
rows: 2,
|
|
3724
|
-
placeholder: "e.g. Short card description.",
|
|
3725
|
-
onChange: (e) => updateCard(idx, {
|
|
3726
|
-
...card,
|
|
3727
|
-
body: e.target.value ? { type: "mrkdwn", text: e.target.value } : void 0
|
|
3728
|
-
})
|
|
3729
|
-
}
|
|
3730
|
-
) })
|
|
3911
|
+
/* @__PURE__ */ jsxRuntime.jsx(CardEditor, { block: card, idPrefix: `carousel-card-${idx}`, onChange: (next) => updateCard(idx, next) })
|
|
3731
3912
|
] }, idx)),
|
|
3732
3913
|
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: addCard, disabled: elements.length >= MAX_CARDS, className: "self-start", children: [
|
|
3733
3914
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-3.5 w-3.5" }),
|
|
@@ -4189,7 +4370,7 @@ function TextItemCard({
|
|
|
4189
4370
|
id: `ctx-text-${index}`,
|
|
4190
4371
|
value: element.text,
|
|
4191
4372
|
rows: 2,
|
|
4192
|
-
placeholder: "e.g. Posted by @
|
|
4373
|
+
placeholder: "e.g. Posted by @riley",
|
|
4193
4374
|
onChange: (e) => onChange({ ...element, text: e.target.value })
|
|
4194
4375
|
}
|
|
4195
4376
|
) }),
|
|
@@ -4274,7 +4455,7 @@ function ImageItemCard({
|
|
|
4274
4455
|
{
|
|
4275
4456
|
id: `ctx-img-alt-${index}`,
|
|
4276
4457
|
value: element.alt_text,
|
|
4277
|
-
placeholder: "e.g.
|
|
4458
|
+
placeholder: "e.g. Riley's avatar",
|
|
4278
4459
|
onChange: (e) => onChange({ ...element, alt_text: e.target.value })
|
|
4279
4460
|
}
|
|
4280
4461
|
) })
|
|
@@ -8607,6 +8788,8 @@ var SURFACE_DROPPABLE_ID = "builder-surface";
|
|
|
8607
8788
|
function Surface({
|
|
8608
8789
|
blocks,
|
|
8609
8790
|
workspaceName,
|
|
8791
|
+
authorName,
|
|
8792
|
+
authorIcon,
|
|
8610
8793
|
previewHooks,
|
|
8611
8794
|
previewTheme,
|
|
8612
8795
|
previewSurface = "message",
|
|
@@ -8682,16 +8865,20 @@ function Surface({
|
|
|
8682
8865
|
{
|
|
8683
8866
|
"aria-label": "Block preview",
|
|
8684
8867
|
className: cn("flex min-w-0 flex-1 flex-col overflow-y-auto bg-muted p-3 sm:p-6"),
|
|
8685
|
-
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 }) })
|
|
8868
|
+
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 }) })
|
|
8686
8869
|
}
|
|
8687
8870
|
);
|
|
8688
8871
|
}
|
|
8689
8872
|
function MessageFrame({
|
|
8690
8873
|
workspaceName,
|
|
8874
|
+
authorName,
|
|
8875
|
+
authorIcon,
|
|
8691
8876
|
isDark,
|
|
8692
8877
|
children
|
|
8693
8878
|
}) {
|
|
8694
|
-
const
|
|
8879
|
+
const displayName = authorName ?? workspaceName ?? "Your app";
|
|
8880
|
+
const initial = displayName.slice(0, 1).toUpperCase();
|
|
8881
|
+
const safeIcon = authorIcon && isSafeImageSrc(authorIcon) ? authorIcon : null;
|
|
8695
8882
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8696
8883
|
"div",
|
|
8697
8884
|
{
|
|
@@ -8705,7 +8892,7 @@ function MessageFrame({
|
|
|
8705
8892
|
{
|
|
8706
8893
|
className: cn("flex items-center gap-2 px-5 pt-3 pb-1 text-xs", isDark ? "text-white/60" : "text-[#616061]"),
|
|
8707
8894
|
children: [
|
|
8708
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8895
|
+
safeIcon ? /* @__PURE__ */ jsxRuntime.jsx("img", { src: safeIcon, alt: "", className: "h-7 w-7 shrink-0 rounded object-cover" }) : /* @__PURE__ */ jsxRuntime.jsx(
|
|
8709
8896
|
"span",
|
|
8710
8897
|
{
|
|
8711
8898
|
className: cn(
|
|
@@ -8715,17 +8902,7 @@ function MessageFrame({
|
|
|
8715
8902
|
children: initial
|
|
8716
8903
|
}
|
|
8717
8904
|
),
|
|
8718
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-bold text-sm", isDark ? "text-white" : "text-[#1d1c1d]"), children:
|
|
8719
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8720
|
-
"span",
|
|
8721
|
-
{
|
|
8722
|
-
className: cn(
|
|
8723
|
-
"rounded px-1 text-[10px] font-semibold",
|
|
8724
|
-
isDark ? "bg-white/10 text-white/70" : "bg-[#f3f3f3] text-[#616061]"
|
|
8725
|
-
),
|
|
8726
|
-
children: "APP"
|
|
8727
|
-
}
|
|
8728
|
-
),
|
|
8905
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: cn("font-bold text-sm", isDark ? "text-white" : "text-[#1d1c1d]"), children: displayName }),
|
|
8729
8906
|
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "10:37 AM" })
|
|
8730
8907
|
]
|
|
8731
8908
|
}
|
|
@@ -8927,6 +9104,14 @@ var SURFACE_OPTIONS = [
|
|
|
8927
9104
|
];
|
|
8928
9105
|
var DEFAULT_DOCS_HREF = "https://docs.slack.dev/reference/block-kit/blocks";
|
|
8929
9106
|
var DEFAULT_DOCS_LABEL = "Docs";
|
|
9107
|
+
function formatMessageTs(ts) {
|
|
9108
|
+
const seconds = Number.parseFloat(ts);
|
|
9109
|
+
if (!Number.isFinite(seconds)) return ts;
|
|
9110
|
+
const date = new Date(seconds * 1e3);
|
|
9111
|
+
if (Number.isNaN(date.getTime())) return ts;
|
|
9112
|
+
return date.toLocaleString(void 0, { dateStyle: "medium", timeStyle: "short" });
|
|
9113
|
+
}
|
|
9114
|
+
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";
|
|
8930
9115
|
function Toolbar2({
|
|
8931
9116
|
onClear,
|
|
8932
9117
|
onOpenJson,
|
|
@@ -8943,7 +9128,14 @@ function Toolbar2({
|
|
|
8943
9128
|
showThemeControl = true,
|
|
8944
9129
|
docsLink,
|
|
8945
9130
|
errorCount,
|
|
8946
|
-
sendButtonLabel = "
|
|
9131
|
+
sendButtonLabel = "Review & send",
|
|
9132
|
+
editingEnabled = false,
|
|
9133
|
+
editBadge,
|
|
9134
|
+
onOpenLoad,
|
|
9135
|
+
onOpenUpdate,
|
|
9136
|
+
onExitEdit,
|
|
9137
|
+
loadButtonLabel = "Load message",
|
|
9138
|
+
updateButtonLabel = "Review & update"
|
|
8947
9139
|
}) {
|
|
8948
9140
|
const activeTheme = THEME_OPTIONS.find((t) => t.value === previewTheme) ?? THEME_OPTIONS[0];
|
|
8949
9141
|
const activeSurface = SURFACE_OPTIONS.find((s) => s.value === previewSurface) ?? SURFACE_OPTIONS[0];
|
|
@@ -8953,184 +9145,210 @@ function Toolbar2({
|
|
|
8953
9145
|
const docsLabel = docsLink === false ? null : docsLink?.label ?? DEFAULT_DOCS_LABEL;
|
|
8954
9146
|
const [surfaceMenuOpen, setSurfaceMenuOpen] = React.useState(false);
|
|
8955
9147
|
const [themeMenuOpen, setThemeMenuOpen] = React.useState(false);
|
|
8956
|
-
const [
|
|
8957
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8958
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex
|
|
8959
|
-
|
|
8960
|
-
Button,
|
|
8961
|
-
|
|
8962
|
-
|
|
8963
|
-
|
|
8964
|
-
|
|
8965
|
-
|
|
8966
|
-
className: "md:hidden",
|
|
8967
|
-
"aria-label": "Add a block",
|
|
8968
|
-
children: [
|
|
8969
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4" }),
|
|
8970
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Blocks" })
|
|
8971
|
-
]
|
|
8972
|
-
}
|
|
8973
|
-
) : null,
|
|
8974
|
-
showSurfaceControl ? /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: surfaceMenuOpen, onOpenChange: setSurfaceMenuOpen, children: [
|
|
8975
|
-
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": `Preview surface: ${activeSurface.label}`, children: [
|
|
8976
|
-
/* @__PURE__ */ jsxRuntime.jsx(activeSurface.Icon, { className: "h-3.5 w-3.5" }),
|
|
8977
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: activeSurface.label }),
|
|
8978
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3.5 w-3.5 opacity-60" })
|
|
8979
|
-
] }) }),
|
|
8980
|
-
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { align: "start", className: "w-36 p-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8981
|
-
Menu,
|
|
9148
|
+
const [sendMenuOpen, setSendMenuOpen] = React.useState(false);
|
|
9149
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9150
|
+
/* @__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: [
|
|
9151
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 flex-1 items-center gap-1 sm:gap-2", children: [
|
|
9152
|
+
editingEnabled && !editBadge ? /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: onOpenLoad, "aria-label": loadButtonLabel, children: [
|
|
9153
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-3.5 w-3.5" }),
|
|
9154
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: loadButtonLabel })
|
|
9155
|
+
] }) : null,
|
|
9156
|
+
onOpenPalette ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9157
|
+
Button,
|
|
8982
9158
|
{
|
|
8983
|
-
|
|
8984
|
-
|
|
8985
|
-
|
|
8986
|
-
|
|
8987
|
-
|
|
8988
|
-
|
|
9159
|
+
type: "button",
|
|
9160
|
+
variant: "ghost",
|
|
9161
|
+
size: "sm",
|
|
9162
|
+
onClick: onOpenPalette,
|
|
9163
|
+
className: "md:hidden",
|
|
9164
|
+
"aria-label": "Add a block",
|
|
9165
|
+
children: [
|
|
9166
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Plus, { className: "h-4 w-4" }),
|
|
9167
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { children: "Blocks" })
|
|
9168
|
+
]
|
|
9169
|
+
}
|
|
9170
|
+
) : null,
|
|
9171
|
+
showSurfaceControl ? /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: surfaceMenuOpen, onOpenChange: setSurfaceMenuOpen, children: [
|
|
9172
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": `Preview surface: ${activeSurface.label}`, children: [
|
|
9173
|
+
/* @__PURE__ */ jsxRuntime.jsx(activeSurface.Icon, { className: "h-3.5 w-3.5" }),
|
|
9174
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: activeSurface.label }),
|
|
9175
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "hidden h-3.5 w-3.5 opacity-60 md:inline" })
|
|
9176
|
+
] }) }),
|
|
9177
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { align: "start", className: "w-36 p-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9178
|
+
Menu,
|
|
9179
|
+
{
|
|
9180
|
+
ariaLabel: "Preview surface",
|
|
9181
|
+
options: surfaceOptions,
|
|
9182
|
+
value: previewSurface,
|
|
9183
|
+
onChange: (next) => {
|
|
9184
|
+
onPreviewSurfaceChange(next);
|
|
9185
|
+
setSurfaceMenuOpen(false);
|
|
9186
|
+
}
|
|
9187
|
+
}
|
|
9188
|
+
) })
|
|
9189
|
+
] }) : null,
|
|
9190
|
+
showThemeControl ? /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: themeMenuOpen, onOpenChange: setThemeMenuOpen, children: [
|
|
9191
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", size: "sm", "aria-label": `Preview theme: ${activeTheme.label}`, children: [
|
|
9192
|
+
/* @__PURE__ */ jsxRuntime.jsx(activeTheme.Icon, { className: "h-3.5 w-3.5" }),
|
|
9193
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: activeTheme.label }),
|
|
9194
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3.5 w-3.5 opacity-60" })
|
|
9195
|
+
] }) }),
|
|
9196
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { align: "start", className: "w-32 p-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9197
|
+
Menu,
|
|
9198
|
+
{
|
|
9199
|
+
ariaLabel: "Preview theme",
|
|
9200
|
+
options: THEME_OPTIONS,
|
|
9201
|
+
value: previewTheme,
|
|
9202
|
+
onChange: (next) => {
|
|
9203
|
+
onPreviewThemeChange(next);
|
|
9204
|
+
setThemeMenuOpen(false);
|
|
9205
|
+
}
|
|
8989
9206
|
}
|
|
9207
|
+
) })
|
|
9208
|
+
] }) : null,
|
|
9209
|
+
docsHref ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9210
|
+
"a",
|
|
9211
|
+
{
|
|
9212
|
+
href: docsHref,
|
|
9213
|
+
target: "_blank",
|
|
9214
|
+
rel: "noreferrer noopener",
|
|
9215
|
+
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",
|
|
9216
|
+
"aria-label": `${docsLabel} (opens in a new tab)`,
|
|
9217
|
+
children: [
|
|
9218
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BookOpen, { className: "h-3.5 w-3.5" }),
|
|
9219
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: docsLabel }),
|
|
9220
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "hidden h-3 w-3 opacity-50 md:inline" })
|
|
9221
|
+
]
|
|
8990
9222
|
}
|
|
8991
|
-
)
|
|
8992
|
-
] })
|
|
8993
|
-
|
|
8994
|
-
|
|
8995
|
-
|
|
8996
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: activeTheme.label }),
|
|
8997
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3.5 w-3.5 opacity-60" })
|
|
8998
|
-
] }) }),
|
|
8999
|
-
/* @__PURE__ */ jsxRuntime.jsx(PopoverContent, { align: "start", className: "w-32 p-1", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9000
|
-
Menu,
|
|
9223
|
+
) : null
|
|
9224
|
+
] }),
|
|
9225
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 sm:gap-2", children: [
|
|
9226
|
+
errorCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9227
|
+
Button,
|
|
9001
9228
|
{
|
|
9002
|
-
|
|
9003
|
-
|
|
9004
|
-
|
|
9005
|
-
|
|
9006
|
-
|
|
9007
|
-
|
|
9008
|
-
|
|
9229
|
+
type: "button",
|
|
9230
|
+
variant: "ghost",
|
|
9231
|
+
size: "sm",
|
|
9232
|
+
onClick: onOpenIssues,
|
|
9233
|
+
className: "border border-red-200! bg-red-50 text-red-700 hover:bg-red-100 hover:text-red-700",
|
|
9234
|
+
"aria-label": `${errorCount} ${errorCount === 1 ? "issue" : "issues"}`,
|
|
9235
|
+
children: [
|
|
9236
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5" }),
|
|
9237
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
9238
|
+
errorCount,
|
|
9239
|
+
" ",
|
|
9240
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: errorCount === 1 ? "issue" : "issues" })
|
|
9241
|
+
] })
|
|
9242
|
+
]
|
|
9009
9243
|
}
|
|
9010
|
-
)
|
|
9011
|
-
|
|
9012
|
-
docsHref ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9013
|
-
"a",
|
|
9014
|
-
{
|
|
9015
|
-
href: docsHref,
|
|
9016
|
-
target: "_blank",
|
|
9017
|
-
rel: "noreferrer noopener",
|
|
9018
|
-
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",
|
|
9019
|
-
"aria-label": `${docsLabel} (opens in a new tab)`,
|
|
9020
|
-
children: [
|
|
9021
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.BookOpen, { className: "h-3.5 w-3.5" }),
|
|
9022
|
-
docsLabel,
|
|
9023
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-3 w-3 opacity-50" })
|
|
9024
|
-
]
|
|
9025
|
-
}
|
|
9026
|
-
) : null
|
|
9027
|
-
] }),
|
|
9028
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1 sm:gap-2", children: [
|
|
9029
|
-
errorCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9030
|
-
Button,
|
|
9031
|
-
{
|
|
9032
|
-
type: "button",
|
|
9033
|
-
variant: "ghost",
|
|
9034
|
-
size: "sm",
|
|
9035
|
-
onClick: onOpenIssues,
|
|
9036
|
-
className: "border border-red-200! bg-red-50 text-red-700 hover:bg-red-100 hover:text-red-700",
|
|
9037
|
-
"aria-label": `${errorCount} ${errorCount === 1 ? "issue" : "issues"}`,
|
|
9038
|
-
children: [
|
|
9039
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5" }),
|
|
9040
|
-
/* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
9041
|
-
errorCount,
|
|
9042
|
-
" ",
|
|
9043
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden sm:inline", children: errorCount === 1 ? "issue" : "issues" })
|
|
9044
|
-
] })
|
|
9045
|
-
]
|
|
9046
|
-
}
|
|
9047
|
-
) : null,
|
|
9048
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9049
|
-
Button,
|
|
9050
|
-
{
|
|
9051
|
-
type: "button",
|
|
9052
|
-
variant: "ghost",
|
|
9053
|
-
size: "sm",
|
|
9054
|
-
onClick: onClear,
|
|
9055
|
-
disabled: !canClear,
|
|
9056
|
-
className: "hidden hover:bg-destructive/10 hover:text-destructive sm:inline-flex",
|
|
9057
|
-
"aria-label": "Clear all blocks",
|
|
9058
|
-
children: [
|
|
9059
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" }),
|
|
9060
|
-
"Clear"
|
|
9061
|
-
]
|
|
9062
|
-
}
|
|
9063
|
-
),
|
|
9064
|
-
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9065
|
-
Button,
|
|
9066
|
-
{
|
|
9067
|
-
type: "button",
|
|
9068
|
-
variant: "ghost",
|
|
9069
|
-
size: "sm",
|
|
9070
|
-
onClick: onOpenJson,
|
|
9071
|
-
"aria-label": "View JSON",
|
|
9072
|
-
className: "hidden sm:inline-flex",
|
|
9073
|
-
children: [
|
|
9074
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { className: "h-3.5 w-3.5" }),
|
|
9075
|
-
"View JSON"
|
|
9076
|
-
]
|
|
9077
|
-
}
|
|
9078
|
-
),
|
|
9079
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: moreMenuOpen, onOpenChange: setMoreMenuOpen, children: [
|
|
9080
|
-
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9244
|
+
) : null,
|
|
9245
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9081
9246
|
Button,
|
|
9082
9247
|
{
|
|
9083
9248
|
type: "button",
|
|
9084
9249
|
variant: "ghost",
|
|
9085
9250
|
size: "sm",
|
|
9086
|
-
|
|
9087
|
-
|
|
9088
|
-
className: "
|
|
9089
|
-
|
|
9251
|
+
onClick: onClear,
|
|
9252
|
+
disabled: !canClear,
|
|
9253
|
+
className: "hover:bg-destructive/10 hover:text-destructive",
|
|
9254
|
+
"aria-label": "Clear all blocks",
|
|
9255
|
+
children: [
|
|
9256
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Trash2, { className: "h-3.5 w-3.5" }),
|
|
9257
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: "Clear" })
|
|
9258
|
+
]
|
|
9090
9259
|
}
|
|
9091
|
-
)
|
|
9092
|
-
/* @__PURE__ */ jsxRuntime.
|
|
9093
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9094
|
-
|
|
9095
|
-
|
|
9096
|
-
|
|
9097
|
-
|
|
9098
|
-
|
|
9099
|
-
|
|
9100
|
-
|
|
9101
|
-
|
|
9102
|
-
|
|
9103
|
-
|
|
9104
|
-
|
|
9105
|
-
|
|
9106
|
-
|
|
9107
|
-
|
|
9108
|
-
|
|
9109
|
-
|
|
9110
|
-
|
|
9111
|
-
|
|
9112
|
-
|
|
9113
|
-
}
|
|
9114
|
-
|
|
9115
|
-
|
|
9116
|
-
|
|
9117
|
-
|
|
9118
|
-
|
|
9119
|
-
|
|
9120
|
-
|
|
9121
|
-
|
|
9122
|
-
|
|
9123
|
-
|
|
9124
|
-
|
|
9125
|
-
|
|
9126
|
-
|
|
9127
|
-
|
|
9260
|
+
),
|
|
9261
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", size: "sm", onClick: onOpenJson, "aria-label": "View JSON", children: [
|
|
9262
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Code2, { className: "h-3.5 w-3.5" }),
|
|
9263
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: "View JSON" })
|
|
9264
|
+
] }),
|
|
9265
|
+
editBadge ? (
|
|
9266
|
+
// A message is loaded: split button. Main action updates it in
|
|
9267
|
+
// place; the menu also offers posting the blocks as a new message.
|
|
9268
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-stretch", children: [
|
|
9269
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9270
|
+
Button,
|
|
9271
|
+
{
|
|
9272
|
+
type: "button",
|
|
9273
|
+
size: "sm",
|
|
9274
|
+
onClick: onOpenUpdate,
|
|
9275
|
+
disabled: !canSend,
|
|
9276
|
+
"aria-label": updateButtonLabel,
|
|
9277
|
+
className: "rounded-r-none",
|
|
9278
|
+
children: [
|
|
9279
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-3.5 w-3.5" }),
|
|
9280
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: updateButtonLabel })
|
|
9281
|
+
]
|
|
9282
|
+
}
|
|
9283
|
+
),
|
|
9284
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Popover, { open: sendMenuOpen, onOpenChange: setSendMenuOpen, children: [
|
|
9285
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
9286
|
+
Button,
|
|
9287
|
+
{
|
|
9288
|
+
type: "button",
|
|
9289
|
+
size: "sm",
|
|
9290
|
+
"aria-label": "More message options",
|
|
9291
|
+
"aria-haspopup": "menu",
|
|
9292
|
+
className: "rounded-l-none border-l border-l-primary-foreground/30! px-1.5",
|
|
9293
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDown, { className: "h-3.5 w-3.5" })
|
|
9294
|
+
}
|
|
9295
|
+
) }),
|
|
9296
|
+
/* @__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: [
|
|
9297
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9298
|
+
"button",
|
|
9299
|
+
{
|
|
9300
|
+
type: "button",
|
|
9301
|
+
role: "menuitem",
|
|
9302
|
+
disabled: !canSend,
|
|
9303
|
+
onClick: () => {
|
|
9304
|
+
setSendMenuOpen(false);
|
|
9305
|
+
onOpenUpdate?.();
|
|
9306
|
+
},
|
|
9307
|
+
className: SEND_MENU_ITEM,
|
|
9308
|
+
children: [
|
|
9309
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-3.5 w-3.5" }),
|
|
9310
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "Update message" })
|
|
9311
|
+
]
|
|
9312
|
+
}
|
|
9313
|
+
),
|
|
9314
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9315
|
+
"button",
|
|
9316
|
+
{
|
|
9317
|
+
type: "button",
|
|
9318
|
+
role: "menuitem",
|
|
9319
|
+
disabled: !canSend,
|
|
9320
|
+
onClick: () => {
|
|
9321
|
+
setSendMenuOpen(false);
|
|
9322
|
+
onOpenSend();
|
|
9323
|
+
},
|
|
9324
|
+
className: SEND_MENU_ITEM,
|
|
9325
|
+
children: [
|
|
9326
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3.5 w-3.5" }),
|
|
9327
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children: "Send as a new message" })
|
|
9328
|
+
]
|
|
9329
|
+
}
|
|
9330
|
+
)
|
|
9331
|
+
] }) })
|
|
9332
|
+
] })
|
|
9333
|
+
] })
|
|
9334
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick: onOpenSend, disabled: !canSend, "aria-label": sendButtonLabel, children: [
|
|
9335
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Send, { className: "h-3.5 w-3.5" }),
|
|
9336
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "hidden md:inline", children: sendButtonLabel })
|
|
9337
|
+
] })
|
|
9338
|
+
] })
|
|
9339
|
+
] }),
|
|
9340
|
+
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: [
|
|
9341
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Pencil, { className: "h-4 w-4 shrink-0 text-primary" }),
|
|
9342
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 flex-1 text-sm", children: [
|
|
9343
|
+
"References an existing message in ",
|
|
9344
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold", children: editBadge.channelLabel }),
|
|
9345
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-1 text-xs opacity-70", title: editBadge.ts, children: formatMessageTs(editBadge.ts) })
|
|
9128
9346
|
] }),
|
|
9129
|
-
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", size: "sm", onClick:
|
|
9130
|
-
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.
|
|
9131
|
-
|
|
9347
|
+
/* @__PURE__ */ jsxRuntime.jsxs(Button, { type: "button", variant: "ghost", size: "sm", onClick: onExitEdit, className: "shrink-0", children: [
|
|
9348
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.X, { className: "h-3.5 w-3.5" }),
|
|
9349
|
+
"Switch to a new message"
|
|
9132
9350
|
] })
|
|
9133
|
-
] })
|
|
9351
|
+
] }) : null
|
|
9134
9352
|
] });
|
|
9135
9353
|
}
|
|
9136
9354
|
function Menu({
|
|
@@ -9188,52 +9406,132 @@ function Menu({
|
|
|
9188
9406
|
);
|
|
9189
9407
|
}) });
|
|
9190
9408
|
}
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9409
|
+
function UpdateDialog({
|
|
9410
|
+
open,
|
|
9411
|
+
onOpenChange,
|
|
9412
|
+
target,
|
|
9413
|
+
blocks,
|
|
9414
|
+
loadSendAsUserStatus,
|
|
9415
|
+
onUpdate,
|
|
9416
|
+
confirmUpdateLabel = "Update message",
|
|
9417
|
+
errorCount,
|
|
9418
|
+
onShowIssues
|
|
9198
9419
|
}) {
|
|
9199
|
-
|
|
9200
|
-
|
|
9201
|
-
|
|
9202
|
-
|
|
9203
|
-
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
|
|
9210
|
-
|
|
9420
|
+
const asUser = target.editableVia === "user";
|
|
9421
|
+
const [userStatus, setUserStatus] = React.useState(null);
|
|
9422
|
+
const [status, setStatus] = React.useState({ kind: "idle" });
|
|
9423
|
+
const loadSendAsUserStatusRef = React.useRef(loadSendAsUserStatus);
|
|
9424
|
+
React.useEffect(() => {
|
|
9425
|
+
loadSendAsUserStatusRef.current = loadSendAsUserStatus;
|
|
9426
|
+
});
|
|
9427
|
+
const refreshSendAsUser = React.useCallback(() => {
|
|
9428
|
+
loadSendAsUserStatusRef.current().then(setUserStatus).catch(() => setUserStatus({ canSendAsUser: false }));
|
|
9429
|
+
}, []);
|
|
9430
|
+
React.useEffect(() => {
|
|
9431
|
+
if (!open) {
|
|
9432
|
+
return;
|
|
9211
9433
|
}
|
|
9212
|
-
|
|
9213
|
-
|
|
9214
|
-
|
|
9215
|
-
|
|
9216
|
-
icon,
|
|
9217
|
-
trailingIcon,
|
|
9218
|
-
children,
|
|
9219
|
-
onSelect
|
|
9220
|
-
}) {
|
|
9221
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9222
|
-
"a",
|
|
9223
|
-
{
|
|
9224
|
-
role: "menuitem",
|
|
9225
|
-
href,
|
|
9226
|
-
target: "_blank",
|
|
9227
|
-
rel: "noreferrer noopener",
|
|
9228
|
-
onClick: onSelect,
|
|
9229
|
-
className: ACTION_ITEM_BASE,
|
|
9230
|
-
children: [
|
|
9231
|
-
icon,
|
|
9232
|
-
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex-1", children }),
|
|
9233
|
-
trailingIcon
|
|
9234
|
-
]
|
|
9434
|
+
setStatus({ kind: "idle" });
|
|
9435
|
+
if (asUser) {
|
|
9436
|
+
setUserStatus(null);
|
|
9437
|
+
refreshSendAsUser();
|
|
9235
9438
|
}
|
|
9236
|
-
);
|
|
9439
|
+
}, [open, asUser, refreshSendAsUser]);
|
|
9440
|
+
React.useEffect(() => {
|
|
9441
|
+
if (!open || !asUser) {
|
|
9442
|
+
return;
|
|
9443
|
+
}
|
|
9444
|
+
const handler = () => refreshSendAsUser();
|
|
9445
|
+
window.addEventListener("focus", handler);
|
|
9446
|
+
return () => window.removeEventListener("focus", handler);
|
|
9447
|
+
}, [open, asUser, refreshSendAsUser]);
|
|
9448
|
+
const needsSignIn = asUser && userStatus !== null && !userStatus.canSendAsUser;
|
|
9449
|
+
const handleSubmit = async () => {
|
|
9450
|
+
setStatus({ kind: "updating" });
|
|
9451
|
+
try {
|
|
9452
|
+
const result = await onUpdate({
|
|
9453
|
+
channelId: target.channelId,
|
|
9454
|
+
ts: target.ts,
|
|
9455
|
+
blocks: toSlackBlocks(blocks),
|
|
9456
|
+
asUser
|
|
9457
|
+
});
|
|
9458
|
+
if (result.ok) {
|
|
9459
|
+
setStatus({ kind: "idle" });
|
|
9460
|
+
onOpenChange(false);
|
|
9461
|
+
return;
|
|
9462
|
+
}
|
|
9463
|
+
setStatus({ kind: "error", error: result.error ?? "Update failed." });
|
|
9464
|
+
} catch (e) {
|
|
9465
|
+
setStatus({ kind: "error", error: e instanceof Error ? e.message : "Update failed." });
|
|
9466
|
+
}
|
|
9467
|
+
};
|
|
9468
|
+
const channelLabel = target.channelName ? `#${target.channelName}` : target.channelId;
|
|
9469
|
+
return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "w-[calc(100vw-1.5rem)] max-w-lg rounded-lg", children: [
|
|
9470
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
|
|
9471
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Update message" }),
|
|
9472
|
+
/* @__PURE__ */ jsxRuntime.jsx(DialogDescription, { children: "This replaces the message that's already posted. It stays in the same channel and can't be moved." })
|
|
9473
|
+
] }),
|
|
9474
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
9475
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
9476
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Channel" }),
|
|
9477
|
+
/* @__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 })
|
|
9478
|
+
] }),
|
|
9479
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
9480
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Posting as" }),
|
|
9481
|
+
/* @__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" }),
|
|
9482
|
+
needsSignIn && userStatus?.oauthUrl && isSafeHref(userStatus.oauthUrl) && /* @__PURE__ */ jsxRuntime.jsxs("p", { className: "text-xs text-muted-foreground", children: [
|
|
9483
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
9484
|
+
"a",
|
|
9485
|
+
{
|
|
9486
|
+
href: userStatus.oauthUrl,
|
|
9487
|
+
target: "_blank",
|
|
9488
|
+
rel: "noopener noreferrer",
|
|
9489
|
+
className: "inline-flex items-center gap-1 text-primary hover:underline",
|
|
9490
|
+
children: [
|
|
9491
|
+
"Sign in with Slack ",
|
|
9492
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ExternalLink, { className: "h-3 w-3" })
|
|
9493
|
+
]
|
|
9494
|
+
}
|
|
9495
|
+
),
|
|
9496
|
+
" ",
|
|
9497
|
+
"to update your own message."
|
|
9498
|
+
] }),
|
|
9499
|
+
needsSignIn && !userStatus?.oauthUrl && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Sign in with Slack to update your own message." })
|
|
9500
|
+
] }),
|
|
9501
|
+
errorCount > 0 ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9502
|
+
"button",
|
|
9503
|
+
{
|
|
9504
|
+
type: "button",
|
|
9505
|
+
onClick: onShowIssues,
|
|
9506
|
+
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",
|
|
9507
|
+
children: [
|
|
9508
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.AlertTriangle, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
9509
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "flex-1", children: [
|
|
9510
|
+
"Fix ",
|
|
9511
|
+
errorCount,
|
|
9512
|
+
" ",
|
|
9513
|
+
errorCount === 1 ? "issue" : "issues",
|
|
9514
|
+
" before updating."
|
|
9515
|
+
] }),
|
|
9516
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0 underline", children: "Show issues" })
|
|
9517
|
+
]
|
|
9518
|
+
}
|
|
9519
|
+
) : null,
|
|
9520
|
+
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 })
|
|
9521
|
+
] }),
|
|
9522
|
+
/* @__PURE__ */ jsxRuntime.jsxs(DialogFooter, { children: [
|
|
9523
|
+
/* @__PURE__ */ jsxRuntime.jsx(Button, { type: "button", variant: "ghost", onClick: () => onOpenChange(false), children: "Cancel" }),
|
|
9524
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9525
|
+
Button,
|
|
9526
|
+
{
|
|
9527
|
+
type: "button",
|
|
9528
|
+
onClick: handleSubmit,
|
|
9529
|
+
disabled: status.kind === "updating" || blocks.length === 0 || errorCount > 0 || needsSignIn,
|
|
9530
|
+
children: status.kind === "updating" ? "Updating\u2026" : confirmUpdateLabel
|
|
9531
|
+
}
|
|
9532
|
+
)
|
|
9533
|
+
] })
|
|
9534
|
+
] }) });
|
|
9237
9535
|
}
|
|
9238
9536
|
function BlockKitchen(props) {
|
|
9239
9537
|
const {
|
|
@@ -9245,6 +9543,10 @@ function BlockKitchen(props) {
|
|
|
9245
9543
|
loadChannels,
|
|
9246
9544
|
loadSendAsUserStatus,
|
|
9247
9545
|
onSend,
|
|
9546
|
+
editing,
|
|
9547
|
+
loadButtonLabel,
|
|
9548
|
+
updateButtonLabel,
|
|
9549
|
+
confirmUpdateLabel,
|
|
9248
9550
|
palette,
|
|
9249
9551
|
disabledBlockTypes,
|
|
9250
9552
|
showPaletteSearch,
|
|
@@ -9290,6 +9592,10 @@ function BlockKitchen(props) {
|
|
|
9290
9592
|
}, [blocks]);
|
|
9291
9593
|
const [jsonOpen, setJsonOpen] = React.useState(false);
|
|
9292
9594
|
const [sendOpen, setSendOpen] = React.useState(false);
|
|
9595
|
+
const [updateOpen, setUpdateOpen] = React.useState(false);
|
|
9596
|
+
const [loadOpen, setLoadOpen] = React.useState(false);
|
|
9597
|
+
const [editTarget, setEditTarget] = React.useState(null);
|
|
9598
|
+
const activeEditTarget = editing ? editTarget : null;
|
|
9293
9599
|
const [issuesOpen, setIssuesOpen] = React.useState(false);
|
|
9294
9600
|
const [paletteOpen, setPaletteOpen] = React.useState(false);
|
|
9295
9601
|
const [openBlockId, setOpenBlockId] = React.useState(null);
|
|
@@ -9410,7 +9716,21 @@ function BlockKitchen(props) {
|
|
|
9410
9716
|
allowedSurfaces,
|
|
9411
9717
|
showThemeControl: isPreviewThemeControlled ? false : showThemeControl,
|
|
9412
9718
|
docsLink,
|
|
9413
|
-
sendButtonLabel
|
|
9719
|
+
sendButtonLabel,
|
|
9720
|
+
editingEnabled: !!editing,
|
|
9721
|
+
editBadge: activeEditTarget ? {
|
|
9722
|
+
channelLabel: activeEditTarget.channelName ? `#${activeEditTarget.channelName}` : activeEditTarget.channelId,
|
|
9723
|
+
ts: activeEditTarget.ts
|
|
9724
|
+
} : null,
|
|
9725
|
+
onOpenLoad: () => setLoadOpen(true),
|
|
9726
|
+
onOpenUpdate: () => setUpdateOpen(true),
|
|
9727
|
+
onExitEdit: () => {
|
|
9728
|
+
setEditTarget(null);
|
|
9729
|
+
replaceAll([]);
|
|
9730
|
+
setLoadOpen(true);
|
|
9731
|
+
},
|
|
9732
|
+
loadButtonLabel,
|
|
9733
|
+
updateButtonLabel
|
|
9414
9734
|
}
|
|
9415
9735
|
),
|
|
9416
9736
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-0 flex-1 items-stretch", children: [
|
|
@@ -9429,6 +9749,8 @@ function BlockKitchen(props) {
|
|
|
9429
9749
|
{
|
|
9430
9750
|
blocks,
|
|
9431
9751
|
workspaceName,
|
|
9752
|
+
authorName: activeEditTarget?.username,
|
|
9753
|
+
authorIcon: activeEditTarget?.iconUrl,
|
|
9432
9754
|
previewHooks: mergedPreviewHooks,
|
|
9433
9755
|
previewTheme,
|
|
9434
9756
|
previewSurface,
|
|
@@ -9494,6 +9816,52 @@ function BlockKitchen(props) {
|
|
|
9494
9816
|
}
|
|
9495
9817
|
}
|
|
9496
9818
|
),
|
|
9819
|
+
activeEditTarget && editing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
9820
|
+
UpdateDialog,
|
|
9821
|
+
{
|
|
9822
|
+
open: updateOpen,
|
|
9823
|
+
onOpenChange: setUpdateOpen,
|
|
9824
|
+
target: activeEditTarget,
|
|
9825
|
+
blocks: blockPayloads,
|
|
9826
|
+
loadSendAsUserStatus,
|
|
9827
|
+
onUpdate: editing.onUpdate,
|
|
9828
|
+
confirmUpdateLabel,
|
|
9829
|
+
errorCount: validation.total,
|
|
9830
|
+
onShowIssues: () => {
|
|
9831
|
+
setUpdateOpen(false);
|
|
9832
|
+
setIssuesOpen(true);
|
|
9833
|
+
}
|
|
9834
|
+
}
|
|
9835
|
+
) : null,
|
|
9836
|
+
editing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
9837
|
+
LoadMessageDialog,
|
|
9838
|
+
{
|
|
9839
|
+
open: loadOpen,
|
|
9840
|
+
onOpenChange: setLoadOpen,
|
|
9841
|
+
onLoadMessage: editing.onLoadMessage,
|
|
9842
|
+
loadRecentMessages: editing.loadRecentMessages,
|
|
9843
|
+
onLoaded: (result) => {
|
|
9844
|
+
replaceAll(result.blocks);
|
|
9845
|
+
setEditTarget({
|
|
9846
|
+
channelId: result.channelId,
|
|
9847
|
+
channelName: result.channelName,
|
|
9848
|
+
ts: result.ts,
|
|
9849
|
+
editableVia: result.editableVia,
|
|
9850
|
+
workspaceName: result.workspaceName,
|
|
9851
|
+
username: result.username,
|
|
9852
|
+
iconUrl: result.iconUrl
|
|
9853
|
+
});
|
|
9854
|
+
setLoadOpen(false);
|
|
9855
|
+
},
|
|
9856
|
+
onOpenAsNew: (loadedBlocks) => {
|
|
9857
|
+
if (loadedBlocks) {
|
|
9858
|
+
replaceAll(loadedBlocks);
|
|
9859
|
+
}
|
|
9860
|
+
setEditTarget(null);
|
|
9861
|
+
setLoadOpen(false);
|
|
9862
|
+
}
|
|
9863
|
+
}
|
|
9864
|
+
) : null,
|
|
9497
9865
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9498
9866
|
IssuesSheet,
|
|
9499
9867
|
{
|