@tightknitai/block-kitchen 0.10.25 → 0.10.27
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 +4 -1
- package/dist/helpers.d.cts +2 -2
- package/dist/helpers.d.ts +2 -2
- package/dist/index.cjs +437 -85
- 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 +438 -86
- package/dist/index.js.map +1 -1
- package/dist/{palette-DTE9U5si.d.cts → palette-xi4VWU0p.d.cts} +37 -1
- package/dist/{palette-DTE9U5si.d.ts → palette-xi4VWU0p.d.ts} +37 -1
- package/dist/palette.cjs.map +1 -1
- package/dist/palette.d.cts +1 -1
- package/dist/palette.d.ts +1 -1
- package/dist/palette.js.map +1 -1
- package/dist/styles.css +2 -2
- package/package.json +6 -6
package/dist/index.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { useSensors, useSensor, PointerSensor, TouchSensor, KeyboardSensor, pointerWithin, closestCenter, DndContext, DragOverlay, useDroppable, useDraggable } from '@dnd-kit/core';
|
|
2
2
|
import { sortableKeyboardCoordinates, SortableContext, verticalListSortingStrategy, useSortable } from '@dnd-kit/sortable';
|
|
3
|
-
import { X, Circle, Sparkles, FileText, AlignLeft, MousePointerClick, TextCursorInput, LayoutTemplate, Bell, Pilcrow, Image, Video, GalleryHorizontal, Table, ChartColumnBig, Container, Loader2, ExternalLink, AlertTriangle, ChevronRight, ChevronLeft, GripVertical, ChevronsUpDown, Check, Sun, Moon, MessageSquare, AppWindow, Home, Plus, ChevronDown, BookOpen, Undo2, Redo2, Trash2, Code2, Pencil, Send, Search, Copy, Info, CheckCircle2, LayoutGrid, ArrowUp, ArrowDown, Lock, Type, Bold, Italic, Strikethrough, Underline, Code, AtSign, Hash, List, ListOrdered, Quote, Smile, Link as Link$1 } from 'lucide-react';
|
|
3
|
+
import { X, Circle, Sparkles, FileText, AlignLeft, MousePointerClick, TextCursorInput, LayoutTemplate, Bell, Pilcrow, Image, Video, GalleryHorizontal, Table, ChartColumnBig, Container, Loader2, ExternalLink, AlertTriangle, ChevronRight, ChevronLeft, GripVertical, ChevronsUpDown, Check, Sun, Moon, MessageSquare, AppWindow, Home, Plus, ChevronDown, BookOpen, Undo2, Redo2, Trash2, Code2, Pencil, Send, Search, Copy, Info, CheckCircle2, LayoutGrid, ArrowUp, ArrowDown, ImagePlus, Lock, Type, Upload, Bold, Italic, Strikethrough, Underline, Code, AtSign, Hash, List, ListOrdered, Quote, Smile, Link as Link$1 } from 'lucide-react';
|
|
4
4
|
import * as React from 'react';
|
|
5
5
|
import { createContext, useContext, useState, useRef, useEffect, useCallback, useMemo, useId, useSyncExternalStore, useLayoutEffect } from 'react';
|
|
6
6
|
import { clsx } from 'clsx';
|
|
@@ -1928,6 +1928,36 @@ function CustomEmojiProvider({ customEmojis, children }) {
|
|
|
1928
1928
|
function useCustomEmojis() {
|
|
1929
1929
|
return useContext(CustomEmojiContext);
|
|
1930
1930
|
}
|
|
1931
|
+
var DEFAULT_IMAGE_UPLOAD_ACCEPT = ["image/png", "image/jpeg", "image/gif"];
|
|
1932
|
+
var ImageUploadContext = createContext(null);
|
|
1933
|
+
function ImageUploadProvider({
|
|
1934
|
+
imageUpload,
|
|
1935
|
+
children
|
|
1936
|
+
}) {
|
|
1937
|
+
const uploadImage = imageUpload?.uploadImage;
|
|
1938
|
+
const accept = imageUpload?.accept;
|
|
1939
|
+
const value = useMemo(
|
|
1940
|
+
() => uploadImage ? { uploadImage, accept: accept ?? DEFAULT_IMAGE_UPLOAD_ACCEPT } : null,
|
|
1941
|
+
[uploadImage, accept]
|
|
1942
|
+
);
|
|
1943
|
+
return /* @__PURE__ */ jsx(ImageUploadContext.Provider, { value, children });
|
|
1944
|
+
}
|
|
1945
|
+
function useImageUpload() {
|
|
1946
|
+
return useContext(ImageUploadContext);
|
|
1947
|
+
}
|
|
1948
|
+
function isAcceptedImage(file, accept) {
|
|
1949
|
+
return accept.includes(file.type);
|
|
1950
|
+
}
|
|
1951
|
+
function uploadErrorMessage(error) {
|
|
1952
|
+
return error instanceof Error && error.message ? error.message : "Upload failed. Try again.";
|
|
1953
|
+
}
|
|
1954
|
+
function isFileDrag(dataTransfer) {
|
|
1955
|
+
return Boolean(dataTransfer && Array.from(dataTransfer.types).includes("Files"));
|
|
1956
|
+
}
|
|
1957
|
+
function formatList(accept) {
|
|
1958
|
+
const names = accept.map((type) => type.replace(/^image\//, "").toUpperCase());
|
|
1959
|
+
return names.length > 1 ? `${names.slice(0, -1).join(", ")} or ${names[names.length - 1]}` : names[0] ?? "";
|
|
1960
|
+
}
|
|
1931
1961
|
var MentionsContext = createContext(null);
|
|
1932
1962
|
function MentionsProvider({ mentions, children }) {
|
|
1933
1963
|
return /* @__PURE__ */ jsx(MentionsContext.Provider, { value: mentions ?? null, children });
|
|
@@ -3239,6 +3269,13 @@ var PopoverContent = React.forwardRef(({ className, align = "start", sideOffset
|
|
|
3239
3269
|
}
|
|
3240
3270
|
) }));
|
|
3241
3271
|
PopoverContent.displayName = PopoverPrimitive.Content.displayName;
|
|
3272
|
+
function returnFocusUnlessMoved(event) {
|
|
3273
|
+
const active = document.activeElement;
|
|
3274
|
+
const closing = event.target instanceof Node ? event.target : null;
|
|
3275
|
+
if (active && active !== document.body && !closing?.contains(active)) {
|
|
3276
|
+
event.preventDefault();
|
|
3277
|
+
}
|
|
3278
|
+
}
|
|
3242
3279
|
function matchesQuery(name, query) {
|
|
3243
3280
|
const needle = query.replace(/^\s*#\s*/, "").trim().toLowerCase();
|
|
3244
3281
|
return needle === "" || name.toLowerCase().includes(needle);
|
|
@@ -4474,7 +4511,7 @@ function PaletteItem({
|
|
|
4474
4511
|
{
|
|
4475
4512
|
ref: setNodeRef,
|
|
4476
4513
|
className: cn(
|
|
4477
|
-
"group flex items-
|
|
4514
|
+
"group flex items-start gap-2 rounded px-2 py-1 text-sm text-muted-foreground transition-colors hover:bg-accent hover:text-foreground has-[:focus-visible]:bg-accent has-[:focus-visible]:text-foreground",
|
|
4478
4515
|
isDragging && "opacity-50"
|
|
4479
4516
|
),
|
|
4480
4517
|
children: [
|
|
@@ -4482,16 +4519,12 @@ function PaletteItem({
|
|
|
4482
4519
|
"div",
|
|
4483
4520
|
{
|
|
4484
4521
|
ref: setActivatorNodeRef,
|
|
4485
|
-
className: "-my-1 flex min-w-0 flex-1 cursor-grab items-
|
|
4522
|
+
className: "-my-1 flex min-w-0 flex-1 cursor-grab items-start gap-2 rounded py-1 active:cursor-grabbing focus-visible:outline-none",
|
|
4486
4523
|
...attributes,
|
|
4487
4524
|
...listeners,
|
|
4488
4525
|
children: [
|
|
4489
|
-
/* @__PURE__ */ jsx(GripVertical, { className: "h-3.5 w-3.5 shrink-0" }),
|
|
4490
|
-
/* @__PURE__ */ jsx(
|
|
4491
|
-
variant.badge ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4492
|
-
" ",
|
|
4493
|
-
/* @__PURE__ */ jsx(VariantBadge, { badge: variant.badge })
|
|
4494
|
-
] }) : null
|
|
4526
|
+
/* @__PURE__ */ jsx(GripVertical, { className: "mt-[3px] h-3.5 w-3.5 shrink-0" }),
|
|
4527
|
+
/* @__PURE__ */ jsx(RailLabel, { variant })
|
|
4495
4528
|
]
|
|
4496
4529
|
}
|
|
4497
4530
|
),
|
|
@@ -4516,13 +4549,15 @@ function LockedPaletteItem({
|
|
|
4516
4549
|
}) {
|
|
4517
4550
|
const select = variant.onLockedSelect;
|
|
4518
4551
|
const className = cn(
|
|
4519
|
-
"flex w-full
|
|
4520
|
-
isSheet ? "min-h-11 gap-3 rounded-md px-3 py-2 text-sm font-medium" : "gap-2 rounded px-2 py-1 text-sm"
|
|
4552
|
+
"flex w-full text-left text-muted-foreground",
|
|
4553
|
+
isSheet ? "min-h-11 items-center gap-3 rounded-md px-3 py-2 text-sm font-medium" : "items-start gap-2 rounded px-2 py-1 text-sm"
|
|
4521
4554
|
);
|
|
4522
4555
|
const content = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4523
|
-
/* @__PURE__ */ jsx(Lock, { "aria-hidden": true, className: cn("shrink-0", isSheet ? "h-4 w-4" : "h-3.5 w-3.5") }),
|
|
4524
|
-
/* @__PURE__ */
|
|
4525
|
-
|
|
4556
|
+
/* @__PURE__ */ jsx(Lock, { "aria-hidden": true, className: cn("shrink-0", isSheet ? "h-4 w-4" : "mt-[3px] h-3.5 w-3.5") }),
|
|
4557
|
+
isSheet ? /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
4558
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: variant.label }),
|
|
4559
|
+
variant.badge ? /* @__PURE__ */ jsx(VariantBadge, { badge: variant.badge }) : null
|
|
4560
|
+
] }) : /* @__PURE__ */ jsx(RailLabel, { variant })
|
|
4526
4561
|
] });
|
|
4527
4562
|
if (!select) {
|
|
4528
4563
|
return /* @__PURE__ */ jsx("div", { "aria-disabled": "true", className, children: content });
|
|
@@ -4544,12 +4579,31 @@ function LockedPaletteItem({
|
|
|
4544
4579
|
}
|
|
4545
4580
|
);
|
|
4546
4581
|
}
|
|
4582
|
+
function RailLabel({ variant }) {
|
|
4583
|
+
if (!variant.badge) {
|
|
4584
|
+
return /* @__PURE__ */ jsx("span", { className: "truncate", children: variant.label });
|
|
4585
|
+
}
|
|
4586
|
+
return /* @__PURE__ */ jsxs("span", { className: "flex min-w-0 flex-col items-start gap-0.5", children: [
|
|
4587
|
+
/* @__PURE__ */ jsx("span", { className: "max-w-full truncate", children: variant.label }),
|
|
4588
|
+
" ",
|
|
4589
|
+
/* @__PURE__ */ jsx(VariantBadge, { badge: variant.badge })
|
|
4590
|
+
] });
|
|
4591
|
+
}
|
|
4547
4592
|
function VariantBadge({ badge }) {
|
|
4548
4593
|
const Icon = badge.icon;
|
|
4549
|
-
return /* @__PURE__ */ jsxs(
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4594
|
+
return /* @__PURE__ */ jsxs(
|
|
4595
|
+
"span",
|
|
4596
|
+
{
|
|
4597
|
+
className: cn(
|
|
4598
|
+
"inline-flex shrink-0 items-center gap-1 rounded-full border bg-background px-1.5 text-[10px] font-medium leading-4 text-muted-foreground",
|
|
4599
|
+
badge.className
|
|
4600
|
+
),
|
|
4601
|
+
children: [
|
|
4602
|
+
Icon ? /* @__PURE__ */ jsx(Icon, { "aria-hidden": true, className: "h-2.5 w-2.5 shrink-0" }) : null,
|
|
4603
|
+
badge.label
|
|
4604
|
+
]
|
|
4605
|
+
}
|
|
4606
|
+
);
|
|
4553
4607
|
}
|
|
4554
4608
|
function SendDialog({
|
|
4555
4609
|
open,
|
|
@@ -4713,6 +4767,73 @@ function SendDialog({
|
|
|
4713
4767
|
] })
|
|
4714
4768
|
] }) });
|
|
4715
4769
|
}
|
|
4770
|
+
var ALT_TEXT_MAX_LENGTH = 2e3;
|
|
4771
|
+
function altTextFromFileName(file) {
|
|
4772
|
+
const name = file.name.replace(/\.[^.]+$/, "").trim();
|
|
4773
|
+
return (name || "Image").slice(0, ALT_TEXT_MAX_LENGTH);
|
|
4774
|
+
}
|
|
4775
|
+
function useCanvasImageDrop({
|
|
4776
|
+
upload,
|
|
4777
|
+
enabled,
|
|
4778
|
+
onAddBlock
|
|
4779
|
+
}) {
|
|
4780
|
+
const [dragging, setDragging] = useState(false);
|
|
4781
|
+
const [pending, setPending] = useState(0);
|
|
4782
|
+
const [error, setError] = useState(null);
|
|
4783
|
+
const onAddBlockRef = useRef(onAddBlock);
|
|
4784
|
+
onAddBlockRef.current = onAddBlock;
|
|
4785
|
+
const addFiles = async (activeUpload, files) => {
|
|
4786
|
+
const images = files.filter((file) => isAcceptedImage(file, activeUpload.accept));
|
|
4787
|
+
const skipped = files.length - images.length;
|
|
4788
|
+
setError(
|
|
4789
|
+
skipped > 0 ? `${skipped === 1 ? "1 file was" : `${skipped} files were`} skipped. Only ${formatList(activeUpload.accept)} images can be added.` : null
|
|
4790
|
+
);
|
|
4791
|
+
if (images.length === 0) {
|
|
4792
|
+
return;
|
|
4793
|
+
}
|
|
4794
|
+
setPending((count) => count + images.length);
|
|
4795
|
+
const results = await Promise.allSettled(images.map((file) => activeUpload.uploadImage(file)));
|
|
4796
|
+
setPending((count) => count - images.length);
|
|
4797
|
+
const failures = [];
|
|
4798
|
+
results.forEach((result, idx) => {
|
|
4799
|
+
const file = images[idx];
|
|
4800
|
+
if (result.status === "fulfilled") {
|
|
4801
|
+
onAddBlockRef.current?.({ type: "image", image_url: result.value.url, alt_text: altTextFromFileName(file) });
|
|
4802
|
+
} else {
|
|
4803
|
+
failures.push(`Couldn't upload "${file.name}": ${uploadErrorMessage(result.reason)}`);
|
|
4804
|
+
}
|
|
4805
|
+
});
|
|
4806
|
+
if (failures.length > 0) {
|
|
4807
|
+
setError(failures.join(" "));
|
|
4808
|
+
}
|
|
4809
|
+
};
|
|
4810
|
+
const isOwnEvent = (e) => isFileDrag(e.dataTransfer) && e.currentTarget.contains(e.target);
|
|
4811
|
+
const handlers = upload && enabled && onAddBlock ? {
|
|
4812
|
+
onDragOver: (e) => {
|
|
4813
|
+
if (!isOwnEvent(e)) {
|
|
4814
|
+
return;
|
|
4815
|
+
}
|
|
4816
|
+
e.preventDefault();
|
|
4817
|
+
e.dataTransfer.dropEffect = "copy";
|
|
4818
|
+
setDragging(true);
|
|
4819
|
+
},
|
|
4820
|
+
onDragLeave: (e) => {
|
|
4821
|
+
const next = e.relatedTarget;
|
|
4822
|
+
if (!next || !e.currentTarget.contains(next)) {
|
|
4823
|
+
setDragging(false);
|
|
4824
|
+
}
|
|
4825
|
+
},
|
|
4826
|
+
onDrop: (e) => {
|
|
4827
|
+
if (!isOwnEvent(e)) {
|
|
4828
|
+
return;
|
|
4829
|
+
}
|
|
4830
|
+
e.preventDefault();
|
|
4831
|
+
setDragging(false);
|
|
4832
|
+
void addFiles(upload, Array.from(e.dataTransfer.files));
|
|
4833
|
+
}
|
|
4834
|
+
} : void 0;
|
|
4835
|
+
return { handlers, dragging, pending, error, dismissError: () => setError(null) };
|
|
4836
|
+
}
|
|
4716
4837
|
function BlockActionButtons({
|
|
4717
4838
|
actions,
|
|
4718
4839
|
position,
|
|
@@ -4967,6 +5088,129 @@ function AlertEditor({ block, onChange }) {
|
|
|
4967
5088
|
) })
|
|
4968
5089
|
] });
|
|
4969
5090
|
}
|
|
5091
|
+
function ImageUrlInput({
|
|
5092
|
+
id,
|
|
5093
|
+
value,
|
|
5094
|
+
placeholder,
|
|
5095
|
+
onChange
|
|
5096
|
+
}) {
|
|
5097
|
+
const upload = useImageUpload();
|
|
5098
|
+
const input = /* @__PURE__ */ jsx(Input, { id, type: "url", value, placeholder, onChange: (e) => onChange(e.target.value) });
|
|
5099
|
+
if (!upload) {
|
|
5100
|
+
return input;
|
|
5101
|
+
}
|
|
5102
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-1.5", children: [
|
|
5103
|
+
/* @__PURE__ */ jsx(UploadDropZone, { upload, inputId: id, onUploaded: onChange, variant: "inline" }),
|
|
5104
|
+
input
|
|
5105
|
+
] });
|
|
5106
|
+
}
|
|
5107
|
+
function UploadDropZone({
|
|
5108
|
+
upload,
|
|
5109
|
+
inputId,
|
|
5110
|
+
onUploaded,
|
|
5111
|
+
variant
|
|
5112
|
+
}) {
|
|
5113
|
+
const [uploading, setUploading] = useState(false);
|
|
5114
|
+
const [dragging, setDragging] = useState(false);
|
|
5115
|
+
const [error, setError] = useState(null);
|
|
5116
|
+
const fileInputRef = useRef(null);
|
|
5117
|
+
const onUploadedRef = useRef(onUploaded);
|
|
5118
|
+
onUploadedRef.current = onUploaded;
|
|
5119
|
+
const uploadFile = async (file) => {
|
|
5120
|
+
if (!isAcceptedImage(file, upload.accept)) {
|
|
5121
|
+
setError(`"${file.name}" isn't a supported image. Use ${formatList(upload.accept)}.`);
|
|
5122
|
+
return;
|
|
5123
|
+
}
|
|
5124
|
+
setError(null);
|
|
5125
|
+
setUploading(true);
|
|
5126
|
+
try {
|
|
5127
|
+
const { url } = await upload.uploadImage(file);
|
|
5128
|
+
onUploadedRef.current(url);
|
|
5129
|
+
} catch (err) {
|
|
5130
|
+
setError(uploadErrorMessage(err));
|
|
5131
|
+
} finally {
|
|
5132
|
+
setUploading(false);
|
|
5133
|
+
}
|
|
5134
|
+
};
|
|
5135
|
+
const onDragOver = (e) => {
|
|
5136
|
+
if (!isFileDrag(e.dataTransfer)) {
|
|
5137
|
+
return;
|
|
5138
|
+
}
|
|
5139
|
+
e.preventDefault();
|
|
5140
|
+
e.stopPropagation();
|
|
5141
|
+
setDragging(true);
|
|
5142
|
+
};
|
|
5143
|
+
const onDrop = (e) => {
|
|
5144
|
+
if (!isFileDrag(e.dataTransfer)) {
|
|
5145
|
+
return;
|
|
5146
|
+
}
|
|
5147
|
+
e.preventDefault();
|
|
5148
|
+
e.stopPropagation();
|
|
5149
|
+
setDragging(false);
|
|
5150
|
+
const [file] = Array.from(e.dataTransfer.files);
|
|
5151
|
+
if (file && !uploading) {
|
|
5152
|
+
void uploadFile(file);
|
|
5153
|
+
}
|
|
5154
|
+
};
|
|
5155
|
+
const fileInput = /* @__PURE__ */ jsx(
|
|
5156
|
+
"input",
|
|
5157
|
+
{
|
|
5158
|
+
ref: fileInputRef,
|
|
5159
|
+
id: `${inputId}-file`,
|
|
5160
|
+
type: "file",
|
|
5161
|
+
accept: upload.accept.join(","),
|
|
5162
|
+
className: "hidden",
|
|
5163
|
+
tabIndex: -1,
|
|
5164
|
+
"aria-hidden": "true",
|
|
5165
|
+
onChange: (e) => {
|
|
5166
|
+
const file = e.target.files?.[0];
|
|
5167
|
+
e.target.value = "";
|
|
5168
|
+
if (file) {
|
|
5169
|
+
void uploadFile(file);
|
|
5170
|
+
}
|
|
5171
|
+
}
|
|
5172
|
+
}
|
|
5173
|
+
);
|
|
5174
|
+
const pickButton = (label) => /* @__PURE__ */ jsx(Button, { type: "button", size: "sm", className: "h-7", disabled: uploading, onClick: () => fileInputRef.current?.click(), children: label });
|
|
5175
|
+
const dropHandlers = { onDragOver, onDragLeave: () => setDragging(false), onDrop };
|
|
5176
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
5177
|
+
variant === "panel" ? /* @__PURE__ */ jsxs(
|
|
5178
|
+
"section",
|
|
5179
|
+
{
|
|
5180
|
+
"aria-label": "Upload an image",
|
|
5181
|
+
...dropHandlers,
|
|
5182
|
+
className: cn(
|
|
5183
|
+
"flex flex-col items-center justify-center gap-2 rounded-md border border-dashed px-4 py-6 text-center text-xs text-muted-foreground transition-colors",
|
|
5184
|
+
dragging && "border-primary bg-primary/5 text-primary"
|
|
5185
|
+
),
|
|
5186
|
+
children: [
|
|
5187
|
+
/* @__PURE__ */ jsx(Upload, { className: cn("h-5 w-5", uploading && "animate-pulse"), "aria-hidden": "true" }),
|
|
5188
|
+
/* @__PURE__ */ jsx("span", { "aria-live": "polite", children: uploading ? "Uploading\u2026" : dragging ? "Drop to upload" : "Drag an image here, or" }),
|
|
5189
|
+
pickButton("Choose file"),
|
|
5190
|
+
/* @__PURE__ */ jsx("span", { className: "text-[11px]", children: formatList(upload.accept) }),
|
|
5191
|
+
fileInput
|
|
5192
|
+
]
|
|
5193
|
+
}
|
|
5194
|
+
) : /* @__PURE__ */ jsxs(
|
|
5195
|
+
"section",
|
|
5196
|
+
{
|
|
5197
|
+
"aria-label": "Upload an image",
|
|
5198
|
+
...dropHandlers,
|
|
5199
|
+
className: cn(
|
|
5200
|
+
"flex items-center gap-2 rounded-md border border-dashed px-3 py-2 text-[11px] text-muted-foreground transition-colors",
|
|
5201
|
+
dragging && "border-primary bg-primary/5 text-primary"
|
|
5202
|
+
),
|
|
5203
|
+
children: [
|
|
5204
|
+
/* @__PURE__ */ jsx(Upload, { className: cn("h-3.5 w-3.5 shrink-0", uploading && "animate-pulse"), "aria-hidden": "true" }),
|
|
5205
|
+
/* @__PURE__ */ jsx("span", { className: "flex-1", "aria-live": "polite", children: uploading ? "Uploading\u2026" : dragging ? "Drop to upload" : "Drop an image here, or paste a URL below" }),
|
|
5206
|
+
pickButton("Upload image"),
|
|
5207
|
+
fileInput
|
|
5208
|
+
]
|
|
5209
|
+
}
|
|
5210
|
+
),
|
|
5211
|
+
error ? /* @__PURE__ */ jsx("p", { role: "alert", className: "text-[11px] leading-snug text-destructive", children: error }) : null
|
|
5212
|
+
] });
|
|
5213
|
+
}
|
|
4970
5214
|
function CardEditor({
|
|
4971
5215
|
block,
|
|
4972
5216
|
onChange,
|
|
@@ -5073,13 +5317,12 @@ function ImageFields({
|
|
|
5073
5317
|
};
|
|
5074
5318
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-2 rounded-md border bg-muted/20 p-3", children: [
|
|
5075
5319
|
/* @__PURE__ */ jsx(EditorField, { label, help, htmlFor: `${idPrefix}-url`, children: /* @__PURE__ */ jsx(
|
|
5076
|
-
|
|
5320
|
+
ImageUrlInput,
|
|
5077
5321
|
{
|
|
5078
5322
|
id: `${idPrefix}-url`,
|
|
5079
|
-
type: "url",
|
|
5080
5323
|
value: url,
|
|
5081
5324
|
placeholder: "e.g. https://example.com/image.png",
|
|
5082
|
-
onChange: (
|
|
5325
|
+
onChange: (next) => update({ url: next })
|
|
5083
5326
|
}
|
|
5084
5327
|
) }),
|
|
5085
5328
|
/* @__PURE__ */ jsx(EditorField, { label: "Alt text", help: "Describes the image for screen readers.", htmlFor: `${idPrefix}-alt`, children: /* @__PURE__ */ jsx(
|
|
@@ -7639,15 +7882,14 @@ function ContainerEditor({ block, onChange }) {
|
|
|
7639
7882
|
}
|
|
7640
7883
|
) : null,
|
|
7641
7884
|
/* @__PURE__ */ jsx(EditorField, { label: "Icon URL", help: "Optional image shown left of the title.", htmlFor: "container-icon", children: /* @__PURE__ */ jsx(
|
|
7642
|
-
|
|
7885
|
+
ImageUrlInput,
|
|
7643
7886
|
{
|
|
7644
7887
|
id: "container-icon",
|
|
7645
|
-
type: "url",
|
|
7646
7888
|
value: iconUrl,
|
|
7647
7889
|
placeholder: "https://example.com/icon.png",
|
|
7648
|
-
onChange: (
|
|
7890
|
+
onChange: (url) => onChange({
|
|
7649
7891
|
...block,
|
|
7650
|
-
icon:
|
|
7892
|
+
icon: url ? { type: "image", image_url: url, alt_text: iconAlt || "Container icon" } : void 0
|
|
7651
7893
|
})
|
|
7652
7894
|
}
|
|
7653
7895
|
) }),
|
|
@@ -8145,13 +8387,12 @@ function ImageItemCard({
|
|
|
8145
8387
|
help: "A publicly accessible image URL. Best at small sizes (around 20px).",
|
|
8146
8388
|
htmlFor: `ctx-img-url-${index}`,
|
|
8147
8389
|
children: /* @__PURE__ */ jsx(
|
|
8148
|
-
|
|
8390
|
+
ImageUrlInput,
|
|
8149
8391
|
{
|
|
8150
8392
|
id: `ctx-img-url-${index}`,
|
|
8151
|
-
type: "url",
|
|
8152
8393
|
value: element.image_url,
|
|
8153
8394
|
placeholder: "e.g. https://example.com/avatar.png",
|
|
8154
|
-
onChange: (
|
|
8395
|
+
onChange: (url) => onChange({ ...element, image_url: url })
|
|
8155
8396
|
}
|
|
8156
8397
|
)
|
|
8157
8398
|
}
|
|
@@ -8893,36 +9134,44 @@ function HeaderEditor({ block, onChange }) {
|
|
|
8893
9134
|
] });
|
|
8894
9135
|
}
|
|
8895
9136
|
function ImageEditor({ block, onChange }) {
|
|
8896
|
-
const
|
|
9137
|
+
const upload = useImageUpload();
|
|
9138
|
+
const [urlSource, setUrlSource] = useState(upload ? "upload" : "url");
|
|
9139
|
+
const isSlackFile = "slack_file" in block;
|
|
9140
|
+
const source = isSlackFile ? "slack_file" : upload ? urlSource : "url";
|
|
8897
9141
|
const titleText = block.title?.text ?? "";
|
|
8898
9142
|
const setSource = (next) => {
|
|
8899
9143
|
if (next === source) {
|
|
8900
9144
|
return;
|
|
8901
9145
|
}
|
|
8902
|
-
if (next
|
|
9146
|
+
if (next !== "slack_file") {
|
|
9147
|
+
setUrlSource(next);
|
|
9148
|
+
}
|
|
9149
|
+
if (next !== "slack_file" && isSlackFile) {
|
|
8903
9150
|
const { slack_file: _omit, ...rest } = block;
|
|
8904
9151
|
onChange({ image_url: "", ...rest });
|
|
8905
|
-
} else {
|
|
9152
|
+
} else if (next === "slack_file") {
|
|
8906
9153
|
const { image_url: _omit, ...rest } = block;
|
|
8907
9154
|
onChange({ slack_file: { id: "" }, ...rest });
|
|
8908
9155
|
}
|
|
8909
9156
|
};
|
|
9157
|
+
const sourceOptions = [
|
|
9158
|
+
...upload ? [["upload", "Upload image"]] : [],
|
|
9159
|
+
["url", "Public URL"],
|
|
9160
|
+
["slack_file", "Slack file"]
|
|
9161
|
+
];
|
|
8910
9162
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
8911
9163
|
/* @__PURE__ */ jsx(
|
|
8912
9164
|
EditorField,
|
|
8913
9165
|
{
|
|
8914
9166
|
label: "Image source",
|
|
8915
|
-
help: "Where the image comes from: a public URL, or a file already uploaded to your Slack workspace.",
|
|
9167
|
+
help: upload ? "Where the image comes from: a file from your device, a public URL, or a file already uploaded to your Slack workspace." : "Where the image comes from: a public URL, or a file already uploaded to your Slack workspace.",
|
|
8916
9168
|
children: /* @__PURE__ */ jsx(
|
|
8917
9169
|
RadioGroup,
|
|
8918
9170
|
{
|
|
8919
9171
|
value: source,
|
|
8920
9172
|
onValueChange: (v) => setSource(v),
|
|
8921
9173
|
className: "flex flex-row flex-wrap gap-3",
|
|
8922
|
-
children: [
|
|
8923
|
-
["url", "Public URL"],
|
|
8924
|
-
["slack_file", "Slack file"]
|
|
8925
|
-
].map(([value, label]) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
9174
|
+
children: sourceOptions.map(([value, label]) => /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5", children: [
|
|
8926
9175
|
/* @__PURE__ */ jsx(RadioGroupItem, { value, id: `img-source-${value}` }),
|
|
8927
9176
|
/* @__PURE__ */ jsx(Label, { htmlFor: `img-source-${value}`, className: "text-xs", children: label })
|
|
8928
9177
|
] }, value))
|
|
@@ -8930,7 +9179,15 @@ function ImageEditor({ block, onChange }) {
|
|
|
8930
9179
|
)
|
|
8931
9180
|
}
|
|
8932
9181
|
),
|
|
8933
|
-
"slack_file" in block ? /* @__PURE__ */ jsx(SlackFileFields, { block, onChange }) :
|
|
9182
|
+
"slack_file" in block ? /* @__PURE__ */ jsx(SlackFileFields, { block, onChange }) : source === "upload" && upload ? /* @__PURE__ */ jsx(
|
|
9183
|
+
UploadDropZone,
|
|
9184
|
+
{
|
|
9185
|
+
upload,
|
|
9186
|
+
inputId: "img-upload",
|
|
9187
|
+
variant: "panel",
|
|
9188
|
+
onUploaded: (url) => onChange({ ...block, image_url: url })
|
|
9189
|
+
}
|
|
9190
|
+
) : /* @__PURE__ */ jsx(EditorField, { label: "Image URL", help: "A publicly accessible image URL (PNG, JPG, GIF).", htmlFor: "img-url", children: /* @__PURE__ */ jsx(
|
|
8934
9191
|
Input,
|
|
8935
9192
|
{
|
|
8936
9193
|
id: "img-url",
|
|
@@ -10113,13 +10370,12 @@ function ImageAccessoryFields({ image, onChange }) {
|
|
|
10113
10370
|
help: "A publicly accessible image URL (PNG, JPG, GIF).",
|
|
10114
10371
|
htmlFor: "section-acc-img-url",
|
|
10115
10372
|
children: /* @__PURE__ */ jsx(
|
|
10116
|
-
|
|
10373
|
+
ImageUrlInput,
|
|
10117
10374
|
{
|
|
10118
10375
|
id: "section-acc-img-url",
|
|
10119
|
-
type: "url",
|
|
10120
10376
|
value: image.image_url ?? "",
|
|
10121
10377
|
placeholder: "e.g. https://example.com/thumb.png",
|
|
10122
|
-
onChange: (
|
|
10378
|
+
onChange: (url) => onChange({ ...image, image_url: url })
|
|
10123
10379
|
}
|
|
10124
10380
|
)
|
|
10125
10381
|
}
|
|
@@ -10482,10 +10738,24 @@ function BlockEditor({
|
|
|
10482
10738
|
const custom = useCustomBlockEditor(block);
|
|
10483
10739
|
const CustomForm = custom?.component;
|
|
10484
10740
|
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-3", children: [
|
|
10485
|
-
/* @__PURE__ */
|
|
10486
|
-
"
|
|
10487
|
-
|
|
10488
|
-
|
|
10741
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between gap-2", children: [
|
|
10742
|
+
/* @__PURE__ */ jsxs("h3", { className: "text-sm font-semibold text-foreground", children: [
|
|
10743
|
+
"Edit ",
|
|
10744
|
+
custom ? custom.label : labelForBlockType(block.type)
|
|
10745
|
+
] }),
|
|
10746
|
+
onDone ? /* @__PURE__ */ jsx(
|
|
10747
|
+
Button,
|
|
10748
|
+
{
|
|
10749
|
+
type: "button",
|
|
10750
|
+
variant: "ghost",
|
|
10751
|
+
size: "icon",
|
|
10752
|
+
"aria-label": "Close editor",
|
|
10753
|
+
className: "-my-1 -mr-1 h-7 w-7 text-muted-foreground",
|
|
10754
|
+
onClick: onDone,
|
|
10755
|
+
children: /* @__PURE__ */ jsx(X, {})
|
|
10756
|
+
}
|
|
10757
|
+
) : null
|
|
10758
|
+
] }),
|
|
10489
10759
|
errors && errors.length > 0 ? /* @__PURE__ */ jsx("ul", { className: "flex flex-col gap-0.5 rounded-md border border-destructive/30 bg-destructive/5 p-2 text-xs text-destructive", children: errors.map((err, i) => /* @__PURE__ */ jsx("li", { children: err }, i)) }) : null,
|
|
10490
10760
|
CustomForm ? /* @__PURE__ */ jsx(CustomForm, { block, onChange }) : dispatch(block, onChange),
|
|
10491
10761
|
/* @__PURE__ */ jsx(
|
|
@@ -10647,15 +10917,23 @@ function BlockRow({
|
|
|
10647
10917
|
children: preview
|
|
10648
10918
|
}
|
|
10649
10919
|
) }),
|
|
10650
|
-
/* @__PURE__ */ jsx(
|
|
10651
|
-
|
|
10920
|
+
/* @__PURE__ */ jsx(
|
|
10921
|
+
PopoverContent,
|
|
10652
10922
|
{
|
|
10653
|
-
|
|
10654
|
-
|
|
10655
|
-
|
|
10656
|
-
|
|
10923
|
+
className: "w-[min(32rem,calc(100vw-1.5rem))] sm:w-[32rem]",
|
|
10924
|
+
align: "start",
|
|
10925
|
+
onCloseAutoFocus: returnFocusUnlessMoved,
|
|
10926
|
+
children: /* @__PURE__ */ jsx(
|
|
10927
|
+
BlockEditor,
|
|
10928
|
+
{
|
|
10929
|
+
block: builderBlock.block,
|
|
10930
|
+
errors,
|
|
10931
|
+
onChange: (next) => onUpdate(builderBlock.id, next),
|
|
10932
|
+
onDone: () => onOpenChange?.(false)
|
|
10933
|
+
}
|
|
10934
|
+
)
|
|
10657
10935
|
}
|
|
10658
|
-
)
|
|
10936
|
+
)
|
|
10659
10937
|
] });
|
|
10660
10938
|
const adornment = position && renderBlockAdornment?.(position);
|
|
10661
10939
|
const hoverChrome = /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -10921,7 +11199,7 @@ function ContainerRow({
|
|
|
10921
11199
|
hasErrors ? "border-destructive/60" : "border-border"
|
|
10922
11200
|
),
|
|
10923
11201
|
children: [
|
|
10924
|
-
/* @__PURE__ */ jsxs(Popover, { open: isOpen, onOpenChange: (open) => onOpenBlockChange?.(
|
|
11202
|
+
/* @__PURE__ */ jsxs(Popover, { open: isOpen, onOpenChange: (open) => onOpenBlockChange?.(id, open), children: [
|
|
10925
11203
|
/* @__PURE__ */ jsx(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
|
|
10926
11204
|
"div",
|
|
10927
11205
|
{
|
|
@@ -10933,7 +11211,7 @@ function ContainerRow({
|
|
|
10933
11211
|
onKeyDown: (e) => {
|
|
10934
11212
|
if (e.key === "Enter" || e.key === " ") {
|
|
10935
11213
|
e.preventDefault();
|
|
10936
|
-
onOpenBlockChange?.(!isOpen
|
|
11214
|
+
onOpenBlockChange?.(id, !isOpen);
|
|
10937
11215
|
}
|
|
10938
11216
|
},
|
|
10939
11217
|
className: "flex w-full cursor-grab items-center gap-2 border-b bg-muted/40 px-3 py-2 text-left transition-colors hover:bg-muted active:cursor-grabbing",
|
|
@@ -10947,15 +11225,23 @@ function ContainerRow({
|
|
|
10947
11225
|
]
|
|
10948
11226
|
}
|
|
10949
11227
|
) }),
|
|
10950
|
-
/* @__PURE__ */ jsx(
|
|
10951
|
-
|
|
11228
|
+
/* @__PURE__ */ jsx(
|
|
11229
|
+
PopoverContent,
|
|
10952
11230
|
{
|
|
10953
|
-
|
|
10954
|
-
|
|
10955
|
-
|
|
10956
|
-
|
|
11231
|
+
className: "w-[min(32rem,calc(100vw-1.5rem))] sm:w-[32rem]",
|
|
11232
|
+
align: "start",
|
|
11233
|
+
onCloseAutoFocus: returnFocusUnlessMoved,
|
|
11234
|
+
children: /* @__PURE__ */ jsx(
|
|
11235
|
+
BlockEditor,
|
|
11236
|
+
{
|
|
11237
|
+
block,
|
|
11238
|
+
errors,
|
|
11239
|
+
onChange: (next) => onUpdate(id, next),
|
|
11240
|
+
onDone: () => onOpenBlockChange?.(id, false)
|
|
11241
|
+
}
|
|
11242
|
+
)
|
|
10957
11243
|
}
|
|
10958
|
-
)
|
|
11244
|
+
)
|
|
10959
11245
|
] }),
|
|
10960
11246
|
/* @__PURE__ */ jsx(
|
|
10961
11247
|
"div",
|
|
@@ -10984,7 +11270,7 @@ function ContainerRow({
|
|
|
10984
11270
|
previewTheme,
|
|
10985
11271
|
errors: errorsByBlockId?.get(child.id),
|
|
10986
11272
|
isOpen: openBlockId === child.id,
|
|
10987
|
-
onOpenChange: (open) => onOpenBlockChange?.(
|
|
11273
|
+
onOpenChange: (open) => onOpenBlockChange?.(child.id, open),
|
|
10988
11274
|
onUpdate,
|
|
10989
11275
|
onDuplicate,
|
|
10990
11276
|
onDelete,
|
|
@@ -11019,7 +11305,7 @@ function ContainerRow({
|
|
|
11019
11305
|
{
|
|
11020
11306
|
type: "button",
|
|
11021
11307
|
"aria-label": `Show ${errors.length} validation ${errors.length === 1 ? "issue" : "issues"}`,
|
|
11022
|
-
onClick: () => onOpenBlockChange?.(id),
|
|
11308
|
+
onClick: () => onOpenBlockChange?.(id, true),
|
|
11023
11309
|
className: "flex h-6 w-6 items-center justify-center rounded text-destructive hover:bg-destructive/10 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
11024
11310
|
children: /* @__PURE__ */ jsx(AlertTriangle, { className: "h-3.5 w-3.5" })
|
|
11025
11311
|
}
|
|
@@ -11038,7 +11324,7 @@ function ContainerRow({
|
|
|
11038
11324
|
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Move down", disabled: index >= total - 1, onClick: () => onReorder(id, index + 1), children: /* @__PURE__ */ jsx(ArrowDown, { className: "h-3.5 w-3.5" }) })
|
|
11039
11325
|
] }) : null,
|
|
11040
11326
|
/* @__PURE__ */ jsx(BlockActionButtons, { actions: blockActions, position, variant: "toolbar" }),
|
|
11041
|
-
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Edit", onClick: () => onOpenBlockChange?.(id), children: /* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" }) }),
|
|
11327
|
+
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Edit", onClick: () => onOpenBlockChange?.(id, true), children: /* @__PURE__ */ jsx(Pencil, { className: "h-3.5 w-3.5" }) }),
|
|
11042
11328
|
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Duplicate", onClick: () => onDuplicate(id), children: /* @__PURE__ */ jsx(Copy, { className: "h-3.5 w-3.5" }) }),
|
|
11043
11329
|
/* @__PURE__ */ jsx(ToolbarButton2, { label: "Delete", destructive: true, onClick: () => onDelete(id), children: /* @__PURE__ */ jsx(Trash2, { className: "h-3.5 w-3.5" }) })
|
|
11044
11330
|
]
|
|
@@ -11071,7 +11357,7 @@ function ContainerRow({
|
|
|
11071
11357
|
{
|
|
11072
11358
|
type: "button",
|
|
11073
11359
|
"aria-label": "Edit container",
|
|
11074
|
-
onClick: () => onOpenBlockChange?.(id),
|
|
11360
|
+
onClick: () => onOpenBlockChange?.(id, true),
|
|
11075
11361
|
className: "flex h-9 w-9 items-center justify-center rounded text-muted-foreground hover:bg-accent hover:text-foreground",
|
|
11076
11362
|
children: /* @__PURE__ */ jsx(Pencil, { className: "h-4 w-4" })
|
|
11077
11363
|
}
|
|
@@ -11149,10 +11435,14 @@ function Surface({
|
|
|
11149
11435
|
isPaletteDrag = false,
|
|
11150
11436
|
onOpenPalette,
|
|
11151
11437
|
blockActions,
|
|
11152
|
-
renderBlockAdornment
|
|
11438
|
+
renderBlockAdornment,
|
|
11439
|
+
onAddBlock,
|
|
11440
|
+
imageDropEnabled = true
|
|
11153
11441
|
}) {
|
|
11154
11442
|
const { setNodeRef, isOver } = useDroppable({ id: SURFACE_DROPPABLE_ID });
|
|
11155
11443
|
const isDark = previewTheme === "dark";
|
|
11444
|
+
const imageDrop = useCanvasImageDrop({ upload: useImageUpload(), enabled: imageDropEnabled, onAddBlock });
|
|
11445
|
+
const isDropTarget = isPaletteDrag || imageDrop.dragging;
|
|
11156
11446
|
const showEndDropZone = isPaletteDrag && isOver && blocks.length > 0;
|
|
11157
11447
|
const blocksList = /* @__PURE__ */ jsx(
|
|
11158
11448
|
"div",
|
|
@@ -11161,10 +11451,19 @@ function Surface({
|
|
|
11161
11451
|
className: cn(
|
|
11162
11452
|
"flex min-h-[180px] flex-col px-3 py-2 transition-colors sm:min-h-[240px] sm:px-5",
|
|
11163
11453
|
isDark ? "bg-[#1a1d21]" : "bg-white",
|
|
11164
|
-
|
|
11165
|
-
isPaletteDrag && isOver && (isDark ? "bg-[#2c3036]" : "bg-[#eaf0ff]")
|
|
11454
|
+
isDropTarget && (isDark ? "bg-[#22262c] outline-2 outline-primary/40 -outline-offset-2 outline-dashed" : "bg-[#f5f8ff] outline-2 outline-primary/40 -outline-offset-2 outline-dashed"),
|
|
11455
|
+
(isPaletteDrag && isOver || imageDrop.dragging) && (isDark ? "bg-[#2c3036]" : "bg-[#eaf0ff]")
|
|
11166
11456
|
),
|
|
11167
|
-
children: blocks.length === 0 ? /* @__PURE__ */ jsx(
|
|
11457
|
+
children: blocks.length === 0 ? /* @__PURE__ */ jsx(
|
|
11458
|
+
EmptyState,
|
|
11459
|
+
{
|
|
11460
|
+
isDark,
|
|
11461
|
+
isPaletteDrag,
|
|
11462
|
+
isOver,
|
|
11463
|
+
isFileDrag: imageDrop.dragging,
|
|
11464
|
+
onOpenPalette
|
|
11465
|
+
}
|
|
11466
|
+
) : /* @__PURE__ */ jsxs(SortableContext, { items: blocks.map((b) => b.id), strategy: verticalListSortingStrategy, children: [
|
|
11168
11467
|
blocks.map(
|
|
11169
11468
|
(block, idx) => block.block.type === "container" ? /* @__PURE__ */ jsx(
|
|
11170
11469
|
ContainerRow,
|
|
@@ -11194,7 +11493,7 @@ function Surface({
|
|
|
11194
11493
|
previewTheme,
|
|
11195
11494
|
errors: errorsByBlockId?.get(block.id),
|
|
11196
11495
|
isOpen: openBlockId === block.id,
|
|
11197
|
-
onOpenChange: (open) => onOpenBlockChange?.(
|
|
11496
|
+
onOpenChange: (open) => onOpenBlockChange?.(block.id, open),
|
|
11198
11497
|
onUpdate,
|
|
11199
11498
|
onDuplicate,
|
|
11200
11499
|
onDelete,
|
|
@@ -11209,7 +11508,7 @@ function Surface({
|
|
|
11209
11508
|
block.id
|
|
11210
11509
|
)
|
|
11211
11510
|
),
|
|
11212
|
-
showEndDropZone ? /* @__PURE__ */ jsx(DropIndicator2, {}) : null
|
|
11511
|
+
showEndDropZone || imageDrop.dragging ? /* @__PURE__ */ jsx(DropIndicator2, {}) : null
|
|
11213
11512
|
] })
|
|
11214
11513
|
}
|
|
11215
11514
|
);
|
|
@@ -11218,16 +11517,28 @@ function Surface({
|
|
|
11218
11517
|
{
|
|
11219
11518
|
"aria-label": "Block preview",
|
|
11220
11519
|
className: cn("flex min-w-0 flex-1 flex-col overflow-y-auto bg-muted p-3 sm:p-6"),
|
|
11221
|
-
|
|
11222
|
-
|
|
11223
|
-
|
|
11224
|
-
|
|
11225
|
-
|
|
11226
|
-
|
|
11227
|
-
|
|
11228
|
-
|
|
11229
|
-
|
|
11230
|
-
|
|
11520
|
+
...imageDrop.handlers,
|
|
11521
|
+
children: /* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-2xl", children: [
|
|
11522
|
+
imageDrop.handlers ? /* @__PURE__ */ jsx(
|
|
11523
|
+
ImageDropStatus,
|
|
11524
|
+
{
|
|
11525
|
+
dragging: imageDrop.dragging,
|
|
11526
|
+
pending: imageDrop.pending,
|
|
11527
|
+
error: imageDrop.error,
|
|
11528
|
+
onDismissError: imageDrop.dismissError
|
|
11529
|
+
}
|
|
11530
|
+
) : null,
|
|
11531
|
+
previewSurface === "modal" ? /* @__PURE__ */ jsx(ModalFrame, { isDark, children: blocksList }) : previewSurface === "app_home" ? /* @__PURE__ */ jsx(AppHomeFrame, { workspaceName, isDark, children: blocksList }) : /* @__PURE__ */ jsx(
|
|
11532
|
+
SlackMessageFrame,
|
|
11533
|
+
{
|
|
11534
|
+
workspaceName,
|
|
11535
|
+
authorName,
|
|
11536
|
+
authorIcon,
|
|
11537
|
+
isDark,
|
|
11538
|
+
children: blocksList
|
|
11539
|
+
}
|
|
11540
|
+
)
|
|
11541
|
+
] })
|
|
11231
11542
|
}
|
|
11232
11543
|
);
|
|
11233
11544
|
}
|
|
@@ -11356,9 +11667,10 @@ function EmptyState({
|
|
|
11356
11667
|
isDark,
|
|
11357
11668
|
isPaletteDrag,
|
|
11358
11669
|
isOver,
|
|
11670
|
+
isFileDrag: isFileDrag2 = false,
|
|
11359
11671
|
onOpenPalette
|
|
11360
11672
|
}) {
|
|
11361
|
-
const active = isPaletteDrag && isOver;
|
|
11673
|
+
const active = isPaletteDrag && isOver || isFileDrag2;
|
|
11362
11674
|
return /* @__PURE__ */ jsxs(
|
|
11363
11675
|
"div",
|
|
11364
11676
|
{
|
|
@@ -11385,7 +11697,7 @@ function EmptyState({
|
|
|
11385
11697
|
"text-sm font-semibold transition-colors",
|
|
11386
11698
|
active ? "text-primary" : isDark ? "text-white" : "text-[#1d1c1d]"
|
|
11387
11699
|
),
|
|
11388
|
-
children: active ? "Drop to add block" : "Start adding blocks!"
|
|
11700
|
+
children: isFileDrag2 ? "Drop to add image" : active ? "Drop to add block" : "Start adding blocks!"
|
|
11389
11701
|
}
|
|
11390
11702
|
),
|
|
11391
11703
|
/* @__PURE__ */ jsx("p", { className: "text-xs", children: active ? "Release to insert it here." : /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
@@ -11409,6 +11721,40 @@ function EmptyState({
|
|
|
11409
11721
|
}
|
|
11410
11722
|
);
|
|
11411
11723
|
}
|
|
11724
|
+
function ImageDropStatus({
|
|
11725
|
+
dragging,
|
|
11726
|
+
pending,
|
|
11727
|
+
error,
|
|
11728
|
+
onDismissError
|
|
11729
|
+
}) {
|
|
11730
|
+
const progress = dragging ? "Drop images to add them at the end of the message." : pending > 0 ? `Uploading ${pending === 1 ? "1 image" : `${pending} images`}\u2026` : null;
|
|
11731
|
+
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
11732
|
+
/* @__PURE__ */ jsx("div", { role: "status", className: "empty:hidden", children: progress ? /* @__PURE__ */ jsxs("p", { className: "mb-2 flex items-center gap-1.5 text-xs text-muted-foreground", children: [
|
|
11733
|
+
/* @__PURE__ */ jsx(ImagePlus, { className: cn("h-3.5 w-3.5", pending > 0 && !dragging && "animate-pulse"), "aria-hidden": "true" }),
|
|
11734
|
+
progress
|
|
11735
|
+
] }) : null }),
|
|
11736
|
+
error ? /* @__PURE__ */ jsxs(
|
|
11737
|
+
"div",
|
|
11738
|
+
{
|
|
11739
|
+
role: "alert",
|
|
11740
|
+
className: "mb-2 flex items-start gap-2 rounded-md border border-destructive/40 bg-destructive/10 px-3 py-2 text-xs text-destructive",
|
|
11741
|
+
children: [
|
|
11742
|
+
/* @__PURE__ */ jsx("p", { className: "flex-1", children: error }),
|
|
11743
|
+
/* @__PURE__ */ jsx(
|
|
11744
|
+
"button",
|
|
11745
|
+
{
|
|
11746
|
+
type: "button",
|
|
11747
|
+
"aria-label": "Dismiss",
|
|
11748
|
+
onClick: onDismissError,
|
|
11749
|
+
className: "rounded p-0.5 hover:bg-destructive/10 focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-ring",
|
|
11750
|
+
children: /* @__PURE__ */ jsx(X, { className: "h-3.5 w-3.5" })
|
|
11751
|
+
}
|
|
11752
|
+
)
|
|
11753
|
+
]
|
|
11754
|
+
}
|
|
11755
|
+
) : null
|
|
11756
|
+
] });
|
|
11757
|
+
}
|
|
11412
11758
|
function DropIndicator2() {
|
|
11413
11759
|
return /* @__PURE__ */ jsx("div", { "aria-hidden": "true", className: "pointer-events-none relative my-1 h-0.5 w-full rounded-full bg-primary", children: /* @__PURE__ */ jsx("span", { className: "-left-1 -top-[3px] absolute h-2 w-2 rounded-full bg-primary shadow-[0_0_0_2px_var(--color-background)]" }) });
|
|
11414
11760
|
}
|
|
@@ -11971,6 +12317,7 @@ function BlockKitchen(props) {
|
|
|
11971
12317
|
blockEditors,
|
|
11972
12318
|
customEmojis,
|
|
11973
12319
|
mentions,
|
|
12320
|
+
imageUpload,
|
|
11974
12321
|
loadChannels,
|
|
11975
12322
|
loadSendAsUserStatus,
|
|
11976
12323
|
onSend,
|
|
@@ -12101,6 +12448,9 @@ function BlockKitchen(props) {
|
|
|
12101
12448
|
setPaletteAdvanced(false);
|
|
12102
12449
|
}
|
|
12103
12450
|
const [openBlockId, setOpenBlockId] = useState(null);
|
|
12451
|
+
const setBlockOpen = useCallback((id, open) => {
|
|
12452
|
+
setOpenBlockId((current) => open ? id : current === id ? null : current);
|
|
12453
|
+
}, []);
|
|
12104
12454
|
const [uncontrolledPreviewTheme, setUncontrolledPreviewTheme] = useState(defaultPreviewTheme);
|
|
12105
12455
|
const isPreviewThemeControlled = controlledPreviewTheme !== void 0;
|
|
12106
12456
|
const previewTheme = controlledPreviewTheme ?? uncontrolledPreviewTheme;
|
|
@@ -12354,7 +12704,7 @@ function BlockKitchen(props) {
|
|
|
12354
12704
|
}
|
|
12355
12705
|
)
|
|
12356
12706
|
] }),
|
|
12357
|
-
/* @__PURE__ */ jsx(MentionsProvider, { mentions, children: /* @__PURE__ */ jsx(BlockEditorsProvider, { blockEditors, children: /* @__PURE__ */ jsx(
|
|
12707
|
+
/* @__PURE__ */ jsx(MentionsProvider, { mentions, children: /* @__PURE__ */ jsx(ImageUploadProvider, { imageUpload, children: /* @__PURE__ */ jsx(BlockEditorsProvider, { blockEditors, children: /* @__PURE__ */ jsx(
|
|
12358
12708
|
Surface,
|
|
12359
12709
|
{
|
|
12360
12710
|
blocks,
|
|
@@ -12366,7 +12716,7 @@ function BlockKitchen(props) {
|
|
|
12366
12716
|
previewSurface,
|
|
12367
12717
|
errorsByBlockId: validation.byBlockId,
|
|
12368
12718
|
openBlockId,
|
|
12369
|
-
onOpenBlockChange:
|
|
12719
|
+
onOpenBlockChange: setBlockOpen,
|
|
12370
12720
|
onUpdate: updateBlock,
|
|
12371
12721
|
onDuplicate: duplicateBlock,
|
|
12372
12722
|
onDelete: removeBlock,
|
|
@@ -12374,9 +12724,11 @@ function BlockKitchen(props) {
|
|
|
12374
12724
|
isPaletteDrag: activePaletteVariant !== null,
|
|
12375
12725
|
onOpenPalette: () => setPaletteOpen(true),
|
|
12376
12726
|
blockActions,
|
|
12377
|
-
renderBlockAdornment
|
|
12727
|
+
renderBlockAdornment,
|
|
12728
|
+
onAddBlock: addBlock,
|
|
12729
|
+
imageDropEnabled: !disabledBlockTypes?.includes("image")
|
|
12378
12730
|
}
|
|
12379
|
-
) }) })
|
|
12731
|
+
) }) }) })
|
|
12380
12732
|
] })
|
|
12381
12733
|
]
|
|
12382
12734
|
}
|