@helpai/elements 0.19.2 → 0.19.3

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/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, L as Link, S as ServerConfig, b as SiteConfig, c as StartConversationResponse, W as WidgetConfig, d as WidgetConfigPartial, e as WidgetSettings, f as WidgetSettingsPartial } from './deployment-H2uevlHy.js';
1
+ export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, L as Link, S as ServerConfig, b as SiteConfig, c as StartConversationResponse, W as WidgetConfig, d as WidgetConfigPartial, e as WidgetSettings, f as WidgetSettingsPartial } from './deployment-BvNoqfIC.js';
2
2
  import 'zod';
3
3
 
4
4
  /**
package/index.mjs CHANGED
@@ -462,7 +462,7 @@ var DEFAULT_ATTACHMENTS = {
462
462
  maxCount: 10,
463
463
  accept: "*/*"
464
464
  };
465
- var DEFAULT_WELCOME = { animation: "typewriter", speed: 60 };
465
+ var DEFAULT_WELCOME = { animation: "instant", speed: 60 };
466
466
  var DEFAULT_FEATURES = {
467
467
  files: true,
468
468
  voice: "local",
@@ -4776,19 +4776,23 @@ function MessageList({
4776
4776
  const [showJump, setShowJump] = useState6(false);
4777
4777
  const [scrolling, setScrolling] = useState6(false);
4778
4778
  const hasHydratedRef = useRef5(false);
4779
+ const detachedRef = useRef5(false);
4780
+ const autoPinAtRef = useRef5(0);
4781
+ const pinBottom = (el) => {
4782
+ autoPinAtRef.current = performance.now();
4783
+ el.scrollTop = el.scrollHeight;
4784
+ };
4779
4785
  const firstMessageId = messages.value[0]?.id;
4780
4786
  useLayoutEffect(() => {
4781
4787
  const el = ref.current;
4782
4788
  if (!el) return;
4783
4789
  if (messages.value.length === 0) return;
4784
4790
  hasHydratedRef.current = true;
4785
- const pinBottom = () => {
4786
- el.scrollTop = el.scrollHeight;
4787
- };
4788
- pinBottom();
4789
- const resizeObs = new ResizeObserver(pinBottom);
4791
+ const pinNow = () => pinBottom(el);
4792
+ pinNow();
4793
+ const resizeObs = new ResizeObserver(pinNow);
4790
4794
  resizeObs.observe(el);
4791
- const mutationObs = new MutationObserver(pinBottom);
4795
+ const mutationObs = new MutationObserver(pinNow);
4792
4796
  mutationObs.observe(el, { childList: true, subtree: true, characterData: true });
4793
4797
  const timerId = setTimeout(() => {
4794
4798
  resizeObs.disconnect();
@@ -4804,8 +4808,14 @@ function MessageList({
4804
4808
  const el = ref.current;
4805
4809
  if (!el) return;
4806
4810
  if (!hasHydratedRef.current) return;
4811
+ if (messages.value.at(-1)?.role === "user") {
4812
+ detachedRef.current = false;
4813
+ pinBottom(el);
4814
+ return;
4815
+ }
4816
+ if (detachedRef.current) return;
4807
4817
  const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
4808
- if (distanceFromBottom < STICK_THRESHOLD) el.scrollTop = el.scrollHeight;
4818
+ if (distanceFromBottom < STICK_THRESHOLD) pinBottom(el);
4809
4819
  }, [messages.value.length]);
4810
4820
  useEffect8(() => {
4811
4821
  const el = ref.current;
@@ -4813,8 +4823,9 @@ function MessageList({
4813
4823
  const last = messages.value.at(-1);
4814
4824
  if (!last) return;
4815
4825
  const pinIfNear = () => {
4826
+ if (detachedRef.current) return;
4816
4827
  const distance = el.scrollHeight - el.scrollTop - el.clientHeight;
4817
- if (distance < STICK_THRESHOLD * 2) el.scrollTop = el.scrollHeight;
4828
+ if (distance < STICK_THRESHOLD * 2) pinBottom(el);
4818
4829
  };
4819
4830
  if (last.status !== "streaming") {
4820
4831
  const rafId = requestAnimationFrame(pinIfNear);
@@ -4828,8 +4839,8 @@ function MessageList({
4828
4839
  const activeFormId = form?.form.id;
4829
4840
  useLayoutEffect(() => {
4830
4841
  const el = ref.current;
4831
- if (!el || !activeFormId) return;
4832
- el.scrollTop = el.scrollHeight;
4842
+ if (!el || !activeFormId || detachedRef.current) return;
4843
+ pinBottom(el);
4833
4844
  }, [activeFormId]);
4834
4845
  useEffect8(() => {
4835
4846
  const el = ref.current;
@@ -4838,6 +4849,9 @@ function MessageList({
4838
4849
  let idleTimer;
4839
4850
  const onScroll = () => {
4840
4851
  syncJump();
4852
+ if (performance.now() - autoPinAtRef.current > 150) {
4853
+ detachedRef.current = el.scrollHeight - el.scrollTop - el.clientHeight > 8;
4854
+ }
4841
4855
  setScrolling(true);
4842
4856
  clearTimeout(idleTimer);
4843
4857
  idleTimer = setTimeout(() => setScrolling(false), DIVIDER_IDLE_MS);
@@ -4851,7 +4865,9 @@ function MessageList({
4851
4865
  }, []);
4852
4866
  const jumpToBottom = () => {
4853
4867
  const el = ref.current;
4854
- if (el) el.scrollTop = el.scrollHeight;
4868
+ if (!el) return;
4869
+ detachedRef.current = false;
4870
+ pinBottom(el);
4855
4871
  };
4856
4872
  const rows = [];
4857
4873
  let prevDay = "";
package/package.json CHANGED
@@ -80,5 +80,5 @@
80
80
  ],
81
81
  "type": "module",
82
82
  "types": "./index.d.ts",
83
- "version": "0.19.2"
83
+ "version": "0.19.3"
84
84
  }
package/schema.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, E as Endpoints, L as Link, P as PAGE_AREA_SUGGESTIONS, g as PageContext, S as ServerConfig, b as SiteConfig, c as StartConversationResponse, U as UserContext, W as WidgetConfig, d as WidgetConfigPartial, e as WidgetSettings, f as WidgetSettingsPartial, h as assetSchema, i as blocksConfigSchema, j as connectionConfigPartialSchema, k as connectionConfigSchema, l as cssColorSchema, m as cssLengthSchema, n as endpointsSchema, o as linkSchema, p as localeSchema, q as pageContextSchema, s as serverConfigSchema, r as siteConfigSchema, t as startConversationResponseSchema, u as userContextSchema, v as uuid7Schema, w as widgetConfigPartialSchema, x as widgetConfigSchema, y as widgetSettingsPartialSchema, z as widgetSettingsSchema } from './deployment-H2uevlHy.js';
1
+ export { A as Asset, B as BlocksConfig, C as ConnectionConfig, a as ConnectionConfigPartial, E as Endpoints, L as Link, P as PAGE_AREA_SUGGESTIONS, g as PageContext, S as ServerConfig, b as SiteConfig, c as StartConversationResponse, U as UserContext, W as WidgetConfig, d as WidgetConfigPartial, e as WidgetSettings, f as WidgetSettingsPartial, h as assetSchema, i as blocksConfigSchema, j as connectionConfigPartialSchema, k as connectionConfigSchema, l as cssColorSchema, m as cssLengthSchema, n as endpointsSchema, o as linkSchema, p as localeSchema, q as pageContextSchema, s as serverConfigSchema, r as siteConfigSchema, t as startConversationResponseSchema, u as userContextSchema, v as uuid7Schema, w as widgetConfigPartialSchema, x as widgetConfigSchema, y as widgetSettingsPartialSchema, z as widgetSettingsSchema } from './deployment-BvNoqfIC.js';
2
2
  import { z } from 'zod';
3
3
 
4
4
  /**
@@ -56,9 +56,9 @@ declare const presentationSchema: z.ZodObject<{
56
56
  inset: z.ZodOptional<z.ZodString>;
57
57
  initialSize: z.ZodDefault<z.ZodEnum<{
58
58
  fullscreen: "fullscreen";
59
- normal: "normal";
60
59
  expanded: "expanded";
61
60
  auto: "auto";
61
+ normal: "normal";
62
62
  }>>;
63
63
  autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
64
64
  }, z.core.$loose>>;
@@ -148,9 +148,9 @@ declare const launcherSizeSchema: z.ZodEnum<{
148
148
  }>;
149
149
  type LauncherSize = z.infer<typeof launcherSizeSchema>;
150
150
  declare const calloutShapeSchema: z.ZodEnum<{
151
+ callout: "callout";
151
152
  pill: "pill";
152
153
  bubble: "bubble";
153
- callout: "callout";
154
154
  }>;
155
155
  type CalloutShape = z.infer<typeof calloutShapeSchema>;
156
156
  declare const calloutPositionSchema: z.ZodEnum<{
@@ -162,9 +162,9 @@ type CalloutPosition = z.infer<typeof calloutPositionSchema>;
162
162
  declare const launcherCalloutSchema: z.ZodObject<{
163
163
  text: z.ZodDefault<z.ZodString>;
164
164
  shape: z.ZodDefault<z.ZodEnum<{
165
+ callout: "callout";
165
166
  pill: "pill";
166
167
  bubble: "bubble";
167
- callout: "callout";
168
168
  }>>;
169
169
  position: z.ZodDefault<z.ZodEnum<{
170
170
  auto: "auto";
@@ -195,9 +195,9 @@ declare const launcherOptionsSchema: z.ZodObject<{
195
195
  callout: z.ZodOptional<z.ZodObject<{
196
196
  text: z.ZodDefault<z.ZodString>;
197
197
  shape: z.ZodDefault<z.ZodEnum<{
198
+ callout: "callout";
198
199
  pill: "pill";
199
200
  bubble: "bubble";
200
- callout: "callout";
201
201
  }>>;
202
202
  position: z.ZodDefault<z.ZodEnum<{
203
203
  auto: "auto";
@@ -240,9 +240,9 @@ type LauncherOptions = z.infer<typeof launcherOptionsSchema>;
240
240
 
241
241
  declare const initialSizeSchema: z.ZodEnum<{
242
242
  fullscreen: "fullscreen";
243
- normal: "normal";
244
243
  expanded: "expanded";
245
244
  auto: "auto";
245
+ normal: "normal";
246
246
  }>;
247
247
  declare const resizeOptionsSchema: z.ZodObject<{
248
248
  enabled: z.ZodDefault<z.ZodBoolean>;
@@ -269,9 +269,9 @@ declare const sizeOptionsSchema: z.ZodObject<{
269
269
  inset: z.ZodOptional<z.ZodString>;
270
270
  initialSize: z.ZodDefault<z.ZodEnum<{
271
271
  fullscreen: "fullscreen";
272
- normal: "normal";
273
272
  expanded: "expanded";
274
273
  auto: "auto";
274
+ normal: "normal";
275
275
  }>>;
276
276
  autoSizeBreakpoint: z.ZodDefault<z.ZodNumber>;
277
277
  }, z.core.$loose>;
@@ -323,43 +323,43 @@ type FeatureFlags = z.infer<typeof featureFlagsSchema>;
323
323
  */
324
324
 
325
325
  declare const actionNameSchema: z.ZodEnum<{
326
+ close: "close";
326
327
  expand: "expand";
327
328
  fullscreen: "fullscreen";
328
329
  popOut: "popOut";
329
- close: "close";
330
- language: "language";
330
+ clear: "clear";
331
331
  theme: "theme";
332
+ language: "language";
332
333
  textSize: "textSize";
333
334
  history: "history";
334
- clear: "clear";
335
335
  sound: "sound";
336
336
  }>;
337
337
  type ActionName = z.infer<typeof actionNameSchema>;
338
338
  declare const headerActionsSchema: z.ZodArray<z.ZodEnum<{
339
+ close: "close";
339
340
  expand: "expand";
340
341
  fullscreen: "fullscreen";
341
342
  popOut: "popOut";
342
- close: "close";
343
- language: "language";
343
+ clear: "clear";
344
344
  theme: "theme";
345
+ language: "language";
345
346
  textSize: "textSize";
346
347
  history: "history";
347
- clear: "clear";
348
348
  sound: "sound";
349
349
  }>>;
350
350
  type HeaderActions = z.infer<typeof headerActionsSchema>;
351
351
  /** Section wrapper — `actions` list wrapped under `header` in the dashboard form. */
352
352
  declare const headerSchema: z.ZodObject<{
353
353
  actions: z.ZodOptional<z.ZodArray<z.ZodEnum<{
354
+ close: "close";
354
355
  expand: "expand";
355
356
  fullscreen: "fullscreen";
356
357
  popOut: "popOut";
357
- close: "close";
358
- language: "language";
358
+ clear: "clear";
359
359
  theme: "theme";
360
+ language: "language";
360
361
  textSize: "textSize";
361
362
  history: "history";
362
- clear: "clear";
363
363
  sound: "sound";
364
364
  }>>>;
365
365
  }, z.core.$loose>;
@@ -375,33 +375,33 @@ type HeaderOptions = z.infer<typeof headerSchema>;
375
375
  */
376
376
 
377
377
  declare const feedbackEventSchema: z.ZodEnum<{
378
+ voiceStart: "voiceStart";
379
+ voiceStop: "voiceStop";
378
380
  error: "error";
379
381
  messageReceived: "messageReceived";
380
382
  messageSent: "messageSent";
381
- voiceStart: "voiceStart";
382
- voiceStop: "voiceStop";
383
383
  }>;
384
384
  type FeedbackEvent = z.infer<typeof feedbackEventSchema>;
385
385
  declare const soundOptionsSchema: z.ZodObject<{
386
386
  enabled: z.ZodDefault<z.ZodBoolean>;
387
387
  volume: z.ZodDefault<z.ZodNumber>;
388
388
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
389
+ voiceStart: "voiceStart";
390
+ voiceStop: "voiceStop";
389
391
  error: "error";
390
392
  messageReceived: "messageReceived";
391
393
  messageSent: "messageSent";
392
- voiceStart: "voiceStart";
393
- voiceStop: "voiceStop";
394
394
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
395
395
  }, z.core.$loose>;
396
396
  type SoundOptions = z.infer<typeof soundOptionsSchema>;
397
397
  declare const hapticsOptionsSchema: z.ZodObject<{
398
398
  enabled: z.ZodDefault<z.ZodBoolean>;
399
399
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
400
+ voiceStart: "voiceStart";
401
+ voiceStop: "voiceStop";
400
402
  error: "error";
401
403
  messageReceived: "messageReceived";
402
404
  messageSent: "messageSent";
403
- voiceStart: "voiceStart";
404
- voiceStop: "voiceStop";
405
405
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
406
406
  }, z.core.$loose>;
407
407
  type HapticsOptions = z.infer<typeof hapticsOptionsSchema>;
@@ -410,21 +410,21 @@ declare const feedbackSchema: z.ZodObject<{
410
410
  enabled: z.ZodDefault<z.ZodBoolean>;
411
411
  volume: z.ZodDefault<z.ZodNumber>;
412
412
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
413
+ voiceStart: "voiceStart";
414
+ voiceStop: "voiceStop";
413
415
  error: "error";
414
416
  messageReceived: "messageReceived";
415
417
  messageSent: "messageSent";
416
- voiceStart: "voiceStart";
417
- voiceStop: "voiceStop";
418
418
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodString]>>>;
419
419
  }, z.core.$loose>>;
420
420
  haptics: z.ZodOptional<z.ZodObject<{
421
421
  enabled: z.ZodDefault<z.ZodBoolean>;
422
422
  events: z.ZodOptional<z.ZodRecord<z.ZodEnum<{
423
+ voiceStart: "voiceStart";
424
+ voiceStop: "voiceStop";
423
425
  error: "error";
424
426
  messageReceived: "messageReceived";
425
427
  messageSent: "messageSent";
426
- voiceStart: "voiceStart";
427
- voiceStop: "voiceStop";
428
428
  }> & z.core.$partial, z.ZodUnion<readonly [z.ZodBoolean, z.ZodNumber, z.ZodArray<z.ZodNumber>]>>>;
429
429
  }, z.core.$loose>>;
430
430
  }, z.core.$loose>;
@@ -565,16 +565,16 @@ type FooterOptions = z.infer<typeof footerSchema>;
565
565
 
566
566
  declare const fieldTypeSchema: z.ZodEnum<{
567
567
  number: "number";
568
+ select: "select";
569
+ textarea: "textarea";
570
+ time: "time";
568
571
  text: "text";
572
+ checkbox: "checkbox";
573
+ radio: "radio";
569
574
  url: "url";
570
575
  email: "email";
571
576
  tel: "tel";
572
577
  date: "date";
573
- time: "time";
574
- textarea: "textarea";
575
- select: "select";
576
- radio: "radio";
577
- checkbox: "checkbox";
578
578
  multiselect: "multiselect";
579
579
  }>;
580
580
  type FieldType = z.infer<typeof fieldTypeSchema>;
@@ -599,16 +599,16 @@ declare const formFieldSchema: z.ZodObject<{
599
599
  label: z.ZodString;
600
600
  type: z.ZodEnum<{
601
601
  number: "number";
602
+ select: "select";
603
+ textarea: "textarea";
604
+ time: "time";
602
605
  text: "text";
606
+ checkbox: "checkbox";
607
+ radio: "radio";
603
608
  url: "url";
604
609
  email: "email";
605
610
  tel: "tel";
606
611
  date: "date";
607
- time: "time";
608
- textarea: "textarea";
609
- select: "select";
610
- radio: "radio";
611
- checkbox: "checkbox";
612
612
  multiselect: "multiselect";
613
613
  }>;
614
614
  placeholder: z.ZodOptional<z.ZodString>;
@@ -659,16 +659,16 @@ declare const formDefSchema: z.ZodObject<{
659
659
  label: z.ZodString;
660
660
  type: z.ZodEnum<{
661
661
  number: "number";
662
+ select: "select";
663
+ textarea: "textarea";
664
+ time: "time";
662
665
  text: "text";
666
+ checkbox: "checkbox";
667
+ radio: "radio";
663
668
  url: "url";
664
669
  email: "email";
665
670
  tel: "tel";
666
671
  date: "date";
667
- time: "time";
668
- textarea: "textarea";
669
- select: "select";
670
- radio: "radio";
671
- checkbox: "checkbox";
672
672
  multiselect: "multiselect";
673
673
  }>;
674
674
  placeholder: z.ZodOptional<z.ZodString>;
@@ -717,16 +717,16 @@ declare const formsSchema: z.ZodArray<z.ZodObject<{
717
717
  label: z.ZodString;
718
718
  type: z.ZodEnum<{
719
719
  number: "number";
720
+ select: "select";
721
+ textarea: "textarea";
722
+ time: "time";
720
723
  text: "text";
724
+ checkbox: "checkbox";
725
+ radio: "radio";
721
726
  url: "url";
722
727
  email: "email";
723
728
  tel: "tel";
724
729
  date: "date";
725
- time: "time";
726
- textarea: "textarea";
727
- select: "select";
728
- radio: "radio";
729
- checkbox: "checkbox";
730
730
  multiselect: "multiselect";
731
731
  }>;
732
732
  placeholder: z.ZodOptional<z.ZodString>;
@@ -798,18 +798,18 @@ type I18nOptions = z.infer<typeof i18nSchema>;
798
798
  */
799
799
 
800
800
  declare const moduleLayoutSchema: z.ZodEnum<{
801
+ home: "home";
801
802
  chat: "chat";
802
803
  help: "help";
803
- home: "home";
804
804
  news: "news";
805
805
  }>;
806
806
  type ModuleLayout = z.infer<typeof moduleLayoutSchema>;
807
807
  declare const moduleSchema: z.ZodObject<{
808
808
  label: z.ZodString;
809
809
  layout: z.ZodEnum<{
810
+ home: "home";
810
811
  chat: "chat";
811
812
  help: "help";
812
- home: "home";
813
813
  news: "news";
814
814
  }>;
815
815
  contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -835,9 +835,9 @@ type ModuleOptions = z.infer<typeof moduleSchema>;
835
835
  declare const modulesSchema: z.ZodArray<z.ZodObject<{
836
836
  label: z.ZodString;
837
837
  layout: z.ZodEnum<{
838
+ home: "home";
838
839
  chat: "chat";
839
840
  help: "help";
840
- home: "home";
841
841
  news: "news";
842
842
  }>;
843
843
  contentTags: z.ZodOptional<z.ZodArray<z.ZodString>>;
package/schema.json CHANGED
@@ -911,7 +911,7 @@
911
911
  "type": "object",
912
912
  "properties": {
913
913
  "animation": {
914
- "default": "typewriter",
914
+ "default": "instant",
915
915
  "description": "How welcome messages render — `typewriter` types each message in character-by-character; `instant` shows them whole.",
916
916
  "type": "string",
917
917
  "enum": [
@@ -932,14 +932,14 @@
932
932
  "speed"
933
933
  ],
934
934
  "additionalProperties": {},
935
- "description": "How welcome messages render — typewriter effect with adjustable cps speed.",
935
+ "description": "How welcome messages render — instant by default; opt into a typewriter effect with adjustable cps speed.",
936
936
  "examples": [
937
937
  {
938
- "animation": "typewriter",
939
- "speed": 60
938
+ "animation": "instant"
940
939
  },
941
940
  {
942
- "animation": "instant"
941
+ "animation": "typewriter",
942
+ "speed": 60
943
943
  }
944
944
  ]
945
945
  },
@@ -2665,7 +2665,7 @@
2665
2665
  "type": "object",
2666
2666
  "properties": {
2667
2667
  "animation": {
2668
- "default": "typewriter",
2668
+ "default": "instant",
2669
2669
  "description": "How welcome messages render — `typewriter` types each message in character-by-character; `instant` shows them whole.",
2670
2670
  "type": "string",
2671
2671
  "enum": [
@@ -2686,14 +2686,14 @@
2686
2686
  "speed"
2687
2687
  ],
2688
2688
  "additionalProperties": {},
2689
- "description": "How welcome messages render — typewriter effect with adjustable cps speed.",
2689
+ "description": "How welcome messages render — instant by default; opt into a typewriter effect with adjustable cps speed.",
2690
2690
  "examples": [
2691
2691
  {
2692
- "animation": "typewriter",
2693
- "speed": 60
2692
+ "animation": "instant"
2694
2693
  },
2695
2694
  {
2696
- "animation": "instant"
2695
+ "animation": "typewriter",
2696
+ "speed": 60
2697
2697
  }
2698
2698
  ]
2699
2699
  },
package/schema.mjs CHANGED
@@ -345,12 +345,12 @@ var composerOptionsSchema = z10.object({
345
345
  import { z as z11 } from "zod";
346
346
  var welcomeAnimationSchema = z11.enum(["typewriter", "instant"]);
347
347
  var welcomeOptionsSchema = z11.object({
348
- animation: welcomeAnimationSchema.default("typewriter").describe(
348
+ animation: welcomeAnimationSchema.default("instant").describe(
349
349
  "How welcome messages render \u2014 `typewriter` types each message in character-by-character; `instant` shows them whole."
350
350
  ),
351
351
  speed: z11.number().int().min(1).max(2e3).default(60).describe("Typewriter speed in characters per second. Only meaningful when `animation = typewriter`.")
352
- }).loose().describe("How welcome messages render \u2014 typewriter effect with adjustable cps speed.").meta({
353
- examples: [{ animation: "typewriter", speed: 60 }, { animation: "instant" }]
352
+ }).loose().describe("How welcome messages render \u2014 instant by default; opt into a typewriter effect with adjustable cps speed.").meta({
353
+ examples: [{ animation: "instant" }, { animation: "typewriter", speed: 60 }]
354
354
  });
355
355
 
356
356
  // src/schema/widget/footer.ts
package/web-component.mjs CHANGED
@@ -447,7 +447,7 @@ var DEFAULT_ATTACHMENTS = {
447
447
  maxCount: 10,
448
448
  accept: "*/*"
449
449
  };
450
- var DEFAULT_WELCOME = { animation: "typewriter", speed: 60 };
450
+ var DEFAULT_WELCOME = { animation: "instant", speed: 60 };
451
451
  var DEFAULT_FEATURES = {
452
452
  files: true,
453
453
  voice: "local",
@@ -4831,19 +4831,23 @@ function MessageList({
4831
4831
  const [showJump, setShowJump] = useState6(false);
4832
4832
  const [scrolling, setScrolling] = useState6(false);
4833
4833
  const hasHydratedRef = useRef5(false);
4834
+ const detachedRef = useRef5(false);
4835
+ const autoPinAtRef = useRef5(0);
4836
+ const pinBottom = (el) => {
4837
+ autoPinAtRef.current = performance.now();
4838
+ el.scrollTop = el.scrollHeight;
4839
+ };
4834
4840
  const firstMessageId = messages.value[0]?.id;
4835
4841
  useLayoutEffect(() => {
4836
4842
  const el = ref.current;
4837
4843
  if (!el) return;
4838
4844
  if (messages.value.length === 0) return;
4839
4845
  hasHydratedRef.current = true;
4840
- const pinBottom = () => {
4841
- el.scrollTop = el.scrollHeight;
4842
- };
4843
- pinBottom();
4844
- const resizeObs = new ResizeObserver(pinBottom);
4846
+ const pinNow = () => pinBottom(el);
4847
+ pinNow();
4848
+ const resizeObs = new ResizeObserver(pinNow);
4845
4849
  resizeObs.observe(el);
4846
- const mutationObs = new MutationObserver(pinBottom);
4850
+ const mutationObs = new MutationObserver(pinNow);
4847
4851
  mutationObs.observe(el, { childList: true, subtree: true, characterData: true });
4848
4852
  const timerId = setTimeout(() => {
4849
4853
  resizeObs.disconnect();
@@ -4859,8 +4863,14 @@ function MessageList({
4859
4863
  const el = ref.current;
4860
4864
  if (!el) return;
4861
4865
  if (!hasHydratedRef.current) return;
4866
+ if (messages.value.at(-1)?.role === "user") {
4867
+ detachedRef.current = false;
4868
+ pinBottom(el);
4869
+ return;
4870
+ }
4871
+ if (detachedRef.current) return;
4862
4872
  const distanceFromBottom = el.scrollHeight - el.scrollTop - el.clientHeight;
4863
- if (distanceFromBottom < STICK_THRESHOLD) el.scrollTop = el.scrollHeight;
4873
+ if (distanceFromBottom < STICK_THRESHOLD) pinBottom(el);
4864
4874
  }, [messages.value.length]);
4865
4875
  useEffect8(() => {
4866
4876
  const el = ref.current;
@@ -4868,8 +4878,9 @@ function MessageList({
4868
4878
  const last = messages.value.at(-1);
4869
4879
  if (!last) return;
4870
4880
  const pinIfNear = () => {
4881
+ if (detachedRef.current) return;
4871
4882
  const distance = el.scrollHeight - el.scrollTop - el.clientHeight;
4872
- if (distance < STICK_THRESHOLD * 2) el.scrollTop = el.scrollHeight;
4883
+ if (distance < STICK_THRESHOLD * 2) pinBottom(el);
4873
4884
  };
4874
4885
  if (last.status !== "streaming") {
4875
4886
  const rafId = requestAnimationFrame(pinIfNear);
@@ -4883,8 +4894,8 @@ function MessageList({
4883
4894
  const activeFormId = form?.form.id;
4884
4895
  useLayoutEffect(() => {
4885
4896
  const el = ref.current;
4886
- if (!el || !activeFormId) return;
4887
- el.scrollTop = el.scrollHeight;
4897
+ if (!el || !activeFormId || detachedRef.current) return;
4898
+ pinBottom(el);
4888
4899
  }, [activeFormId]);
4889
4900
  useEffect8(() => {
4890
4901
  const el = ref.current;
@@ -4893,6 +4904,9 @@ function MessageList({
4893
4904
  let idleTimer;
4894
4905
  const onScroll = () => {
4895
4906
  syncJump();
4907
+ if (performance.now() - autoPinAtRef.current > 150) {
4908
+ detachedRef.current = el.scrollHeight - el.scrollTop - el.clientHeight > 8;
4909
+ }
4896
4910
  setScrolling(true);
4897
4911
  clearTimeout(idleTimer);
4898
4912
  idleTimer = setTimeout(() => setScrolling(false), DIVIDER_IDLE_MS);
@@ -4906,7 +4920,9 @@ function MessageList({
4906
4920
  }, []);
4907
4921
  const jumpToBottom = () => {
4908
4922
  const el = ref.current;
4909
- if (el) el.scrollTop = el.scrollHeight;
4923
+ if (!el) return;
4924
+ detachedRef.current = false;
4925
+ pinBottom(el);
4910
4926
  };
4911
4927
  const rows = [];
4912
4928
  let prevDay = "";