@particle-academy/react-fancy 5.37.0 → 5.39.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 +133 -0
  2. package/dist/{index-C8PKWA_5.d.cts → Composer.types-CuSPnaOt.d.cts} +103 -7
  3. package/dist/{index-C8PKWA_5.d.ts → Composer.types-CuSPnaOt.d.ts} +103 -7
  4. package/dist/autocomplete.cjs +3 -3
  5. package/dist/autocomplete.js +2 -2
  6. package/dist/chunk-2JOWGYAJ.js +609 -0
  7. package/dist/chunk-2JOWGYAJ.js.map +1 -0
  8. package/dist/chunk-6TZPM43Q.cjs +616 -0
  9. package/dist/chunk-6TZPM43Q.cjs.map +1 -0
  10. package/dist/{chunk-FXP4JLGU.cjs → chunk-AR3JOPGT.cjs} +3 -3
  11. package/dist/{chunk-FXP4JLGU.cjs.map → chunk-AR3JOPGT.cjs.map} +1 -1
  12. package/dist/{chunk-23FTDEGR.cjs → chunk-BZOU7VJQ.cjs} +97 -84
  13. package/dist/chunk-BZOU7VJQ.cjs.map +1 -0
  14. package/dist/{chunk-35EN5AYE.js → chunk-CF5KRDN4.js} +6 -3
  15. package/dist/chunk-CF5KRDN4.js.map +1 -0
  16. package/dist/{chunk-DNV7MUEE.cjs → chunk-FJ2GMQLC.cjs} +117 -27
  17. package/dist/chunk-FJ2GMQLC.cjs.map +1 -0
  18. package/dist/{chunk-6ASZUE4T.js → chunk-FQLL2JI7.js} +3 -3
  19. package/dist/{chunk-6ASZUE4T.js.map → chunk-FQLL2JI7.js.map} +1 -1
  20. package/dist/{chunk-ZH3SPBVB.js → chunk-IECPLOSZ.js} +3 -3
  21. package/dist/{chunk-ZH3SPBVB.js.map → chunk-IECPLOSZ.js.map} +1 -1
  22. package/dist/{chunk-E2SZBIAV.cjs → chunk-IWQ3ZFLZ.cjs} +5 -5
  23. package/dist/{chunk-E2SZBIAV.cjs.map → chunk-IWQ3ZFLZ.cjs.map} +1 -1
  24. package/dist/{chunk-QBNR5IVM.cjs → chunk-MFBUK4RV.cjs} +3 -3
  25. package/dist/{chunk-QBNR5IVM.cjs.map → chunk-MFBUK4RV.cjs.map} +1 -1
  26. package/dist/{chunk-2XAVAPDA.js → chunk-MXAVGOHW.js} +99 -85
  27. package/dist/chunk-MXAVGOHW.js.map +1 -0
  28. package/dist/{chunk-ISPCXIJZ.cjs → chunk-X7H75WVP.cjs} +6 -3
  29. package/dist/chunk-X7H75WVP.cjs.map +1 -0
  30. package/dist/{chunk-O3WEV562.js → chunk-YLPVTEUH.js} +118 -28
  31. package/dist/chunk-YLPVTEUH.js.map +1 -0
  32. package/dist/{chunk-O2ZHORSC.js → chunk-Z6RVBZQ4.js} +3 -3
  33. package/dist/{chunk-O2ZHORSC.js.map → chunk-Z6RVBZQ4.js.map} +1 -1
  34. package/dist/composer.cjs +10 -2
  35. package/dist/composer.d.cts +7 -2
  36. package/dist/composer.d.ts +7 -2
  37. package/dist/composer.js +5 -1
  38. package/dist/editor.cjs +1 -1
  39. package/dist/editor.js +1 -1
  40. package/dist/{index-DXUAAZzE.d.ts → index-BsIBOwaK.d.cts} +46 -1
  41. package/dist/{index-DXUAAZzE.d.cts → index-S4FC1yFK.d.ts} +46 -1
  42. package/dist/index.cjs +40 -35
  43. package/dist/index.d.cts +3 -2
  44. package/dist/index.d.ts +3 -2
  45. package/dist/index.js +8 -7
  46. package/dist/inputs.cjs +3 -3
  47. package/dist/inputs.js +2 -2
  48. package/dist/json-editor.cjs +14 -14
  49. package/dist/json-editor.js +3 -3
  50. package/dist/prompt-input.cjs +5 -3
  51. package/dist/prompt-input.d.cts +2 -1
  52. package/dist/prompt-input.d.ts +2 -1
  53. package/dist/prompt-input.js +4 -2
  54. package/dist/select.cjs +3 -3
  55. package/dist/select.js +2 -2
  56. package/dist/tooltip.cjs +2 -2
  57. package/dist/tooltip.js +1 -1
  58. package/package.json +1 -1
  59. package/dist/chunk-23FTDEGR.cjs.map +0 -1
  60. package/dist/chunk-2XAVAPDA.js.map +0 -1
  61. package/dist/chunk-35EN5AYE.js.map +0 -1
  62. package/dist/chunk-DNV7MUEE.cjs.map +0 -1
  63. package/dist/chunk-ISPCXIJZ.cjs.map +0 -1
  64. package/dist/chunk-O3WEV562.js.map +0 -1
