composeai 0.1.7 → 0.1.9
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/dist/index.cjs +140 -8
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +55 -1
- package/dist/index.d.ts +55 -1
- package/dist/index.js +140 -8
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/composer.css +31 -0
package/dist/index.d.cts
CHANGED
|
@@ -531,6 +531,20 @@ interface GhostedAutoCompleteConfig {
|
|
|
531
531
|
*/
|
|
532
532
|
minLength?: number;
|
|
533
533
|
}
|
|
534
|
+
/**
|
|
535
|
+
* Object form of {@link ComposerProps.animatedPlaceholder}. Use it when you
|
|
536
|
+
* need to opt into looping; the bare `string[]` form is equivalent to
|
|
537
|
+
* `{ phrases, loop: false }`.
|
|
538
|
+
*/
|
|
539
|
+
interface AnimatedPlaceholderConfig {
|
|
540
|
+
/** Phrases the empty editor types out, in order. */
|
|
541
|
+
phrases: string[];
|
|
542
|
+
/**
|
|
543
|
+
* Cycle the list forever. Defaults to `false` — the list plays through once
|
|
544
|
+
* and then settles (see {@link ComposerProps.animatedPlaceholder}).
|
|
545
|
+
*/
|
|
546
|
+
loop?: boolean;
|
|
547
|
+
}
|
|
534
548
|
/**
|
|
535
549
|
* Editor helpers handed to a {@link CustomAction} when it's clicked, so a
|
|
536
550
|
* custom toolbar button can mutate the composer the same way a slash command
|
|
@@ -748,6 +762,46 @@ interface ComposerProps {
|
|
|
748
762
|
*/
|
|
749
763
|
focusShortcut?: string | false | null;
|
|
750
764
|
placeholder?: string;
|
|
765
|
+
/**
|
|
766
|
+
* Animated placeholder: a list of phrases the empty editor cycles through
|
|
767
|
+
* with a typewriter effect — each phrase is revealed one character at a
|
|
768
|
+
* time, held, erased, and the next begins. The animation takes precedence
|
|
769
|
+
* over the static {@link placeholder} while the editor is empty and pauses
|
|
770
|
+
* the moment the user starts typing.
|
|
771
|
+
*
|
|
772
|
+
* Pass a `string[]` for the default behaviour, or an
|
|
773
|
+
* {@link AnimatedPlaceholderConfig} to enable looping.
|
|
774
|
+
*
|
|
775
|
+
* **Looping** (`loop`, default `false`):
|
|
776
|
+
* - `loop: false` — play through the list once, then settle: on the
|
|
777
|
+
* {@link placeholder} prop if one was given, otherwise on the last phrase
|
|
778
|
+
* (left on screen).
|
|
779
|
+
* - `loop: true` — cycle the list forever.
|
|
780
|
+
*
|
|
781
|
+
* Honours `prefers-reduced-motion` by showing the first phrase statically.
|
|
782
|
+
*
|
|
783
|
+
* @example
|
|
784
|
+
* // Play once, then rest on the last phrase (no `placeholder` given):
|
|
785
|
+
* <Composer
|
|
786
|
+
* animatedPlaceholder={[
|
|
787
|
+
* "Ask me anything…",
|
|
788
|
+
* "Summarize this thread",
|
|
789
|
+
* "Draft a reply to Alex",
|
|
790
|
+
* ]}
|
|
791
|
+
* onSend={...}
|
|
792
|
+
* />
|
|
793
|
+
*
|
|
794
|
+
* @example
|
|
795
|
+
* // Loop forever:
|
|
796
|
+
* <Composer
|
|
797
|
+
* animatedPlaceholder={{
|
|
798
|
+
* phrases: ["Ask me anything…", "Summarize this thread"],
|
|
799
|
+
* loop: true,
|
|
800
|
+
* }}
|
|
801
|
+
* onSend={...}
|
|
802
|
+
* />
|
|
803
|
+
*/
|
|
804
|
+
animatedPlaceholder?: string[] | AnimatedPlaceholderConfig;
|
|
751
805
|
/**
|
|
752
806
|
* Shorthand for `classNames.root`. Kept for back-compat; if both are set,
|
|
753
807
|
* the two are merged (`className` first, then `classNames.root`).
|
|
@@ -1016,4 +1070,4 @@ interface SuggestionRowProps {
|
|
|
1016
1070
|
}
|
|
1017
1071
|
declare function SuggestionRow({ items, onSelect, className }: SuggestionRowProps): react.JSX.Element;
|
|
1018
1072
|
|
|
1019
|
-
export { type Attachment, type AttachmentKind, type AttachmentOptions, type AttachmentStatus, type AttachmentTypeOption, type AttachmentsConfig, Composer, type ComposerFeatures, type ComposerHandle, type ComposerIcons, type ComposerPromptBehavior, type ComposerPromptsConfig, type ComposerProps, type ComposerSlot, type ComposerSlotClassNames, type ComposerSlots, type ComposerSubmitPayload, type ComposerSxMap, type ComposerSxValue, type ComposerTokens, type CustomAction, type CustomActionContext, type DiagramRenderer, type GhostedAutoCompleteConfig, type IconComponent, type IconProps, type MarkdownConfig, type MarkdownMode, type MentionConfig, type MentionItem, type MentionRef, type MermaidConfig, type SendButtonRenderProps, type SlashCommand, type SlashCommandContext, type SlashConfig, type StopButtonRenderProps, SuggestionRow, type SuggestionRowProps };
|
|
1073
|
+
export { type AnimatedPlaceholderConfig, type Attachment, type AttachmentKind, type AttachmentOptions, type AttachmentStatus, type AttachmentTypeOption, type AttachmentsConfig, Composer, type ComposerFeatures, type ComposerHandle, type ComposerIcons, type ComposerPromptBehavior, type ComposerPromptsConfig, type ComposerProps, type ComposerSlot, type ComposerSlotClassNames, type ComposerSlots, type ComposerSubmitPayload, type ComposerSxMap, type ComposerSxValue, type ComposerTokens, type CustomAction, type CustomActionContext, type DiagramRenderer, type GhostedAutoCompleteConfig, type IconComponent, type IconProps, type MarkdownConfig, type MarkdownMode, type MentionConfig, type MentionItem, type MentionRef, type MermaidConfig, type SendButtonRenderProps, type SlashCommand, type SlashCommandContext, type SlashConfig, type StopButtonRenderProps, SuggestionRow, type SuggestionRowProps };
|
package/dist/index.d.ts
CHANGED
|
@@ -531,6 +531,20 @@ interface GhostedAutoCompleteConfig {
|
|
|
531
531
|
*/
|
|
532
532
|
minLength?: number;
|
|
533
533
|
}
|
|
534
|
+
/**
|
|
535
|
+
* Object form of {@link ComposerProps.animatedPlaceholder}. Use it when you
|
|
536
|
+
* need to opt into looping; the bare `string[]` form is equivalent to
|
|
537
|
+
* `{ phrases, loop: false }`.
|
|
538
|
+
*/
|
|
539
|
+
interface AnimatedPlaceholderConfig {
|
|
540
|
+
/** Phrases the empty editor types out, in order. */
|
|
541
|
+
phrases: string[];
|
|
542
|
+
/**
|
|
543
|
+
* Cycle the list forever. Defaults to `false` — the list plays through once
|
|
544
|
+
* and then settles (see {@link ComposerProps.animatedPlaceholder}).
|
|
545
|
+
*/
|
|
546
|
+
loop?: boolean;
|
|
547
|
+
}
|
|
534
548
|
/**
|
|
535
549
|
* Editor helpers handed to a {@link CustomAction} when it's clicked, so a
|
|
536
550
|
* custom toolbar button can mutate the composer the same way a slash command
|
|
@@ -748,6 +762,46 @@ interface ComposerProps {
|
|
|
748
762
|
*/
|
|
749
763
|
focusShortcut?: string | false | null;
|
|
750
764
|
placeholder?: string;
|
|
765
|
+
/**
|
|
766
|
+
* Animated placeholder: a list of phrases the empty editor cycles through
|
|
767
|
+
* with a typewriter effect — each phrase is revealed one character at a
|
|
768
|
+
* time, held, erased, and the next begins. The animation takes precedence
|
|
769
|
+
* over the static {@link placeholder} while the editor is empty and pauses
|
|
770
|
+
* the moment the user starts typing.
|
|
771
|
+
*
|
|
772
|
+
* Pass a `string[]` for the default behaviour, or an
|
|
773
|
+
* {@link AnimatedPlaceholderConfig} to enable looping.
|
|
774
|
+
*
|
|
775
|
+
* **Looping** (`loop`, default `false`):
|
|
776
|
+
* - `loop: false` — play through the list once, then settle: on the
|
|
777
|
+
* {@link placeholder} prop if one was given, otherwise on the last phrase
|
|
778
|
+
* (left on screen).
|
|
779
|
+
* - `loop: true` — cycle the list forever.
|
|
780
|
+
*
|
|
781
|
+
* Honours `prefers-reduced-motion` by showing the first phrase statically.
|
|
782
|
+
*
|
|
783
|
+
* @example
|
|
784
|
+
* // Play once, then rest on the last phrase (no `placeholder` given):
|
|
785
|
+
* <Composer
|
|
786
|
+
* animatedPlaceholder={[
|
|
787
|
+
* "Ask me anything…",
|
|
788
|
+
* "Summarize this thread",
|
|
789
|
+
* "Draft a reply to Alex",
|
|
790
|
+
* ]}
|
|
791
|
+
* onSend={...}
|
|
792
|
+
* />
|
|
793
|
+
*
|
|
794
|
+
* @example
|
|
795
|
+
* // Loop forever:
|
|
796
|
+
* <Composer
|
|
797
|
+
* animatedPlaceholder={{
|
|
798
|
+
* phrases: ["Ask me anything…", "Summarize this thread"],
|
|
799
|
+
* loop: true,
|
|
800
|
+
* }}
|
|
801
|
+
* onSend={...}
|
|
802
|
+
* />
|
|
803
|
+
*/
|
|
804
|
+
animatedPlaceholder?: string[] | AnimatedPlaceholderConfig;
|
|
751
805
|
/**
|
|
752
806
|
* Shorthand for `classNames.root`. Kept for back-compat; if both are set,
|
|
753
807
|
* the two are merged (`className` first, then `classNames.root`).
|
|
@@ -1016,4 +1070,4 @@ interface SuggestionRowProps {
|
|
|
1016
1070
|
}
|
|
1017
1071
|
declare function SuggestionRow({ items, onSelect, className }: SuggestionRowProps): react.JSX.Element;
|
|
1018
1072
|
|
|
1019
|
-
export { type Attachment, type AttachmentKind, type AttachmentOptions, type AttachmentStatus, type AttachmentTypeOption, type AttachmentsConfig, Composer, type ComposerFeatures, type ComposerHandle, type ComposerIcons, type ComposerPromptBehavior, type ComposerPromptsConfig, type ComposerProps, type ComposerSlot, type ComposerSlotClassNames, type ComposerSlots, type ComposerSubmitPayload, type ComposerSxMap, type ComposerSxValue, type ComposerTokens, type CustomAction, type CustomActionContext, type DiagramRenderer, type GhostedAutoCompleteConfig, type IconComponent, type IconProps, type MarkdownConfig, type MarkdownMode, type MentionConfig, type MentionItem, type MentionRef, type MermaidConfig, type SendButtonRenderProps, type SlashCommand, type SlashCommandContext, type SlashConfig, type StopButtonRenderProps, SuggestionRow, type SuggestionRowProps };
|
|
1073
|
+
export { type AnimatedPlaceholderConfig, type Attachment, type AttachmentKind, type AttachmentOptions, type AttachmentStatus, type AttachmentTypeOption, type AttachmentsConfig, Composer, type ComposerFeatures, type ComposerHandle, type ComposerIcons, type ComposerPromptBehavior, type ComposerPromptsConfig, type ComposerProps, type ComposerSlot, type ComposerSlotClassNames, type ComposerSlots, type ComposerSubmitPayload, type ComposerSxMap, type ComposerSxValue, type ComposerTokens, type CustomAction, type CustomActionContext, type DiagramRenderer, type GhostedAutoCompleteConfig, type IconComponent, type IconProps, type MarkdownConfig, type MarkdownMode, type MentionConfig, type MentionItem, type MentionRef, type MermaidConfig, type SendButtonRenderProps, type SlashCommand, type SlashCommandContext, type SlashConfig, type StopButtonRenderProps, SuggestionRow, type SuggestionRowProps };
|
package/dist/index.js
CHANGED
|
@@ -800,6 +800,7 @@ function useComposerContext() {
|
|
|
800
800
|
}
|
|
801
801
|
function EditorShell({
|
|
802
802
|
placeholder,
|
|
803
|
+
animated,
|
|
803
804
|
mode,
|
|
804
805
|
variant,
|
|
805
806
|
multiline,
|
|
@@ -818,7 +819,11 @@ function EditorShell({
|
|
|
818
819
|
const editor = slotProps("editor", editorClass, classNames, sx);
|
|
819
820
|
const editorResolved = resolveSx(sx?.editor);
|
|
820
821
|
const placeholderBase = mirrorEditorPadding(editorResolved);
|
|
821
|
-
const placeholderClass =
|
|
822
|
+
const placeholderClass = cn(
|
|
823
|
+
isCompact ? "composer-placeholder composer-placeholder--compact" : multiline ? "composer-placeholder composer-placeholder--multiline" : "composer-placeholder composer-placeholder--inline",
|
|
824
|
+
// Adds the blinking caret after the typewriter text.
|
|
825
|
+
animated && "composer-placeholder--animated"
|
|
826
|
+
);
|
|
822
827
|
const placeholderProps = slotProps(
|
|
823
828
|
"placeholder",
|
|
824
829
|
placeholderClass,
|
|
@@ -3386,14 +3391,18 @@ function SlashCommandPlugin({ config, onSubmit }) {
|
|
|
3386
3391
|
config.trigger ?? "/",
|
|
3387
3392
|
{ minLength: 0, maxLength: 32, allowWhitespace: false }
|
|
3388
3393
|
);
|
|
3394
|
+
const itemsRef = useRef(config.items);
|
|
3395
|
+
itemsRef.current = config.items;
|
|
3396
|
+
const isAsync = !isSyncItems(config.items);
|
|
3389
3397
|
useEffect(() => {
|
|
3390
|
-
|
|
3398
|
+
const items = itemsRef.current;
|
|
3399
|
+
if (isSyncItems(items)) {
|
|
3391
3400
|
setIsLoading(false);
|
|
3392
3401
|
return;
|
|
3393
3402
|
}
|
|
3394
3403
|
let cancelled = false;
|
|
3395
3404
|
setIsLoading(true);
|
|
3396
|
-
Promise.resolve(
|
|
3405
|
+
Promise.resolve(items(query)).then((res) => {
|
|
3397
3406
|
if (cancelled) return;
|
|
3398
3407
|
setAsyncItems(res);
|
|
3399
3408
|
setIsLoading(false);
|
|
@@ -3401,7 +3410,7 @@ function SlashCommandPlugin({ config, onSubmit }) {
|
|
|
3401
3410
|
return () => {
|
|
3402
3411
|
cancelled = true;
|
|
3403
3412
|
};
|
|
3404
|
-
}, [query,
|
|
3413
|
+
}, [query, isAsync]);
|
|
3405
3414
|
const allItems = useMemo(() => {
|
|
3406
3415
|
return isSyncItems(config.items) ? config.items : asyncItems ?? [];
|
|
3407
3416
|
}, [config.items, asyncItems]);
|
|
@@ -3592,14 +3601,18 @@ function MentionPlugin({ config }) {
|
|
|
3592
3601
|
maxLength: 32,
|
|
3593
3602
|
allowWhitespace: false
|
|
3594
3603
|
});
|
|
3604
|
+
const itemsRef = useRef(config.items);
|
|
3605
|
+
itemsRef.current = config.items;
|
|
3606
|
+
const isAsync = !isSyncItems2(config.items);
|
|
3595
3607
|
useEffect(() => {
|
|
3596
|
-
|
|
3608
|
+
const items = itemsRef.current;
|
|
3609
|
+
if (isSyncItems2(items)) {
|
|
3597
3610
|
setIsLoading(false);
|
|
3598
3611
|
return;
|
|
3599
3612
|
}
|
|
3600
3613
|
let cancelled = false;
|
|
3601
3614
|
setIsLoading(true);
|
|
3602
|
-
Promise.resolve(
|
|
3615
|
+
Promise.resolve(items(query)).then((res) => {
|
|
3603
3616
|
if (cancelled) return;
|
|
3604
3617
|
setAsyncItems(res);
|
|
3605
3618
|
setIsLoading(false);
|
|
@@ -3607,7 +3620,7 @@ function MentionPlugin({ config }) {
|
|
|
3607
3620
|
return () => {
|
|
3608
3621
|
cancelled = true;
|
|
3609
3622
|
};
|
|
3610
|
-
}, [query,
|
|
3623
|
+
}, [query, isAsync]);
|
|
3611
3624
|
const allItems = useMemo(() => {
|
|
3612
3625
|
return isSyncItems2(config.items) ? config.items : asyncItems ?? [];
|
|
3613
3626
|
}, [config.items, asyncItems]);
|
|
@@ -4927,6 +4940,107 @@ function useComposerHandle(ref, onSubmit) {
|
|
|
4927
4940
|
};
|
|
4928
4941
|
}, [editor, ref, onSubmit, addFiles]);
|
|
4929
4942
|
}
|
|
4943
|
+
var DEFAULT_TIMING = {
|
|
4944
|
+
typeSpeed: 55,
|
|
4945
|
+
deleteSpeed: 28,
|
|
4946
|
+
holdDuration: 1800,
|
|
4947
|
+
pauseDuration: 450
|
|
4948
|
+
};
|
|
4949
|
+
function useAnimatedPlaceholder(phrases, enabled, options) {
|
|
4950
|
+
const [state, setState] = useState({
|
|
4951
|
+
text: "",
|
|
4952
|
+
active: true
|
|
4953
|
+
});
|
|
4954
|
+
const optsRef = useRef({});
|
|
4955
|
+
optsRef.current = options ?? {};
|
|
4956
|
+
const active = enabled && Array.isArray(phrases) && phrases.length > 0;
|
|
4957
|
+
const key = active ? phrases.join("\u241F") : "";
|
|
4958
|
+
const loop = !!options?.loop;
|
|
4959
|
+
const phrasesRef = useRef(phrases);
|
|
4960
|
+
phrasesRef.current = phrases;
|
|
4961
|
+
useEffect(() => {
|
|
4962
|
+
if (!active) {
|
|
4963
|
+
setState({ text: "", active: true });
|
|
4964
|
+
return;
|
|
4965
|
+
}
|
|
4966
|
+
const list = phrasesRef.current;
|
|
4967
|
+
const lastIdx = list.length - 1;
|
|
4968
|
+
const reduceMotion = typeof window !== "undefined" && typeof window.matchMedia === "function" && window.matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
4969
|
+
if (reduceMotion) {
|
|
4970
|
+
setState({ text: list[0], active: false });
|
|
4971
|
+
return;
|
|
4972
|
+
}
|
|
4973
|
+
let timer;
|
|
4974
|
+
let phraseIdx = 0;
|
|
4975
|
+
let charIdx = 0;
|
|
4976
|
+
let phase = "typing";
|
|
4977
|
+
const tick = () => {
|
|
4978
|
+
const timing = { ...DEFAULT_TIMING, ...optsRef.current };
|
|
4979
|
+
const { typeSpeed, deleteSpeed, holdDuration, pauseDuration } = timing;
|
|
4980
|
+
const settleTo = optsRef.current.settleTo;
|
|
4981
|
+
const current = list[phraseIdx];
|
|
4982
|
+
const isLast = phraseIdx === lastIdx;
|
|
4983
|
+
switch (phase) {
|
|
4984
|
+
case "typing": {
|
|
4985
|
+
charIdx += 1;
|
|
4986
|
+
setState({ text: current.slice(0, charIdx), active: true });
|
|
4987
|
+
if (charIdx >= current.length) {
|
|
4988
|
+
phase = "holding";
|
|
4989
|
+
timer = setTimeout(tick, holdDuration);
|
|
4990
|
+
} else {
|
|
4991
|
+
timer = setTimeout(tick, typeSpeed);
|
|
4992
|
+
}
|
|
4993
|
+
break;
|
|
4994
|
+
}
|
|
4995
|
+
case "holding": {
|
|
4996
|
+
if (!loop && isLast) {
|
|
4997
|
+
if (settleTo !== void 0) {
|
|
4998
|
+
phase = "settling";
|
|
4999
|
+
timer = setTimeout(tick, deleteSpeed);
|
|
5000
|
+
} else {
|
|
5001
|
+
setState({ text: current, active: false });
|
|
5002
|
+
}
|
|
5003
|
+
} else {
|
|
5004
|
+
phase = "deleting";
|
|
5005
|
+
timer = setTimeout(tick, deleteSpeed);
|
|
5006
|
+
}
|
|
5007
|
+
break;
|
|
5008
|
+
}
|
|
5009
|
+
case "deleting": {
|
|
5010
|
+
charIdx -= 1;
|
|
5011
|
+
setState({ text: current.slice(0, Math.max(0, charIdx)), active: true });
|
|
5012
|
+
if (charIdx <= 0) {
|
|
5013
|
+
phase = "pausing";
|
|
5014
|
+
timer = setTimeout(tick, pauseDuration);
|
|
5015
|
+
} else {
|
|
5016
|
+
timer = setTimeout(tick, deleteSpeed);
|
|
5017
|
+
}
|
|
5018
|
+
break;
|
|
5019
|
+
}
|
|
5020
|
+
case "pausing": {
|
|
5021
|
+
phraseIdx = phraseIdx >= lastIdx ? 0 : phraseIdx + 1;
|
|
5022
|
+
charIdx = 0;
|
|
5023
|
+
phase = "typing";
|
|
5024
|
+
timer = setTimeout(tick, typeSpeed);
|
|
5025
|
+
break;
|
|
5026
|
+
}
|
|
5027
|
+
case "settling": {
|
|
5028
|
+
charIdx -= 1;
|
|
5029
|
+
if (charIdx <= 0) {
|
|
5030
|
+
setState({ text: settleTo ?? "", active: false });
|
|
5031
|
+
} else {
|
|
5032
|
+
setState({ text: current.slice(0, charIdx), active: true });
|
|
5033
|
+
timer = setTimeout(tick, deleteSpeed);
|
|
5034
|
+
}
|
|
5035
|
+
break;
|
|
5036
|
+
}
|
|
5037
|
+
}
|
|
5038
|
+
};
|
|
5039
|
+
timer = setTimeout(tick, DEFAULT_TIMING.typeSpeed);
|
|
5040
|
+
return () => clearTimeout(timer);
|
|
5041
|
+
}, [active, key, loop]);
|
|
5042
|
+
return active ? state : null;
|
|
5043
|
+
}
|
|
4930
5044
|
|
|
4931
5045
|
// src/internal/shortcut.ts
|
|
4932
5046
|
var MODIFIERS = /* @__PURE__ */ new Set([
|
|
@@ -5004,6 +5118,7 @@ function matchesShortcut(parsed, event) {
|
|
|
5004
5118
|
var Composer = forwardRef(function Composer2(props, ref) {
|
|
5005
5119
|
const {
|
|
5006
5120
|
placeholder = "Send a message\u2026",
|
|
5121
|
+
animatedPlaceholder,
|
|
5007
5122
|
onSend,
|
|
5008
5123
|
onStop,
|
|
5009
5124
|
isStreaming,
|
|
@@ -5033,6 +5148,7 @@ var Composer = forwardRef(function Composer2(props, ref) {
|
|
|
5033
5148
|
attachmentOptions,
|
|
5034
5149
|
dir
|
|
5035
5150
|
} = props;
|
|
5151
|
+
const hasPlaceholder = props.placeholder != null;
|
|
5036
5152
|
const tokenStyle = useMemo(() => {
|
|
5037
5153
|
const derived = color ? deriveColorTokens(color) : null;
|
|
5038
5154
|
if (!derived && !tokens) return void 0;
|
|
@@ -5076,6 +5192,8 @@ var Composer = forwardRef(function Composer2(props, ref) {
|
|
|
5076
5192
|
ComposerCard,
|
|
5077
5193
|
{
|
|
5078
5194
|
placeholder,
|
|
5195
|
+
animatedPlaceholder,
|
|
5196
|
+
hasPlaceholder,
|
|
5079
5197
|
initialValue,
|
|
5080
5198
|
handleRef: ref,
|
|
5081
5199
|
onSend,
|
|
@@ -5113,6 +5231,8 @@ var RICH_NODES = [
|
|
|
5113
5231
|
var PLAIN_NODES = [MentionNode];
|
|
5114
5232
|
function ComposerCard({
|
|
5115
5233
|
placeholder,
|
|
5234
|
+
animatedPlaceholder,
|
|
5235
|
+
hasPlaceholder,
|
|
5116
5236
|
initialValue,
|
|
5117
5237
|
handleRef,
|
|
5118
5238
|
onSend,
|
|
@@ -5174,6 +5294,8 @@ function ComposerCard({
|
|
|
5174
5294
|
ComposerInner,
|
|
5175
5295
|
{
|
|
5176
5296
|
placeholder,
|
|
5297
|
+
animatedPlaceholder,
|
|
5298
|
+
hasPlaceholder,
|
|
5177
5299
|
mode,
|
|
5178
5300
|
variant,
|
|
5179
5301
|
multiline,
|
|
@@ -5194,6 +5316,8 @@ function ComposerCard({
|
|
|
5194
5316
|
}
|
|
5195
5317
|
function ComposerInner({
|
|
5196
5318
|
placeholder,
|
|
5319
|
+
animatedPlaceholder,
|
|
5320
|
+
hasPlaceholder,
|
|
5197
5321
|
mode,
|
|
5198
5322
|
variant,
|
|
5199
5323
|
multiline,
|
|
@@ -5324,6 +5448,13 @@ function ComposerInner({
|
|
|
5324
5448
|
});
|
|
5325
5449
|
}, [editor, registerRunPrompt, submit]);
|
|
5326
5450
|
const isCompact = variant === "compact";
|
|
5451
|
+
const animatedPhrases = Array.isArray(animatedPlaceholder) ? animatedPlaceholder : animatedPlaceholder?.phrases;
|
|
5452
|
+
const animatedLoop = Array.isArray(animatedPlaceholder) ? false : !!animatedPlaceholder?.loop;
|
|
5453
|
+
const animatedFrame = useAnimatedPlaceholder(animatedPhrases, !hasText, {
|
|
5454
|
+
loop: animatedLoop,
|
|
5455
|
+
settleTo: hasPlaceholder ? placeholder : void 0
|
|
5456
|
+
});
|
|
5457
|
+
const effectivePlaceholder = animatedFrame?.text ?? placeholder;
|
|
5327
5458
|
const mermaidActive = multiline && mode === "markdown" && !!features.mermaid;
|
|
5328
5459
|
const toolbarSlot = /* @__PURE__ */ jsx(Toolbar, { extras: toolbarExtras, variant, submit });
|
|
5329
5460
|
const sendButton = /* @__PURE__ */ jsx(
|
|
@@ -5347,7 +5478,8 @@ function ComposerInner({
|
|
|
5347
5478
|
/* @__PURE__ */ jsx(
|
|
5348
5479
|
EditorShell,
|
|
5349
5480
|
{
|
|
5350
|
-
placeholder,
|
|
5481
|
+
placeholder: effectivePlaceholder,
|
|
5482
|
+
animated: animatedFrame?.active ?? false,
|
|
5351
5483
|
mode,
|
|
5352
5484
|
variant,
|
|
5353
5485
|
multiline,
|