@tightknitai/block-kitchen 0.10.8 → 0.10.10
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/dist/index.cjs +311 -51
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +314 -54
- package/dist/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -14,10 +14,10 @@ var nanoid = require('nanoid');
|
|
|
14
14
|
var reactSlot = require('@radix-ui/react-slot');
|
|
15
15
|
var classVarianceAuthority = require('class-variance-authority');
|
|
16
16
|
var LabelPrimitive = require('@radix-ui/react-label');
|
|
17
|
+
var PopoverPrimitive = require('@radix-ui/react-popover');
|
|
17
18
|
require('slack-blocks-to-jsx/dist/style.css');
|
|
18
19
|
var slackBlocksToJsx = require('slack-blocks-to-jsx');
|
|
19
20
|
var utilities = require('@dnd-kit/utilities');
|
|
20
|
-
var PopoverPrimitive = require('@radix-ui/react-popover');
|
|
21
21
|
var RadioGroupPrimitive = require('@radix-ui/react-radio-group');
|
|
22
22
|
var Link = require('@tiptap/extension-link');
|
|
23
23
|
var react = require('@tiptap/react');
|
|
@@ -53,6 +53,11 @@ var Link__default = /*#__PURE__*/_interopDefault(Link);
|
|
|
53
53
|
var StarterKit__default = /*#__PURE__*/_interopDefault(StarterKit);
|
|
54
54
|
|
|
55
55
|
// src/components/block-kitchen.tsx
|
|
56
|
+
|
|
57
|
+
// src/lib/channel-label.ts
|
|
58
|
+
function channelLabel(name) {
|
|
59
|
+
return `# ${name}`;
|
|
60
|
+
}
|
|
56
61
|
function cn(...inputs) {
|
|
57
62
|
return tailwindMerge.twMerge(clsx.clsx(inputs));
|
|
58
63
|
}
|
|
@@ -3065,6 +3070,220 @@ var Label = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__
|
|
|
3065
3070
|
}
|
|
3066
3071
|
));
|
|
3067
3072
|
Label.displayName = LabelPrimitive__namespace.Root.displayName;
|
|
3073
|
+
var Popover = PopoverPrimitive__namespace.Root;
|
|
3074
|
+
var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
|
|
3075
|
+
var PopoverAnchor = PopoverPrimitive__namespace.Anchor;
|
|
3076
|
+
var PopoverContent = React__namespace.forwardRef(({ className, align = "start", sideOffset = 8, collisionPadding = 16, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
3077
|
+
PopoverPrimitive__namespace.Content,
|
|
3078
|
+
{
|
|
3079
|
+
ref,
|
|
3080
|
+
align,
|
|
3081
|
+
sideOffset,
|
|
3082
|
+
collisionPadding,
|
|
3083
|
+
className: cn(
|
|
3084
|
+
"bk-portal-content z-50 max-h-[var(--radix-popover-content-available-height)] w-80 overflow-y-auto rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
|
|
3085
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
3086
|
+
className
|
|
3087
|
+
),
|
|
3088
|
+
...props
|
|
3089
|
+
}
|
|
3090
|
+
) }));
|
|
3091
|
+
PopoverContent.displayName = PopoverPrimitive__namespace.Content.displayName;
|
|
3092
|
+
function matchesQuery(name, query) {
|
|
3093
|
+
const needle = query.replace(/^\s*#\s*/, "").trim().toLowerCase();
|
|
3094
|
+
return needle === "" || name.toLowerCase().includes(needle);
|
|
3095
|
+
}
|
|
3096
|
+
function ChannelCombobox({
|
|
3097
|
+
id,
|
|
3098
|
+
channels,
|
|
3099
|
+
value,
|
|
3100
|
+
onChange,
|
|
3101
|
+
placeholder = "Search channels\u2026",
|
|
3102
|
+
className
|
|
3103
|
+
}) {
|
|
3104
|
+
const [open, setOpen] = React.useState(false);
|
|
3105
|
+
const [query, setQuery] = React.useState("");
|
|
3106
|
+
const [activeIndex, setActiveIndex] = React.useState(-1);
|
|
3107
|
+
const inputRef = React.useRef(null);
|
|
3108
|
+
const listRef = React.useRef(null);
|
|
3109
|
+
const domId = React.useId();
|
|
3110
|
+
const listboxId = `${domId}-listbox`;
|
|
3111
|
+
const optionDomId = (index) => `${domId}-option-${index}`;
|
|
3112
|
+
const selected = channels.find((c) => c.id === value) ?? null;
|
|
3113
|
+
const filtered = React.useMemo(
|
|
3114
|
+
() => open ? channels.filter((c) => matchesQuery(c.name, query)) : channels,
|
|
3115
|
+
[channels, open, query]
|
|
3116
|
+
);
|
|
3117
|
+
const inputValue = open ? query : selected ? channelLabel(selected.name) : "";
|
|
3118
|
+
React.useEffect(() => {
|
|
3119
|
+
if (!open) {
|
|
3120
|
+
setActiveIndex(-1);
|
|
3121
|
+
return;
|
|
3122
|
+
}
|
|
3123
|
+
setActiveIndex((prev) => {
|
|
3124
|
+
if (prev >= 0 && prev < filtered.length) {
|
|
3125
|
+
return prev;
|
|
3126
|
+
}
|
|
3127
|
+
const selectedIndex = filtered.findIndex((c) => c.id === value);
|
|
3128
|
+
return selectedIndex >= 0 ? selectedIndex : filtered.length > 0 ? 0 : -1;
|
|
3129
|
+
});
|
|
3130
|
+
}, [open, filtered, value]);
|
|
3131
|
+
React.useEffect(() => {
|
|
3132
|
+
if (!open || activeIndex < 0) {
|
|
3133
|
+
return;
|
|
3134
|
+
}
|
|
3135
|
+
const row = listRef.current?.querySelectorAll('[role="option"]')[activeIndex];
|
|
3136
|
+
row?.scrollIntoView?.({ block: "nearest" });
|
|
3137
|
+
}, [open, activeIndex]);
|
|
3138
|
+
const openList = () => {
|
|
3139
|
+
setQuery("");
|
|
3140
|
+
setOpen(true);
|
|
3141
|
+
};
|
|
3142
|
+
const closeList = () => {
|
|
3143
|
+
setOpen(false);
|
|
3144
|
+
setQuery("");
|
|
3145
|
+
};
|
|
3146
|
+
const commit = (channel) => {
|
|
3147
|
+
onChange(channel.id);
|
|
3148
|
+
closeList();
|
|
3149
|
+
inputRef.current?.focus();
|
|
3150
|
+
};
|
|
3151
|
+
const moveActive = (delta) => {
|
|
3152
|
+
if (!open) {
|
|
3153
|
+
openList();
|
|
3154
|
+
return;
|
|
3155
|
+
}
|
|
3156
|
+
if (filtered.length === 0) {
|
|
3157
|
+
return;
|
|
3158
|
+
}
|
|
3159
|
+
setActiveIndex((prev) => {
|
|
3160
|
+
const next = prev + delta;
|
|
3161
|
+
return next < 0 ? filtered.length - 1 : next >= filtered.length ? 0 : next;
|
|
3162
|
+
});
|
|
3163
|
+
};
|
|
3164
|
+
const handleKeyDown = (e) => {
|
|
3165
|
+
switch (e.key) {
|
|
3166
|
+
case "ArrowDown":
|
|
3167
|
+
e.preventDefault();
|
|
3168
|
+
moveActive(1);
|
|
3169
|
+
break;
|
|
3170
|
+
case "ArrowUp":
|
|
3171
|
+
e.preventDefault();
|
|
3172
|
+
moveActive(-1);
|
|
3173
|
+
break;
|
|
3174
|
+
case "Home":
|
|
3175
|
+
if (open && filtered.length > 0) {
|
|
3176
|
+
e.preventDefault();
|
|
3177
|
+
setActiveIndex(0);
|
|
3178
|
+
}
|
|
3179
|
+
break;
|
|
3180
|
+
case "End":
|
|
3181
|
+
if (open && filtered.length > 0) {
|
|
3182
|
+
e.preventDefault();
|
|
3183
|
+
setActiveIndex(filtered.length - 1);
|
|
3184
|
+
}
|
|
3185
|
+
break;
|
|
3186
|
+
case "Enter": {
|
|
3187
|
+
if (!open) {
|
|
3188
|
+
break;
|
|
3189
|
+
}
|
|
3190
|
+
e.preventDefault();
|
|
3191
|
+
const active = filtered[activeIndex];
|
|
3192
|
+
if (active) {
|
|
3193
|
+
commit(active);
|
|
3194
|
+
}
|
|
3195
|
+
break;
|
|
3196
|
+
}
|
|
3197
|
+
case "Escape":
|
|
3198
|
+
if (open) {
|
|
3199
|
+
e.stopPropagation();
|
|
3200
|
+
closeList();
|
|
3201
|
+
}
|
|
3202
|
+
break;
|
|
3203
|
+
case "Tab":
|
|
3204
|
+
if (open) {
|
|
3205
|
+
closeList();
|
|
3206
|
+
}
|
|
3207
|
+
break;
|
|
3208
|
+
}
|
|
3209
|
+
};
|
|
3210
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(Popover, { open, onOpenChange: (next) => next ? openList() : closeList(), children: [
|
|
3211
|
+
/* @__PURE__ */ jsxRuntime.jsx(PopoverAnchor, { asChild: true, children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
3212
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3213
|
+
Input,
|
|
3214
|
+
{
|
|
3215
|
+
ref: inputRef,
|
|
3216
|
+
id,
|
|
3217
|
+
role: "combobox",
|
|
3218
|
+
"aria-expanded": open,
|
|
3219
|
+
"aria-controls": listboxId,
|
|
3220
|
+
"aria-autocomplete": "list",
|
|
3221
|
+
"aria-activedescendant": open && activeIndex >= 0 ? optionDomId(activeIndex) : void 0,
|
|
3222
|
+
autoComplete: "off",
|
|
3223
|
+
spellCheck: false,
|
|
3224
|
+
value: inputValue,
|
|
3225
|
+
placeholder,
|
|
3226
|
+
onChange: (e) => {
|
|
3227
|
+
setQuery(e.target.value);
|
|
3228
|
+
setOpen(true);
|
|
3229
|
+
},
|
|
3230
|
+
onKeyDown: handleKeyDown,
|
|
3231
|
+
onClick: () => open ? closeList() : openList(),
|
|
3232
|
+
className: cn("pr-9", className)
|
|
3233
|
+
}
|
|
3234
|
+
),
|
|
3235
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3236
|
+
lucideReact.ChevronsUpDown,
|
|
3237
|
+
{
|
|
3238
|
+
"aria-hidden": true,
|
|
3239
|
+
className: "pointer-events-none absolute right-3 top-1/2 h-4 w-4 -translate-y-1/2 text-muted-foreground"
|
|
3240
|
+
}
|
|
3241
|
+
)
|
|
3242
|
+
] }) }),
|
|
3243
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3244
|
+
PopoverContent,
|
|
3245
|
+
{
|
|
3246
|
+
ref: listRef,
|
|
3247
|
+
onOpenAutoFocus: (e) => e.preventDefault(),
|
|
3248
|
+
onCloseAutoFocus: (e) => e.preventDefault(),
|
|
3249
|
+
onInteractOutside: (e) => {
|
|
3250
|
+
if (e.target instanceof Node && inputRef.current?.contains(e.target)) {
|
|
3251
|
+
e.preventDefault();
|
|
3252
|
+
}
|
|
3253
|
+
},
|
|
3254
|
+
sideOffset: 4,
|
|
3255
|
+
className: "max-h-[min(15rem,var(--radix-popover-content-available-height))] w-[var(--radix-popover-trigger-width)] min-w-48 p-1",
|
|
3256
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { role: "listbox", id: listboxId, "aria-label": "Channels", children: filtered.length === 0 ? /* @__PURE__ */ jsxRuntime.jsx("p", { className: "px-2 py-3 text-center text-xs text-muted-foreground", children: "No channels match that search." }) : filtered.map((channel, index) => {
|
|
3257
|
+
const isSelected = channel.id === value;
|
|
3258
|
+
return (
|
|
3259
|
+
// biome-ignore lint/a11y/useFocusableInteractive: options in an aria-activedescendant combobox must stay unfocusable — focus belongs to the input, which is what makes typing filter the list.
|
|
3260
|
+
// biome-ignore lint/a11y/useKeyWithClickEvents: the keyboard path lives on that same input, which drives this list via aria-activedescendant.
|
|
3261
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
3262
|
+
"div",
|
|
3263
|
+
{
|
|
3264
|
+
id: optionDomId(index),
|
|
3265
|
+
role: "option",
|
|
3266
|
+
"aria-selected": isSelected,
|
|
3267
|
+
onPointerDown: (e) => e.preventDefault(),
|
|
3268
|
+
onClick: () => commit(channel),
|
|
3269
|
+
onMouseMove: () => setActiveIndex(index),
|
|
3270
|
+
className: cn(
|
|
3271
|
+
"flex cursor-pointer items-center gap-2 rounded-sm px-2 py-1.5 text-sm text-foreground",
|
|
3272
|
+
index === activeIndex && "bg-accent"
|
|
3273
|
+
),
|
|
3274
|
+
children: [
|
|
3275
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: cn("h-3.5 w-3.5 shrink-0", isSelected ? "opacity-100" : "opacity-0") }),
|
|
3276
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "truncate", children: channelLabel(channel.name) })
|
|
3277
|
+
]
|
|
3278
|
+
},
|
|
3279
|
+
channel.id
|
|
3280
|
+
)
|
|
3281
|
+
);
|
|
3282
|
+
}) })
|
|
3283
|
+
}
|
|
3284
|
+
)
|
|
3285
|
+
] });
|
|
3286
|
+
}
|
|
3068
3287
|
function SlackBlockPreview({
|
|
3069
3288
|
block,
|
|
3070
3289
|
hooks,
|
|
@@ -3544,20 +3763,14 @@ function LoadMessageDialog({
|
|
|
3544
3763
|
channels === null && !channelsError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Loading channels\u2026" }),
|
|
3545
3764
|
channelsError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive", children: channelsError }),
|
|
3546
3765
|
channels && channels.length === 0 && !channelsError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "No public channels available." }),
|
|
3547
|
-
channels && channels.length > 0 && /* @__PURE__ */ jsxRuntime.
|
|
3548
|
-
|
|
3766
|
+
channels && channels.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
3767
|
+
ChannelCombobox,
|
|
3549
3768
|
{
|
|
3550
3769
|
id: "recent-channel-picker",
|
|
3770
|
+
channels,
|
|
3551
3771
|
value: channelId,
|
|
3552
|
-
onChange:
|
|
3553
|
-
|
|
3554
|
-
children: [
|
|
3555
|
-
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "", disabled: true, children: "Select a channel\u2026" }),
|
|
3556
|
-
channels.map((c) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: c.id, children: [
|
|
3557
|
-
"#",
|
|
3558
|
-
c.name
|
|
3559
|
-
] }, c.id))
|
|
3560
|
-
]
|
|
3772
|
+
onChange: setChannelId,
|
|
3773
|
+
placeholder: "Select a channel\u2026"
|
|
3561
3774
|
}
|
|
3562
3775
|
)
|
|
3563
3776
|
] }),
|
|
@@ -3751,7 +3964,7 @@ function PreviewPane({
|
|
|
3751
3964
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-w-0 shrink-0 flex-col gap-2 lg:min-h-0 lg:flex-1", children: [
|
|
3752
3965
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex shrink-0 flex-wrap items-center gap-2", children: [
|
|
3753
3966
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-medium uppercase tracking-wide text-muted-foreground", children: "Preview" }),
|
|
3754
|
-
target?.channelName || target?.channelId ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded border px-1.5 py-px text-[10px] font-medium text-muted-foreground", children: target.channelName ?
|
|
3967
|
+
target?.channelName || target?.channelId ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "rounded border px-1.5 py-px text-[10px] font-medium text-muted-foreground", children: target.channelName ? channelLabel(target.channelName) : target.channelId }) : null,
|
|
3755
3968
|
target?.editableVia ? /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "rounded border px-1.5 py-px text-[10px] font-medium uppercase tracking-wide text-muted-foreground", children: [
|
|
3756
3969
|
"Editable as ",
|
|
3757
3970
|
editableLabel(target.editableVia)
|
|
@@ -4207,19 +4420,7 @@ function SendDialog({
|
|
|
4207
4420
|
channels === null && !channelsError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "Loading channels\u2026" }),
|
|
4208
4421
|
channelsError && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-destructive", children: channelsError }),
|
|
4209
4422
|
channels && channels.length === 0 && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "No public channels available." }),
|
|
4210
|
-
channels && channels.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4211
|
-
"select",
|
|
4212
|
-
{
|
|
4213
|
-
id: "channel-picker",
|
|
4214
|
-
value: channelId,
|
|
4215
|
-
onChange: (e) => setChannelId(e.target.value),
|
|
4216
|
-
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",
|
|
4217
|
-
children: channels.map((c) => /* @__PURE__ */ jsxRuntime.jsxs("option", { value: c.id, children: [
|
|
4218
|
-
"#",
|
|
4219
|
-
c.name
|
|
4220
|
-
] }, c.id))
|
|
4221
|
-
}
|
|
4222
|
-
)
|
|
4423
|
+
channels && channels.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(ChannelCombobox, { id: "channel-picker", channels, value: channelId, onChange: setChannelId })
|
|
4223
4424
|
] }),
|
|
4224
4425
|
renderSendExtras ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex flex-col gap-1.5", children: renderSendExtras({
|
|
4225
4426
|
channelId: channelId || null,
|
|
@@ -4262,24 +4463,6 @@ function SendDialog({
|
|
|
4262
4463
|
] })
|
|
4263
4464
|
] }) });
|
|
4264
4465
|
}
|
|
4265
|
-
var Popover = PopoverPrimitive__namespace.Root;
|
|
4266
|
-
var PopoverTrigger = PopoverPrimitive__namespace.Trigger;
|
|
4267
|
-
var PopoverContent = React__namespace.forwardRef(({ className, align = "start", sideOffset = 8, collisionPadding = 16, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(PopoverPrimitive__namespace.Portal, { children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4268
|
-
PopoverPrimitive__namespace.Content,
|
|
4269
|
-
{
|
|
4270
|
-
ref,
|
|
4271
|
-
align,
|
|
4272
|
-
sideOffset,
|
|
4273
|
-
collisionPadding,
|
|
4274
|
-
className: cn(
|
|
4275
|
-
"bk-portal-content z-50 max-h-[var(--radix-popover-content-available-height)] w-80 overflow-y-auto rounded-md border bg-popover p-4 text-popover-foreground shadow-md outline-none",
|
|
4276
|
-
"data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
4277
|
-
className
|
|
4278
|
-
),
|
|
4279
|
-
...props
|
|
4280
|
-
}
|
|
4281
|
-
) }));
|
|
4282
|
-
PopoverContent.displayName = PopoverPrimitive__namespace.Content.displayName;
|
|
4283
4466
|
var RadioGroup = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(RadioGroupPrimitive__namespace.Root, { className: cn("grid gap-2", className), ...props, ref }));
|
|
4284
4467
|
RadioGroup.displayName = RadioGroupPrimitive__namespace.Root.displayName;
|
|
4285
4468
|
var RadioGroupItem = React__namespace.forwardRef(({ className, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -6112,12 +6295,44 @@ function HeaderEditor({ block, onChange }) {
|
|
|
6112
6295
|
] });
|
|
6113
6296
|
}
|
|
6114
6297
|
function ImageEditor({ block, onChange }) {
|
|
6115
|
-
|
|
6116
|
-
return /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-xs text-muted-foreground", children: "This image references a Slack file. Not editable in the visual builder." });
|
|
6117
|
-
}
|
|
6298
|
+
const source = "slack_file" in block ? "slack_file" : "url";
|
|
6118
6299
|
const titleText = block.title?.text ?? "";
|
|
6300
|
+
const setSource = (next) => {
|
|
6301
|
+
if (next === source) {
|
|
6302
|
+
return;
|
|
6303
|
+
}
|
|
6304
|
+
if (next === "url") {
|
|
6305
|
+
const { slack_file: _omit, ...rest } = block;
|
|
6306
|
+
onChange({ image_url: "", ...rest });
|
|
6307
|
+
} else {
|
|
6308
|
+
const { image_url: _omit, ...rest } = block;
|
|
6309
|
+
onChange({ slack_file: { id: "" }, ...rest });
|
|
6310
|
+
}
|
|
6311
|
+
};
|
|
6119
6312
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
6120
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6313
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6314
|
+
EditorField,
|
|
6315
|
+
{
|
|
6316
|
+
label: "Image source",
|
|
6317
|
+
help: "Where the image comes from: a public URL, or a file already uploaded to your Slack workspace.",
|
|
6318
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6319
|
+
RadioGroup,
|
|
6320
|
+
{
|
|
6321
|
+
value: source,
|
|
6322
|
+
onValueChange: (v) => setSource(v),
|
|
6323
|
+
className: "flex flex-row flex-wrap gap-3",
|
|
6324
|
+
children: [
|
|
6325
|
+
["url", "Public URL"],
|
|
6326
|
+
["slack_file", "Slack file"]
|
|
6327
|
+
].map(([value, label]) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
6328
|
+
/* @__PURE__ */ jsxRuntime.jsx(RadioGroupItem, { value, id: `img-source-${value}` }),
|
|
6329
|
+
/* @__PURE__ */ jsxRuntime.jsx(Label, { htmlFor: `img-source-${value}`, className: "text-xs", children: label })
|
|
6330
|
+
] }, value))
|
|
6331
|
+
}
|
|
6332
|
+
)
|
|
6333
|
+
}
|
|
6334
|
+
),
|
|
6335
|
+
"slack_file" in block ? /* @__PURE__ */ jsxRuntime.jsx(SlackFileFields, { block, onChange }) : /* @__PURE__ */ jsxRuntime.jsx(EditorField, { label: "Image URL", help: "A publicly accessible image URL (PNG, JPG, GIF).", htmlFor: "img-url", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6121
6336
|
Input,
|
|
6122
6337
|
{
|
|
6123
6338
|
id: "img-url",
|
|
@@ -6161,6 +6376,51 @@ function ImageEditor({ block, onChange }) {
|
|
|
6161
6376
|
) })
|
|
6162
6377
|
] });
|
|
6163
6378
|
}
|
|
6379
|
+
function SlackFileFields({
|
|
6380
|
+
block,
|
|
6381
|
+
onChange
|
|
6382
|
+
}) {
|
|
6383
|
+
const fileId = "id" in block.slack_file ? block.slack_file.id : "";
|
|
6384
|
+
const fileUrl = "url" in block.slack_file ? block.slack_file.url : "";
|
|
6385
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
6386
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-[11px] leading-snug text-muted-foreground", children: "References a file already uploaded to your Slack workspace. The preview can't render workspace files \u2014 switch the source to Public URL to see the image here." }),
|
|
6387
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6388
|
+
EditorField,
|
|
6389
|
+
{
|
|
6390
|
+
label: "File ID",
|
|
6391
|
+
help: "The Slack file's ID. Slack accepts an ID or a URL, not both, so filling this clears File URL.",
|
|
6392
|
+
htmlFor: "img-file-id",
|
|
6393
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6394
|
+
Input,
|
|
6395
|
+
{
|
|
6396
|
+
id: "img-file-id",
|
|
6397
|
+
value: fileId,
|
|
6398
|
+
placeholder: "e.g. F0123456789",
|
|
6399
|
+
onChange: (e) => onChange({ ...block, slack_file: { id: e.target.value } })
|
|
6400
|
+
}
|
|
6401
|
+
)
|
|
6402
|
+
}
|
|
6403
|
+
),
|
|
6404
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
6405
|
+
EditorField,
|
|
6406
|
+
{
|
|
6407
|
+
label: "File URL",
|
|
6408
|
+
help: "The file's Slack-hosted URL. Filling this clears File ID.",
|
|
6409
|
+
htmlFor: "img-file-url",
|
|
6410
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
6411
|
+
Input,
|
|
6412
|
+
{
|
|
6413
|
+
id: "img-file-url",
|
|
6414
|
+
type: "url",
|
|
6415
|
+
value: fileUrl,
|
|
6416
|
+
placeholder: "e.g. https://files.slack.com/files-pri/T0123-F0123/image.png",
|
|
6417
|
+
onChange: (e) => onChange({ ...block, slack_file: { url: e.target.value } })
|
|
6418
|
+
}
|
|
6419
|
+
)
|
|
6420
|
+
}
|
|
6421
|
+
)
|
|
6422
|
+
] });
|
|
6423
|
+
}
|
|
6164
6424
|
function InputEditor({ block, onChange }) {
|
|
6165
6425
|
const updateElement = (next) => {
|
|
6166
6426
|
onChange({ ...block, element: next });
|
|
@@ -10401,7 +10661,7 @@ function UpdateDialog({
|
|
|
10401
10661
|
setStatus({ kind: "error", error: e instanceof Error ? e.message : "Update failed." });
|
|
10402
10662
|
}
|
|
10403
10663
|
};
|
|
10404
|
-
const
|
|
10664
|
+
const channelText = target.channelName ? channelLabel(target.channelName) : target.channelId;
|
|
10405
10665
|
return /* @__PURE__ */ jsxRuntime.jsx(Dialog, { open, onOpenChange, children: /* @__PURE__ */ jsxRuntime.jsxs(DialogContent, { className: "w-[calc(100vw-1.5rem)] max-w-lg rounded-lg", children: [
|
|
10406
10666
|
/* @__PURE__ */ jsxRuntime.jsxs(DialogHeader, { children: [
|
|
10407
10667
|
/* @__PURE__ */ jsxRuntime.jsx(DialogTitle, { children: "Update message" }),
|
|
@@ -10410,7 +10670,7 @@ function UpdateDialog({
|
|
|
10410
10670
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4", children: [
|
|
10411
10671
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
10412
10672
|
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Channel" }),
|
|
10413
|
-
/* @__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:
|
|
10673
|
+
/* @__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: channelText })
|
|
10414
10674
|
] }),
|
|
10415
10675
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
10416
10676
|
/* @__PURE__ */ jsxRuntime.jsx(Label, { children: "Posting as" }),
|
|
@@ -10776,7 +11036,7 @@ function BlockKitchen(props) {
|
|
|
10776
11036
|
loadEnabled,
|
|
10777
11037
|
updateEnabled: Boolean(onUpdate),
|
|
10778
11038
|
editBadge: activeEditTarget ? {
|
|
10779
|
-
channelLabel: activeEditTarget.channelName ?
|
|
11039
|
+
channelLabel: activeEditTarget.channelName ? channelLabel(activeEditTarget.channelName) : activeEditTarget.channelId,
|
|
10780
11040
|
ts: activeEditTarget.ts
|
|
10781
11041
|
} : null,
|
|
10782
11042
|
onOpenLoad: () => setLoadOpen(true),
|