package/CHANGELOG.md CHANGED
@@ -11,6 +11,139 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
11
11
 
12
12
  ## [Unreleased]
13
13
 
14
+ ## [5.39.0] - 2026-10-15
15
+
16
+ ### Added
17
+
18
+ - **`PromptInput` gets inline paste pills** — the same ones `Composer` gained in
19
+ 5.38.0, built on the same code (react-fancy#32, asked for by Genie 2, whose chat
20
+ composer this is).
21
+
22
+ ```tsx
23
+ <PromptInput budgetTokens={200_000} pasteThreshold={500} pasteImages previewChars={30}
24
+ onSubmit={(text, attachments) => send(text, attachments)} />
25
+ ```
26
+
27
+ - A paste of `pasteThreshold`+ characters becomes `Pasted text · N characters`
28
+ **where it was pasted**, on a line of its own. Clicking it puts the full text
29
+ back right there; hovering shows the first and last `previewChars`.
30
+ - **`pasteImages`**: a pasted image becomes an inline `Pasted image N` pill AND
31
+ arrives in `onSubmit`'s attachments with its File, in message order. The text
32
+ marks where it sat as `[Pasted image N]`.
33
+ - `onSubmit` receives every text pill expanded where it sits — never a marker —
34
+ and **a message that is only a paste can be sent**.
35
+ - **The send contract is unchanged**: Ctrl/⌘+Enter sends, plain Enter is a
36
+ newline, and the `/` and `@` pickers, drop-to-attach and the file picker all
37
+ work in the inline editor exactly as in the textarea.
38
+ - `renderPastePreview` and `pasteClassNames` restyle the pills and popover.
39
+
40
+ Asked for as chips beside the input carried as `text/plain` attachments; built
41
+ inline instead, to the owner's own spec given against screenshots of this
42
+ composer. The text still reaches the model — positioned where the person put it.
43
+
44
+ - **A quieter `PromptInput` footer**, each part opt-in:
45
+ - `attachButton="icon"` — paperclip only, with an accessible name and a tooltip.
46
+ - `sendButton="icon"` — a compact send button whose tooltip carries the shortcut
47
+ (`Send · Ctrl+Enter`), replacing the inline kbd hint.
48
+ - `meter="near-limit"` — hidden until usage passes `meterShowAt` (0.75), muted
49
+ until `meterWarnAt` (0.9), warning colour past it. `meter="hidden"` never
50
+ shows it.
51
+ - **`usedTokens`** — the caller's REAL usage (an agent's context, say). The
52
+ meter shows it plus the draft's estimate; before, it could only estimate the
53
+ draft as length ÷ `charsPerToken`, which is why a host had to fake the budget.
54
+
55
+ Handles: `data-react-fancy-prompt-input-attach`, `-send`, `-meter` (with
56
+ `data-level`: `ok` / `caution` / `warn` / `muted`).
57
+
58
+ ### Changed
59
+
60
+ - `Composer` and `PromptInput` now share one implementation of inline paste
61
+ pills (`useInlinePaste`), so the two cannot disagree about what a pill means.
62
+ No behaviour change to `Composer`; all its tests pass untouched.
63
+ - `Composer`'s internal inline pill moved to its own file. No behaviour or API
64
+ change; its props were being read as `Composer`'s by the showcase's docs
65
+ coverage check.
66
+
67
+ **What you must DO: nothing.** Every option defaults to the old behaviour: no
68
+ `pasteThreshold` or `pasteImages` means the textarea you had, and the footer is
69
+ unchanged unless you ask.
70
+
71
+ ## [5.38.0] - 2026-10-14
72
+
73
+ ### Added
74
+
75
+ - **`Composer` can put paste pills IN the message, where the paste happened.**
76
+
77
+ ```tsx
78
+ <Composer pasteThreshold={500} pastePlacement="inline" pasteImages previewChars={30}
79
+ onSubmit={(text, { images }) => send(text, images)} />
80
+ ```
81
+
82
+ ```
83
+ This is what [Pasted image 1] I mean and this
84
+ [Pasted text · 669 characters]
85
+ ```
86
+
87
+ - **A text pill gets a line to itself** — a newline above (unless it is already
88
+ at the start of a line) and below (unless one already follows).
89
+ - **Clicking a text pill removes it and puts the full text exactly where it
90
+ sat**, not appended to the end.
91
+ - **An image pill sits in the sentence** — `Pasted image 1`, numbered by
92
+ arrival, and the number survives deleting an earlier one. Hovering shows a
93
+ thumbnail. Opt-in with `pasteImages`; see below for why.
94
+ - **Backspace deletes a pill like a character**, and the held paste goes with
95
+ it: the message is the one record of what is attached.
96
+ - **A send carries every pill where it sits.** Text pills are expanded in place;
97
+ each image's place is marked `[Pasted image N]` in the text and the images
98
+ arrive as `onSubmit`'s new second argument, in message order.
99
+
100
+ With `pastePlacement="inline"`, `value` carries a marker per pill
101
+ (`pasteMarker(id)`, exported), so a host or agent can attach a paste by writing
102
+ the marker and the held paste. `onSubmit` never sees a marker. A marker naming
103
+ nothing held stays text, so pasted content cannot invent an attachment.
104
+
105
+ This is the MOIC estate's own design — the pill as a marker inside the message —
106
+ which is why they never adopted the beside-the-input layout. Asked for by the
107
+ owner against screenshots of exactly that layout.
108
+
109
+ **`pasteImages` is off by default** because turning it on is a promise to read
110
+ `onSubmit`'s second argument: a pill reads as "attached", and an image a host
111
+ never sends is one the person believes went and did not. A clipboard with text
112
+ AND an image pastes the text — copying from a document often adds a picture of
113
+ the selection, and holding it would turn a pasted sentence into a screenshot of
114
+ it.
115
+
116
+ - **The pills and their hover popover are restyleable.** `classNames` —
117
+ `pill`, `textPill`, `imagePill`, `preview`, `remove`, `input` — merged onto the
118
+ defaults, so a restyle can be one class or a whole new look.
119
+ `renderPastePreview` replaces what the popover shows. Both placements.
120
+
121
+ - **`previewChars`** — characters of a held paste shown at each end of the hover
122
+ preview. Default stays 20.
123
+
124
+ - **`heldImages` / `onHeldImagesChange`** — controllable, per the component
125
+ contract, like `heldPastes`.
126
+
127
+ - **`usePastePills().hold(text)`** — hold a paste unconditionally and get its id
128
+ back, for a host that places the pill itself. `Composer`'s inline placement is
129
+ its caller.
130
+
131
+ ### Fixed
132
+
133
+ - **`usePastePills` could mint an id a controlled list already held.** Its counter
134
+ started at 1 whatever the list contained, so a host that seeded `paste-1` got a
135
+ second `paste-1` on the next paste — two pills on one id, and expanding either
136
+ took both. It now skips taken ids.
137
+
138
+ - **`Tooltip`'s arrow kept its own dark colour when the bubble was restyled**, so
139
+ `className="bg-white"` gave a dark arrow pointing out of a white bubble. The
140
+ arrow now inherits the bubble's background.
141
+
142
+ **What you must DO: nothing.** `pastePlacement` defaults to `"above"`, which is
143
+ 5.31.0's behaviour unchanged; `pasteImages` is off; `previewChars` defaults to the
144
+ old 20; and `onSubmit`'s second argument is ignorable, so a one-argument handler
145
+ still type-checks.
146
+
14
147
  ## [5.37.0] - 2026-10-11
