@particle-academy/react-fancy 5.43.0 → 5.44.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +31 -0
- package/dist/{Composer.types-CuSPnaOt.d.cts → PastePills.types-CDyotkUb.d.cts} +35 -82
- package/dist/{Composer.types-CuSPnaOt.d.ts → PastePills.types-CDyotkUb.d.ts} +35 -82
- package/dist/PastedFilesInput-CrgNoEBd.d.ts +141 -0
- package/dist/PastedFilesInput-DQ1eZaHk.d.cts +141 -0
- package/dist/{chunk-IPNJMHJ3.cjs → chunk-2QIGXSSZ.cjs} +105 -3
- package/dist/chunk-2QIGXSSZ.cjs.map +1 -0
- package/dist/{chunk-BZOU7VJQ.cjs → chunk-BR27AXFE.cjs} +16 -10
- package/dist/chunk-BR27AXFE.cjs.map +1 -0
- package/dist/{chunk-G4WYCWIQ.js → chunk-DMFJJ73P.js} +3 -3
- package/dist/{chunk-G4WYCWIQ.js.map → chunk-DMFJJ73P.js.map} +1 -1
- package/dist/{chunk-2VIDYJUG.js → chunk-EEWRLFTI.js} +107 -5
- package/dist/chunk-EEWRLFTI.js.map +1 -0
- package/dist/{chunk-SF5OAVGD.js → chunk-JZCAMPIA.js} +12 -4
- package/dist/chunk-JZCAMPIA.js.map +1 -0
- package/dist/{chunk-2JOWGYAJ.js → chunk-KYZNCVRD.js} +213 -179
- package/dist/chunk-KYZNCVRD.js.map +1 -0
- package/dist/{chunk-MXAVGOHW.js → chunk-L637KPEA.js} +12 -6
- package/dist/chunk-L637KPEA.js.map +1 -0
- package/dist/{chunk-6TZPM43Q.cjs → chunk-MSRYJETY.cjs} +219 -178
- package/dist/chunk-MSRYJETY.cjs.map +1 -0
- package/dist/{chunk-K4NHVCY6.cjs → chunk-S5ZYG5MG.cjs} +8 -8
- package/dist/{chunk-K4NHVCY6.cjs.map → chunk-S5ZYG5MG.cjs.map} +1 -1
- package/dist/{chunk-UUBHUSUP.cjs → chunk-Z3FIU77M.cjs} +14 -6
- package/dist/chunk-Z3FIU77M.cjs.map +1 -0
- package/dist/composer.cjs +4 -4
- package/dist/composer.d.cts +93 -3
- package/dist/composer.d.ts +93 -3
- package/dist/composer.js +2 -2
- package/dist/{index-S4FC1yFK.d.ts → index-BF5qsQur.d.cts} +8 -2
- package/dist/{index-BsIBOwaK.d.cts → index-BZON-gXr.d.ts} +8 -2
- package/dist/index.cjs +75 -63
- package/dist/index.d.cts +4 -3
- package/dist/index.d.ts +4 -3
- package/dist/index.js +12 -12
- package/dist/input.cjs +6 -2
- package/dist/input.d.cts +34 -0
- package/dist/input.d.ts +34 -0
- package/dist/input.js +5 -1
- package/dist/inputs.cjs +8 -6
- package/dist/inputs.d.cts +1 -0
- package/dist/inputs.d.ts +1 -0
- package/dist/inputs.js +4 -2
- package/dist/json-editor.cjs +15 -13
- package/dist/json-editor.js +4 -2
- package/dist/paste-pills.cjs +65 -0
- package/dist/paste-pills.cjs.map +1 -0
- package/dist/paste-pills.d.cts +34 -0
- package/dist/paste-pills.d.ts +34 -0
- package/dist/paste-pills.js +8 -0
- package/dist/paste-pills.js.map +1 -0
- package/dist/prompt-input.cjs +3 -3
- package/dist/prompt-input.d.cts +2 -2
- package/dist/prompt-input.d.ts +2 -2
- package/dist/prompt-input.js +2 -2
- package/package.json +11 -1
- package/dist/chunk-2JOWGYAJ.js.map +0 -1
- package/dist/chunk-2VIDYJUG.js.map +0 -1
- package/dist/chunk-6TZPM43Q.cjs.map +0 -1
- package/dist/chunk-BZOU7VJQ.cjs.map +0 -1
- package/dist/chunk-IPNJMHJ3.cjs.map +0 -1
- package/dist/chunk-MXAVGOHW.js.map +0 -1
- package/dist/chunk-SF5OAVGD.js.map +0 -1
- package/dist/chunk-UUBHUSUP.cjs.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
import { useInlinePaste, withSeparators, endsOf, InlinePasteEditor } from './chunk-
|
|
1
|
+
import { useInlinePaste, withSeparators, endsOf, InlinePasteEditor, PastedFilesInput } from './chunk-KYZNCVRD.js';
|
|
2
2
|
import { useControllableState } from './chunk-EDYAXGUM.js';
|
|
3
3
|
import { cn } from './chunk-MMW2JGKZ.js';
|
|
4
|
-
import { forwardRef, useRef, useCallback } from 'react';
|
|
4
|
+
import { forwardRef, useRef, useMemo, useCallback } from 'react';
|
|
5
5
|
import { jsxs, jsx, Fragment } from 'react/jsx-runtime';
|
|
6
6
|
|
|
7
7
|
var PREVIEW_CHARS = 20;
|
|
@@ -24,7 +24,8 @@ var Composer = forwardRef(
|
|
|
24
24
|
heldPastes: controlledHeldPastes,
|
|
25
25
|
onHeldPastesChange,
|
|
26
26
|
heldImages: controlledHeldImages,
|
|
27
|
-
onHeldImagesChange
|
|
27
|
+
onHeldImagesChange,
|
|
28
|
+
pasteFilesName
|
|
28
29
|
}, ref) {
|
|
29
30
|
const inline = pastePlacement === "inline";
|
|
30
31
|
const [value, setValue] = useControllableState(
|
|
@@ -49,6 +50,10 @@ var Composer = forwardRef(
|
|
|
49
50
|
});
|
|
50
51
|
const pills = paste.pills;
|
|
51
52
|
const heldPastes = paste.heldPastes;
|
|
53
|
+
const pastedFiles = useMemo(
|
|
54
|
+
() => inline && pasteImages ? paste.imagesIn(value).map((i) => i.file) : [],
|
|
55
|
+
[inline, pasteImages, paste, value]
|
|
56
|
+
);
|
|
52
57
|
const handlePaste = useCallback(
|
|
53
58
|
(e) => {
|
|
54
59
|
pills.handlePaste(e);
|
|
@@ -186,7 +191,8 @@ ${text}` : text);
|
|
|
186
191
|
className: classNames?.input
|
|
187
192
|
}
|
|
188
193
|
),
|
|
189
|
-
paste.portals
|
|
194
|
+
paste.portals,
|
|
195
|
+
pasteImages && pasteFilesName && /* @__PURE__ */ jsx(PastedFilesInput, { name: pasteFilesName, files: pastedFiles })
|
|
190
196
|
] }) : /* @__PURE__ */ jsx(
|
|
191
197
|
"textarea",
|
|
192
198
|
{
|
|
@@ -225,5 +231,5 @@ ${text}` : text);
|
|
|
225
231
|
Composer.displayName = "Composer";
|
|
226
232
|
|
|
227
233
|
export { Composer };
|
|
228
|
-
//# sourceMappingURL=chunk-
|
|
229
|
-
//# sourceMappingURL=chunk-
|
|
234
|
+
//# sourceMappingURL=chunk-L637KPEA.js.map
|
|
235
|
+
//# sourceMappingURL=chunk-L637KPEA.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/components/Composer/Composer.tsx"],"names":["Composer","paste"],"mappings":"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","file":"chunk-L637KPEA.js","sourcesContent":["import { forwardRef, useCallback, useMemo, useRef } from \"react\";\nimport { cn } from \"../../utils/cn\";\nimport { useControllableState } from \"../../hooks/use-controllable-state\";\nimport {\n endsOf,\n InlinePasteEditor,\n PastedFilesInput,\n useInlinePaste,\n withSeparators,\n type HeldPaste,\n type InlinePasteEditorHandle,\n} from \"../PastePills\";\nimport type { ComposerProps } from \"./Composer.types\";\n\n/** Characters of a held paste shown at each end of the hover preview, unless `previewChars` says otherwise. */\nconst PREVIEW_CHARS = 20;\n\nexport const Composer = forwardRef<HTMLDivElement, ComposerProps>(\n function Composer(\n {\n value: controlledValue,\n defaultValue = \"\",\n onChange,\n onSubmit,\n placeholder = \"Type a message...\",\n actions,\n disabled = false,\n className,\n pasteThreshold,\n pastePlacement = \"above\",\n pasteImages = false,\n previewChars = PREVIEW_CHARS,\n renderPastePreview,\n classNames,\n heldPastes: controlledHeldPastes,\n onHeldPastesChange,\n heldImages: controlledHeldImages,\n onHeldImagesChange,\n pasteFilesName,\n },\n ref,\n ) {\n const inline = pastePlacement === \"inline\";\n const [value, setValue] = useControllableState(\n controlledValue,\n defaultValue,\n onChange,\n );\n const textareaRef = useRef<HTMLTextAreaElement>(null);\n const editorRef = useRef<InlinePasteEditorHandle>(null);\n /*\n * The holding logic lives in `usePastePills`, wrapped by `useInlinePaste` for\n * the inline placement — which `PromptInput` shares, so the two components\n * cannot disagree about what a pill means. The rule that must not drift is\n * the one below: a send with pills still closed carries the text.\n */\n const paste = useInlinePaste({\n pasteThreshold,\n pasteImages,\n previewChars,\n renderPastePreview,\n classNames,\n disabled,\n heldPastes: controlledHeldPastes,\n onHeldPastesChange,\n heldImages: controlledHeldImages,\n onHeldImagesChange,\n editorRef,\n });\n const pills = paste.pills;\n const heldPastes = paste.heldPastes;\n const pastedFiles = useMemo(\n () => (inline && pasteImages ? paste.imagesIn(value).map((i) => i.file) : []),\n [inline, pasteImages, paste, value],\n );\n\n const handlePaste = useCallback(\n (e: React.ClipboardEvent<HTMLTextAreaElement>) => {\n // Composable by design, so this reads as a question rather than a handover.\n // Nothing else here wants the paste, so the answer is simply ignored.\n pills.handlePaste(e);\n },\n [pills],\n );\n\n const handleInlineChange = useCallback(\n (next: string) => {\n setValue(next);\n paste.prune(next);\n },\n [setValue, paste],\n );\n\n /** Everything the person believes they are sending, in the order they built it. */\n const composeOutgoing = useCallback(() => {\n if (inline) return paste.expand(value);\n\n return [value, ...heldPastes.map((p) => p.text)].filter(Boolean).join(\"\\n\\n\");\n }, [inline, value, heldPastes, paste]);\n\n const hasContent = value.trim().length > 0 || (!inline && heldPastes.length > 0);\n\n const focusInput = useCallback(() => {\n if (inline) editorRef.current?.focus();\n else textareaRef.current?.focus();\n }, [inline]);\n\n const handleSubmit = useCallback(() => {\n if (!hasContent || disabled) return;\n\n /*\n * THE DANGEROUS STATE, and the reason this feature needed a spec rather than\n * a guess. A pill reads as \"your paste is attached\" — so a send that drops it\n * means asking a question about a document without the document, and nobody\n * can tell: the sender believes it went, the receiver sees a question about\n * nothing.\n *\n * Above the input, held pastes go out in arrival order after what was typed,\n * because people type the question BEFORE pasting the thing it is about.\n * Inline, every pill goes out exactly where it sits.\n */\n const images = inline ? paste.imagesIn(value) : [];\n\n onSubmit?.(composeOutgoing(), { images });\n setValue(\"\");\n paste.clear();\n focusInput();\n }, [hasContent, disabled, value, inline, paste, onSubmit, composeOutgoing, setValue, focusInput]);\n\n const handleKeyDown = (e: React.KeyboardEvent<HTMLTextAreaElement>) => {\n if (e.key === \"Enter\" && !e.shiftKey) {\n e.preventDefault();\n handleSubmit();\n }\n };\n\n /** Above the input: click a pill to dump it in, APPENDED to what is already typed. */\n const insertPaste = useCallback(\n (held: HeldPaste) => {\n // `expand` removes it and hands back the text; inserting is this\n // component's job because the hook owns no DOM.\n const text = pills.expand(held.id);\n\n if (text === undefined) return;\n\n setValue((current) => (current ? `${current}\\n\\n${text}` : text));\n textareaRef.current?.focus();\n },\n [pills, setValue],\n );\n\n return (\n <div\n data-react-fancy-composer=\"\"\n ref={ref}\n className={cn(\n \"rounded-xl border border-zinc-200 bg-white dark:border-zinc-700 dark:bg-zinc-900\",\n disabled && \"opacity-50\",\n className,\n )}\n >\n {!inline && heldPastes.length > 0 && (\n <div\n data-react-fancy-composer-paste-pills=\"\"\n className=\"flex flex-wrap gap-1.5 px-3 pt-3\"\n >\n {heldPastes.map((paste) => (\n // `group` + `group-hover` rather than hover state: the preview is\n // presentation, and a useState for it would be one more thing an\n // agent could desynchronise.\n <span key={paste.id} className=\"group relative inline-flex\">\n <button\n type=\"button\"\n data-react-fancy-composer-paste-pill={paste.id}\n onClick={() => insertPaste(paste)}\n disabled={disabled}\n // No `title`. A native tooltip plus the hover preview below\n // renders TWO tooltips on the same hover, at different delays.\n // The label says what clicking does; the preview says what the\n // text is, and it is linked rather than merely adjacent so a\n // screen reader reaches it too.\n aria-label={`Insert this pasted text, ${withSeparators(paste.text.length)} characters`}\n aria-describedby={`${paste.id}-preview`}\n // `pr-7` leaves room for the absolutely-positioned × that sits\n // over this button's right edge. With a smaller right padding the\n // × lands on top of the label.\n className={cn(\n \"inline-flex items-center gap-1.5 rounded-full border border-zinc-200 bg-zinc-50 py-1 pl-2.5 pr-7 text-xs text-zinc-700 transition-colors hover:bg-zinc-100 dark:border-zinc-700 dark:bg-zinc-800 dark:text-zinc-200 dark:hover:bg-zinc-700\",\n classNames?.pill,\n classNames?.textPill,\n )}\n >\n <span>\n Pasted text · {withSeparators(paste.text.length)} characters\n </span>\n </button>\n\n <button\n type=\"button\"\n data-react-fancy-composer-paste-pill-remove={paste.id}\n onClick={() => pills.remove(paste.id)}\n disabled={disabled}\n aria-label=\"Discard this pasted text\"\n className={cn(\n \"absolute right-1 top-1/2 -translate-y-1/2 rounded-full px-1 text-xs text-zinc-400 transition-colors hover:text-zinc-700 dark:hover:text-zinc-100\",\n classNames?.remove,\n )}\n >\n ×\n </button>\n\n <span\n id={`${paste.id}-preview`}\n data-react-fancy-composer-paste-pill-preview={paste.id}\n role=\"tooltip\"\n className={cn(\n \"pointer-events-none absolute bottom-full left-0 z-10 mb-1 hidden max-w-xs whitespace-pre-wrap break-all rounded-md bg-zinc-900 px-2 py-1 text-xs text-white group-hover:block dark:bg-zinc-100 dark:text-zinc-900\",\n classNames?.preview,\n )}\n >\n {renderPastePreview?.({ kind: \"text\", paste }) ??\n endsOf(paste.text, previewChars)}\n </span>\n </span>\n ))}\n </div>\n )}\n\n {inline ? (\n <>\n <InlinePasteEditor\n ref={editorRef}\n value={value}\n known={paste.known}\n onChange={handleInlineChange}\n onSubmit={handleSubmit}\n onPaste={paste.decidePaste}\n onHostsChange={paste.onHostsChange}\n placeholder={placeholder}\n disabled={disabled}\n className={classNames?.input}\n />\n {paste.portals}\n {pasteImages && pasteFilesName && (\n <PastedFilesInput name={pasteFilesName} files={pastedFiles} />\n )}\n </>\n ) : (\n <textarea\n ref={textareaRef}\n value={value}\n onChange={(e) => setValue(e.target.value)}\n onKeyDown={handleKeyDown}\n onPaste={handlePaste}\n placeholder={placeholder}\n disabled={disabled}\n rows={3}\n className={cn(\n \"w-full resize-none bg-transparent px-4 pt-3 text-sm outline-none placeholder:text-zinc-400\",\n classNames?.input,\n )}\n />\n )}\n <div className=\"flex items-center justify-between border-t border-zinc-100 px-3 py-2 dark:border-zinc-800\">\n <div className=\"flex items-center gap-1\">{actions}</div>\n <button\n type=\"button\"\n onClick={handleSubmit}\n disabled={disabled || !hasContent}\n className=\"rounded-lg bg-zinc-900 px-3 py-1.5 text-sm font-medium text-white transition-colors hover:bg-zinc-800 disabled:opacity-50 dark:bg-white dark:text-zinc-900 dark:hover:bg-zinc-100\"\n >\n Send\n </button>\n </div>\n </div>\n );\n },\n);\n\nComposer.displayName = \"Composer\";\n"]}
|
|
@@ -4,37 +4,9 @@ var chunkX7H75WVP_cjs = require('./chunk-X7H75WVP.cjs');
|
|
|
4
4
|
var chunkSNHU2AI4_cjs = require('./chunk-SNHU2AI4.cjs');
|
|
5
5
|
var chunkZU5Q77OT_cjs = require('./chunk-ZU5Q77OT.cjs');
|
|
6
6
|
var react = require('react');
|
|
7
|
-
var jsxRuntime = require('react/jsx-runtime');
|
|
8
7
|
var reactDom = require('react-dom');
|
|
8
|
+
var jsxRuntime = require('react/jsx-runtime');
|
|
9
9
|
|
|
10
|
-
// src/components/Composer/paste-markers.ts
|
|
11
|
-
var PILL_MARK = "\uFFFC";
|
|
12
|
-
var MARKER = /\uFFFC([^\uFFFC\n]+)\uFFFC/g;
|
|
13
|
-
function pasteMarker(id) {
|
|
14
|
-
return `${PILL_MARK}${id}${PILL_MARK}`;
|
|
15
|
-
}
|
|
16
|
-
function segmentValue(value, known) {
|
|
17
|
-
const out = [];
|
|
18
|
-
let last = 0;
|
|
19
|
-
for (const match of value.matchAll(MARKER)) {
|
|
20
|
-
const id = match[1];
|
|
21
|
-
if (!known.has(id)) continue;
|
|
22
|
-
const start = match.index ?? 0;
|
|
23
|
-
if (start > last) out.push({ type: "text", text: value.slice(last, start) });
|
|
24
|
-
out.push({ type: "pill", id });
|
|
25
|
-
last = start + match[0].length;
|
|
26
|
-
}
|
|
27
|
-
if (last < value.length) out.push({ type: "text", text: value.slice(last) });
|
|
28
|
-
return out;
|
|
29
|
-
}
|
|
30
|
-
function markedIds(value) {
|
|
31
|
-
return Array.from(value.matchAll(MARKER), (m) => m[1]);
|
|
32
|
-
}
|
|
33
|
-
function expandMarkers(value, pastes, images) {
|
|
34
|
-
const text = new Map(pastes.map((p) => [p.id, p.text]));
|
|
35
|
-
const image = new Map(images.map((i) => [i.id, `[${i.label}]`]));
|
|
36
|
-
return value.replace(MARKER, (whole, id) => text.get(id) ?? image.get(id) ?? whole);
|
|
37
|
-
}
|
|
38
10
|
function usePastePills({
|
|
39
11
|
threshold,
|
|
40
12
|
heldPastes: controlledHeldPastes,
|
|
@@ -147,6 +119,169 @@ function InlinePill({
|
|
|
147
119
|
}
|
|
148
120
|
) });
|
|
149
121
|
}
|
|
122
|
+
|
|
123
|
+
// src/components/PastePills/paste-markers.ts
|
|
124
|
+
var PILL_MARK = "\uFFFC";
|
|
125
|
+
var MARKER = /\uFFFC([^\uFFFC\n]+)\uFFFC/g;
|
|
126
|
+
function pasteMarker(id) {
|
|
127
|
+
return `${PILL_MARK}${id}${PILL_MARK}`;
|
|
128
|
+
}
|
|
129
|
+
function segmentValue(value, known) {
|
|
130
|
+
const out = [];
|
|
131
|
+
let last = 0;
|
|
132
|
+
for (const match of value.matchAll(MARKER)) {
|
|
133
|
+
const id = match[1];
|
|
134
|
+
if (!known.has(id)) continue;
|
|
135
|
+
const start = match.index ?? 0;
|
|
136
|
+
if (start > last) out.push({ type: "text", text: value.slice(last, start) });
|
|
137
|
+
out.push({ type: "pill", id });
|
|
138
|
+
last = start + match[0].length;
|
|
139
|
+
}
|
|
140
|
+
if (last < value.length) out.push({ type: "text", text: value.slice(last) });
|
|
141
|
+
return out;
|
|
142
|
+
}
|
|
143
|
+
function markedIds(value) {
|
|
144
|
+
return Array.from(value.matchAll(MARKER), (m) => m[1]);
|
|
145
|
+
}
|
|
146
|
+
function expandMarkers(value, pastes, images) {
|
|
147
|
+
const text = new Map(pastes.map((p) => [p.id, p.text]));
|
|
148
|
+
const image = new Map(images.map((i) => [i.id, `[${i.label}]`]));
|
|
149
|
+
return value.replace(MARKER, (whole, id) => text.get(id) ?? image.get(id) ?? whole);
|
|
150
|
+
}
|
|
151
|
+
function useInlinePaste({
|
|
152
|
+
pasteThreshold,
|
|
153
|
+
pasteImages = false,
|
|
154
|
+
previewChars,
|
|
155
|
+
renderPastePreview,
|
|
156
|
+
classNames,
|
|
157
|
+
disabled,
|
|
158
|
+
heldPastes: controlledHeldPastes,
|
|
159
|
+
onHeldPastesChange,
|
|
160
|
+
heldImages: controlledHeldImages,
|
|
161
|
+
onHeldImagesChange,
|
|
162
|
+
editorRef,
|
|
163
|
+
blockText = true
|
|
164
|
+
}) {
|
|
165
|
+
const pills = usePastePills({
|
|
166
|
+
threshold: pasteThreshold,
|
|
167
|
+
heldPastes: controlledHeldPastes,
|
|
168
|
+
onHeldPastesChange
|
|
169
|
+
});
|
|
170
|
+
const heldPastes = pills.heldPastes;
|
|
171
|
+
const [heldImages, setHeldImages] = chunkSNHU2AI4_cjs.useControllableState(
|
|
172
|
+
controlledHeldImages,
|
|
173
|
+
[],
|
|
174
|
+
onHeldImagesChange
|
|
175
|
+
);
|
|
176
|
+
const imageCount = react.useRef(0);
|
|
177
|
+
const known = react.useMemo(
|
|
178
|
+
() => /* @__PURE__ */ new Set([...heldPastes.map((p) => p.id), ...heldImages.map((i) => i.id)]),
|
|
179
|
+
[heldPastes, heldImages]
|
|
180
|
+
);
|
|
181
|
+
const holdImage = react.useCallback(
|
|
182
|
+
(file) => {
|
|
183
|
+
let id;
|
|
184
|
+
do {
|
|
185
|
+
imageCount.current += 1;
|
|
186
|
+
id = `image-${imageCount.current}`;
|
|
187
|
+
} while (heldImages.some((i) => i.id === id));
|
|
188
|
+
const image = { id, file, label: `Pasted image ${imageCount.current}` };
|
|
189
|
+
setHeldImages((current) => [...current, image]);
|
|
190
|
+
return id;
|
|
191
|
+
},
|
|
192
|
+
[heldImages, setHeldImages]
|
|
193
|
+
);
|
|
194
|
+
const decidePaste = react.useCallback(
|
|
195
|
+
(data) => {
|
|
196
|
+
const text = data?.getData("text/plain") ?? "";
|
|
197
|
+
if (pasteImages && text === "") {
|
|
198
|
+
const files = Array.from(data?.files ?? []).filter(
|
|
199
|
+
(f) => f.type.startsWith("image/")
|
|
200
|
+
);
|
|
201
|
+
if (files.length > 0) {
|
|
202
|
+
return files.map((file) => ({ id: holdImage(file), block: false }));
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
if (pasteThreshold && pasteThreshold > 0 && text.length >= pasteThreshold) {
|
|
206
|
+
return [{ id: pills.hold(text), block: blockText }];
|
|
207
|
+
}
|
|
208
|
+
return null;
|
|
209
|
+
},
|
|
210
|
+
[pasteImages, pasteThreshold, holdImage, pills, blockText]
|
|
211
|
+
);
|
|
212
|
+
const prune = react.useCallback(
|
|
213
|
+
(next) => {
|
|
214
|
+
const present = new Set(markedIds(next));
|
|
215
|
+
for (const paste of heldPastes) if (!present.has(paste.id)) pills.remove(paste.id);
|
|
216
|
+
if (heldImages.some((i) => !present.has(i.id))) {
|
|
217
|
+
setHeldImages((current) => current.filter((i) => present.has(i.id)));
|
|
218
|
+
}
|
|
219
|
+
},
|
|
220
|
+
[heldPastes, heldImages, pills, setHeldImages]
|
|
221
|
+
);
|
|
222
|
+
const [hosts, setHosts] = react.useState(/* @__PURE__ */ new Map());
|
|
223
|
+
const onHostsChange = react.useCallback((next) => {
|
|
224
|
+
setHosts((prev) => {
|
|
225
|
+
if (prev.size === next.size && [...next].every(([id, el]) => prev.get(id) === el)) {
|
|
226
|
+
return prev;
|
|
227
|
+
}
|
|
228
|
+
return next;
|
|
229
|
+
});
|
|
230
|
+
}, []);
|
|
231
|
+
const expandPill = react.useCallback(
|
|
232
|
+
(id) => {
|
|
233
|
+
const text = pills.expand(id);
|
|
234
|
+
if (text === void 0) return;
|
|
235
|
+
editorRef.current?.replacePill(id, text);
|
|
236
|
+
},
|
|
237
|
+
[pills, editorRef]
|
|
238
|
+
);
|
|
239
|
+
const expand = react.useCallback(
|
|
240
|
+
(value) => expandMarkers(value, heldPastes, heldImages),
|
|
241
|
+
[heldPastes, heldImages]
|
|
242
|
+
);
|
|
243
|
+
const imagesIn = react.useCallback(
|
|
244
|
+
(value) => markedIds(value).flatMap((id) => heldImages.filter((i) => i.id === id)),
|
|
245
|
+
[heldImages]
|
|
246
|
+
);
|
|
247
|
+
const clear = react.useCallback(() => {
|
|
248
|
+
pills.clear();
|
|
249
|
+
setHeldImages([]);
|
|
250
|
+
}, [pills, setHeldImages]);
|
|
251
|
+
const portals = Array.from(hosts, ([id, host]) => {
|
|
252
|
+
const paste = heldPastes.find((p) => p.id === id);
|
|
253
|
+
const image = paste ? void 0 : heldImages.find((i) => i.id === id);
|
|
254
|
+
const preview = paste ? { kind: "text", paste } : image ? { kind: "image", image } : null;
|
|
255
|
+
return preview ? reactDom.createPortal(
|
|
256
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
257
|
+
InlinePill,
|
|
258
|
+
{
|
|
259
|
+
preview,
|
|
260
|
+
previewChars,
|
|
261
|
+
renderPastePreview,
|
|
262
|
+
classNames,
|
|
263
|
+
disabled,
|
|
264
|
+
onExpand: expandPill
|
|
265
|
+
}
|
|
266
|
+
),
|
|
267
|
+
host,
|
|
268
|
+
id
|
|
269
|
+
) : null;
|
|
270
|
+
});
|
|
271
|
+
return {
|
|
272
|
+
pills,
|
|
273
|
+
heldPastes,
|
|
274
|
+
heldImages,
|
|
275
|
+
known,
|
|
276
|
+
decidePaste,
|
|
277
|
+
prune,
|
|
278
|
+
onHostsChange,
|
|
279
|
+
expand,
|
|
280
|
+
imagesIn,
|
|
281
|
+
clear,
|
|
282
|
+
portals
|
|
283
|
+
};
|
|
284
|
+
}
|
|
150
285
|
var HOST_ATTR = "data-react-fancy-composer-paste-host";
|
|
151
286
|
function serialize(parent, keep) {
|
|
152
287
|
let out = "";
|
|
@@ -247,7 +382,12 @@ var InlinePasteEditor = react.forwardRef(
|
|
|
247
382
|
submitKey = "enter",
|
|
248
383
|
onKeyDown,
|
|
249
384
|
placeholderClassName,
|
|
250
|
-
maxHeight
|
|
385
|
+
maxHeight,
|
|
386
|
+
multiline = true,
|
|
387
|
+
id,
|
|
388
|
+
ariaLabelledBy,
|
|
389
|
+
ariaInvalid,
|
|
390
|
+
style
|
|
251
391
|
}, ref) {
|
|
252
392
|
const rootRef = react.useRef(null);
|
|
253
393
|
const lastValue = react.useRef(null);
|
|
@@ -255,7 +395,7 @@ var InlinePasteEditor = react.forwardRef(
|
|
|
255
395
|
const knownRef = react.useRef(known);
|
|
256
396
|
knownRef.current = known;
|
|
257
397
|
const keep = react.useCallback(
|
|
258
|
-
(
|
|
398
|
+
(id2) => knownRef.current.has(id2) || pending.current.has(id2),
|
|
259
399
|
[]
|
|
260
400
|
);
|
|
261
401
|
const reportHosts = react.useCallback(() => {
|
|
@@ -263,8 +403,8 @@ var InlinePasteEditor = react.forwardRef(
|
|
|
263
403
|
if (!root) return;
|
|
264
404
|
const hosts = /* @__PURE__ */ new Map();
|
|
265
405
|
root.querySelectorAll(`[${HOST_ATTR}]`).forEach((el) => {
|
|
266
|
-
const
|
|
267
|
-
if (keep(
|
|
406
|
+
const id2 = el.getAttribute(HOST_ATTR);
|
|
407
|
+
if (keep(id2)) hosts.set(id2, el);
|
|
268
408
|
});
|
|
269
409
|
onHostsChange(hosts);
|
|
270
410
|
}, [keep, onHostsChange]);
|
|
@@ -357,9 +497,9 @@ var InlinePasteEditor = react.forwardRef(
|
|
|
357
497
|
react.useLayoutEffect(() => {
|
|
358
498
|
const root = rootRef.current;
|
|
359
499
|
if (!root) return;
|
|
360
|
-
for (const
|
|
500
|
+
for (const id2 of pending.current) if (known.has(id2)) pending.current.delete(id2);
|
|
361
501
|
const wanted = segmentValue(value, known).flatMap((s) => s.type === "pill" ? [s.id] : []).join(PILL_MARK);
|
|
362
|
-
const onScreen = Array.from(root.querySelectorAll(`[${HOST_ATTR}]`)).map((el) => el.getAttribute(HOST_ATTR)).filter((
|
|
502
|
+
const onScreen = Array.from(root.querySelectorAll(`[${HOST_ATTR}]`)).map((el) => el.getAttribute(HOST_ATTR)).filter((id2) => id2 !== null && keep(id2)).join(PILL_MARK);
|
|
363
503
|
if (value === lastValue.current && wanted === onScreen) return;
|
|
364
504
|
render(value);
|
|
365
505
|
}, [value, known, keep, render]);
|
|
@@ -375,11 +515,11 @@ var InlinePasteEditor = react.forwardRef(
|
|
|
375
515
|
selection?.removeAllRanges();
|
|
376
516
|
selection?.addRange(range);
|
|
377
517
|
},
|
|
378
|
-
replacePill(
|
|
518
|
+
replacePill(id2, text) {
|
|
379
519
|
const root = rootRef.current;
|
|
380
520
|
const host = Array.from(
|
|
381
521
|
root?.querySelectorAll(`[${HOST_ATTR}]`) ?? []
|
|
382
|
-
).find((el) => el.getAttribute(HOST_ATTR) ===
|
|
522
|
+
).find((el) => el.getAttribute(HOST_ATTR) === id2);
|
|
383
523
|
if (!root || !host) return;
|
|
384
524
|
const node = document.createTextNode(text);
|
|
385
525
|
host.replaceWith(node);
|
|
@@ -403,20 +543,21 @@ var InlinePasteEditor = react.forwardRef(
|
|
|
403
543
|
if (disabled) return;
|
|
404
544
|
const pills = onPaste(e.clipboardData);
|
|
405
545
|
if (pills === null) {
|
|
406
|
-
|
|
546
|
+
const text = (e.clipboardData?.getData("text/plain") ?? "").replace(/\r\n?/g, "\n");
|
|
547
|
+
insertText(multiline ? text : text.replace(/\n+/g, " "));
|
|
407
548
|
return;
|
|
408
549
|
}
|
|
409
|
-
for (const { id } of pills) pending.current.add(
|
|
550
|
+
for (const { id: id2 } of pills) pending.current.add(id2);
|
|
410
551
|
insert((before, after) => {
|
|
411
552
|
const nodes = [];
|
|
412
|
-
for (const { id, block } of pills) {
|
|
553
|
+
for (const { id: id2, block } of pills) {
|
|
413
554
|
if (block) {
|
|
414
555
|
const precededByBreak = nodes.length === 0 ? before === "" || before.endsWith("\n") : nodes[nodes.length - 1].textContent === "\n";
|
|
415
556
|
if (!precededByBreak) nodes.push(document.createTextNode("\n"));
|
|
416
|
-
nodes.push(makeHost(
|
|
557
|
+
nodes.push(makeHost(id2));
|
|
417
558
|
nodes.push(document.createTextNode("\n"));
|
|
418
559
|
} else {
|
|
419
|
-
nodes.push(makeHost(
|
|
560
|
+
nodes.push(makeHost(id2));
|
|
420
561
|
}
|
|
421
562
|
}
|
|
422
563
|
const last = nodes[nodes.length - 1];
|
|
@@ -429,7 +570,7 @@ var InlinePasteEditor = react.forwardRef(
|
|
|
429
570
|
if (e.defaultPrevented) return;
|
|
430
571
|
if (e.key !== "Enter" || e.nativeEvent.isComposing) return;
|
|
431
572
|
e.preventDefault();
|
|
432
|
-
const sends = submitKey === "mod-enter" ? e.ctrlKey || e.metaKey : !e.shiftKey;
|
|
573
|
+
const sends = !multiline || (submitKey === "mod-enter" ? e.ctrlKey || e.metaKey : !e.shiftKey);
|
|
433
574
|
if (sends) {
|
|
434
575
|
onSubmit();
|
|
435
576
|
} else {
|
|
@@ -452,9 +593,12 @@ var InlinePasteEditor = react.forwardRef(
|
|
|
452
593
|
"div",
|
|
453
594
|
{
|
|
454
595
|
ref: rootRef,
|
|
596
|
+
id,
|
|
455
597
|
"data-react-fancy-composer-input": "",
|
|
456
598
|
role: "textbox",
|
|
457
|
-
"aria-multiline":
|
|
599
|
+
"aria-multiline": multiline,
|
|
600
|
+
"aria-labelledby": ariaLabelledBy,
|
|
601
|
+
"aria-invalid": ariaInvalid || void 0,
|
|
458
602
|
"aria-placeholder": placeholder,
|
|
459
603
|
"aria-disabled": disabled || void 0,
|
|
460
604
|
contentEditable: !disabled,
|
|
@@ -462,7 +606,7 @@ var InlinePasteEditor = react.forwardRef(
|
|
|
462
606
|
onInput: emit,
|
|
463
607
|
onPaste: handlePaste,
|
|
464
608
|
onKeyDown: handleKeyDown,
|
|
465
|
-
style: maxHeight === void 0 ?
|
|
609
|
+
style: maxHeight === void 0 ? style : { ...style, maxHeight },
|
|
466
610
|
className: chunkZU5Q77OT_cjs.cn(
|
|
467
611
|
"max-h-72 min-h-[4.5rem] w-full overflow-y-auto whitespace-pre-wrap break-words bg-transparent px-4 pt-3 text-sm outline-none",
|
|
468
612
|
className
|
|
@@ -472,145 +616,42 @@ var InlinePasteEditor = react.forwardRef(
|
|
|
472
616
|
] });
|
|
473
617
|
}
|
|
474
618
|
);
|
|
475
|
-
function
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
[],
|
|
497
|
-
onHeldImagesChange
|
|
498
|
-
);
|
|
499
|
-
const imageCount = react.useRef(0);
|
|
500
|
-
const known = react.useMemo(
|
|
501
|
-
() => /* @__PURE__ */ new Set([...heldPastes.map((p) => p.id), ...heldImages.map((i) => i.id)]),
|
|
502
|
-
[heldPastes, heldImages]
|
|
503
|
-
);
|
|
504
|
-
const holdImage = react.useCallback(
|
|
505
|
-
(file) => {
|
|
506
|
-
let id;
|
|
507
|
-
do {
|
|
508
|
-
imageCount.current += 1;
|
|
509
|
-
id = `image-${imageCount.current}`;
|
|
510
|
-
} while (heldImages.some((i) => i.id === id));
|
|
511
|
-
const image = { id, file, label: `Pasted image ${imageCount.current}` };
|
|
512
|
-
setHeldImages((current) => [...current, image]);
|
|
513
|
-
return id;
|
|
514
|
-
},
|
|
515
|
-
[heldImages, setHeldImages]
|
|
516
|
-
);
|
|
517
|
-
const decidePaste = react.useCallback(
|
|
518
|
-
(data) => {
|
|
519
|
-
const text = data?.getData("text/plain") ?? "";
|
|
520
|
-
if (pasteImages && text === "") {
|
|
521
|
-
const files = Array.from(data?.files ?? []).filter(
|
|
522
|
-
(f) => f.type.startsWith("image/")
|
|
523
|
-
);
|
|
524
|
-
if (files.length > 0) {
|
|
525
|
-
return files.map((file) => ({ id: holdImage(file), block: false }));
|
|
526
|
-
}
|
|
527
|
-
}
|
|
528
|
-
if (pasteThreshold && pasteThreshold > 0 && text.length >= pasteThreshold) {
|
|
529
|
-
return [{ id: pills.hold(text), block: true }];
|
|
530
|
-
}
|
|
531
|
-
return null;
|
|
532
|
-
},
|
|
533
|
-
[pasteImages, pasteThreshold, holdImage, pills]
|
|
534
|
-
);
|
|
535
|
-
const prune = react.useCallback(
|
|
536
|
-
(next) => {
|
|
537
|
-
const present = new Set(markedIds(next));
|
|
538
|
-
for (const paste of heldPastes) if (!present.has(paste.id)) pills.remove(paste.id);
|
|
539
|
-
if (heldImages.some((i) => !present.has(i.id))) {
|
|
540
|
-
setHeldImages((current) => current.filter((i) => present.has(i.id)));
|
|
541
|
-
}
|
|
542
|
-
},
|
|
543
|
-
[heldPastes, heldImages, pills, setHeldImages]
|
|
544
|
-
);
|
|
545
|
-
const [hosts, setHosts] = react.useState(/* @__PURE__ */ new Map());
|
|
546
|
-
const onHostsChange = react.useCallback((next) => {
|
|
547
|
-
setHosts((prev) => {
|
|
548
|
-
if (prev.size === next.size && [...next].every(([id, el]) => prev.get(id) === el)) {
|
|
549
|
-
return prev;
|
|
550
|
-
}
|
|
551
|
-
return next;
|
|
552
|
-
});
|
|
553
|
-
}, []);
|
|
554
|
-
const expandPill = react.useCallback(
|
|
555
|
-
(id) => {
|
|
556
|
-
const text = pills.expand(id);
|
|
557
|
-
if (text === void 0) return;
|
|
558
|
-
editorRef.current?.replacePill(id, text);
|
|
559
|
-
},
|
|
560
|
-
[pills, editorRef]
|
|
561
|
-
);
|
|
562
|
-
const expand = react.useCallback(
|
|
563
|
-
(value) => expandMarkers(value, heldPastes, heldImages),
|
|
564
|
-
[heldPastes, heldImages]
|
|
565
|
-
);
|
|
566
|
-
const imagesIn = react.useCallback(
|
|
567
|
-
(value) => markedIds(value).flatMap((id) => heldImages.filter((i) => i.id === id)),
|
|
568
|
-
[heldImages]
|
|
619
|
+
function PastedFilesInput({ name, files, form }) {
|
|
620
|
+
const ref = react.useRef(null);
|
|
621
|
+
react.useEffect(() => {
|
|
622
|
+
const el = ref.current;
|
|
623
|
+
if (!el || typeof DataTransfer === "undefined") return;
|
|
624
|
+
const transfer = new DataTransfer();
|
|
625
|
+
for (const file of files) transfer.items.add(file);
|
|
626
|
+
el.files = transfer.files;
|
|
627
|
+
}, [files]);
|
|
628
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
629
|
+
"input",
|
|
630
|
+
{
|
|
631
|
+
ref,
|
|
632
|
+
type: "file",
|
|
633
|
+
name,
|
|
634
|
+
form,
|
|
635
|
+
multiple: true,
|
|
636
|
+
hidden: true,
|
|
637
|
+
tabIndex: -1,
|
|
638
|
+
"data-react-fancy-pasted-files": name
|
|
639
|
+
}
|
|
569
640
|
);
|
|
570
|
-
const clear = react.useCallback(() => {
|
|
571
|
-
pills.clear();
|
|
572
|
-
setHeldImages([]);
|
|
573
|
-
}, [pills, setHeldImages]);
|
|
574
|
-
const portals = Array.from(hosts, ([id, host]) => {
|
|
575
|
-
const paste = heldPastes.find((p) => p.id === id);
|
|
576
|
-
const image = paste ? void 0 : heldImages.find((i) => i.id === id);
|
|
577
|
-
const preview = paste ? { kind: "text", paste } : image ? { kind: "image", image } : null;
|
|
578
|
-
return preview ? reactDom.createPortal(
|
|
579
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
580
|
-
InlinePill,
|
|
581
|
-
{
|
|
582
|
-
preview,
|
|
583
|
-
previewChars,
|
|
584
|
-
renderPastePreview,
|
|
585
|
-
classNames,
|
|
586
|
-
disabled,
|
|
587
|
-
onExpand: expandPill
|
|
588
|
-
}
|
|
589
|
-
),
|
|
590
|
-
host,
|
|
591
|
-
id
|
|
592
|
-
) : null;
|
|
593
|
-
});
|
|
594
|
-
return {
|
|
595
|
-
pills,
|
|
596
|
-
heldPastes,
|
|
597
|
-
heldImages,
|
|
598
|
-
known,
|
|
599
|
-
decidePaste,
|
|
600
|
-
prune,
|
|
601
|
-
onHostsChange,
|
|
602
|
-
expand,
|
|
603
|
-
imagesIn,
|
|
604
|
-
clear,
|
|
605
|
-
portals
|
|
606
|
-
};
|
|
607
641
|
}
|
|
608
642
|
|
|
643
|
+
exports.HOST_ATTR = HOST_ATTR;
|
|
609
644
|
exports.InlinePasteEditor = InlinePasteEditor;
|
|
645
|
+
exports.InlinePill = InlinePill;
|
|
646
|
+
exports.PILL_MARK = PILL_MARK;
|
|
647
|
+
exports.PastedFilesInput = PastedFilesInput;
|
|
610
648
|
exports.endsOf = endsOf;
|
|
649
|
+
exports.expandMarkers = expandMarkers;
|
|
650
|
+
exports.markedIds = markedIds;
|
|
611
651
|
exports.pasteMarker = pasteMarker;
|
|
652
|
+
exports.segmentValue = segmentValue;
|
|
612
653
|
exports.useInlinePaste = useInlinePaste;
|
|
613
654
|
exports.usePastePills = usePastePills;
|
|
614
655
|
exports.withSeparators = withSeparators;
|
|
615
|
-
//# sourceMappingURL=chunk-
|
|
616
|
-
//# sourceMappingURL=chunk-
|
|
656
|
+
//# sourceMappingURL=chunk-MSRYJETY.cjs.map
|
|
657
|
+
//# sourceMappingURL=chunk-MSRYJETY.cjs.map
|