@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.
- package/CHANGELOG.md +133 -0
- package/dist/{index-C8PKWA_5.d.cts → Composer.types-CuSPnaOt.d.cts} +103 -7
- package/dist/{index-C8PKWA_5.d.ts → Composer.types-CuSPnaOt.d.ts} +103 -7
- package/dist/autocomplete.cjs +3 -3
- package/dist/autocomplete.js +2 -2
- package/dist/chunk-2JOWGYAJ.js +609 -0
- package/dist/chunk-2JOWGYAJ.js.map +1 -0
- package/dist/chunk-6TZPM43Q.cjs +616 -0
- package/dist/chunk-6TZPM43Q.cjs.map +1 -0
- package/dist/{chunk-FXP4JLGU.cjs → chunk-AR3JOPGT.cjs} +3 -3
- package/dist/{chunk-FXP4JLGU.cjs.map → chunk-AR3JOPGT.cjs.map} +1 -1
- package/dist/{chunk-23FTDEGR.cjs → chunk-BZOU7VJQ.cjs} +97 -84
- package/dist/chunk-BZOU7VJQ.cjs.map +1 -0
- package/dist/{chunk-35EN5AYE.js → chunk-CF5KRDN4.js} +6 -3
- package/dist/chunk-CF5KRDN4.js.map +1 -0
- package/dist/{chunk-DNV7MUEE.cjs → chunk-FJ2GMQLC.cjs} +117 -27
- package/dist/chunk-FJ2GMQLC.cjs.map +1 -0
- package/dist/{chunk-6ASZUE4T.js → chunk-FQLL2JI7.js} +3 -3
- package/dist/{chunk-6ASZUE4T.js.map → chunk-FQLL2JI7.js.map} +1 -1
- package/dist/{chunk-ZH3SPBVB.js → chunk-IECPLOSZ.js} +3 -3
- package/dist/{chunk-ZH3SPBVB.js.map → chunk-IECPLOSZ.js.map} +1 -1
- package/dist/{chunk-E2SZBIAV.cjs → chunk-IWQ3ZFLZ.cjs} +5 -5
- package/dist/{chunk-E2SZBIAV.cjs.map → chunk-IWQ3ZFLZ.cjs.map} +1 -1
- package/dist/{chunk-QBNR5IVM.cjs → chunk-MFBUK4RV.cjs} +3 -3
- package/dist/{chunk-QBNR5IVM.cjs.map → chunk-MFBUK4RV.cjs.map} +1 -1
- package/dist/{chunk-2XAVAPDA.js → chunk-MXAVGOHW.js} +99 -85
- package/dist/chunk-MXAVGOHW.js.map +1 -0
- package/dist/{chunk-ISPCXIJZ.cjs → chunk-X7H75WVP.cjs} +6 -3
- package/dist/chunk-X7H75WVP.cjs.map +1 -0
- package/dist/{chunk-O3WEV562.js → chunk-YLPVTEUH.js} +118 -28
- package/dist/chunk-YLPVTEUH.js.map +1 -0
- package/dist/{chunk-O2ZHORSC.js → chunk-Z6RVBZQ4.js} +3 -3
- package/dist/{chunk-O2ZHORSC.js.map → chunk-Z6RVBZQ4.js.map} +1 -1
- package/dist/composer.cjs +10 -2
- package/dist/composer.d.cts +7 -2
- package/dist/composer.d.ts +7 -2
- package/dist/composer.js +5 -1
- package/dist/editor.cjs +1 -1
- package/dist/editor.js +1 -1
- package/dist/{index-DXUAAZzE.d.ts → index-BsIBOwaK.d.cts} +46 -1
- package/dist/{index-DXUAAZzE.d.cts → index-S4FC1yFK.d.ts} +46 -1
- package/dist/index.cjs +40 -35
- package/dist/index.d.cts +3 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.js +8 -7
- package/dist/inputs.cjs +3 -3
- package/dist/inputs.js +2 -2
- package/dist/json-editor.cjs +14 -14
- package/dist/json-editor.js +3 -3
- package/dist/prompt-input.cjs +5 -3
- package/dist/prompt-input.d.cts +2 -1
- package/dist/prompt-input.d.ts +2 -1
- package/dist/prompt-input.js +4 -2
- package/dist/select.cjs +3 -3
- package/dist/select.js +2 -2
- package/dist/tooltip.cjs +2 -2
- package/dist/tooltip.js +1 -1
- package/package.json +1 -1
- package/dist/chunk-23FTDEGR.cjs.map +0 -1
- package/dist/chunk-2XAVAPDA.js.map +0 -1
- package/dist/chunk-35EN5AYE.js.map +0 -1
- package/dist/chunk-DNV7MUEE.cjs.map +0 -1
- package/dist/chunk-ISPCXIJZ.cjs.map +0 -1
- 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
|
-
|
|
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
|
|
128
|
-
*
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
128
|
-
*
|
|
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
|
-
|
|
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 };
|
package/dist/autocomplete.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
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
|
|
17
|
+
get: function () { return chunkMFBUK4RV_cjs.Autocomplete; }
|
|
18
18
|
});
|
|
19
19
|
//# sourceMappingURL=autocomplete.cjs.map
|
|
20
20
|
//# sourceMappingURL=autocomplete.cjs.map
|
package/dist/autocomplete.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
export { Autocomplete } from './chunk-
|
|
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';
|