15
148
 
16
149
  ### Changed
@@ -1,4 +1,3 @@
1
- import * as react from 'react';
2
1
  import { ReactNode } from 'react';
3
2
 
4
3
  /**
@@ -56,6 +55,14 @@ interface UsePastePillsResult {
56
55
  * }
57
56
  */
58
57
  handlePaste: (event: PasteEventLike) => boolean;
58
+ /**
59
+ * Hold `text` unconditionally and return the new pill's id.
60
+ *
61
+ * For a host that decides for itself what to hold and needs to know WHICH pill
62
+ * it made — `Composer`'s inline placement puts the pill at the caret, so it needs
63
+ * the id at paste time. Ignores `threshold`; the caller has already decided.
64
+ */
65
+ hold: (text: string) => string;
59
66
  /**
60
67
  * Removes the paste and returns its text, for the host to insert into its own
61
68
  * surface. `undefined` if there is no such id.
@@ -111,21 +118,78 @@ interface UsePastePillsResult {
111
118
  * **It gets no further surface without a real caller.** No extra options, no second
112
119
  * hook. An API with one hypothetical consumer is how a package accumulates surface
113
120
  * nobody uses.
121
+ *
122
+ * `hold` (5.38.0) met that bar: `Composer`'s inline placement — MOIC's
123
+ * pill-inside-the-message design, built into the component — needs the id of the
124
+ * pill it just made so it can put it at the caret.
114
125
  */
