@ourlu/assistant-sdk 0.2.4 → 0.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/dist/iife/audio.v1.028c93fe.js +160 -0
  2. package/dist/iife/audio.v1.051ececf.js +183 -0
  3. package/dist/iife/audio.v1.200db1a6.js +208 -0
  4. package/dist/iife/audio.v1.20858b08.js +191 -0
  5. package/dist/iife/audio.v1.2690e445.js +179 -0
  6. package/dist/iife/audio.v1.2742ff12.js +188 -0
  7. package/dist/iife/audio.v1.70af81b3.js +191 -0
  8. package/dist/iife/audio.v1.95146620.js +1 -1
  9. package/dist/iife/audio.v1.b330baaf.js +166 -0
  10. package/dist/iife/audio.v1.bb9c2d88.js +181 -0
  11. package/dist/iife/audio.v1.ea7571b2.js +182 -0
  12. package/dist/iife/audio.v1.fc0aa8af.js +191 -0
  13. package/dist/iife/audio.v1.js +107 -95
  14. package/dist/iife/engine.v1.19c589a2.js +861 -0
  15. package/dist/iife/engine.v1.2b5bb43b.js +3 -3
  16. package/dist/iife/engine.v1.3b09dc20.js +3 -3
  17. package/dist/iife/engine.v1.56074e5a.js +769 -0
  18. package/dist/iife/engine.v1.61c10e6c.js +770 -0
  19. package/dist/iife/engine.v1.773fc15d.js +2 -2
  20. package/dist/iife/engine.v1.80d2230f.js +3 -3
  21. package/dist/iife/engine.v1.940ba9ea.js +764 -0
  22. package/dist/iife/engine.v1.99a33ee2.js +767 -0
  23. package/dist/iife/engine.v1.9ca6b7ec.js +3 -3
  24. package/dist/iife/engine.v1.a1f7dea2.js +764 -0
  25. package/dist/iife/engine.v1.bc9c0b5e.js +838 -0
  26. package/dist/iife/engine.v1.c0c00bd0.js +3 -3
  27. package/dist/iife/engine.v1.c127656e.js +820 -0
  28. package/dist/iife/engine.v1.c54c9a1a.js +3 -3
  29. package/dist/iife/engine.v1.d1052e81.js +3 -3
  30. package/dist/iife/engine.v1.ec035c58.js +782 -0
  31. package/dist/iife/engine.v1.f6d23a0f.js +770 -0
  32. package/dist/iife/engine.v1.js +116 -25
  33. package/dist/iife/loader.v1.js +9 -1
  34. package/dist/iife/plu.v1.cc853a2d.js +458 -0
  35. package/dist/iife/plu.v1.js +458 -0
  36. package/dist/iife/signalement.v1.d321dfde.js +518 -0
  37. package/dist/iife/signalement.v1.js +518 -0
  38. package/dist/iife/ui.v1.00abf020.js +895 -0
  39. package/dist/iife/ui.v1.0caedc90.js +1018 -0
  40. package/dist/iife/ui.v1.0ccf99d5.js +997 -0
  41. package/dist/iife/ui.v1.11a41f0d.js +1007 -0
  42. package/dist/iife/ui.v1.12986798.js +962 -0
  43. package/dist/iife/ui.v1.15b2cd71.js +986 -0
  44. package/dist/iife/ui.v1.163772e6.js +962 -0
  45. package/dist/iife/ui.v1.3a1d08a0.js +1007 -0
  46. package/dist/iife/ui.v1.3c0cf4da.js +947 -0
  47. package/dist/iife/ui.v1.3fcff562.js +997 -0
  48. package/dist/iife/ui.v1.44616ccb.js +986 -0
  49. package/dist/iife/ui.v1.4e202266.js +1007 -0
  50. package/dist/iife/ui.v1.6becaa84.js +895 -0
  51. package/dist/iife/ui.v1.6c9e4995.js +895 -0
  52. package/dist/iife/ui.v1.7432d2af.js +995 -0
  53. package/dist/iife/ui.v1.84d77387.js +1003 -0
  54. package/dist/iife/ui.v1.857a0e8b.js +986 -0
  55. package/dist/iife/ui.v1.88bf5494.js +898 -0
  56. package/dist/iife/ui.v1.89fbfdd9.js +963 -0
  57. package/dist/iife/ui.v1.a588a766.js +997 -0
  58. package/dist/iife/ui.v1.a8cfe724.js +900 -0
  59. package/dist/iife/ui.v1.cd72e7c3.js +1006 -0
  60. package/dist/iife/ui.v1.e007c7c4.js +926 -0
  61. package/dist/iife/ui.v1.e24ba2bd.js +903 -0
  62. package/dist/iife/ui.v1.e8703c6d.js +1006 -0
  63. package/dist/iife/ui.v1.f1d8e998.js +903 -0
  64. package/dist/iife/ui.v1.f6857351.js +995 -0
  65. package/dist/iife/ui.v1.fc52b520.js +895 -0
  66. package/dist/iife/ui.v1.js +145 -86
  67. package/dist/iife/widget-manifest.json +5 -3
  68. package/package.json +3 -1
