@particle-academy/react-fancy 5.31.0 → 5.33.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 (171) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/LICENSE +21 -0
  3. package/dist/accordion-panel.cjs +8 -8
  4. package/dist/accordion-panel.js +2 -2
  5. package/dist/autocomplete.cjs +3 -3
  6. package/dist/autocomplete.js +2 -2
  7. package/dist/carousel.cjs +8 -8
  8. package/dist/carousel.js +2 -2
  9. package/dist/checkbox-group.cjs +3 -3
  10. package/dist/checkbox-group.js +2 -2
  11. package/dist/checkbox.cjs +3 -3
  12. package/dist/checkbox.js +2 -2
  13. package/dist/{chunk-7MSIREUY.cjs → chunk-23FTDEGR.cjs} +59 -27
  14. package/dist/chunk-23FTDEGR.cjs.map +1 -0
  15. package/dist/{chunk-TQFQUNV3.js → chunk-2KAJ4L7C.js} +3 -3
  16. package/dist/{chunk-TQFQUNV3.js.map → chunk-2KAJ4L7C.js.map} +1 -1
  17. package/dist/{chunk-L5KKMJ2Q.js → chunk-2VIDYJUG.js} +3 -3
  18. package/dist/{chunk-L5KKMJ2Q.js.map → chunk-2VIDYJUG.js.map} +1 -1
  19. package/dist/{chunk-NH5XJ6VD.js → chunk-2XAVAPDA.js} +58 -27
  20. package/dist/chunk-2XAVAPDA.js.map +1 -0
  21. package/dist/{chunk-3EIB7RPD.cjs → chunk-3Q4NSAEA.cjs} +4 -4
  22. package/dist/{chunk-3EIB7RPD.cjs.map → chunk-3Q4NSAEA.cjs.map} +1 -1
  23. package/dist/{chunk-H6F6ZWAG.js → chunk-4HRD4S25.js} +3 -3
  24. package/dist/{chunk-H6F6ZWAG.js.map → chunk-4HRD4S25.js.map} +1 -1
  25. package/dist/{chunk-LY7PZEF4.cjs → chunk-6IBBAOQC.cjs} +4 -4
  26. package/dist/{chunk-LY7PZEF4.cjs.map → chunk-6IBBAOQC.cjs.map} +1 -1
  27. package/dist/{chunk-RFLPFQFF.js → chunk-BMTTSBHF.js} +3 -3
  28. package/dist/{chunk-RFLPFQFF.js.map → chunk-BMTTSBHF.js.map} +1 -1
  29. package/dist/{chunk-ASCATIDJ.js → chunk-BQ77ZWFM.js} +6 -6
  30. package/dist/{chunk-ASCATIDJ.js.map → chunk-BQ77ZWFM.js.map} +1 -1
  31. package/dist/{chunk-JM2H642B.cjs → chunk-BVRPDMB7.cjs} +4 -4
  32. package/dist/{chunk-JM2H642B.cjs.map → chunk-BVRPDMB7.cjs.map} +1 -1
  33. package/dist/{chunk-JDRKYYXP.cjs → chunk-BZDXX6E3.cjs} +4 -4
  34. package/dist/{chunk-JDRKYYXP.cjs.map → chunk-BZDXX6E3.cjs.map} +1 -1
  35. package/dist/{chunk-VUKIFFWK.cjs → chunk-BZZDHDMK.cjs} +5 -5
  36. package/dist/{chunk-VUKIFFWK.cjs.map → chunk-BZZDHDMK.cjs.map} +1 -1
  37. package/dist/{chunk-6SO2ZX3J.cjs → chunk-DHIUMQLP.cjs} +4 -4
  38. package/dist/{chunk-6SO2ZX3J.cjs.map → chunk-DHIUMQLP.cjs.map} +1 -1
  39. package/dist/chunk-EDYAXGUM.js +27 -0
  40. package/dist/chunk-EDYAXGUM.js.map +1 -0
  41. package/dist/{chunk-MRRKDRZU.js → chunk-EIUS2K72.js} +3 -3
  42. package/dist/{chunk-MRRKDRZU.js.map → chunk-EIUS2K72.js.map} +1 -1
  43. package/dist/{chunk-6PF5ENWM.js → chunk-F2GAZZVS.js} +3 -3
  44. package/dist/{chunk-6PF5ENWM.js.map → chunk-F2GAZZVS.js.map} +1 -1
  45. package/dist/{chunk-VME5743O.js → chunk-FNEPZ33A.js} +3 -3
  46. package/dist/{chunk-VME5743O.js.map → chunk-FNEPZ33A.js.map} +1 -1
  47. package/dist/{chunk-JP4C3ROX.js → chunk-FNJDMGJ3.js} +3 -3
  48. package/dist/{chunk-JP4C3ROX.js.map → chunk-FNJDMGJ3.js.map} +1 -1
  49. package/dist/{chunk-UA2C2U3M.cjs → chunk-FPZYPD3N.cjs} +4 -4
  50. package/dist/{chunk-UA2C2U3M.cjs.map → chunk-FPZYPD3N.cjs.map} +1 -1
  51. package/dist/{chunk-SX4CSO6C.js → chunk-FSRPZYZZ.js} +3 -3
  52. package/dist/{chunk-SX4CSO6C.js.map → chunk-FSRPZYZZ.js.map} +1 -1
  53. package/dist/{chunk-IRD6UXDK.cjs → chunk-FVTCPERB.cjs} +5 -5
  54. package/dist/{chunk-IRD6UXDK.cjs.map → chunk-FVTCPERB.cjs.map} +1 -1
  55. package/dist/{chunk-FUG3OCGP.js → chunk-G73TVXDQ.js} +3 -3
  56. package/dist/{chunk-FUG3OCGP.js.map → chunk-G73TVXDQ.js.map} +1 -1
  57. package/dist/{chunk-LHNC42J3.cjs → chunk-IPNJMHJ3.cjs} +4 -4
  58. package/dist/{chunk-LHNC42J3.cjs.map → chunk-IPNJMHJ3.cjs.map} +1 -1
  59. package/dist/{chunk-PIFJECFU.js → chunk-LBU3T2LF.js} +3 -3
  60. package/dist/{chunk-PIFJECFU.js.map → chunk-LBU3T2LF.js.map} +1 -1
  61. package/dist/{chunk-YAJYIRQL.cjs → chunk-LLA33GKC.cjs} +4 -4
  62. package/dist/{chunk-YAJYIRQL.cjs.map → chunk-LLA33GKC.cjs.map} +1 -1
  63. package/dist/{chunk-HIOMHITU.cjs → chunk-LQFQ2UKU.cjs} +5 -5
  64. package/dist/{chunk-HIOMHITU.cjs.map → chunk-LQFQ2UKU.cjs.map} +1 -1
  65. package/dist/{chunk-6ZDXG5VC.js → chunk-NBAHXZHJ.js} +3 -3
  66. package/dist/{chunk-6ZDXG5VC.js.map → chunk-NBAHXZHJ.js.map} +1 -1
  67. package/dist/{chunk-IUT3Q2EC.js → chunk-NE3Z4AWP.js} +3 -3
  68. package/dist/{chunk-IUT3Q2EC.js.map → chunk-NE3Z4AWP.js.map} +1 -1
  69. package/dist/{chunk-MIUSTEIV.js → chunk-O2ZHORSC.js} +3 -3
  70. package/dist/{chunk-MIUSTEIV.js.map → chunk-O2ZHORSC.js.map} +1 -1
  71. package/dist/{chunk-L2FPIFMN.js → chunk-OC75GWX5.js} +3 -3
  72. package/dist/{chunk-L2FPIFMN.js.map → chunk-OC75GWX5.js.map} +1 -1
  73. package/dist/{chunk-GKEWT3DW.js → chunk-OTCLBINT.js} +3 -3
  74. package/dist/{chunk-GKEWT3DW.js.map → chunk-OTCLBINT.js.map} +1 -1
  75. package/dist/{chunk-XXBW4EUO.js → chunk-P7Q2YIIS.js} +3 -3
  76. package/dist/{chunk-XXBW4EUO.js.map → chunk-P7Q2YIIS.js.map} +1 -1
  77. package/dist/{chunk-YTXBU6QC.cjs → chunk-QBNR5IVM.cjs} +4 -4
  78. package/dist/{chunk-YTXBU6QC.cjs.map → chunk-QBNR5IVM.cjs.map} +1 -1
  79. package/dist/{chunk-I3RPL3GE.js → chunk-RUSRAKKA.js} +3 -3
  80. package/dist/{chunk-I3RPL3GE.js.map → chunk-RUSRAKKA.js.map} +1 -1
  81. package/dist/{chunk-ZTC3EQFZ.cjs → chunk-S5KUYX3Z.cjs} +4 -4
  82. package/dist/{chunk-ZTC3EQFZ.cjs.map → chunk-S5KUYX3Z.cjs.map} +1 -1
  83. package/dist/chunk-SNHU2AI4.cjs +29 -0
  84. package/dist/chunk-SNHU2AI4.cjs.map +1 -0
  85. package/dist/{chunk-JV6RDIA6.cjs → chunk-T45XK5GN.cjs} +7 -7
  86. package/dist/{chunk-JV6RDIA6.cjs.map → chunk-T45XK5GN.cjs.map} +1 -1
  87. package/dist/{chunk-RKG2Q2HT.cjs → chunk-U7PFHQBN.cjs} +4 -4
  88. package/dist/{chunk-RKG2Q2HT.cjs.map → chunk-U7PFHQBN.cjs.map} +1 -1
  89. package/dist/{chunk-LAQGBLIU.cjs → chunk-VKXNCYLE.cjs} +14 -5
  90. package/dist/chunk-VKXNCYLE.cjs.map +1 -0
  91. package/dist/{chunk-3FG5K7A7.js → chunk-VYHZEQIG.js} +3 -3
  92. package/dist/{chunk-3FG5K7A7.js.map → chunk-VYHZEQIG.js.map} +1 -1
  93. package/dist/{chunk-32HCJ5GD.js → chunk-W6RDAZJC.js} +14 -5
  94. package/dist/chunk-W6RDAZJC.js.map +1 -0
  95. package/dist/{chunk-N6K2CTSU.cjs → chunk-WIS4QRGK.cjs} +4 -4
  96. package/dist/{chunk-N6K2CTSU.cjs.map → chunk-WIS4QRGK.cjs.map} +1 -1
  97. package/dist/{chunk-2LBRS6Z4.js → chunk-XDJSFGXW.js} +3 -3
  98. package/dist/{chunk-2LBRS6Z4.js.map → chunk-XDJSFGXW.js.map} +1 -1
  99. package/dist/{chunk-6LOV75CN.cjs → chunk-XK5WHQ3O.cjs} +4 -4
  100. package/dist/{chunk-6LOV75CN.cjs.map → chunk-XK5WHQ3O.cjs.map} +1 -1
  101. package/dist/{chunk-B5KK7NYP.cjs → chunk-Y52NXM73.cjs} +4 -4
  102. package/dist/{chunk-B5KK7NYP.cjs.map → chunk-Y52NXM73.cjs.map} +1 -1
  103. package/dist/{chunk-YLDYGT5O.js → chunk-YD4SXA6K.js} +3 -3
  104. package/dist/{chunk-YLDYGT5O.js.map → chunk-YD4SXA6K.js.map} +1 -1
  105. package/dist/{chunk-NR346SKH.cjs → chunk-YMDYDUBH.cjs} +4 -4
  106. package/dist/{chunk-NR346SKH.cjs.map → chunk-YMDYDUBH.cjs.map} +1 -1
  107. package/dist/{chunk-SCGE6DCE.cjs → chunk-YMU3SS6D.cjs} +14 -14
  108. package/dist/{chunk-SCGE6DCE.cjs.map → chunk-YMU3SS6D.cjs.map} +1 -1
  109. package/dist/{chunk-PWLBHNOA.cjs → chunk-Z3NSPDTW.cjs} +4 -4
  110. package/dist/{chunk-PWLBHNOA.cjs.map → chunk-Z3NSPDTW.cjs.map} +1 -1
  111. package/dist/{chunk-BJYTI2ID.cjs → chunk-ZUQUL53P.cjs} +4 -4
  112. package/dist/{chunk-BJYTI2ID.cjs.map → chunk-ZUQUL53P.cjs.map} +1 -1
  113. package/dist/color-picker.cjs +3 -3
  114. package/dist/color-picker.js +2 -2
  115. package/dist/composer.cjs +3 -3
  116. package/dist/composer.d.cts +2 -50
  117. package/dist/composer.d.ts +2 -50
  118. package/dist/composer.js +2 -2
  119. package/dist/date-picker.cjs +3 -3
  120. package/dist/date-picker.js +2 -2
  121. package/dist/editor.cjs +4 -4
  122. package/dist/editor.js +2 -2
  123. package/dist/emoji-select.cjs +3 -3
  124. package/dist/emoji-select.js +2 -2
  125. package/dist/file-browser.cjs +6 -6
  126. package/dist/file-browser.js +2 -2
  127. package/dist/file-upload.cjs +3 -3
  128. package/dist/file-upload.js +1 -1
  129. package/dist/index-C8PKWA_5.d.cts +153 -0
  130. package/dist/index-C8PKWA_5.d.ts +153 -0
  131. package/dist/index.cjs +78 -74
  132. package/dist/index.d.cts +34 -1
  133. package/dist/index.d.ts +34 -1
  134. package/dist/index.js +25 -25
  135. package/dist/input.cjs +3 -3
  136. package/dist/input.js +2 -2
  137. package/dist/inputs.cjs +17 -17
  138. package/dist/inputs.js +9 -9
  139. package/dist/json-editor.cjs +17 -17
  140. package/dist/json-editor.js +6 -6
  141. package/dist/mobile-menu.cjs +1 -1
  142. package/dist/mobile-menu.js +1 -1
  143. package/dist/multi-switch.cjs +3 -3
  144. package/dist/multi-switch.js +2 -2
  145. package/dist/otp-input.cjs +3 -3
  146. package/dist/otp-input.js +2 -2
  147. package/dist/pillbox.cjs +3 -3
  148. package/dist/pillbox.js +2 -2
  149. package/dist/radio-group.cjs +3 -3
  150. package/dist/radio-group.js +2 -2
  151. package/dist/sidebar.cjs +4 -4
  152. package/dist/sidebar.js +2 -2
  153. package/dist/slider.cjs +3 -3
  154. package/dist/slider.js +2 -2
  155. package/dist/switch.cjs +3 -3
  156. package/dist/switch.js +2 -2
  157. package/dist/table.cjs +12 -12
  158. package/dist/table.js +2 -2
  159. package/dist/tabs.cjs +4 -4
  160. package/dist/tabs.js +2 -2
  161. package/dist/time-picker.cjs +3 -3
  162. package/dist/time-picker.js +2 -2
  163. package/package.json +1 -1
  164. package/dist/chunk-32HCJ5GD.js.map +0 -1
  165. package/dist/chunk-6FQGMVF2.js +0 -25
  166. package/dist/chunk-6FQGMVF2.js.map +0 -1
  167. package/dist/chunk-7MSIREUY.cjs.map +0 -1
  168. package/dist/chunk-LAQGBLIU.cjs.map +0 -1
  169. package/dist/chunk-NH5XJ6VD.js.map +0 -1
  170. package/dist/chunk-OUOEQZHY.cjs +0 -27
  171. package/dist/chunk-OUOEQZHY.cjs.map +0 -1