115
126
  declare function usePastePills({ threshold, heldPastes: controlledHeldPastes, onHeldPastesChange, }?: UsePastePillsOptions): UsePastePillsResult;
116
127
 
128
+ /**
129
+ * An image pasted into a `Composer` and held as a pill.
130
+ *
131
+ * `label` is stored rather than derived because the number in it is the order of
132
+ * ARRIVAL: "Pasted image 2" must stay 2 after image 1 is deleted, and nothing left
133
+ * in the list could recompute that.
134
+ */
135
+ interface HeldImage {
136
+ id: string;
137
+ file: File;
138
+ label: string;
139
+ }
140
+ /** The marker for a held paste or image, for a host or agent writing `value` itself. */
141
+ declare function pasteMarker(id: string): string;
142
+
143
+ /** What a hover preview is being asked to show. */
144
+ type ComposerPastePreview = {
145
+ kind: "text";
146
+ paste: HeldPaste;
147
+ } | {
148
+ kind: "image";
149
+ image: HeldImage;
150
+ };
151
+ /**
152
+ * Classes for the paste pills, MERGED onto the defaults rather than replacing them,
153
+ * so a restyle can be one class or a whole new look.
154
+ */
155
+ interface ComposerPasteClassNames {
156
+ /** Every pill, text or image. */
157
+ pill?: string;
158
+ /** Text pills only — `Pasted text · 669 characters`. */
159
+ textPill?: string;
160
+ /** Image pills only — `Pasted image 1`. */
161
+ imagePill?: string;
162
+ /** The hover popover. */
163
+ preview?: string;
164
+ /** The × discard control (beside-the-input placement only; inline pills are backspaced). */
165
+ remove?: string;
166
+ /** The editable surface itself. */
167
+ input?: string;
168
+ }
169
+ interface ComposerSubmitExtras {
170
+ /**
171
+ * Images still pasted into the message when it was sent, in the order they
172
+ * appear in it. Each one's place in the sent text is marked `[Pasted image N]`,
173
+ * matching its `label`.
174
+ */
175
+ images: HeldImage[];
176
+ }
117
177
  interface ComposerProps {
118
178
  value?: string;
119
179
  defaultValue?: string;
120
180
  onChange?: (value: string) => void;
121
- onSubmit?: (value: string) => void;
181
+ /**
182
+ * The second argument only ever carries anything with `pasteImages` on. A
183
+ * one-argument handler stays valid.
184
+ */
185
+ onSubmit?: (value: string, extras: ComposerSubmitExtras) => void;
122
186
  placeholder?: string;
123
187
  actions?: ReactNode;
124
188
  disabled?: boolean;
125
189
  className?: string;
126
190
  /**
127
- * Hold a paste of at least this many characters beside the composer as a pill,
128
- * instead of inserting it. Try 500 — about a long paragraph.
191
+ * Hold a paste of at least this many characters as a pill, instead of inserting
192
+ * it. Try 500 — about a long paragraph.
129
193
  *
130
194
  * **Omit it and paste behaves exactly as it always has.** Opt-in on purpose:
131
195
  * paste is a fundamental interaction and this library is past 1.0, so a minor
@@ -136,6 +200,37 @@ interface ComposerProps {
136
200
  * ceremony for an address or a name.
137
201
  */
138
202
  pasteThreshold?: number;
203
+ /**
204
+ * Where a pill goes.
205
+ *
206
+ * - `"above"` (default, and the only behaviour before 5.38.0) — in a row above
207
+ * the input; a send appends held text after what was typed.
208
+ * - `"inline"` — **in the message, where the paste happened.** A text pill gets
209
+ * a line to itself; clicking it puts the full text back exactly there; an
210
+ * image pill sits in the sentence. Backspace deletes a pill like a character.
211
+ *
212
+ * With `"inline"`, `value` carries a marker for each pill (see `pasteMarker`),
213
+ * because the message is then the one record of what is attached and where.
214
+ * `onSubmit` always receives the expanded text, never a marker.
215
+ */
216
+ pastePlacement?: "above" | "inline";
217
+ /**
218
+ * Hold a pasted IMAGE as a pill (`"inline"` placement only). Off by default —
219
+ * turning it on is a promise to read `onSubmit`'s second argument, because a pill
220
+ * reads as "attached" and an image a host never sends is an attachment the
221
+ * person believes went and did not.
222
+ *
223
+ * A clipboard carrying text as well as an image (copying from a document often
224
+ * includes a picture of the selection) pastes the TEXT: the image there is a
225
+ * rendering, not the thing that was copied.
226
+ */
227
+ pasteImages?: boolean;
228
+ /** Characters of a held text paste shown at EACH end of its hover preview. Default 20. */
229
+ previewChars?: number;
230
+ /** Replace the hover popover's content. Its box is styled by `classNames.preview`. */
231
+ renderPastePreview?: (preview: ComposerPastePreview) => ReactNode;
232
+ /** Restyle the pills and their popover. */
233
+ classNames?: ComposerPasteClassNames;
139
234
  /**
140
235
  * The held pastes, if you want to own them.
141
236
  *
@@ -146,8 +241,9 @@ interface ComposerProps {
146
241
  */
147
242
  heldPastes?: HeldPaste[];
148
243
  onHeldPastesChange?: (pastes: HeldPaste[]) => void;
244
+ /** The held images, if you want to own them. Same reasoning as `heldPastes`. */
245
+ heldImages?: HeldImage[];
246
+ onHeldImagesChange?: (images: HeldImage[]) => void;
149
247
  }