@@ -169,13 +169,13 @@ function installMascotTheme(ui) {
169
169
  return fetch(normalizedMascotUrl, { method: "GET", credentials: "omit" })
170
170
  .then(function(response) {
171
171
  if (!response.ok) {
172
- throw new Error("mascot fetch failed");
172
+ throw new Error("Impossible de charger la mascotte.");
173
173
  }
174
174
  return response.text();
175
175
  })
176
176
  .then(function(rawSvgMarkup) {
177
177
  if (!rawSvgMarkup || rawSvgMarkup.indexOf("<svg") === -1) {
178
- throw new Error("mascot SVG invalide ou reponse non-SVG pour " + normalizedMascotUrl);
178
+ throw new Error("Mascotte SVG invalide ou réponse non-SVG pour " + normalizedMascotUrl);
179
179
  }
180
180
  var themedSvgMarkup = ui.replaceSvgColorTokens(rawSvgMarkup, replacementMap);
181
181
  var themedDataUrl = ui.encodeSvgToDataUrl(themedSvgMarkup);
@@ -384,11 +384,25 @@ function installWidgetCssBuilder(ui) {
384
384
  };
385
385
  };
386
386
 
387
+ WidgetCssBuilder.prototype.darkenHex = function(hex, percent) {
388
+ var h = String(hex || "#000000").replace("#", "");
389
+ if (h.length !== 6) h = "000000";
390
+ var r = Math.max(0, Math.round(parseInt(h.slice(0, 2), 16) * (1 - percent / 100)));
391
+ var g = Math.max(0, Math.round(parseInt(h.slice(2, 4), 16) * (1 - percent / 100)));
392
+ var b = Math.max(0, Math.round(parseInt(h.slice(4, 6), 16) * (1 - percent / 100)));
393
+ return "#" + ("0" + r.toString(16)).slice(-2) + ("0" + g.toString(16)).slice(-2) + ("0" + b.toString(16)).slice(-2);
394
+ };
395
+
396
+ WidgetCssBuilder.prototype.resolveBackground = function(baseColor, gradientEnabled, autoMode, manualColor2, darkenPct) {
397
+ if (!gradientEnabled) return baseColor;
398
+ var color2 = autoMode ? this.darkenHex(baseColor, darkenPct) : (manualColor2 || this.darkenHex(baseColor, darkenPct));
399
+ return "linear-gradient(135deg," + baseColor + " 0%," + color2 + " 100%)";
400
+ };
401
+
387
402
  WidgetCssBuilder.prototype.build = function() {
388
403
  var cfg = this.config;
389
404
  var side = cfg.position === "bottom-left" ? "left" : "right";
390
- var resizeCorner = cfg.position === "bottom-left" ? "right" : "left";
391
- var gradient = "linear-gradient(135deg," + cfg.primaryColor + " 0%,#0047b3 100%)";
405
+ var headerBg = this.resolveBackground(cfg.primaryColor, cfg.headerGradientEnabled !== false, cfg.headerGradientColor2Auto !== false, cfg.headerGradientColor2, 25);
392
406
  var panelBg = ui.hexToRgba(cfg.panelBackgroundColor, cfg.panelBackgroundAlpha);
393
407
  var layout = this.resolveLayout();
394
408
  var pw = layout.panelWidth + "px";
@@ -396,17 +410,22 @@ function installWidgetCssBuilder(ui) {
396
410
  var mhVh = layout.panelMaxHeightVh + "vh";
397
411
  var br = layout.borderRadius + "px";
398
412
 
413
+ var userBubbleBase = cfg.userBubbleColor || cfg.primaryColor;
414
+ var userBubbleBg = this.resolveBackground(userBubbleBase, cfg.userBubbleGradientEnabled === true, cfg.userBubbleGradientColor2Auto !== false, cfg.userBubbleGradientColor2, 25);
415
+ var assistantBubbleBase = cfg.assistantBubbleColor || "#f0f4f8";
416
+ var assistantBubbleBg = this.resolveBackground(assistantBubbleBase, cfg.assistantBubbleGradientEnabled === true, cfg.assistantBubbleGradientColor2Auto !== false, cfg.assistantBubbleGradientColor2, 15);
417
+ var assistantBubbleTextColor = cfg.assistantBubbleTextColor || "#1a1a2e";
418
+
399
419
  return [
400
420
  this.buildResetAndBase(),
401
- this.buildBubble(side, gradient, cfg.primaryColor),
421
+ this.buildBubble(side, headerBg, cfg.primaryColor),
402
422
  this.buildPanel(side, pw, ph, mhVh, panelBg, br),
403
- this.buildHeader(gradient, br),
423
+ this.buildHeader(headerBg, br),
404
424
  this.buildNotes(),
405
425
  this.buildMessages(),
406
- this.buildMessageBubbles(cfg.primaryColor),
426
+ this.buildMessageBubbles(userBubbleBg, assistantBubbleBg, assistantBubbleTextColor),
407
427
  this.buildTypingAndError(),
408
428
  this.buildComposer(cfg.primaryColor, br),
409
- this.buildResizeHandle(resizeCorner),
410
429
  this.buildMobileOverrides()
411
430
  ].join("\n");
412
431
  };
@@ -455,7 +474,7 @@ function installWidgetCssBuilder(ui) {
455
474
  return [
456
475
  "#cm-disclaimer,#cm-transparency{font-size:13px;display:flex;align-items:center;gap:8px;padding:8px 14px;flex-shrink:0}",
457
476
  "#cm-disclaimer{background:#e8f4fd;color:#1a5276;border-bottom:1px solid #b3d9f2}",
458
- "#cm-transparency{color:#555;border-top:1px solid #eee;background:#fff}",
477
+ "#cm-transparency{color:#555;border-top:1px solid #eee;background:#fff;display:none}",
459
478
  ".cm-close-note{background:none;border:none;cursor:pointer;border-radius:6px;padding:4px 8px;min-width:32px;min-height:32px;width:32px;opacity:.6;transition:opacity .15s,background .15s;flex-shrink:0;display:flex;align-items:center;justify-content:center;margin-left:auto}",
460
479
  ".cm-close-note:hover{opacity:1;background:rgba(0,0,0,.08)}",
461
480
  ".cm-close-note svg{width:16px;height:16px}"
@@ -473,11 +492,11 @@ function installWidgetCssBuilder(ui) {
473
492
  ].join("\n");
474
493
  };
475
494
 
476
- WidgetCssBuilder.prototype.buildMessageBubbles = function(primaryColor) {
495
+ WidgetCssBuilder.prototype.buildMessageBubbles = function(userBubbleBg, assistantBubbleBg, assistantTextColor) {
477
496
  return [
478
497
  ".cm-msg{max-width:88%;padding:12px 16px;border-radius:16px;font-size:15px;line-height:1.55;word-break:break-word;animation:cm-msg-in .25s cubic-bezier(.4,0,.2,1)}",
479
498
  "@keyframes cm-msg-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}",
480
- ".cm-msg.assistant{background:#f0f4f8;color:#1a1a2e;border-bottom-left-radius:4px;align-self:flex-start}",
499
+ ".cm-msg.assistant{background:" + assistantBubbleBg + ";color:" + assistantTextColor + ";border-bottom-left-radius:4px;align-self:flex-start}",
481
500
  ".cm-msg.assistant p{margin:0 0 10px}",
482
501
  ".cm-msg.assistant p:last-child{margin-bottom:0}",
483
502
  ".cm-msg.assistant ul,.cm-msg.assistant ol{margin:0 0 10px 20px;padding:0}",
@@ -487,7 +506,7 @@ function installWidgetCssBuilder(ui) {
487
506
  ".cm-msg.assistant pre{margin:0 0 10px;padding:10px 12px;background:#1f2937;color:#f9fafb;border-radius:10px;overflow-x:auto;font-size:13px}",
488
507
  ".cm-msg.assistant pre code{background:transparent;color:inherit;padding:0;font-size:inherit}",
489
508
  ".cm-msg.assistant h3,.cm-msg.assistant h4{margin:0 0 8px;font-size:15px;line-height:1.35;font-weight:600}",
490
- ".cm-msg.user{background:" + primaryColor + ";color:#fff;border-bottom-right-radius:4px;align-self:flex-end}"
509
+ ".cm-msg.user{background:" + userBubbleBg + ";color:#fff;border-bottom-right-radius:4px;align-self:flex-end}"
491
510
  ].join("\n");
492
511
  };
493
512
 
@@ -504,11 +523,14 @@ function installWidgetCssBuilder(ui) {
504
523
 
505
524
  WidgetCssBuilder.prototype.buildComposer = function(primaryColor, borderRadius) {
506
525
  return [
507
- "#cm-form{display:flex;align-items:flex-end;gap:8px;padding:12px 16px;border-top:1px solid #eee;background:#fff;border-radius:0 0 " + borderRadius + " " + borderRadius + "}",
526
+ "#cm-form{display:flex;flex-wrap:wrap;align-items:flex-end;gap:8px;padding:12px 16px;border-top:1px solid #eee;background:#fff;border-radius:0 0 " + borderRadius + " " + borderRadius + ";flex-shrink:0}",
527
+ "#cm-form.cm-multiline #cm-input{order:-1;flex-basis:100%;width:100%}",
528
+ "#cm-form.cm-multiline #cm-mic{margin-right:auto}",
508
529
  "#cm-input{flex:1;border:1.5px solid #d1d5db;border-radius:14px;padding:12px 16px;min-height:48px;max-height:200px;resize:none;outline:none;line-height:1.5;font-size:15px;transition:border-color .2s,box-shadow .2s;overflow-y:auto}",
509
530
  "#cm-input:focus{border-color:" + primaryColor + ";box-shadow:0 0 0 3px rgba(0,102,255,.15)}",
510
531
  "#cm-input::placeholder{color:#9ca3af}",
511
532
  "#cm-send,#cm-mic{width:48px;height:48px;border-radius:50%;display:flex;align-items:center;justify-content:center;border:none;cursor:pointer;flex-shrink:0;transition:transform .15s,opacity .15s;font-size:18px;-webkit-user-select:none;user-select:none;-webkit-user-drag:none}",
533
+ "#cm-send svg,#cm-mic svg{width:24px !important;height:24px !important;min-width:24px !important;min-height:24px !important;display:block !important}",
512
534
  "#cm-send{background:" + primaryColor + ";color:#fff}",
513
535
  "#cm-send:hover:not(:disabled){transform:scale(1.08)}",
514
536
  "#cm-send:active:not(:disabled){transform:scale(0.94)}",
@@ -520,35 +542,24 @@ function installWidgetCssBuilder(ui) {
520
542
  ].join("\n");
521
543
  };
522
544
 
523
- WidgetCssBuilder.prototype.buildResizeHandle = function(corner) {
524
- var posX = corner === "left" ? "left:0" : "right:0";
525
- var cursorType = corner === "left" ? "ne-resize" : "nw-resize";
526
- return [
527
- "#cm-resize-handle{position:absolute;top:0;" + posX + ";width:28px;height:28px;cursor:" + cursorType + ";z-index:10;display:flex;align-items:center;justify-content:center;opacity:0;transition:opacity .2s}",
528
- "#cm-panel:hover #cm-resize-handle{opacity:.5}",
529
- "#cm-resize-handle:hover{opacity:1 !important}",
530
- "#cm-resize-handle svg{width:14px;height:14px;pointer-events:none}"
531
- ].join("\n");
532
- };
533
-
534
545
  WidgetCssBuilder.prototype.buildMobileOverrides = function() {
535
546
  return [
536
547
  "@media (max-width:600px){",
537
548
  "#cm-bubble{width:56px;height:56px;bottom:16px;right:16px !important;left:auto !important}",
538
549
  "#cm-bubble img{width:72px;height:72px;top:-12px}",
539
- "#cm-panel{left:0 !important;right:0 !important;bottom:0 !important;top:0 !important;width:100% !important;max-width:none !important;height:100dvh !important;height:100vh !important;max-height:none !important;border-radius:0 !important}",
540
- "#cm-header{border-radius:0 !important;padding:14px 16px 14px 72px;min-height:52px}",
541
- "#cm-header-mascot{width:68px;height:68px;left:-4px;top:-6px}",
550
+ "#cm-panel{position:fixed !important;left:0 !important;right:0 !important;bottom:8px;top:16px;width:100% !important;max-width:none !important;height:auto;max-height:none !important;border-radius:12px !important;overflow:visible !important;transition:height .15s ease,top .15s ease}",
551
+ "#cm-header{padding:10px 12px 10px 76px;border-radius:12px 12px 0 0 !important;min-height:48px}",
552
+ "#cm-header-mascot{width:68px;height:68px;left:-4px;top:-12px}",
542
553
  "#cm-title{font-size:16px}",
543
554
  ".cm-header-btn-maximize{display:none !important}",
544
- "#cm-messages{flex:1;padding:12px 16px;gap:12px;overflow-y:auto}",
555
+ "#cm-messages{flex:1;min-height:0;padding:12px 16px;gap:12px;overflow-y:auto}",
545
556
  ".cm-msg{max-width:92%;padding:12px 14px;font-size:15px;border-radius:16px}",
546
- "#cm-form{padding:10px 12px;padding-bottom:calc(10px + env(safe-area-inset-bottom,0px));border-radius:0 !important;gap:8px}",
557
+ "#cm-form{padding:10px 12px;padding-bottom:calc(10px + env(safe-area-inset-bottom,0px));gap:8px;flex-shrink:0;border-radius:0 0 12px 12px !important}",
547
558
  "#cm-input{min-height:44px;font-size:16px;border-radius:14px;padding:10px 14px}",
548
559
  "#cm-send,#cm-mic{width:44px;height:44px}",
560
+ "#cm-send svg,#cm-mic svg{width:24px !important;height:24px !important;min-width:24px !important;min-height:24px !important;display:block !important}",
549
561
  "#cm-typing{padding:6px 16px;font-size:13px}",
550
562
  "#cm-disclaimer,#cm-transparency{font-size:12px;padding:8px 12px}",
551
- "#cm-resize-handle{display:none !important}",
552
563
  "#cm-welcome{font-size:15px;padding:24px 16px}",
553
564
  "}"
554
565
  ].join("\n");
@@ -575,7 +586,6 @@ function installWidgetUIManager(ui) {
575
586
  this.streamingAssistantElement = null;
576
587
  this.streamingAssistantBuffer = "";
577
588
  this.themeOverrideStyle = null;
578
- this._resizeDragState = null;
579
589
  }
580
590
 
581
591
  WidgetUIManager.prototype.mount = function() {
@@ -584,10 +594,6 @@ function installWidgetUIManager(ui) {
584
594
  var css = cssBuilder.build();
585
595
  var esc = ui.escapeHtml;
586
596
  var escAttr = ui.escapeHtmlAttribute;
587
- var resizeCorner = this.config.position === "bottom-left" ? "right" : "left";
588
- var resizeSvg = resizeCorner === "left"
589
- ? '<svg viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><line x1="2" y1="12" x2="12" y2="2"/><line x1="2" y1="7" x2="7" y2="2"/></svg>'
590
- : '<svg viewBox="0 0 14 14" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round"><line x1="12" y1="12" x2="2" y2="2"/><line x1="12" y1="7" x2="7" y2="2"/></svg>';
591
597
 
592
598
  var host = document.createElement("div");
593
599
  host.id = ui.CONTAINER_ID;
@@ -600,8 +606,7 @@ function installWidgetUIManager(ui) {
600
606
  '<img id="cm-bubble-mascot" src="' + escAttr(this.config.mascotUrl) + '" alt="Mascotte assistant" />',
601
607
  "</button>",
602
608
  '<div id="cm-panel" role="dialog" aria-modal="true" aria-label="Chat ' + escAttr(this.config.assistantName) + '">',
603
- '<div id="cm-resize-handle" aria-hidden="true">' + resizeSvg + '</div>',
604
- '<div id="cm-header"><img id="cm-header-mascot" src="' + escAttr(this.config.mascotUrl) + '" alt="" /><h3 id="cm-title">' + esc(this.config.assistantName) + '</h3><div id="cm-header-actions"><button class="cm-header-btn cm-header-btn-maximize" id="cm-maximize" type="button" aria-label="Agrandir"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6"/><path d="M9 21H3v-6"/><path d="M21 3l-7 7"/><path d="M3 21l7-7"/></svg></button><button class="cm-header-btn" id="cm-trash" type="button" aria-label="R\u00e9initialiser"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></svg></button><button class="cm-header-btn" id="cm-close" type="button" aria-label="Fermer l\'assistant"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button></div></div>',
609
+ '<div id="cm-header"><img id="cm-header-mascot" src="' + escAttr(this.config.mascotUrl) + '" alt="" /><h3 id="cm-title">' + esc(this.config.assistantName) + '</h3><div id="cm-header-actions"><button class="cm-header-btn cm-header-btn-maximize" id="cm-maximize" type="button" aria-label="Agrandir"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M15 3h6v6"/><path d="M9 21H3v-6"/><path d="M21 3l-7 7"/><path d="M3 21l7-7"/></svg></button><button class="cm-header-btn" id="cm-close" type="button" aria-label="Fermer l\'assistant"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button></div></div>',
605
610
  this.config.disclaimer ? '<div id="cm-disclaimer"><span>' + esc(this.config.disclaimerText) + '</span><button class="cm-close-note" id="cm-disclaimer-close" type="button" aria-label="Fermer l\'avertissement"><svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg></button></div>' : "",
606
611
  '<div id="cm-messages" aria-live="polite" aria-relevant="additions"><p id="cm-welcome">' + esc(this.config.welcomeMessage) + "</p></div>",
607
612
  '<div id="cm-typing">L\'assistant r\u00e9fl\u00e9chit\u2026</div>',
@@ -629,67 +634,59 @@ function installWidgetUIManager(ui) {
629
634
  root.appendChild(this.themeOverrideStyle);
630
635
  this.bindMascotImageErrorHandlers();
631
636
  this.bindAutoGrowInput();
632
- this.bindResizeHandle();
637
+ this.bindMobileViewportResize();
633
638
  this.applyThemeOverrides();
634
639
  this.applyMascotTheme();
635
640
  return true;
636
641
  };
637
642
 
643
+ WidgetUIManager.prototype.bindMobileViewportResize = function() {
644
+ var panelRef = this.panel;
645
+ if (!panelRef) return;
646
+ var mobileQuery = window.matchMedia("(max-width:600px)");
647
+ if (!window.visualViewport) return;
648
+ var rafId = 0;
649
+ function onViewportResize() {
650
+ if (!mobileQuery.matches) return;
651
+ if (rafId) return;
652
+ rafId = requestAnimationFrame(function() {
653
+ rafId = 0;
654
+ var vv = window.visualViewport;
655
+ if (!vv) return;
656
+ var topMargin = 16;
657
+ var bottomMargin = 8;
658
+ var adjustedTop = Math.round(vv.offsetTop) + topMargin;
659
+ var adjustedHeight = Math.round(vv.height) - topMargin - bottomMargin;
660
+ panelRef.style.height = Math.max(200, adjustedHeight) + "px";
661
+ panelRef.style.top = adjustedTop + "px";
662
+ });
663
+ }
664
+ window.visualViewport.addEventListener("resize", onViewportResize);
665
+ window.visualViewport.addEventListener("scroll", onViewportResize);
666
+ this._mobileQuery = mobileQuery;
667
+ };
668
+
638
669
  WidgetUIManager.prototype.bindAutoGrowInput = function() {
639
670
  var inputEl = this.input;
671
+ var formEl = this.root ? this.root.querySelector("#cm-form") : null;
640
672
  if (!inputEl) return;
673
+ var singleLineHeight = 0;
641
674
  function adjustHeight() {
642
675
  inputEl.style.height = "auto";
643
676
  var scrollH = inputEl.scrollHeight;
644
677
  var maxH = 200;
645
678
  inputEl.style.height = Math.min(scrollH, maxH) + "px";
646
679
  inputEl.style.overflowY = scrollH > maxH ? "auto" : "hidden";
680
+ if (formEl) {
681
+ if (!singleLineHeight && scrollH > 0) singleLineHeight = scrollH;
682
+ var isMultiline = singleLineHeight > 0 && scrollH > singleLineHeight + 4;
683
+ formEl.classList.toggle("cm-multiline", isMultiline);
684
+ }
647
685
  }
648
686
  inputEl.addEventListener("input", adjustHeight);
649
687
  inputEl.style.overflowY = "hidden";
650
688
  };
651
689
 
652
- WidgetUIManager.prototype.bindResizeHandle = function() {
653
- var handle = this.root ? this.root.querySelector("#cm-resize-handle") : null;
654
- var panel = this.panel;
655
- if (!handle || !panel) return;
656
- var self = this;
657
- var isLeftCorner = this.config.position !== "bottom-left";
658
-
659
- handle.addEventListener("mousedown", function(startEvt) {
660
- startEvt.preventDefault();
661
- startEvt.stopPropagation();
662
- var rect = panel.getBoundingClientRect();
663
- self._resizeDragState = {
664
- startX: startEvt.clientX,
665
- startY: startEvt.clientY,
666
- startW: rect.width,
667
- startH: rect.height
668
- };
669
- document.addEventListener("mousemove", onMouseMove);
670
- document.addEventListener("mouseup", onMouseUp);
671
- });
672
-
673
- function onMouseMove(evt) {
674
- var st = self._resizeDragState;
675
- if (!st) return;
676
- var dx = evt.clientX - st.startX;
677
- var dy = evt.clientY - st.startY;
678
- var newW = isLeftCorner ? st.startW - dx : st.startW + dx;
679
- var newH = st.startH - dy;
680
- newW = Math.max(360, Math.min(960, newW));
681
- newH = Math.max(480, Math.min(window.innerHeight - 40, newH));
682
- panel.style.width = newW + "px";
683
- panel.style.height = newH + "px";
684
- }
685
-
686
- function onMouseUp() {
687
- self._resizeDragState = null;
688
- document.removeEventListener("mousemove", onMouseMove);
689
- document.removeEventListener("mouseup", onMouseUp);
690
- }
691
- };
692
-
693
690
  WidgetUIManager.prototype.bindMascotImageErrorHandlers = function() {
694
691
  var self = this;
695
692
  [this.bubbleMascot, this.headerMascot].forEach(function(mascotNode) {
@@ -729,8 +726,6 @@ function installWidgetUIManager(ui) {
729
726
  var maximizeBtn = this.root.querySelector("#cm-maximize");
730
727
  var panelRef = this.panel;
731
728
  if (maximizeBtn && panelRef) maximizeBtn.addEventListener("click", function() { panelRef.classList.toggle("maximized"); });
732
- var trashBtn = this.root.querySelector("#cm-trash");
733
- if (trashBtn && callbacks.onReset) trashBtn.addEventListener("click", callbacks.onReset);
734
729
  };
735
730
 
736
731
  WidgetUIManager.prototype.setMascotSource = function(sourceUrl) {
@@ -833,18 +828,46 @@ function installWidgetUIManager(ui) {
833
828
  WidgetUIManager.prototype.setOpen = function(opened) {
834
829
  this.panel.classList.toggle("open", opened);
835
830
  this.bubble.style.display = opened ? "none" : "flex";
836
- if (opened) this.input.focus();
831
+ if (opened && !("ontouchstart" in window)) this.input.focus();
832
+ this.lockBodyScroll(opened);
833
+ };
834
+
835
+ WidgetUIManager.prototype.lockBodyScroll = function(lock) {
836
+ if (!this._mobileQuery || !this._mobileQuery.matches) return;
837
+ if (lock) {
838
+ this._savedBodyOverflow = document.body.style.overflow;
839
+ this._savedBodyPosition = document.body.style.position;
840
+ this._savedBodyTop = document.body.style.top;
841
+ this._savedBodyWidth = document.body.style.width;
842
+ this._scrollY = window.scrollY;
843
+ document.body.style.overflow = "hidden";
844
+ document.body.style.position = "fixed";
845
+ document.body.style.top = "-" + this._scrollY + "px";
846
+ document.body.style.width = "100%";
847
+ } else {
848
+ document.body.style.overflow = this._savedBodyOverflow || "";
849
+ document.body.style.position = this._savedBodyPosition || "";
850
+ document.body.style.top = this._savedBodyTop || "";
851
+ document.body.style.width = this._savedBodyWidth || "";
852
+ window.scrollTo(0, this._scrollY || 0);
853
+ }
837
854
  };
838
855
 
839
856
  WidgetUIManager.prototype.pullInput = function() {
840
857
  var value = this.input.value.trim();
841
858
  this.input.value = "";
842
- this.input.style.height = "auto";
859
+ this.input.dispatchEvent(new Event("input", { bubbles: true }));
843
860
  return value;
844
861
  };
845
862
 
846
- WidgetUIManager.prototype.setInput = function(value) { this.input.value = String(value || ""); };
863
+ WidgetUIManager.prototype.setInput = function(value) {
864
+ this.input.value = String(value || "");
865
+ this.input.dispatchEvent(new Event("input", { bubbles: true }));
866
+ };
847
867
  WidgetUIManager.prototype.inputValue = function() { return this.input.value; };
868
+ WidgetUIManager.prototype.setInputPlaceholder = function(text) {
869
+ this.input.placeholder = text || "Posez votre question\u2026";
870
+ };
848
871
  WidgetUIManager.prototype.showTyping = function(visible) { this.typing.classList.toggle("visible", Boolean(visible)); };
849
872
 
850
873
  WidgetUIManager.prototype.setComposerDisabled = function(disabled) {
@@ -924,11 +947,47 @@ function installWidgetUIManager(ui) {
924
947
 
925
948
  WidgetUIManager.prototype.setMicListening = function(isListening) {
926
949
  this.micButton.classList.toggle("listening", isListening);
927
- this.micButton.textContent = isListening ? "\u23f9" : "\ud83c\udfa4";
928
- this.micButton.setAttribute("aria-label", isListening ? "Arrêter la dictée vocale" : "Dicter un message");
950
+ this.micButton.innerHTML = isListening
951
+ ? '<svg width="20" height="20" viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="6" width="12" height="12" rx="2"/></svg>'
952
+ : '<svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M12 1a3 3 0 0 0-3 3v8a3 3 0 0 0 6 0V4a3 3 0 0 0-3-3z"/><path d="M19 10v2a7 7 0 0 1-14 0v-2"/><line x1="12" y1="19" x2="12" y2="23"/><line x1="8" y1="23" x2="16" y2="23"/></svg>';
953
+ this.micButton.setAttribute("aria-label", isListening ? "Arr\u00eater la dict\u00e9e vocale" : "Dicter un message");
929
954
  this.input.placeholder = isListening ? "Transcription en cours\u2026" : "Posez votre question\u2026";
930
955
  };
931
956
 
957
+ WidgetUIManager.prototype.getHeader = function() {
958
+ return this.root ? this.root.querySelector("#cm-header") : null;
959
+ };
960
+
961
+ WidgetUIManager.prototype.getPanel = function() {
962
+ return this.panel;
963
+ };
964
+
965
+ WidgetUIManager.prototype.getRoot = function() {
966
+ return this.root;
967
+ };
968
+
969
+ WidgetUIManager.prototype.injectSignalementButton = function(messageNode, onOpen) {
970
+ if (!messageNode) return null;
971
+ var btn = document.createElement("button");
972
+ btn.className = "cm-sig-open-btn";
973
+ btn.type = "button";
974
+ btn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 9v4"/><path d="M12 17h.01"/><path d="M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/></svg>Mon signalement';
975
+ btn.addEventListener("click", function() { if (typeof onOpen === "function") onOpen(); });
976
+ messageNode.appendChild(btn);
977
+ return btn;
978
+ };
979
+
980
+ WidgetUIManager.prototype.injectPluButton = function(messageNode, onOpen) {
981
+ if (!messageNode) return null;
982
+ var btn = document.createElement("button");
983
+ btn.className = "cm-plu-open-btn";
984
+ btn.type = "button";
985
+ btn.innerHTML = '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8"><path d="M3 9l9-7 9 7v11a2 2 0 01-2 2H5a2 2 0 01-2-2z"/><polyline points="9 22 9 12 15 12 15 22"/></svg>Urbanisme';
986
+ btn.addEventListener("click", function() { if (typeof onOpen === "function") onOpen(); });
987
+ messageNode.appendChild(btn);
988
+ return btn;
989
+ };
990
+
932
991
  ui.WidgetUIManager = WidgetUIManager;
933
992
  }
934
993
 
@@ -1,5 +1,7 @@
1
1
  {
2
- "ui.v1.js": "ui.v1.c58e1d58.js",
3
- "audio.v1.js": "audio.v1.95146620.js",
4
- "engine.v1.js": "engine.v1.d1052e81.js"
2
+ "ui.v1.js": "ui.v1.0caedc90.js",
3
+ "audio.v1.js": "audio.v1.20858b08.js",
4
+ "signalement.v1.js": "signalement.v1.d321dfde.js",
5
+ "plu.v1.js": "plu.v1.cc853a2d.js",
6
+ "engine.v1.js": "engine.v1.19c589a2.js"
5
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ourlu/assistant-sdk",
3
- "version": "0.2.4",
3
+ "version": "0.2.6",
4
4
  "description": "SDK JavaScript pour l'assistant conversationnel Ourlu — widget intégrable pour les mairies.",
5
5
  "type": "module",
6
6
  "private": false,
@@ -10,6 +10,8 @@
10
10
  "./loader.v1.js": "./dist/iife/loader.v1.js",
11
11
  "./ui.v1.js": "./dist/iife/ui.v1.js",
12
12
  "./audio.v1.js": "./dist/iife/audio.v1.js",
13
+ "./signalement.v1.js": "./dist/iife/signalement.v1.js",
14
+ "./plu.v1.js": "./dist/iife/plu.v1.js",
13
15
  "./engine.v1.js": "./dist/iife/engine.v1.js"
14
16
  },
15
17
  "files": [