@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.
Files changed (64) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/dist/{Composer.types-CuSPnaOt.d.cts → PastePills.types-CDyotkUb.d.cts} +35 -82
  3. package/dist/{Composer.types-CuSPnaOt.d.ts → PastePills.types-CDyotkUb.d.ts} +35 -82
  4. package/dist/PastedFilesInput-CrgNoEBd.d.ts +141 -0
  5. package/dist/PastedFilesInput-DQ1eZaHk.d.cts +141 -0
  6. package/dist/{chunk-IPNJMHJ3.cjs → chunk-2QIGXSSZ.cjs} +105 -3
  7. package/dist/chunk-2QIGXSSZ.cjs.map +1 -0
  8. package/dist/{chunk-BZOU7VJQ.cjs → chunk-BR27AXFE.cjs} +16 -10
  9. package/dist/chunk-BR27AXFE.cjs.map +1 -0
  10. package/dist/{chunk-G4WYCWIQ.js → chunk-DMFJJ73P.js} +3 -3
  11. package/dist/{chunk-G4WYCWIQ.js.map → chunk-DMFJJ73P.js.map} +1 -1
  12. package/dist/{chunk-2VIDYJUG.js → chunk-EEWRLFTI.js} +107 -5
  13. package/dist/chunk-EEWRLFTI.js.map +1 -0
  14. package/dist/{chunk-SF5OAVGD.js → chunk-JZCAMPIA.js} +12 -4
  15. package/dist/chunk-JZCAMPIA.js.map +1 -0
  16. package/dist/{chunk-2JOWGYAJ.js → chunk-KYZNCVRD.js} +213 -179
  17. package/dist/chunk-KYZNCVRD.js.map +1 -0
  18. package/dist/{chunk-MXAVGOHW.js → chunk-L637KPEA.js} +12 -6
  19. package/dist/chunk-L637KPEA.js.map +1 -0
  20. package/dist/{chunk-6TZPM43Q.cjs → chunk-MSRYJETY.cjs} +219 -178
  21. package/dist/chunk-MSRYJETY.cjs.map +1 -0
  22. package/dist/{chunk-K4NHVCY6.cjs → chunk-S5ZYG5MG.cjs} +8 -8
  23. package/dist/{chunk-K4NHVCY6.cjs.map → chunk-S5ZYG5MG.cjs.map} +1 -1
  24. package/dist/{chunk-UUBHUSUP.cjs → chunk-Z3FIU77M.cjs} +14 -6
  25. package/dist/chunk-Z3FIU77M.cjs.map +1 -0
  26. package/dist/composer.cjs +4 -4
  27. package/dist/composer.d.cts +93 -3
  28. package/dist/composer.d.ts +93 -3
  29. package/dist/composer.js +2 -2
  30. package/dist/{index-S4FC1yFK.d.ts → index-BF5qsQur.d.cts} +8 -2
  31. package/dist/{index-BsIBOwaK.d.cts → index-BZON-gXr.d.ts} +8 -2
  32. package/dist/index.cjs +75 -63
  33. package/dist/index.d.cts +4 -3
  34. package/dist/index.d.ts +4 -3
  35. package/dist/index.js +12 -12
  36. package/dist/input.cjs +6 -2
  37. package/dist/input.d.cts +34 -0
  38. package/dist/input.d.ts +34 -0
  39. package/dist/input.js +5 -1
  40. package/dist/inputs.cjs +8 -6
  41. package/dist/inputs.d.cts +1 -0
  42. package/dist/inputs.d.ts +1 -0
  43. package/dist/inputs.js +4 -2
  44. package/dist/json-editor.cjs +15 -13
  45. package/dist/json-editor.js +4 -2
  46. package/dist/paste-pills.cjs +65 -0
  47. package/dist/paste-pills.cjs.map +1 -0
  48. package/dist/paste-pills.d.cts +34 -0
  49. package/dist/paste-pills.d.ts +34 -0
  50. package/dist/paste-pills.js +8 -0
  51. package/dist/paste-pills.js.map +1 -0
  52. package/dist/prompt-input.cjs +3 -3
  53. package/dist/prompt-input.d.cts +2 -2
  54. package/dist/prompt-input.d.ts +2 -2
  55. package/dist/prompt-input.js +2 -2
  56. package/package.json +11 -1
  57. package/dist/chunk-2JOWGYAJ.js.map +0 -1
  58. package/dist/chunk-2VIDYJUG.js.map +0 -1
  59. package/dist/chunk-6TZPM43Q.cjs.map +0 -1
  60. package/dist/chunk-BZOU7VJQ.cjs.map +0 -1
  61. package/dist/chunk-IPNJMHJ3.cjs.map +0 -1
  62. package/dist/chunk-MXAVGOHW.js.map +0 -1
  63. package/dist/chunk-SF5OAVGD.js.map +0 -1
  64. package/dist/chunk-UUBHUSUP.cjs.map +0 -1
@@ -1,7 +1,7 @@
1
- import { useInlinePaste, withSeparators, endsOf, InlinePasteEditor } from './chunk-2JOWGYAJ.js';
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-MXAVGOHW.js.map
229
- //# sourceMappingURL=chunk-MXAVGOHW.js.map
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
- (id) => knownRef.current.has(id) || pending.current.has(id),
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 id = el.getAttribute(HOST_ATTR);
267
- if (keep(id)) hosts.set(id, el);
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 id of pending.current) if (known.has(id)) pending.current.delete(id);
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((id) => id !== null && keep(id)).join(PILL_MARK);
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(id, text) {
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) === id);
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
- insertText((e.clipboardData?.getData("text/plain") ?? "").replace(/\r\n?/g, "\n"));
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(id);
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(id));
557
+ nodes.push(makeHost(id2));
417
558
  nodes.push(document.createTextNode("\n"));
418
559
  } else {
419
- nodes.push(makeHost(id));
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": "true",
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 ? void 0 : { maxHeight },
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 useInlinePaste({
476
- pasteThreshold,
477
- pasteImages = false,
478
- previewChars,
479
- renderPastePreview,
480
- classNames,
481
- disabled,
482
- heldPastes: controlledHeldPastes,
483
- onHeldPastesChange,
484
- heldImages: controlledHeldImages,
485
- onHeldImagesChange,
486
- editorRef
487
- }) {
488
- const pills = usePastePills({
489
- threshold: pasteThreshold,
490
- heldPastes: controlledHeldPastes,
491
- onHeldPastesChange
492
- });
493
- const heldPastes = pills.heldPastes;
494
- const [heldImages, setHeldImages] = chunkSNHU2AI4_cjs.useControllableState(
495
- controlledHeldImages,
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-6TZPM43Q.cjs.map
616
- //# sourceMappingURL=chunk-6TZPM43Q.cjs.map
656
+ //# sourceMappingURL=chunk-MSRYJETY.cjs.map
657
+ //# sourceMappingURL=chunk-MSRYJETY.cjs.map