150
248
 
151
- declare const Composer: react.ForwardRefExoticComponent<ComposerProps & react.RefAttributes<HTMLDivElement>>;
152
-
153
- export { Composer as C, type HeldPaste as H, type PasteEventLike as P, type UsePastePillsOptions as U, type ComposerProps as a, type UsePastePillsResult as b, usePastePills as u };
249
+ export { type ComposerPasteClassNames as C, type HeldImage as H, type PasteEventLike as P, type UsePastePillsOptions as U, type ComposerPastePreview as a, type ComposerProps as b, type ComposerSubmitExtras as c, type HeldPaste as d, type UsePastePillsResult as e, pasteMarker as p, usePastePills as u };
@@ -1,4 +1,3 @@
1
- import * as react from 'react';
2
1
  import { ReactNode } from 'react';
3
2
 
4
3
  /**
@@ -56,6 +55,14 @@ interface UsePastePillsResult {
56
55
  * }
57
56
  */
58
57
  handlePaste: (event: PasteEventLike) => boolean;
58
+ /**
59
+ * Hold `text` unconditionally and return the new pill's id.
60
+ *
61
+ * For a host that decides for itself what to hold and needs to know WHICH pill
62
+ * it made — `Composer`'s inline placement puts the pill at the caret, so it needs
63
+ * the id at paste time. Ignores `threshold`; the caller has already decided.
64
+ */
65
+ hold: (text: string) => string;
59
66
  /**
60
67
  * Removes the paste and returns its text, for the host to insert into its own
61
68
  * surface. `undefined` if there is no such id.
@@ -111,21 +118,78 @@ interface UsePastePillsResult {
111
118
  * **It gets no further surface without a real caller.** No extra options, no second
112
119
  * hook. An API with one hypothetical consumer is how a package accumulates surface
113
120
  * nobody uses.
121
+ *
122
+ * `hold` (5.38.0) met that bar: `Composer`'s inline placement — MOIC's
123
+ * pill-inside-the-message design, built into the component — needs the id of the
124
+ * pill it just made so it can put it at the caret.
114
125
  */
