@gradeui/ui 3.3.0 → 4.0.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.
@@ -3,7 +3,7 @@ name: MediaSurface
3
3
  import: "@gradeui/ui"
4
4
  props:
5
5
  - aspect?: "video" | "square" | "portrait" | "wide" | "auto" — when omitted, derived from `hint` (album/product/food → square, portrait/poster → portrait, landscape → wide, video/audio/embed/generic → video)
6
- - radius?: "none" | "sm" | "md" | "lg" | "xl" (default "lg") — driven by `--gds-media-radius` CSS var
6
+ - radius?: "none" | "sm" | "md" | "lg" | "xl" (default "none") — driven by `--gds-media-radius` CSS var. Square by default so a slot mounted flush at the top of a Card lets the Card clip it; set `lg`/`xl` for a standalone rounded image
7
7
  - border?: boolean (default false)
8
8
  - loading?: boolean — renders the muted skeleton overlay
9
9
  - hint?: "album" | "portrait" | "landscape" | "poster" | "product" | "food" | "video" | "audio" | "embed" | "3d" | "generic" (default "generic") — picks the placeholder glyph + the default aspect + the future generation provider
@@ -0,0 +1,262 @@
1
+ import * as React from 'react';
2
+ import { LexicalEditor } from 'lexical';
3
+ import { a as DemoSpeed, b as DemoTrigger } from './types-DUwnWaxR.mjs';
4
+
5
+ /**
6
+ * Composer — the generic text composition surface for the design system.
7
+ *
8
+ * The answer wherever a user is composing a message: AI chat input,
9
+ * comment thread reply, post-body editor, future copilot panels.
10
+ * Replaces the textarea-with-buttons pattern that hosts kept rolling
11
+ * by hand.
12
+ *
13
+ * Built on Lexical (Meta's React-first editor framework) so it can do:
14
+ * - rich text formatting (B / I / U / S / code, headings, blockquote,
15
+ * pullquote, lists)
16
+ * - mentions and slash commands via lexical-beautiful-mentions, with
17
+ * a typeahead popover and theme-able tokens
18
+ * - image attachments (paperclip + clipboard paste) when opted in
19
+ * - scripted demo playback for marketing surfaces (types text, opens
20
+ * mention popovers, applies formatting, all via the same step
21
+ * vocabulary as <Code>)
22
+ *
23
+ * Slot-based composition for the action row: hosts that need custom
24
+ * affordances (template picker, voice button, attach-document) pass
25
+ * `leftActions` / `rightActions`. Default Send / Stop / paperclip
26
+ * render only when the host hasn't replaced the slot.
27
+ *
28
+ * Hosts that want the canned "chat composer with paperclip + send"
29
+ * preset should reach for `<AIChatComposer>` instead, which configures
30
+ * this Composer with the right slots wired up.
31
+ *
32
+ * Scripted demos: same `speed` / `trigger` / `play` / `loop` vocabulary
33
+ * as `<Code>`, sharing the underlying `useScriptedDemo` hook from
34
+ * `lib/demo/`. The Composer adds its own verbs (`mention`, `format`,
35
+ * `select`, `submit`) on top of the universal `type` / `wait` / `clear`.
36
+ */
37
+ type ComposerFormat = "bold" | "italic" | "underline" | "strikethrough" | "code" | "h1" | "h2" | "h3" | "blockquote" | "pullquote" | "ul" | "ol";
38
+ interface ComposerMentionItem {
39
+ id: string;
40
+ /** Display value (without the trigger char). */
41
+ value: string;
42
+ /** Optional secondary label shown in the suggester. */
43
+ label?: string;
44
+ /** Avatar URL or initials for the suggester row. */
45
+ avatar?: string;
46
+ /** Arbitrary payload the host can attach to the mention. */
47
+ data?: Record<string, unknown>;
48
+ }
49
+ interface ComposerTriggerConfig {
50
+ /** The trigger character, eg. "@" or "/". */
51
+ char: string;
52
+ /**
53
+ * Items to populate the suggester. Either a static array or a
54
+ * resolver function (sync or async) that receives the typed query.
55
+ * The plugin filters automatically when items is an array.
56
+ */
57
+ items: ComposerMentionItem[] | ((query: string) => ComposerMentionItem[] | Promise<ComposerMentionItem[]>);
58
+ /**
59
+ * Whether to strip the trigger char on insert. Defaults: keep for
60
+ * "@" (mentions read as "@alice"), strip for "/" (commands read as
61
+ * "Insert image" not "/insert-image").
62
+ */
63
+ stripTrigger?: boolean;
64
+ }
65
+ interface ComposerAttachmentConfig {
66
+ /** Master enable. Set true on the prop to use defaults, or pass a config object. */
67
+ enabled?: boolean;
68
+ /** HTML accept attribute on the file input. Default "image/*". */
69
+ accept?: string;
70
+ /** Max number of attachments. Default 10. */
71
+ maxItems?: number;
72
+ /** Allow multiple selection in the file picker. Default true. */
73
+ multiple?: boolean;
74
+ }
75
+ interface ComposerAttachment {
76
+ id: string;
77
+ file: File;
78
+ /** Object URL owned by the composer. Hosts must NOT revoke it. */
79
+ previewUrl: string;
80
+ name: string;
81
+ }
82
+ interface ComposerContent {
83
+ /** Plain text representation of the editor contents (whitespace preserved). */
84
+ text: string;
85
+ /** Lexical editor state serialised to JSON (for round-trip persistence). */
86
+ json: string;
87
+ /** Resolved mention tokens in document order. */
88
+ mentions: Array<{
89
+ trigger: string;
90
+ value: string;
91
+ data?: Record<string, unknown>;
92
+ }>;
93
+ }
94
+ interface ComposerHandle {
95
+ /** Run a demo script imperatively (vs. via `steps` + `trigger="manual"`). */
96
+ play: (steps: ComposerStep[]) => void;
97
+ /** Cancel an in-flight demo. Idempotent. */
98
+ stop: () => void;
99
+ /**
100
+ * One-shot replay of the configured `steps`. Cancels any in-flight
101
+ * run, clears the editor, replays from step 0. Pass a delay (ms) to
102
+ * schedule the replay (useful for chaining demos). Requires `steps`
103
+ * to be configured.
104
+ */
105
+ restart: (delayMs?: number) => void;
106
+ /** Move focus into the editor. */
107
+ focus: () => void;
108
+ /** Wipe the editor. */
109
+ clear: () => void;
110
+ /** Insert plain text at the current selection. */
111
+ insert: (text: string) => void;
112
+ /** Snapshot the current content + mentions. */
113
+ getContent: () => ComposerContent;
114
+ /** Direct access to the underlying Lexical editor (escape hatch). */
115
+ getEditor: () => LexicalEditor | null;
116
+ }
117
+ /**
118
+ * Demo step vocabulary for Composer scripts. Shares `type` / `wait` /
119
+ * `clear` with the universal `lib/demo` verbs; adds composer-specific
120
+ * `mention`, `format`, `select`, `newline`, `submit` on top.
121
+ */
122
+ type ComposerStep = {
123
+ type: "type";
124
+ text: string;
125
+ speed?: DemoSpeed;
126
+ } | {
127
+ type: "wait";
128
+ ms: number;
129
+ } | {
130
+ type: "clear";
131
+ } | {
132
+ type: "newline";
133
+ } | {
134
+ type: "submit";
135
+ } | {
136
+ type: "mention";
137
+ /** Trigger char (must match a registered ComposerTriggerConfig.char). */
138
+ trigger: string;
139
+ /** Value to insert (without the trigger). Looks up the matching item by `value`. */
140
+ value: string;
141
+ /** Optional pre-typed query — the demo types this after the trigger char before "selecting" the value, to show the typeahead in action. */
142
+ query?: string;
143
+ } | {
144
+ type: "format";
145
+ format: ComposerFormat;
146
+ } | {
147
+ type: "select";
148
+ /** Substring to find and select. First match wins. */
149
+ text: string;
150
+ };
151
+ interface ComposerProps {
152
+ /** Placeholder copy shown when empty. */
153
+ placeholder?: string;
154
+ /** Initial plain text content. For richer initial state, use `initialJson`. */
155
+ initialText?: string;
156
+ /** Initial Lexical state JSON (from a previous `onSubmit` round-trip). */
157
+ initialJson?: string;
158
+ /**
159
+ * Available formats. Pass false to disable rich text entirely
160
+ * (plain text mode, half the bundle weight, no toolbar). Default
161
+ * enables a sensible set for most chat / comment surfaces.
162
+ */
163
+ formats?: ComposerFormat[] | false;
164
+ /**
165
+ * Render the formatting toolbar. Default false because most uses
166
+ * are short-form. Set true (or "top") to show the toolbar above the
167
+ * editor. "floating" is planned; not yet implemented.
168
+ */
169
+ toolbar?: boolean | "top";
170
+ /**
171
+ * Mention / slash command configs. Each entry registers one trigger
172
+ * char and its items. Pass `[{ char: "@", items: people }, { char: "/", items: commands }]`
173
+ * for the common chat-app setup.
174
+ */
175
+ triggers?: ComposerTriggerConfig[];
176
+ /**
177
+ * Image attachments (paperclip + clipboard paste). Pass true for
178
+ * defaults, an object to customise, or omit/false to skip the
179
+ * attachment plumbing entirely.
180
+ */
181
+ attachments?: boolean | ComposerAttachmentConfig;
182
+ /** Fires when the user submits (Enter, click Send, or scripted `submit` step). */
183
+ onSubmit?: (content: ComposerContent, attachments?: ComposerAttachment[]) => void;
184
+ /**
185
+ * Fires on every editor change with the current plain text. Use for
186
+ * length validation, controlled-value bridges (eg. AIChatComposer
187
+ * forwarding to a host's `value`/`onChange` pair), or live preview
188
+ * surfaces. Cheap, called frequently; debounce if you need the
189
+ * Lexical state JSON (use `getContent()` via ref instead).
190
+ */
191
+ onChange?: (text: string) => void;
192
+ /**
193
+ * Loading state — disables the editor + paperclip and swaps the
194
+ * default Send button for Stop. Has no effect when `rightActions`
195
+ * overrides the default Send.
196
+ */
197
+ isLoading?: boolean;
198
+ /** Stop handler — required for Stop to be active when loading. */
199
+ onStop?: () => void;
200
+ /** Hard character cap. */
201
+ maxLength?: number;
202
+ /** Auto-focus the editor on mount. Default false. */
203
+ autoFocus?: boolean;
204
+ /** Whether Enter submits. Default true (Shift-Enter still inserts a newline). */
205
+ submitOnEnter?: boolean;
206
+ /**
207
+ * Custom content for the left action slot. Replaces the default
208
+ * paperclip button when `attachments` is enabled.
209
+ */
210
+ leftActions?: React.ReactNode;
211
+ /**
212
+ * Custom content for the right action slot. Replaces the default
213
+ * Send / Stop button. Use the `useComposer()` hook inside to access
214
+ * imperative methods.
215
+ */
216
+ rightActions?: React.ReactNode;
217
+ /** Hide the default Send button without replacing it. */
218
+ hideSend?: boolean;
219
+ /** Scripted demo steps. */
220
+ steps?: ComposerStep[];
221
+ /** What kicks the script off. Defaults to "mount". */
222
+ trigger?: DemoTrigger;
223
+ /** For trigger="manual" — flip true to play. */
224
+ play?: boolean;
225
+ /** Animation feel. */
226
+ speed?: DemoSpeed;
227
+ /** Loop the script forever. */
228
+ loop?: boolean;
229
+ /**
230
+ * Pause between loop iterations (ms). Defaults to 2000. Marketing
231
+ * heroes that want the demo to breathe between repeats bump this
232
+ * higher; tight inline demos drop it.
233
+ */
234
+ loopDelay?: number;
235
+ /**
236
+ * Fires once per loop cycle, AFTER the loopDelay pause and BEFORE
237
+ * the script replays. Use to reset parent state that the script
238
+ * mutated via onSubmit (e.g., wipe a messages list back to its
239
+ * seed before the demo types into it again). The editor is cleared
240
+ * automatically — you only need this hook if state outside the
241
+ * Composer needs to reset too.
242
+ */
243
+ onLoopReset?: () => void;
244
+ /**
245
+ * Bare mode — strip the card chrome (border / bg / rounding). Use
246
+ * when embedding inside an existing card or column layout.
247
+ */
248
+ bare?: boolean;
249
+ /**
250
+ * Read-only mode — disables editing AND focusability. Programmatic
251
+ * updates (including scripted demo playback) still work. Use for
252
+ * marketing surfaces that render a Composer purely for show, so the
253
+ * scripted typing doesn't steal focus from other inputs on the page.
254
+ * Hides the default Send / paperclip action row.
255
+ */
256
+ readOnly?: boolean;
257
+ className?: string;
258
+ }
259
+ declare const Composer: React.ForwardRefExoticComponent<ComposerProps & React.RefAttributes<ComposerHandle>>;
260
+ declare const ComposerReply: React.ForwardRefExoticComponent<ComposerProps & React.RefAttributes<ComposerHandle>>;
261
+
262
+ export { Composer, type ComposerAttachment, type ComposerAttachmentConfig, type ComposerContent, type ComposerFormat, type ComposerHandle, type ComposerMentionItem, type ComposerProps, ComposerReply, type ComposerStep, type ComposerTriggerConfig };
@@ -0,0 +1,262 @@
1
+ import * as React from 'react';
2
+ import { LexicalEditor } from 'lexical';
3
+ import { a as DemoSpeed, b as DemoTrigger } from './types-DUwnWaxR.js';
4
+
5
+ /**
6
+ * Composer — the generic text composition surface for the design system.
7
+ *
8
+ * The answer wherever a user is composing a message: AI chat input,
9
+ * comment thread reply, post-body editor, future copilot panels.
10
+ * Replaces the textarea-with-buttons pattern that hosts kept rolling
11
+ * by hand.
12
+ *
13
+ * Built on Lexical (Meta's React-first editor framework) so it can do:
14
+ * - rich text formatting (B / I / U / S / code, headings, blockquote,
15
+ * pullquote, lists)
16
+ * - mentions and slash commands via lexical-beautiful-mentions, with
17
+ * a typeahead popover and theme-able tokens
18
+ * - image attachments (paperclip + clipboard paste) when opted in
19
+ * - scripted demo playback for marketing surfaces (types text, opens
20
+ * mention popovers, applies formatting, all via the same step
21
+ * vocabulary as <Code>)
22
+ *
23
+ * Slot-based composition for the action row: hosts that need custom
24
+ * affordances (template picker, voice button, attach-document) pass
25
+ * `leftActions` / `rightActions`. Default Send / Stop / paperclip
26
+ * render only when the host hasn't replaced the slot.
27
+ *
28
+ * Hosts that want the canned "chat composer with paperclip + send"
29
+ * preset should reach for `<AIChatComposer>` instead, which configures
30
+ * this Composer with the right slots wired up.
31
+ *
32
+ * Scripted demos: same `speed` / `trigger` / `play` / `loop` vocabulary
33
+ * as `<Code>`, sharing the underlying `useScriptedDemo` hook from
34
+ * `lib/demo/`. The Composer adds its own verbs (`mention`, `format`,
35
+ * `select`, `submit`) on top of the universal `type` / `wait` / `clear`.
36
+ */
37
+ type ComposerFormat = "bold" | "italic" | "underline" | "strikethrough" | "code" | "h1" | "h2" | "h3" | "blockquote" | "pullquote" | "ul" | "ol";
38
+ interface ComposerMentionItem {
39
+ id: string;
40
+ /** Display value (without the trigger char). */
41
+ value: string;
42
+ /** Optional secondary label shown in the suggester. */
43
+ label?: string;
44
+ /** Avatar URL or initials for the suggester row. */
45
+ avatar?: string;
46
+ /** Arbitrary payload the host can attach to the mention. */
47
+ data?: Record<string, unknown>;
48
+ }
49
+ interface ComposerTriggerConfig {
50
+ /** The trigger character, eg. "@" or "/". */
51
+ char: string;
52
+ /**
53
+ * Items to populate the suggester. Either a static array or a
54
+ * resolver function (sync or async) that receives the typed query.
55
+ * The plugin filters automatically when items is an array.
56
+ */
57
+ items: ComposerMentionItem[] | ((query: string) => ComposerMentionItem[] | Promise<ComposerMentionItem[]>);
58
+ /**
59
+ * Whether to strip the trigger char on insert. Defaults: keep for
60
+ * "@" (mentions read as "@alice"), strip for "/" (commands read as
61
+ * "Insert image" not "/insert-image").
62
+ */
63
+ stripTrigger?: boolean;
64
+ }
65
+ interface ComposerAttachmentConfig {
66
+ /** Master enable. Set true on the prop to use defaults, or pass a config object. */
67
+ enabled?: boolean;
68
+ /** HTML accept attribute on the file input. Default "image/*". */
69
+ accept?: string;
70
+ /** Max number of attachments. Default 10. */
71
+ maxItems?: number;
72
+ /** Allow multiple selection in the file picker. Default true. */
73
+ multiple?: boolean;
74
+ }
75
+ interface ComposerAttachment {
76
+ id: string;
77
+ file: File;
78
+ /** Object URL owned by the composer. Hosts must NOT revoke it. */
79
+ previewUrl: string;
80
+ name: string;
81
+ }
82
+ interface ComposerContent {
83
+ /** Plain text representation of the editor contents (whitespace preserved). */
84
+ text: string;
85
+ /** Lexical editor state serialised to JSON (for round-trip persistence). */
86
+ json: string;
87
+ /** Resolved mention tokens in document order. */
88
+ mentions: Array<{
89
+ trigger: string;
90
+ value: string;
91
+ data?: Record<string, unknown>;
92
+ }>;
93
+ }
94
+ interface ComposerHandle {
95
+ /** Run a demo script imperatively (vs. via `steps` + `trigger="manual"`). */
96
+ play: (steps: ComposerStep[]) => void;
97
+ /** Cancel an in-flight demo. Idempotent. */
98
+ stop: () => void;
99
+ /**
100
+ * One-shot replay of the configured `steps`. Cancels any in-flight
101
+ * run, clears the editor, replays from step 0. Pass a delay (ms) to
102
+ * schedule the replay (useful for chaining demos). Requires `steps`
103
+ * to be configured.
104
+ */
105
+ restart: (delayMs?: number) => void;
106
+ /** Move focus into the editor. */
107
+ focus: () => void;
108
+ /** Wipe the editor. */
109
+ clear: () => void;
110
+ /** Insert plain text at the current selection. */
111
+ insert: (text: string) => void;
112
+ /** Snapshot the current content + mentions. */
113
+ getContent: () => ComposerContent;
114
+ /** Direct access to the underlying Lexical editor (escape hatch). */
115
+ getEditor: () => LexicalEditor | null;
116
+ }
117
+ /**
118
+ * Demo step vocabulary for Composer scripts. Shares `type` / `wait` /
119
+ * `clear` with the universal `lib/demo` verbs; adds composer-specific
120
+ * `mention`, `format`, `select`, `newline`, `submit` on top.
121
+ */
122
+ type ComposerStep = {
123
+ type: "type";
124
+ text: string;
125
+ speed?: DemoSpeed;
126
+ } | {
127
+ type: "wait";
128
+ ms: number;
129
+ } | {
130
+ type: "clear";
131
+ } | {
132
+ type: "newline";
133
+ } | {
134
+ type: "submit";
135
+ } | {
136
+ type: "mention";
137
+ /** Trigger char (must match a registered ComposerTriggerConfig.char). */
138
+ trigger: string;
139
+ /** Value to insert (without the trigger). Looks up the matching item by `value`. */
140
+ value: string;
141
+ /** Optional pre-typed query — the demo types this after the trigger char before "selecting" the value, to show the typeahead in action. */
142
+ query?: string;
143
+ } | {
144
+ type: "format";
145
+ format: ComposerFormat;
146
+ } | {
147
+ type: "select";
148
+ /** Substring to find and select. First match wins. */
149
+ text: string;
150
+ };
151
+ interface ComposerProps {
152
+ /** Placeholder copy shown when empty. */
153
+ placeholder?: string;
154
+ /** Initial plain text content. For richer initial state, use `initialJson`. */
155
+ initialText?: string;
156
+ /** Initial Lexical state JSON (from a previous `onSubmit` round-trip). */
157
+ initialJson?: string;
158
+ /**
159
+ * Available formats. Pass false to disable rich text entirely
160
+ * (plain text mode, half the bundle weight, no toolbar). Default
161
+ * enables a sensible set for most chat / comment surfaces.
162
+ */
163
+ formats?: ComposerFormat[] | false;
164
+ /**
165
+ * Render the formatting toolbar. Default false because most uses
166
+ * are short-form. Set true (or "top") to show the toolbar above the
167
+ * editor. "floating" is planned; not yet implemented.
168
+ */
169
+ toolbar?: boolean | "top";
170
+ /**
171
+ * Mention / slash command configs. Each entry registers one trigger
172
+ * char and its items. Pass `[{ char: "@", items: people }, { char: "/", items: commands }]`
173
+ * for the common chat-app setup.
174
+ */
175
+ triggers?: ComposerTriggerConfig[];
176
+ /**
177
+ * Image attachments (paperclip + clipboard paste). Pass true for
178
+ * defaults, an object to customise, or omit/false to skip the
179
+ * attachment plumbing entirely.
180
+ */
181
+ attachments?: boolean | ComposerAttachmentConfig;
182
+ /** Fires when the user submits (Enter, click Send, or scripted `submit` step). */
183
+ onSubmit?: (content: ComposerContent, attachments?: ComposerAttachment[]) => void;
184
+ /**
185
+ * Fires on every editor change with the current plain text. Use for
186
+ * length validation, controlled-value bridges (eg. AIChatComposer
187
+ * forwarding to a host's `value`/`onChange` pair), or live preview
188
+ * surfaces. Cheap, called frequently; debounce if you need the
189
+ * Lexical state JSON (use `getContent()` via ref instead).
190
+ */
191
+ onChange?: (text: string) => void;
192
+ /**
193
+ * Loading state — disables the editor + paperclip and swaps the
194
+ * default Send button for Stop. Has no effect when `rightActions`
195
+ * overrides the default Send.
196
+ */
197
+ isLoading?: boolean;
198
+ /** Stop handler — required for Stop to be active when loading. */
199
+ onStop?: () => void;
200
+ /** Hard character cap. */
201
+ maxLength?: number;
202
+ /** Auto-focus the editor on mount. Default false. */
203
+ autoFocus?: boolean;
204
+ /** Whether Enter submits. Default true (Shift-Enter still inserts a newline). */
205
+ submitOnEnter?: boolean;
206
+ /**
207
+ * Custom content for the left action slot. Replaces the default
208
+ * paperclip button when `attachments` is enabled.
209
+ */
210
+ leftActions?: React.ReactNode;
211
+ /**
212
+ * Custom content for the right action slot. Replaces the default
213
+ * Send / Stop button. Use the `useComposer()` hook inside to access
214
+ * imperative methods.
215
+ */
216
+ rightActions?: React.ReactNode;
217
+ /** Hide the default Send button without replacing it. */
218
+ hideSend?: boolean;
219
+ /** Scripted demo steps. */
220
+ steps?: ComposerStep[];
221
+ /** What kicks the script off. Defaults to "mount". */
222
+ trigger?: DemoTrigger;
223
+ /** For trigger="manual" — flip true to play. */
224
+ play?: boolean;
225
+ /** Animation feel. */
226
+ speed?: DemoSpeed;
227
+ /** Loop the script forever. */
228
+ loop?: boolean;
229
+ /**
230
+ * Pause between loop iterations (ms). Defaults to 2000. Marketing
231
+ * heroes that want the demo to breathe between repeats bump this
232
+ * higher; tight inline demos drop it.
233
+ */
234
+ loopDelay?: number;
235
+ /**
236
+ * Fires once per loop cycle, AFTER the loopDelay pause and BEFORE
237
+ * the script replays. Use to reset parent state that the script
238
+ * mutated via onSubmit (e.g., wipe a messages list back to its
239
+ * seed before the demo types into it again). The editor is cleared
240
+ * automatically — you only need this hook if state outside the
241
+ * Composer needs to reset too.
242
+ */
243
+ onLoopReset?: () => void;
244
+ /**
245
+ * Bare mode — strip the card chrome (border / bg / rounding). Use
246
+ * when embedding inside an existing card or column layout.
247
+ */
248
+ bare?: boolean;
249
+ /**
250
+ * Read-only mode — disables editing AND focusability. Programmatic
251
+ * updates (including scripted demo playback) still work. Use for
252
+ * marketing surfaces that render a Composer purely for show, so the
253
+ * scripted typing doesn't steal focus from other inputs on the page.
254
+ * Hides the default Send / paperclip action row.
255
+ */
256
+ readOnly?: boolean;
257
+ className?: string;
258
+ }
259
+ declare const Composer: React.ForwardRefExoticComponent<ComposerProps & React.RefAttributes<ComposerHandle>>;
260
+ declare const ComposerReply: React.ForwardRefExoticComponent<ComposerProps & React.RefAttributes<ComposerHandle>>;
261
+
262
+ export { Composer, type ComposerAttachment, type ComposerAttachmentConfig, type ComposerContent, type ComposerFormat, type ComposerHandle, type ComposerMentionItem, type ComposerProps, ComposerReply, type ComposerStep, type ComposerTriggerConfig };
@@ -0,0 +1,3 @@
1
+ "use client";
2
+ 'use strict';var e=require('react'),LexicalComposer=require('@lexical/react/LexicalComposer'),LexicalRichTextPlugin=require('@lexical/react/LexicalRichTextPlugin'),LexicalContentEditable=require('@lexical/react/LexicalContentEditable'),LexicalErrorBoundary=require('@lexical/react/LexicalErrorBoundary'),LexicalHistoryPlugin=require('@lexical/react/LexicalHistoryPlugin'),LexicalOnChangePlugin=require('@lexical/react/LexicalOnChangePlugin'),LexicalListPlugin=require('@lexical/react/LexicalListPlugin'),LexicalLinkPlugin=require('@lexical/react/LexicalLinkPlugin'),LexicalComposerContext=require('@lexical/react/LexicalComposerContext'),richText=require('@lexical/rich-text'),list=require('@lexical/list'),link=require('@lexical/link'),code=require('@lexical/code'),selection=require('@lexical/selection'),utils=require('@lexical/utils'),lexical=require('lexical'),lexicalBeautifulMentions=require('lexical-beautiful-mentions'),react=require('motion/react'),lucideReact=require('lucide-react'),clsx=require('clsx'),tailwindMerge=require('tailwind-merge');function _interopNamespace(e){if(e&&e.__esModule)return e;var n=Object.create(null);if(e){Object.keys(e).forEach(function(k){if(k!=='default'){var d=Object.getOwnPropertyDescriptor(e,k);Object.defineProperty(n,k,d.get?d:{enumerable:true,get:function(){return e[k]}});}})}n.default=e;return Object.freeze(n)}var e__namespace=/*#__PURE__*/_interopNamespace(e);var pe={slow:{tokenStagger:70,lineStagger:200,preDelay:500,fadeMs:480},normal:{tokenStagger:22,lineStagger:55,preDelay:200,fadeMs:280},fast:{tokenStagger:8,lineStagger:18,preDelay:60,fadeMs:160}},ce=.55;function E(r,t){return r<=0?Promise.resolve():new Promise((o,s)=>{if(t?.aborted){s(new DOMException("Aborted","AbortError"));return}let n=window.setTimeout(()=>{t?.removeEventListener("abort",a),o();},r),a=()=>{window.clearTimeout(n),s(new DOMException("Aborted","AbortError"));};t?.addEventListener("abort",a,{once:true});})}async function ue(r,t,o=22,s){if(o<=0){t(r);return}for(let n=1;n<=r.length;n++)t(r.slice(0,n)),n<r.length&&await E(o,s);}function de(r){return r instanceof DOMException&&r.name==="AbortError"}var fe="data-motion",we="off",ge="(prefers-reduced-motion: reduce)";function Te(){if(typeof window>"u"||typeof document>"u")return false;let r=window.matchMedia(ge).matches,t=document.documentElement.getAttribute(fe)===we;return r||t}function be(){let[r,t]=e__namespace.useState(false);return e__namespace.useEffect(()=>{let o=()=>t(Te());o();let s=window.matchMedia(ge);s.addEventListener("change",o);let n=new MutationObserver(o);return n.observe(document.documentElement,{attributes:true,attributeFilter:[fe]}),()=>{s.removeEventListener("change",o),n.disconnect();}},[]),r}function he(){let[r,t]=e__namespace.useState(true);return e__namespace.useEffect(()=>{let o=window.self!==window.top,s=()=>document.visibilityState!=="hidden"&&(o||document.hasFocus()),n=()=>t(s());return n(),document.addEventListener("visibilitychange",n),window.addEventListener("focus",n),window.addEventListener("blur",n),window.addEventListener("pageshow",n),()=>{document.removeEventListener("visibilitychange",n),window.removeEventListener("focus",n),window.removeEventListener("blur",n),window.removeEventListener("pageshow",n);}},[]),r}var Se=2e3,De={tokenStagger:0,lineStagger:0,preDelay:0,fadeMs:0};function me(r){let{steps:t,interpret:o,speed:s="normal",trigger:n="mount",play:a,loop:d=false,loopDelay:h=Se,maxLoops:m=1/0,containerRef:R,onComplete:N,onLoopReset:L}=r,p=be(),y=p?De:pe[s],k=p?false:d,A=he(),[I,x]=e__namespace.useState(false),[X,V]=e__namespace.useState(false),[G,q]=e__namespace.useState(-1),$=e__namespace.useRef(null),W=react.useInView(R??$,{once:true,amount:ce}),M=react.useInView(R??$,{amount:ce}),K=A&&(R?M:true),[c,w]=e__namespace.useState(0),f=e__namespace.useMemo(()=>n==="mount"?true:n==="inView"?W:!!a||c>0,[n,W,a,c]),O=e__namespace.useRef(o);O.current=o;let _=e__namespace.useRef(N);_.current=N;let l=e__namespace.useRef(L);l.current=L;let P=e__namespace.useRef(null),T=e__namespace.useRef(null),te=e__namespace.useCallback(()=>{P.current?.abort(),P.current=null,T.current!==null&&(window.clearTimeout(T.current),T.current=null),x(false);},[]),se=e__namespace.useCallback(()=>{w(S=>S+1);},[]),oe=e__namespace.useCallback((S=0)=>{if(P.current?.abort(),P.current=null,T.current!==null&&(window.clearTimeout(T.current),T.current=null),S>0){T.current=window.setTimeout(()=>{T.current=null,w(C=>C+1);},S);return}w(C=>C+1);},[]);return e__namespace.useEffect(()=>()=>{T.current!==null&&(window.clearTimeout(T.current),T.current=null);},[]),e__namespace.useEffect(()=>{if(!t||t.length===0||!p&&(!f||!K))return;let S=new AbortController;P.current=S;let{signal:C}=S,re={speed:y,signal:C,cancelled:()=>C.aborted,reduced:p},ne=true,i=0;return (async()=>{do{x(true),V(false),q(-1);try{await E(n==="inView"?y.preDelay:0,C);for(let u=0;u<t.length;u++){if(C.aborted)return;q(u),await O.current(t[u],re);}if(C.aborted)return;if(q(-1),V(!0),_.current?.(),i+=1,!k||i>=m){x(!1);return}if(await E(h,C),C.aborted)return;l.current?.();}catch(u){if(de(u))return;process.env.NODE_ENV!=="production"&&console.error("[useScriptedDemo] step error:",u),x(false);return}}while(ne&&k&&!C.aborted)})(),()=>{ne=false,S.abort(),P.current===S&&(P.current=null);}},[t,f,K,k,h,y,n,c,p]),{isPlaying:I,isComplete:X,currentIndex:G,play:se,stop:te,restart:oe}}function j(...r){return tailwindMerge.twMerge(clsx.clsx(r))}function Rt({onSubmit:r,enabled:t}){let[o]=LexicalComposerContext.useLexicalComposerContext();return e__namespace.useEffect(()=>{if(t)return o.registerCommand(lexical.KEY_ENTER_COMMAND,s=>s&&s.shiftKey?false:(s?.preventDefault(),r(),true),lexical.COMMAND_PRIORITY_HIGH)},[o,t,r]),null}function vt({onImageFiles:r,enabled:t}){let[o]=LexicalComposerContext.useLexicalComposerContext();return e__namespace.useEffect(()=>{if(!t)return;let s=o.getRootElement();if(!s)return;let n=a=>{let h=Array.from(a.clipboardData?.items??[]).filter(m=>m.kind==="file"&&m.type.startsWith("image/")).map(m=>m.getAsFile()).filter(m=>m!==null);h.length>0&&(a.preventDefault(),r(h));};return s.addEventListener("paste",n),()=>s.removeEventListener("paste",n)},[o,t,r]),null}function Ct({enabled:r}){let[t]=LexicalComposerContext.useLexicalComposerContext();return e__namespace.useEffect(()=>{r&&t.focus();},[t,r]),null}var Re={bold:"bold",italic:"italic",underline:"underline",strikethrough:"strikethrough",code:"code"};function ve(r,t){let o=Re[t];if(o){r.dispatchCommand(lexical.FORMAT_TEXT_COMMAND,o);return}if(t==="ul"){r.dispatchCommand(list.INSERT_UNORDERED_LIST_COMMAND,void 0);return}if(t==="ol"){r.dispatchCommand(list.INSERT_ORDERED_LIST_COMMAND,void 0);return}r.update(()=>{let s=lexical.$getSelection();if(lexical.$isRangeSelection(s)){if(t==="h1"||t==="h2"||t==="h3"){let n=t;selection.$setBlocksType(s,()=>richText.$createHeadingNode(n));return}(t==="blockquote"||t==="pullquote")&&selection.$setBlocksType(s,()=>{let n=richText.$createQuoteNode();return t==="pullquote"&&(n.__pullquote=true),n});}});}function Et(r,t,o,s){r.update(()=>{let n=lexical.$getSelection();if(!lexical.$isRangeSelection(n))return;let a=lexicalBeautifulMentions.$createBeautifulMentionNode(t,o,s);n.insertNodes([a]),n.insertText(" ");});}function wt(r,t){let o=false;return r.update(()=>{let s=lexical.$getRoot(),a=s.getTextContent().indexOf(t);if(a===-1)return;let d=0,h=null,m=0,R=null,N=0,L=p=>{if(!(h&&R)){if(p.getType()==="text"){let y=p,k=y.getTextContentSize(),A=d,I=d+k;!h&&a>=A&&a<I&&(h=y,m=a-A);let x=a+t.length;!R&&x>A&&x<=I&&(R=y,N=x-A),d=I;return}if("getChildren"in p)for(let y of p.getChildren())L(y);else d+=p.getTextContentSize();}};if(L(s),h&&R){let p=h,y=R;p.select(m,0).focus.set(y.getKey(),N,"text"),o=true;}}),o}function Z(r){r.update(()=>{let t=lexical.$getRoot();t.clear();let o=lexical.$createParagraphNode();t.append(o),o.select();});}function Ce(r){let t="",o="",s=[];return r.getEditorState().read(()=>{t=lexical.$getRoot().getTextContent(),o=JSON.stringify(r.getEditorState().toJSON());let n=a=>{if(a.getType()==="beautifulMention"){let d=a;s.push({trigger:d.getTrigger(),value:d.getValue(),data:d.getData()});}if("getChildren"in a)for(let d of a.getChildren())n(d);};n(lexical.$getRoot());}),{text:t,json:o,mentions:s}}var Tt=[{format:"bold",icon:lucideReact.Bold,label:"Bold"},{format:"italic",icon:lucideReact.Italic,label:"Italic"},{format:"underline",icon:lucideReact.Underline,label:"Underline"},{format:"strikethrough",icon:lucideReact.Strikethrough,label:"Strikethrough"},{format:"code",icon:lucideReact.Code,label:"Inline code"},{format:"h1",icon:lucideReact.Heading1,label:"Heading 1"},{format:"h2",icon:lucideReact.Heading2,label:"Heading 2"},{format:"h3",icon:lucideReact.Heading3,label:"Heading 3"},{format:"blockquote",icon:lucideReact.Quote,label:"Blockquote"},{format:"ul",icon:lucideReact.List,label:"Bulleted list"},{format:"ol",icon:lucideReact.ListOrdered,label:"Numbered list"}];function St({formats:r}){let[t]=LexicalComposerContext.useLexicalComposerContext(),[o,s]=e__namespace.useState(()=>new Set);e__namespace.useEffect(()=>utils.mergeRegister(t.registerUpdateListener(({editorState:a})=>{a.read(()=>{let d=lexical.$getSelection();if(!lexical.$isRangeSelection(d))return;let h=new Set;for(let m of ["bold","italic","underline","strikethrough","code"])d.hasFormat(m)&&h.add(m);s(h);});})),[t]);let n=Tt.filter(a=>r.includes(a.format));return e__namespace.createElement("div",{"data-gds-part":"composer-toolbar",className:j("flex flex-wrap items-center gap-0.5","px-2 py-1")},n.map(({format:a,icon:d,label:h})=>{let m=Re[a],R=m?o.has(m):false;return e__namespace.createElement("button",{key:a,type:"button","aria-label":h,title:h,"data-gds-part":"composer-toolbar-button","data-gds-active":R?"true":"false",onClick:()=>ve(t,a),className:j("h-7 w-7 inline-flex items-center justify-center rounded","text-[var(--gds-composer-toolbar-fg)]","hover:bg-[var(--gds-composer-toolbar-hover-bg)]","focus:outline-none focus:ring-2 focus:ring-primary",R&&"bg-[var(--gds-composer-toolbar-active-bg)] text-[var(--gds-composer-toolbar-active-fg)]")},e__namespace.createElement(d,{className:"h-3.5 w-3.5"}))}))}function Dt({attachments:r,onRemove:t}){return e__namespace.createElement(react.AnimatePresence,{initial:false},r.length>0&&e__namespace.createElement(react.motion.div,{initial:{opacity:0,height:0},animate:{opacity:1,height:"auto"},exit:{opacity:0,height:0},transition:{duration:.18},className:"overflow-hidden"},e__namespace.createElement("div",{"data-gds-part":"composer-attachments",className:"flex flex-wrap gap-2 px-2 py-2"},r.map(o=>e__namespace.createElement("div",{key:o.id,className:"relative group"},o.file.type.startsWith("image/")?e__namespace.createElement("img",{src:o.previewUrl,alt:o.name,className:"h-14 w-14 rounded-md object-cover border border-[var(--gds-composer-border)]"}):e__namespace.createElement("div",{className:"h-14 w-14 rounded-md border border-[var(--gds-composer-border)] flex items-center justify-center text-xs px-1 text-center text-[var(--gds-composer-muted-fg)]"},o.name.slice(0,18)),e__namespace.createElement("button",{type:"button",onClick:()=>t(o.id),"aria-label":`Remove ${o.name}`,className:j("absolute -top-1.5 -right-1.5 h-5 w-5 rounded-full","bg-[var(--gds-composer-chip-remove-bg)]","text-[var(--gds-composer-chip-remove-fg)]","flex items-center justify-center","opacity-0 group-hover:opacity-100 focus:opacity-100","focus:outline-none focus:ring-2 focus:ring-primary","transition-opacity")},e__namespace.createElement(lucideReact.X,{className:"w-3 h-3"})))))))}function Nt({placeholder:r,triggers:t,attachmentsCfg:o,formatList:s,showToolbar:n,isLoading:a,onStop:d,maxLength:h,autoFocus:m,submitOnEnter:R=true,leftActions:N,rightActions:L,hideSend:p,steps:y,trigger:k="mount",play:A,speed:I="normal",loop:x=false,loopDelay:X,onLoopReset:V,bare:G,className:q,onSubmit:$,onChange:W,readOnly:M,handleEditorReady:K,submitRef:c,restartRef:w,attachments:f,setAttachments:O,ingestImages:_}){let[l]=LexicalComposerContext.useLexicalComposerContext(),P=e__namespace.useRef(null),T=e__namespace.useRef(null),[te,se]=e__namespace.useState(false);e__namespace.useEffect(()=>{K(l);},[l,K]),e__namespace.useEffect(()=>{l.setEditable(!M);},[l,M]);let oe=e__namespace.useRef(W);oe.current=W,e__namespace.useEffect(()=>l.registerUpdateListener(({editorState:i})=>{i.read(()=>{let v=lexical.$getRoot().getTextContent();se(v.trim().length>0),oe.current?.(v);});}),[l]);let S=e__namespace.useCallback(()=>{if(a)return;let i=Ce(l),v=i.text.trim().length>0,u=f.length>0;!v&&!u||($?.(i,u?f:void 0),Z(l),f.forEach(J=>URL.revokeObjectURL(J.previewUrl)),O([]));},[l,a,f,$,O]);c.current=S;let{restart:C}=me({steps:y,speed:I,trigger:k,play:A,loop:x,loopDelay:X,containerRef:P,onLoopReset:()=>{Z(l),V?.();},interpret:async(i,v)=>{let u=v.signal;if(i.type==="wait")return E(i.ms,u);if(i.type==="clear")return Z(l),E(120,u);if(i.type==="newline")return l.update(()=>{let g=lexical.$getSelection();lexical.$isRangeSelection(g)&&g.insertParagraph();}),E(60,u);if(i.type==="submit")return S(),E(120,u);if(i.type==="format")return ve(l,i.format),l.update(()=>{let g=lexical.$getSelection();if(!lexical.$isRangeSelection(g)||g.isCollapsed())return;let D=g.focus;g.anchor.set(D.key,D.offset,D.type);}),E(80,u);if(i.type==="select")return wt(l,i.text),E(120,u);if(i.type==="mention")return i.query&&(l.update(()=>{let g=lexical.$getSelection();lexical.$isRangeSelection(g)&&g.insertText(i.trigger);}),await ue(i.query,g=>{l.update(()=>{let D=lexical.$getRoot(),Y=D.getTextContent(),B=Y.slice(0,Y.length-i.trigger.length-(g.length-1));D.clear();let Q=lexical.$createParagraphNode();B&&Q.append(lexical.$createTextNode(B)),Q.append(lexical.$createTextNode(i.trigger+g)),D.append(Q);});},v.speed.tokenStagger,u),await E(180,u),l.update(()=>{let g=lexical.$getRoot(),D=g.getTextContent(),Y=i.trigger.length+i.query.length,B=D.slice(0,D.length-Y);g.clear();let Q=lexical.$createParagraphNode();B&&Q.append(lexical.$createTextNode(B)),g.append(Q),Q.select();})),Et(l,i.trigger,i.value),E(120,u);let J=i.speed?{slow:70,normal:22,fast:8}[i.speed]:v.speed.tokenStagger;for(let g=0;g<i.text.length;g++){if(u.aborted)return;let D=i.text[g];l.update(()=>{let Y=lexical.$getSelection();if(!lexical.$isRangeSelection(Y)){lexical.$getRoot().selectEnd();let B=lexical.$getSelection();lexical.$isRangeSelection(B)&&B.insertText(D);return}Y.insertText(D);}),g<i.text.length-1&&await E(J,u);}}});e__namespace.useEffect(()=>{w.current=i=>{Z(l),C(i);};},[l,C,w]);let le=!M&&!L&&!p,re=!M&&!N&&o!==null,ne=!M&&(re||N||le||L);return e__namespace.createElement("div",{ref:P,"data-gds-part":"composer","data-gds-loading":a?"true":"false",className:j("w-full",!G&&["rounded-md","bg-transparent","border border-input","shadow-sm","focus-within:outline-none focus-within:ring-1 focus-within:ring-ring","transition-colors"],q)},n&&e__namespace.createElement(St,{formats:s}),o&&e__namespace.createElement(Dt,{attachments:f,onRemove:i=>{O(v=>{let u=v.find(J=>J.id===i);return u&&URL.revokeObjectURL(u.previewUrl),v.filter(J=>J.id!==i)});}}),e__namespace.createElement("div",{className:"relative"},e__namespace.createElement(LexicalRichTextPlugin.RichTextPlugin,{contentEditable:e__namespace.createElement(LexicalContentEditable.ContentEditable,{"data-gds-part":"composer-editor",className:j("outline-none","px-3 sm:px-4 py-3","text-sm text-[var(--gds-composer-fg)]","min-h-[44px] max-h-[300px] overflow-y-auto","[&_p]:m-0 [&_p+p]:mt-2","[&_h1]:text-xl [&_h1]:font-semibold [&_h1]:mt-2","[&_h2]:text-lg [&_h2]:font-semibold [&_h2]:mt-2","[&_h3]:text-base [&_h3]:font-semibold [&_h3]:mt-2","[&_ul]:list-disc [&_ul]:pl-5 [&_ol]:list-decimal [&_ol]:pl-5","[&_blockquote]:border-l-2 [&_blockquote]:border-[var(--gds-composer-border)] [&_blockquote]:pl-3 [&_blockquote]:italic","[&_code]:bg-[var(--gds-composer-toolbar-active-bg)] [&_code]:px-1 [&_code]:py-0.5 [&_code]:rounded [&_code]:text-xs [&_code]:font-mono",a&&"opacity-60 pointer-events-none"),"aria-placeholder":r??"",placeholder:e__namespace.createElement("div",{"data-gds-part":"composer-placeholder",className:"absolute top-3 left-3 sm:left-4 text-sm text-muted-foreground pointer-events-none select-none"},r),spellCheck:true}),ErrorBoundary:LexicalErrorBoundary.LexicalErrorBoundary}),e__namespace.createElement(LexicalHistoryPlugin.HistoryPlugin,null),e__namespace.createElement(LexicalListPlugin.ListPlugin,null),e__namespace.createElement(LexicalLinkPlugin.LinkPlugin,null),e__namespace.createElement(LexicalOnChangePlugin.OnChangePlugin,{onChange:()=>{}}),e__namespace.createElement(Ct,{enabled:!!m}),e__namespace.createElement(Rt,{onSubmit:S,enabled:R}),o&&e__namespace.createElement(vt,{onImageFiles:_,enabled:true}),t.length>0&&e__namespace.createElement(lexicalBeautifulMentions.BeautifulMentionsPlugin,{items:t.reduce((i,v)=>(typeof v.items=="function"||(i[v.char]=v.items.map(u=>({value:u.value}))),i),{})})),ne&&e__namespace.createElement("div",{"data-gds-part":"composer-actions",className:"flex items-center justify-between gap-2 px-2 pb-2 pt-1"},e__namespace.createElement("div",{className:"flex items-center gap-1"},N??(re&&e__namespace.createElement("button",{type:"button",onClick:()=>T.current?.click(),disabled:a,"aria-label":"Attach image",title:"Attach image",className:j("h-8 w-8 rounded-lg flex items-center justify-center","text-[var(--gds-composer-action-fg)]","hover:text-[var(--gds-composer-fg)]","hover:bg-[var(--gds-composer-toolbar-hover-bg)]","focus:outline-none focus:ring-2 focus:ring-primary","transition-colors","disabled:opacity-50 disabled:cursor-not-allowed")},e__namespace.createElement(lucideReact.Paperclip,{className:"w-4 h-4"})))),L??(le&&e__namespace.createElement("button",{type:"button",onClick:a?d:S,disabled:a?!d:!te&&f.length===0,"aria-label":a?"Stop":"Send",className:j("h-8 w-8 rounded-lg flex items-center justify-center transition-colors flex-shrink-0","focus:outline-none focus:ring-2 focus:ring-primary",a?"bg-red-500 hover:bg-red-600 text-white disabled:opacity-50":te||f.length>0?"bg-primary hover:bg-primary/90 text-primary-foreground":"bg-[var(--gds-composer-toolbar-active-bg)] text-[var(--gds-composer-muted-fg)] cursor-not-allowed")},a?e__namespace.createElement(lucideReact.Square,{className:"w-3.5 h-3.5"}):e__namespace.createElement(lucideReact.Send,{className:"w-3.5 h-3.5"}))),o&&e__namespace.createElement("input",{ref:T,type:"file",accept:o.accept,multiple:o.multiple,onChange:i=>{i.target.files&&_(Array.from(i.target.files)),i.target.value="";},className:"sr-only",tabIndex:-1,"aria-hidden":"true"})))}var Ee=e__namespace.forwardRef(function(t,o){let{initialText:s,initialJson:n,formats:a,toolbar:d,triggers:h,attachments:m,...R}=t,N=e__namespace.useMemo(()=>a===false?[]:a??["bold","italic","underline","strikethrough","code","h1","h2","blockquote","ul","ol"],[a]),L=d===true||d==="top",p=e__namespace.useMemo(()=>{if(!m)return null;let c=m===true?{}:m;return c.enabled===false?null:{enabled:true,accept:c.accept??"image/*",maxItems:c.maxItems??10,multiple:c.multiple??true}},[m]),[y,k]=e__namespace.useState([]),A=e__namespace.useRef(y);A.current=y,e__namespace.useEffect(()=>()=>{A.current.forEach(c=>URL.revokeObjectURL(c.previewUrl));},[]);let I=e__namespace.useCallback(c=>{if(!p)return;let w=c.filter(f=>p.accept?p.accept==="image/*"?f.type.startsWith("image/"):p.accept.split(",").some(O=>{let _=O.trim();return _.endsWith("/*")?f.type.startsWith(_.slice(0,-1)):f.type===_||f.name.toLowerCase().endsWith(_)}):true);w.length!==0&&k(f=>{let O=p.maxItems-f.length;if(O<=0)return f;let _=w.slice(0,O).map(l=>({id:`${l.name}-${l.size}-${Date.now()}-${Math.random().toString(36).slice(2,8)}`,file:l,previewUrl:URL.createObjectURL(l),name:l.name}));return [...f,..._]});},[p]),x=e__namespace.useRef(null),X=e__namespace.useRef(()=>{}),V=e__namespace.useRef(()=>{}),G=e__namespace.useCallback(c=>{x.current=c;},[]);e__namespace.useImperativeHandle(o,()=>({play:c=>{console.warn('[Composer] handle.play(steps) is not wired in v1 \u2014 pass `steps` + `trigger="manual"` and toggle `play` instead.');},stop:()=>{},restart:c=>V.current(c),focus:()=>x.current?.focus(),clear:()=>{let c=x.current;c&&Z(c);},insert:c=>{x.current?.update(()=>{let w=lexical.$getSelection();lexical.$isRangeSelection(w)&&w.insertText(c);});},getContent:()=>x.current?Ce(x.current):{text:"",json:"",mentions:[]},getEditor:()=>x.current}),[]);let q=e__namespace.useMemo(()=>({paragraph:"gds-composer-paragraph",quote:"gds-composer-quote",heading:{h1:"gds-composer-h1",h2:"gds-composer-h2",h3:"gds-composer-h3"},list:{ul:"gds-composer-ul",ol:"gds-composer-ol",listitem:"gds-composer-li"},text:{bold:"font-semibold",italic:"italic",underline:"underline",strikethrough:"line-through",code:"gds-composer-code"},beautifulMentions:{"@":"gds-composer-mention px-1.5 py-0.5 mx-0.5 rounded bg-primary/10 text-primary font-medium","/":"gds-composer-mention px-1.5 py-0.5 mx-0.5 rounded bg-violet-500/15 text-violet-600 dark:text-violet-400 font-medium"}}),[]),$=e__namespace.useMemo(()=>({namespace:"gds-composer",theme:q,onError:c=>{console.error("[Composer]",c);},nodes:[richText.HeadingNode,richText.QuoteNode,list.ListNode,list.ListItemNode,link.LinkNode,link.AutoLinkNode,code.CodeNode,code.CodeHighlightNode,lexicalBeautifulMentions.BeautifulMentionNode],editorState:n||(s?c=>{let w=lexical.$getRoot(),f=lexical.$createParagraphNode();f.append(lexical.$createTextNode(s)),w.append(f);}:void 0)}),[q,n,s]),W=N.length>0,{readOnly:M=false,...K}=R;return e__namespace.createElement(LexicalComposer.LexicalComposer,{initialConfig:{...$,editable:!M}},e__namespace.createElement(Nt,{...K,readOnly:M,triggers:h??[],attachmentsCfg:M?null:p,formatList:N,showToolbar:L&&W&&!M,handleEditorReady:G,submitRef:X,restartRef:V,attachments:y,setAttachments:k,ingestImages:I}))}),Mt=e__namespace.forwardRef(function(t,o){return e__namespace.createElement(Ee,{ref:o,placeholder:"Write a reply\u2026",formats:false,submitOnEnter:false,...t})});exports.Composer=Ee;exports.ComposerReply=Mt;//# sourceMappingURL=composer.js.map
3
+ //# sourceMappingURL=composer.js.map