@@ -0,0 +1,153 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * A paste held beside a composer rather than inserted into it.
6
+ *
7
+ * There is deliberately **no `length` field.** It would be `text.length` and
8
+ * nothing else, and a derived value stored beside its source is a value that can
9
+ * disagree with it — the two drift the moment anything edits one. Read
10
+ * `paste.text.length`.
11
+ */
12
+ interface HeldPaste {
13
+ id: string;
14
+ text: string;
15
+ }
16
+ /**
17
+ * The minimum of a clipboard event this hook touches.
18
+ *
19
+ * Structural rather than `React.ClipboardEvent` so a host can call it from a
20
+ * native listener, a synthetic one, or a test double. React's own event satisfies
21
+ * it.
22
+ */
23
+ interface PasteEventLike {
24
+ clipboardData?: {
25
+ getData(type: string): string;
26
+ } | null;
27
+ preventDefault(): void;
28
+ }
29
+ interface UsePastePillsOptions {
30
+ /**
31
+ * Hold a paste of at least this many characters. Try 500 — about a long
32
+ * paragraph.
33
+ *
34
+ * **No default, on purpose.** Paste is a fundamental interaction, so holding one
35
+ * is something a host asks for rather than something it discovers. Omit this and
36
+ * `handlePaste` always returns `false` and touches nothing.
37
+ */
38
+ threshold?: number;
39
+ /** Own the list yourself. Omit to let the hook keep it. */
40
+ heldPastes?: HeldPaste[];
41
+ onHeldPastesChange?: (pastes: HeldPaste[]) => void;
42
+ }
43
+ interface UsePastePillsResult {
44
+ heldPastes: HeldPaste[];
45
+ /**
46
+ * Call this from your OWN paste handler. Returns `true` if it took the paste —
47
+ * in which case it has already called `preventDefault()` — and `false` if it
48
+ * declined, having touched nothing.
49
+ *
50
+ * Composable on purpose: a host whose handler already intercepts paste for its
51
+ * own reasons needs to ask "did you want this?" rather than hand over the event.
52
+ *
53
+ * function onPaste(e) {
54
+ * if (pills.handlePaste(e)) return;
55
+ * // ...your own handling
56
+ * }
57
+ */
58
+ handlePaste: (event: PasteEventLike) => boolean;
59
+ /**
60
+ * Removes the paste and returns its text, for the host to insert into its own
61
+ * surface. `undefined` if there is no such id.
62
+ *
63
+ * The hook cannot insert it — it owns no DOM and does not know what a host's
64
+ * surface is. That is the point.
65
+ */
66
+ expand: (id: string) => string | undefined;
67
+ /** Discard one without returning it. */
68
+ remove: (id: string) => void;
69
+ /** Empty the list, e.g. after a send. */
70
+ clear: () => void;
71
+ }
72
+ /**
73
+ * Hold a large paste as state, so a composer can show it as a pill instead of
74
+ * turning itself into a scrolling wall.
75
+ *
76
+ * ---------------------------------------------------------------------------
77
+ * Why this is a hook and not just a feature of `Composer`
78
+ * ---------------------------------------------------------------------------
79
+ *
80
+ * `Composer` shipped the behaviour in 5.31.0 and the MOIC estate, who specified it,
81
+ * then established something I had missed: their chat input is a contenteditable
82
+ * rendering inline `[deal:42|Acme]` badges, so they **cannot** adopt `Composer` (a
83
+ * plain textarea) however much they want its behaviour. Their plan to delete their
84
+ * own composer when ours landed could never have worked.
85
+ *
86
+ * So the logic lives here and **`Composer` is its first caller.** One
87
+ * implementation rather than two, which matters more than the convenience: two
88
+ * copies of a rule drift, and the copy nobody reads is the one that rots. The rule
89
+ * that must not drift is the one in `Composer`'s own tests — a send with pills
90
+ * still closed carries the text.
91
+ *
92
+ * It owns no DOM. The host renders the pills.
93
+ *
94
+ * ---------------------------------------------------------------------------
95
+ * Who actually calls this (as of 5.32.0): `Composer`, and nothing else
96
+ * ---------------------------------------------------------------------------
97
+ *
98
+ * The estate that specified it **withdrew before adopting it**, hours after it
99
+ * shipped — their design moved the pill INTO the message as a `[paste:id|label]`
100
+ * marker in the same grammar as their other object tags, which makes the message
101
+ * itself the record of what is attached. A parallel `heldPastes` array would then be
102
+ * a second place answering "what am I sending?", and the two would disagree the
103
+ * moment someone backspaced a badge. Their reasoning was better than the spec.
104
+ *
105
+ * Recorded because a reader should not infer an extension point under active
106
+ * external use. It is kept rather than withdrawn for two reasons that are about
107
+ * cost, not optimism: it is published API on a 5.x package, so removing it needs a
108
+ * major; and `Composer` calls it, so it is exercised by that component's tests on
109
+ * every run and cannot rot unnoticed.
110
+ *
111
+ * **It gets no further surface without a real caller.** No extra options, no second
112
+ * hook. An API with one hypothetical consumer is how a package accumulates surface
113
+ * nobody uses.
114
+ */
115
+ declare function usePastePills({ threshold, heldPastes: controlledHeldPastes, onHeldPastesChange, }?: UsePastePillsOptions): UsePastePillsResult;
116
+
117
+ interface ComposerProps {
118
+ value?: string;
119
+ defaultValue?: string;
120
+ onChange?: (value: string) => void;
121
+ onSubmit?: (value: string) => void;
122
+ placeholder?: string;
123
+ actions?: ReactNode;
124
+ disabled?: boolean;
125
+ className?: string;
126
+ /**
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.
129
+ *
130
+ * **Omit it and paste behaves exactly as it always has.** Opt-in on purpose:
131
+ * paste is a fundamental interaction and this library is past 1.0, so a minor
132
+ * release must not quietly change what pasting does for every consumer. There is
133
+ * no default threshold for the same reason.
134
+ *
135
+ * Below the threshold nothing changes at all — no prevented event, no pill, no
136
+ * ceremony for an address or a name.
137
+ */
138
+ pasteThreshold?: number;
139
+ /**
140
+ * The held pastes, if you want to own them.
141
+ *
142
+ * Controllable rather than internal because the component contract forbids
143
+ * internal-only state for anything an agent might need to read or write — an
144
+ * agent driving this surface has to be able to see that a paste is attached, and
145
+ * to attach one itself.
146
+ */
147
+ heldPastes?: HeldPaste[];
148
+ onHeldPastesChange?: (pastes: HeldPaste[]) => void;
149
+ }
150
+
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 };
@@ -0,0 +1,153 @@
1
+ import * as react from 'react';
2
+ import { ReactNode } from 'react';
3
+
4
+ /**
5
+ * A paste held beside a composer rather than inserted into it.
6
+ *
7
+ * There is deliberately **no `length` field.** It would be `text.length` and
8
+ * nothing else, and a derived value stored beside its source is a value that can
9
+ * disagree with it — the two drift the moment anything edits one. Read
10
+ * `paste.text.length`.
11
+ */
12
+ interface HeldPaste {
13
+ id: string;
14
+ text: string;
15
+ }
16
+ /**
17
+ * The minimum of a clipboard event this hook touches.
18
+ *
19
+ * Structural rather than `React.ClipboardEvent` so a host can call it from a
20
+ * native listener, a synthetic one, or a test double. React's own event satisfies
21
+ * it.
22
+ */
23
+ interface PasteEventLike {
24
+ clipboardData?: {
25
+ getData(type: string): string;
26
+ } | null;
27
+ preventDefault(): void;
28
+ }
29
+ interface UsePastePillsOptions {
30
+ /**
31
+ * Hold a paste of at least this many characters. Try 500 — about a long
32
+ * paragraph.
33
+ *
34
+ * **No default, on purpose.** Paste is a fundamental interaction, so holding one
35
+ * is something a host asks for rather than something it discovers. Omit this and
36
+ * `handlePaste` always returns `false` and touches nothing.
37
+ */
38
+ threshold?: number;
39
+ /** Own the list yourself. Omit to let the hook keep it. */
40
+ heldPastes?: HeldPaste[];
41
+ onHeldPastesChange?: (pastes: HeldPaste[]) => void;
42
+ }
43
+ interface UsePastePillsResult {
44
+ heldPastes: HeldPaste[];
45
+ /**
46
+ * Call this from your OWN paste handler. Returns `true` if it took the paste —
47
+ * in which case it has already called `preventDefault()` — and `false` if it
48
+ * declined, having touched nothing.
49
+ *
50
+ * Composable on purpose: a host whose handler already intercepts paste for its
51
+ * own reasons needs to ask "did you want this?" rather than hand over the event.
52
+ *
53
+ * function onPaste(e) {
54
+ * if (pills.handlePaste(e)) return;
55
+ * // ...your own handling
56
+ * }
57
+ */
58
+ handlePaste: (event: PasteEventLike) => boolean;
59
+ /**
60
+ * Removes the paste and returns its text, for the host to insert into its own
61
+ * surface. `undefined` if there is no such id.
62
+ *
63
+ * The hook cannot insert it — it owns no DOM and does not know what a host's
64
+ * surface is. That is the point.
65
+ */
66
+ expand: (id: string) => string | undefined;
67
+ /** Discard one without returning it. */
68
+ remove: (id: string) => void;
69
+ /** Empty the list, e.g. after a send. */
70
+ clear: () => void;
71
+ }
72
+ /**
73
+ * Hold a large paste as state, so a composer can show it as a pill instead of
74
+ * turning itself into a scrolling wall.
75
+ *
76
+ * ---------------------------------------------------------------------------
77
+ * Why this is a hook and not just a feature of `Composer`
78
+ * ---------------------------------------------------------------------------
79
+ *
80
+ * `Composer` shipped the behaviour in 5.31.0 and the MOIC estate, who specified it,
81
+ * then established something I had missed: their chat input is a contenteditable
82
+ * rendering inline `[deal:42|Acme]` badges, so they **cannot** adopt `Composer` (a
83
+ * plain textarea) however much they want its behaviour. Their plan to delete their
84
+ * own composer when ours landed could never have worked.
85
+ *
86
+ * So the logic lives here and **`Composer` is its first caller.** One
87
+ * implementation rather than two, which matters more than the convenience: two
88
+ * copies of a rule drift, and the copy nobody reads is the one that rots. The rule
89
+ * that must not drift is the one in `Composer`'s own tests — a send with pills
90
+ * still closed carries the text.
91
+ *
92
+ * It owns no DOM. The host renders the pills.
93
+ *
94
+ * ---------------------------------------------------------------------------
95
+ * Who actually calls this (as of 5.32.0): `Composer`, and nothing else
96
+ * ---------------------------------------------------------------------------
97
+ *
98
+ * The estate that specified it **withdrew before adopting it**, hours after it
99
+ * shipped — their design moved the pill INTO the message as a `[paste:id|label]`
100
+ * marker in the same grammar as their other object tags, which makes the message
101
+ * itself the record of what is attached. A parallel `heldPastes` array would then be
102
+ * a second place answering "what am I sending?", and the two would disagree the
103
+ * moment someone backspaced a badge. Their reasoning was better than the spec.
104
+ *
105
+ * Recorded because a reader should not infer an extension point under active
106
+ * external use. It is kept rather than withdrawn for two reasons that are about
107
+ * cost, not optimism: it is published API on a 5.x package, so removing it needs a
108
+ * major; and `Composer` calls it, so it is exercised by that component's tests on
109
+ * every run and cannot rot unnoticed.
110
+ *
111
+ * **It gets no further surface without a real caller.** No extra options, no second
112
+ * hook. An API with one hypothetical consumer is how a package accumulates surface
113
+ * nobody uses.
114
+ */
115
+ declare function usePastePills({ threshold, heldPastes: controlledHeldPastes, onHeldPastesChange, }?: UsePastePillsOptions): UsePastePillsResult;
116
+
117
+ interface ComposerProps {
118
+ value?: string;
119
+ defaultValue?: string;
120
+ onChange?: (value: string) => void;
121
+ onSubmit?: (value: string) => void;
122
+ placeholder?: string;
123
+ actions?: ReactNode;
124
+ disabled?: boolean;
125
+ className?: string;
126
+ /**
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.
129
+ *
130
+ * **Omit it and paste behaves exactly as it always has.** Opt-in on purpose:
131
+ * paste is a fundamental interaction and this library is past 1.0, so a minor
132
+ * release must not quietly change what pasting does for every consumer. There is
133
+ * no default threshold for the same reason.
134
+ *
135
+ * Below the threshold nothing changes at all — no prevented event, no pill, no
136
+ * ceremony for an address or a name.
137
+ */
138
+ pasteThreshold?: number;
139
+ /**
140
+ * The held pastes, if you want to own them.
141
+ *
142
+ * Controllable rather than internal because the component contract forbids
143
+ * internal-only state for anything an agent might need to read or write — an
144
+ * agent driving this surface has to be able to see that a paste is attached, and
145
+ * to attach one itself.
146
+ */
147
+ heldPastes?: HeldPaste[];
148
+ onHeldPastesChange?: (pastes: HeldPaste[]) => void;
149
+ }
150
+
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 };