115
126
  declare function usePastePills({ threshold, heldPastes: controlledHeldPastes, onHeldPastesChange, }?: UsePastePillsOptions): UsePastePillsResult;
116
127
 
128
+ /**
129
+ * An image pasted into a `Composer` and held as a pill.
130
+ *
131
+ * `label` is stored rather than derived because the number in it is the order of
132
+ * ARRIVAL: "Pasted image 2" must stay 2 after image 1 is deleted, and nothing left
133
+ * in the list could recompute that.
134
+ */
135
+ interface HeldImage {
136
+ id: string;
137
+ file: File;
138
+ label: string;
139
+ }
140
+ /** The marker for a held paste or image, for a host or agent writing `value` itself. */
141
+ declare function pasteMarker(id: string): string;
142
+
143
+ /** What a hover preview is being asked to show. */
144
+ type ComposerPastePreview = {
145
+ kind: "text";
146
+ paste: HeldPaste;
147
+ } | {
148
+ kind: "image";
149
+ image: HeldImage;
150
+ };
151
+ /**
152
+ * Classes for the paste pills, MERGED onto the defaults rather than replacing them,
153
+ * so a restyle can be one class or a whole new look.
154
+ */
155
+ interface ComposerPasteClassNames {
156
+ /** Every pill, text or image. */
157
+ pill?: string;
158
+ /** Text pills only — `Pasted text · 669 characters`. */
159
+ textPill?: string;
160
+ /** Image pills only — `Pasted image 1`. */
161
+ imagePill?: string;
162
+ /** The hover popover. */
163
+ preview?: string;
164
+ /** The × discard control (beside-the-input placement only; inline pills are backspaced). */
165
+ remove?: string;
166
+ /** The editable surface itself. */
167
+ input?: string;
168
+ }
169
+ interface ComposerSubmitExtras {
170
+ /**
171
+ * Images still pasted into the message when it was sent, in the order they
172
+ * appear in it. Each one's place in the sent text is marked `[Pasted image N]`,
173
+ * matching its `label`.
174
+ */
175
+ images: HeldImage[];
176
+ }
117
177
  interface ComposerProps {
118
178
  value?: string;
119
179
  defaultValue?: string;
120
180
  onChange?: (value: string) => void;
121
- onSubmit?: (value: string) => void;
181
+ /**
182
+ * The second argument only ever carries anything with `pasteImages` on. A
183
+ * one-argument handler stays valid.
184
+ */
185
+ onSubmit?: (value: string, extras: ComposerSubmitExtras) => void;
122
186
  placeholder?: string;
123
187
  actions?: ReactNode;
124
188
  disabled?: boolean;
125
189
  className?: string;
126
190
  /**
127
- * Hold a paste of at least this many characters beside the composer as a pill,
128
- * instead of inserting it. Try 500 — about a long paragraph.
191
+ * Hold a paste of at least this many characters as a pill, instead of inserting
192
+ * it. Try 500 — about a long paragraph.
129
193
  *
130
194
  * **Omit it and paste behaves exactly as it always has.** Opt-in on purpose:
131
195
  * paste is a fundamental interaction and this library is past 1.0, so a minor
@@ -136,6 +200,37 @@ interface ComposerProps {
136
200
  * ceremony for an address or a name.
137
201
  */
138
202
  pasteThreshold?: number;
203
+ /**
204
+ * Where a pill goes.
205
+ *
206
+ * - `"above"` (default, and the only behaviour before 5.38.0) — in a row above
207
+ * the input; a send appends held text after what was typed.
208
+ * - `"inline"` — **in the message, where the paste happened.** A text pill gets
209
+ * a line to itself; clicking it puts the full text back exactly there; an
210
+ * image pill sits in the sentence. Backspace deletes a pill like a character.
211
+ *
212
+ * With `"inline"`, `value` carries a marker for each pill (see `pasteMarker`),
213
+ * because the message is then the one record of what is attached and where.
214
+ * `onSubmit` always receives the expanded text, never a marker.
215
+ */
216
+ pastePlacement?: "above" | "inline";
217
+ /**
218
+ * Hold a pasted IMAGE as a pill (`"inline"` placement only). Off by default —
219
+ * turning it on is a promise to read `onSubmit`'s second argument, because a pill
220
+ * reads as "attached" and an image a host never sends is an attachment the
221
+ * person believes went and did not.
222
+ *
223
+ * A clipboard carrying text as well as an image (copying from a document often
224
+ * includes a picture of the selection) pastes the TEXT: the image there is a
225
+ * rendering, not the thing that was copied.
226
+ */
227
+ pasteImages?: boolean;
228
+ /** Characters of a held text paste shown at EACH end of its hover preview. Default 20. */
229
+ previewChars?: number;
230
+ /** Replace the hover popover's content. Its box is styled by `classNames.preview`. */
231
+ renderPastePreview?: (preview: ComposerPastePreview) => ReactNode;
232
+ /** Restyle the pills and their popover. */
233
+ classNames?: ComposerPasteClassNames;
139
234
  /**
140
235
  * The held pastes, if you want to own them.
141
236
  *
@@ -146,8 +241,9 @@ interface ComposerProps {
146
241
  */
147
242
  heldPastes?: HeldPaste[];
148
243
  onHeldPastesChange?: (pastes: HeldPaste[]) => void;
244
+ /** The held images, if you want to own them. Same reasoning as `heldPastes`. */
245
+ heldImages?: HeldImage[];
246
+ onHeldImagesChange?: (images: HeldImage[]) => void;
149
247
  }
150
248
 
151
- declare const Composer: react.ForwardRefExoticComponent<ComposerProps & react.RefAttributes<HTMLDivElement>>;
152
-
153
- export { Composer as C, type HeldPaste as H, type PasteEventLike as P, type UsePastePillsOptions as U, type ComposerProps as a, type UsePastePillsResult as b, usePastePills as u };
249
+ export { type ComposerPasteClassNames as C, type HeldImage as H, type PasteEventLike as P, type UsePastePillsOptions as U, type ComposerPastePreview as a, type ComposerProps as b, type ComposerSubmitExtras as c, type HeldPaste as d, type UsePastePillsResult as e, pasteMarker as p, usePastePills as u };
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
- var chunkQBNR5IVM_cjs = require('./chunk-QBNR5IVM.cjs');
4
- require('./chunk-J2DI6RMR.cjs');
3
+ var chunkMFBUK4RV_cjs = require('./chunk-MFBUK4RV.cjs');
5
4
  require('./chunk-KJ22KE56.cjs');
6
5
  require('./chunk-L3V3BYVS.cjs');
6
+ require('./chunk-J2DI6RMR.cjs');
7
7
  require('./chunk-NBZC6LOB.cjs');
8
8
  require('./chunk-57FQGQJK.cjs');
9
9
  require('./chunk-RXDRYWVD.cjs');
@@ -14,7 +14,7 @@ require('./chunk-ZU5Q77OT.cjs');
14
14
 
15
15
  Object.defineProperty(exports, "Autocomplete", {
16
16
  enumerable: true,
17
- get: function () { return chunkQBNR5IVM_cjs.Autocomplete; }
17
+ get: function () { return chunkMFBUK4RV_cjs.Autocomplete; }
18
18
  });
19
19
  //# sourceMappingURL=autocomplete.cjs.map
20
20
  //# sourceMappingURL=autocomplete.cjs.map
@@ -1,7 +1,7 @@
1
- export { Autocomplete } from './chunk-O2ZHORSC.js';
2
- import './chunk-MQ6VGG62.js';
1
+ export { Autocomplete } from './chunk-Z6RVBZQ4.js';
3
2
  import './chunk-OL53XYHF.js';
4
3
  import './chunk-NRXK42LO.js';
4
+ import './chunk-MQ6VGG62.js';
5
5
  import './chunk-WHEXTDPV.js';
6
6
  import './chunk-RGANGU7X.js';
7
7
  import './chunk-JXE5XID6.js';