@subiz/widget-v4 4.1.210 → 4.1.212

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 (130) hide show
  1. package/README.md +21 -2
  2. package/assets/img/dot_chat.svg +3 -0
  3. package/assets/less/chatbox.less +9 -0
  4. package/assets/less/form.less +10 -0
  5. package/assets/less/message.less +114 -13
  6. package/assets/less/widget.less +15 -18
  7. package/compiled_src/call/css.js +1 -1
  8. package/compiled_src/chatbox/Buttons.js +7 -4
  9. package/compiled_src/chatbox/ChatButton.js +127 -29
  10. package/compiled_src/chatbox/Event.js +37 -5
  11. package/compiled_src/chatbox/Events.js +348 -129
  12. package/compiled_src/chatbox/FormAttachment.js +1 -1
  13. package/compiled_src/chatbox/Header.js +7 -2
  14. package/compiled_src/chatbox/InfoMessage.js +1 -1
  15. package/compiled_src/chatbox/MessageInput.js +24 -9
  16. package/compiled_src/chatbox/OrderAttachments.js +13 -13
  17. package/compiled_src/chatbox/QuoteMessage.js +3 -2
  18. package/compiled_src/chatbox/TextMessage.js +22 -18
  19. package/compiled_src/chatbox/Widget.js +200 -129
  20. package/compiled_src/chatbox/block.js +39 -29
  21. package/compiled_src/chatbox/conversation-history.js +44 -0
  22. package/compiled_src/chatbox/event-layout.js +59 -0
  23. package/compiled_src/chatbox/greeting.js +32 -0
  24. package/compiled_src/chatbox/main.js +3 -0
  25. package/compiled_src/common.js +13 -9
  26. package/compiled_src/form/css.js +1 -1
  27. package/compiled_src/lib.js +22 -32
  28. package/compiled_src/notif/css.js +1 -1
  29. package/compiled_src/plugin.js +11 -18
  30. package/compiled_src/popup/css.js +1 -1
  31. package/compiled_src/popup/popup.js +1 -1
  32. package/compiled_src/store/api.js +0 -2
  33. package/compiled_src/store/api_fake.js +1 -1
  34. package/compiled_src/store/attachments.js +28 -0
  35. package/compiled_src/store/chain.js +24 -10
  36. package/compiled_src/store/kv.js +9 -13
  37. package/compiled_src/store/lsdb.js +1 -1
  38. package/compiled_src/store/store.js +356 -117
  39. package/compiled_src/util/common.js +48 -41
  40. package/compiled_src/util/event.js +15 -0
  41. package/compiled_src/util/pubsub.js +28 -13
  42. package/compiled_src/util/url.js +18 -0
  43. package/dist/127.js +13 -13
  44. package/dist/132.js +1 -1
  45. package/dist/1a0f6f3ff1a.127.js +1 -0
  46. package/dist/{1a0d80f6e72.132.js → 1a0f6f3ff1a.132.js} +1 -1
  47. package/dist/{1a0d80f6e72.27.js → 1a0f6f3ff1a.27.js} +1 -1
  48. package/dist/1a0f6f3ff1a.278.js +1 -0
  49. package/dist/{1a0d80f6e72.339.js → 1a0f6f3ff1a.339.js} +1 -1
  50. package/dist/1a0f6f3ff1a.459.js +1 -0
  51. package/dist/1a0f6f3ff1a.app.js +1 -0
  52. package/dist/{1a0d80f6e72.chat.html → 1a0f6f3ff1a.chat.html} +1 -1
  53. package/dist/1a0f6f3ff1a.chat.js +1 -0
  54. package/dist/{1a0d80f6e72.form.html → 1a0f6f3ff1a.form.html} +1 -1
  55. package/dist/1a0f6f3ff1a.form.js +1 -0
  56. package/dist/{1a0d80f6e72.index.html → 1a0f6f3ff1a.index.html} +1 -1
  57. package/dist/{1a0d80f6e72.library.html → 1a0f6f3ff1a.library.html} +1 -1
  58. package/dist/1a0f6f3ff1a.library.js +1 -0
  59. package/dist/{1a0d80f6e72.preview.html → 1a0f6f3ff1a.preview.html} +1 -1
  60. package/dist/1a0f6f3ff1a.preview.js +1 -0
  61. package/dist/1a0f6f3ff1a.webview.js +1 -0
  62. package/dist/27.js +2 -2
  63. package/dist/459.js +2 -2
  64. package/dist/HASH +1 -1
  65. package/dist/assets/img/dot_chat.335fd8a.svg +3 -0
  66. package/dist/screenshoot.js +1523 -619
  67. package/package.json +12 -5
  68. package/src/chatbox/Buttons.js +5 -4
  69. package/src/chatbox/ChatButton.js +133 -39
  70. package/src/chatbox/Event.js +38 -5
  71. package/src/chatbox/Events.js +306 -134
  72. package/src/chatbox/FormAttachment.js +1 -1
  73. package/src/chatbox/Header.js +5 -4
  74. package/src/chatbox/InfoMessage.js +1 -1
  75. package/src/chatbox/MessageInput.js +15 -10
  76. package/src/chatbox/OrderAttachments.js +13 -13
  77. package/src/chatbox/QuoteMessage.js +3 -2
  78. package/src/chatbox/TextMessage.js +21 -20
  79. package/src/chatbox/Widget.js +150 -150
  80. package/src/chatbox/block.js +29 -27
  81. package/src/chatbox/conversation-history.js +37 -0
  82. package/src/chatbox/event-layout.js +72 -0
  83. package/src/chatbox/greeting.js +13 -0
  84. package/src/chatbox/main.js +3 -0
  85. package/src/common.js +15 -9
  86. package/src/lib.js +22 -35
  87. package/src/plugin.js +11 -13
  88. package/src/popup/popup.js +1 -1
  89. package/src/store/api.js +0 -2
  90. package/src/store/api_fake.js +1 -1
  91. package/src/store/attachments.js +21 -0
  92. package/src/store/chain.js +25 -12
  93. package/src/store/kv.js +10 -19
  94. package/src/store/lsdb.js +1 -1
  95. package/src/store/store.js +313 -130
  96. package/src/util/common.js +48 -43
  97. package/src/util/event.js +7 -0
  98. package/src/util/pubsub.js +27 -8
  99. package/src/util/url.js +14 -0
  100. package/test.cjs +59 -0
  101. package/assets/less/contact.less +0 -126
  102. package/compiled_src/util/common.test.js +0 -414
  103. package/compiled_src/util/event.test.js +0 -38
  104. package/compiled_src/util/extractor.test.js +0 -299
  105. package/compiled_src/util/extractor.test2.js +0 -61
  106. package/compiled_src/util/gate.test.js +0 -18
  107. package/compiled_src/util/pubsub.test.js +0 -35
  108. package/dist/1a0d80f6e72.127.js +0 -1
  109. package/dist/1a0d80f6e72.278.js +0 -1
  110. package/dist/1a0d80f6e72.459.js +0 -1
  111. package/dist/1a0d80f6e72.74.js +0 -1
  112. package/dist/1a0d80f6e72.997.js +0 -1
  113. package/dist/1a0d80f6e72.app.js +0 -1
  114. package/dist/1a0d80f6e72.chat.js +0 -1
  115. package/dist/1a0d80f6e72.form.js +0 -1
  116. package/dist/1a0d80f6e72.library.js +0 -1
  117. package/dist/1a0d80f6e72.preview.js +0 -1
  118. package/dist/1a0d80f6e72.webview.js +0 -1
  119. package/dist/74.js +0 -376
  120. package/dist/997.js +0 -37
  121. package/src/contact/contact.js +0 -400
  122. package/src/contact/css.js +0 -1
  123. package/src/util/common.test.js +0 -301
  124. package/src/util/event.test.js +0 -31
  125. package/src/util/extractor.test.js +0 -240
  126. package/src/util/extractor.test2.js +0 -56
  127. package/src/util/gate.test.js +0 -20
  128. package/src/util/pubsub.test.js +0 -37
  129. /package/dist/{1a0d80f6e72.185.js → 1a0f6f3ff1a.185.js} +0 -0
  130. /package/dist/{1a0d80f6e72.490.js → 1a0f6f3ff1a.490.js} +0 -0
package/README.md CHANGED
@@ -4,14 +4,33 @@
4
4
  $ npm run dev
5
5
  ```
6
6
 
7
- visit: http://localhost:8081/acqcsmrppbftadjzxnvo
7
+ visit: http://localhost:8082/?account_id=acqcsmrppbftadjzxnvo
8
8
 
9
9
  ### To test widget in injection mode
10
10
 
11
11
  ``` sh
12
12
  $ npm run dev
13
13
  ```
14
- visit: http://localhost:8081/inject.html?account_id=acqcsmrppbftadjzxnvo
14
+ visit: http://localhost:8082/inject.html?account_id=acqcsmrppbftadjzxnvo
15
+
16
+ ### Checks and release artifacts
17
+
18
+ Use Node.js 26 for development and tests.
19
+
20
+ ```sh
21
+ npm ci
22
+ npm run check
23
+ npm run build
24
+ ```
25
+
26
+ `check` runs the undefined-variable lint check and the tests against source
27
+ code in a DOM environment. Tests cover rendering, recalled messages, safe
28
+ URLs/HTML, upload failures, subscriptions, tickets and cache pagination.
29
+
30
+ `build` updates `compiled_src` before creating the browser bundles. `npm pack`
31
+ also runs the checks and regenerates the library through `prepack`, so the
32
+ published package includes the current source changes. Test files and the
33
+ test runner are excluded from the package.
15
34
 
16
35
 
17
36
  NOTE:
@@ -0,0 +1,3 @@
1
+ <svg width="44" height="44" viewBox="0 0 44 44" fill="none" xmlns="http://www.w3.org/2000/svg">
2
+ <path fill-rule="evenodd" clip-rule="evenodd" d="M22 0C9.84974 0 0 9.84974 0 22C0 34.1503 9.84974 44 22 44C34.1503 44 44 34.1503 44 22C44 9.84974 34.1503 0 22 0ZM16.4104 16.4102C16.6655 16.1402 16.9988 16 17.3333 16H26.6667C27.0012 16 27.3345 16.1402 27.5896 16.4102C27.8464 16.6822 28 17.0627 28 17.4706V24.0588C28 24.4667 27.8464 24.8472 27.5896 25.1192C27.3345 25.3892 27.0012 25.5294 26.6667 25.5294H22.7778C22.5879 25.5294 22.4019 25.5835 22.2415 25.6853L19.8889 27.18V26.5294C19.8889 25.9771 19.4412 25.5294 18.8889 25.5294H17.3333C16.9988 25.5294 16.6655 25.3892 16.4104 25.1192C16.1536 24.8472 16 24.4667 16 24.0588V17.4706C16 17.0627 16.1536 16.6822 16.4104 16.4102ZM17.3333 14C16.4302 14 15.5765 14.3804 14.9564 15.037C14.3381 15.6917 14 16.568 14 17.4706V24.0588C14 24.9614 14.3381 25.8377 14.9564 26.4924C15.5765 27.149 16.4302 27.5294 17.3333 27.5294H17.8889V29C17.8889 29.3648 18.0876 29.7007 18.4073 29.8764C18.7271 30.0521 19.1172 30.0397 19.4251 29.8441L23.0686 27.5294H26.6667C27.5698 27.5294 28.4235 27.149 29.0436 26.4924C29.6619 25.8377 30 24.9614 30 24.0588V17.4706C30 16.568 29.6619 15.6917 29.0436 15.037C28.4235 14.3804 27.5698 14 26.6667 14H17.3333Z" fill="#0047CC"/>
3
+ </svg>
@@ -109,6 +109,15 @@ body div#sbz92 {
109
109
  outline: none;
110
110
  }
111
111
 
112
+ button:focus-visible {
113
+ outline: 2px solid @gray-600;
114
+ outline-offset: 3px;
115
+ }
116
+
117
+ button:not(:disabled) {
118
+ cursor: pointer;
119
+ }
120
+
112
121
  img {
113
122
  overflow: hidden;
114
123
  flex-shrink: 0;
@@ -43,6 +43,8 @@ input.form-control[disabled] {
43
43
  }
44
44
 
45
45
  input[type='text'].form-control.input--error,
46
+ input[type='tel'].form-control.input--error,
47
+ input[type='email'].form-control.input--error,
46
48
  input[type='number'].form-control.input--error,
47
49
  input[type='date'].form-control.input--error,
48
50
  textarea.form-control.input--error,
@@ -52,6 +54,8 @@ select.form-control.input--error {
52
54
  }
53
55
 
54
56
  input[type='text'].form-control,
57
+ input[type='tel'].form-control,
58
+ input[type='email'].form-control,
55
59
  input[type='number'].form-control,
56
60
  input[type='date'].form-control,
57
61
  textarea.form-control,
@@ -87,6 +91,8 @@ input[type='date'].form-control {
87
91
  }
88
92
 
89
93
  input[type='text'].form-control:focus,
94
+ input[type='tel'].form-control:focus,
95
+ input[type='email'].form-control:focus,
90
96
  input[type='number'].form-control:focus,
91
97
  input[type='date'].form-control:focus,
92
98
  textarea.form-control:focus,
@@ -95,6 +101,8 @@ select.form-control:focus {
95
101
  }
96
102
 
97
103
  input[type='text'].form-control.input--error:focus,
104
+ input[type='tel'].form-control.input--error:focus,
105
+ input[type='email'].form-control.input--error:focus,
98
106
  input[type='number'].form-control.input--error:focus,
99
107
  input[type='date'].form-control.input--error:focus,
100
108
  textarea.form-control.input--error:focus,
@@ -462,6 +470,8 @@ select {
462
470
  box-shadow: 0 0 0 1px #eeeeee;
463
471
 
464
472
  input[type='text'].form-control,
473
+ input[type='tel'].form-control,
474
+ input[type='email'].form-control,
465
475
  input[type='number'].form-control,
466
476
  input[type='date'].form-control,
467
477
  select.form-control,
@@ -1,3 +1,47 @@
1
+ .conversation-history-error {
2
+ display: flex;
3
+ align-items: center;
4
+ gap: 8px;
5
+ margin: 8px 0 16px;
6
+ padding: 8px 10px;
7
+ border-radius: 10px;
8
+ background: #f5f6f8;
9
+ color: #737782;
10
+ font-size: 12px;
11
+ line-height: 18px;
12
+ text-align: left;
13
+ }
14
+
15
+ .conversation-history-error__text {
16
+ flex: 1;
17
+ min-width: 0;
18
+ }
19
+
20
+ .conversation-history-error__retry {
21
+ position: relative;
22
+ flex-shrink: 0;
23
+ border: 0;
24
+ border-radius: 6px;
25
+ padding: 5px 8px;
26
+ background: transparent;
27
+ color: #545866;
28
+ font-size: 12px;
29
+ font-weight: 600;
30
+ line-height: 18px;
31
+ cursor: pointer;
32
+ &:hover:not(:disabled) { background: #e8eaf0; }
33
+ &:disabled { cursor: wait; }
34
+ &:focus-visible { outline: 2px solid #737782; outline-offset: 2px; }
35
+ }
36
+
37
+ .conversation-history-error__spinner {
38
+ position: absolute;
39
+ inset: 0;
40
+ display: flex;
41
+ align-items: center;
42
+ justify-content: center;
43
+ }
44
+
1
45
  .widget-body--events-container {
2
46
  overflow-x: hidden;
3
47
  overflow-y: auto;
@@ -127,7 +171,7 @@
127
171
  background-color: @red;
128
172
  }
129
173
 
130
- .message-text--agent.message-text--deleted {
174
+ .message-text--deleted {
131
175
  opacity: 0.7;
132
176
  font-style: italic;
133
177
  }
@@ -147,14 +191,28 @@
147
191
  }
148
192
 
149
193
  .message-block-pre {
194
+ display: block;
195
+ min-width: 0;
150
196
  max-width: 100%;
151
- margin: 0;
152
- overflow-x: auto;
153
- white-space: pre;
197
+ margin: 4px 0;
198
+ padding: 10px 12px;
199
+ border: 1px solid rgba(0, 0, 0, 0.06);
200
+ border-radius: 8px;
201
+ background: rgba(0, 0, 0, 0.03);
202
+ white-space: pre-wrap;
203
+ overflow-wrap: anywhere;
204
+ word-break: normal;
154
205
  }
155
206
 
156
- .message-block-code {
157
- font-family: monospace;
207
+ .message-block-code,
208
+ .message-block-code * {
209
+ font-family: 'SFMono-Regular', Consolas, 'Liberation Mono', Menlo, monospace;
210
+ font-size: 13px;
211
+ line-height: 20px;
212
+ }
213
+
214
+ .message-block-pre .message-block-code {
215
+ display: block;
158
216
  }
159
217
 
160
218
  .message-user__container {
@@ -274,6 +332,54 @@ a.message_error {
274
332
  margin: 10px;
275
333
  }
276
334
 
335
+ .info-message--ended {
336
+ padding-top: 16px;
337
+ }
338
+
339
+ .conversation-event {
340
+ display: block;
341
+ min-width: 0;
342
+ border: 0;
343
+ padding: 0;
344
+ margin: 0;
345
+ }
346
+
347
+ .conversation-history-start {
348
+ display: block;
349
+ height: 1px;
350
+ flex-shrink: 0;
351
+ }
352
+
353
+ .message-user__container--send {
354
+ // Transitions can interpolate the !important styles used by the widget reset.
355
+ transition: transform 260ms cubic-bezier(0.25, 0.46, 0.45, 0.94);
356
+ transform: translate3d(0, 0, 0);
357
+ }
358
+
359
+ .message-user__container--send.message-user__container--enter {
360
+ transform: translate3d(0, 14px, 0);
361
+ }
362
+
363
+ @media (prefers-reduced-motion: reduce) {
364
+ .message-user__container--send {
365
+ transition: none !important;
366
+ }
367
+ .message-user__container--send.message-user__container--enter {
368
+ transform: none !important;
369
+ }
370
+ }
371
+
372
+ .conversation-event--history {
373
+ filter: grayscale(0.8);
374
+ }
375
+
376
+ .conversation-event--history + .conversation-event:not(.conversation-event--history)::before {
377
+ content: '';
378
+ display: block;
379
+ border-top: 2px solid @primary-color-faded;
380
+ margin: 60px 40px;
381
+ }
382
+
277
383
  .message-sender {
278
384
  margin-top: 10px;
279
385
  }
@@ -528,20 +634,15 @@ a.message_error {
528
634
  object-fit: cover;
529
635
  }
530
636
 
531
- .url-button-attachment:first-child {
532
- border-radius: 0;
533
- }
534
- .url-button-attachment:last-child {
535
- }
536
-
537
637
  .url-button-attachment {
538
638
  padding: 10px;
539
639
  display: block;
540
640
  padding-top: 9px;
541
- padding-button: 9px;
641
+ padding-bottom: 9px;
542
642
  text-align: center;
543
643
  border: none;
544
644
  border-top: 1px solid #d8d8d8;
645
+ border-radius: 0;
545
646
  width: 100%;
546
647
  .color(@link);
547
648
  &:hover {
@@ -139,15 +139,6 @@
139
139
  text-align: center;
140
140
  }
141
141
 
142
- .widget-body--empty-icon {
143
- width: 128px;
144
- height: 128px;
145
- .inline-svg-code(~'<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><g data-name="Layer 2"><path d="M130.9 366.9a9.9 9.9 0 0 0-2.9 7.1 10.33 10.33 0 0 0 2.9 7.1 9.73 9.73 0 0 0 7.1 2.9 10.33 10.33 0 0 0 7.1-2.9 9.73 9.73 0 0 0 2.9-7.1 10.52 10.52 0 0 0-2.9-7.1 9.9 9.9 0 0 0-7.1-2.9 10.33 10.33 0 0 0-7.1 2.9zM483.7 282a183.07 183.07 0 0 0 28.3-98C512 82.5 429.5 0 328 0a183.16 183.16 0 0 0-96 27 10 10 0 0 0 10.5 17.1A162.67 162.67 0 0 1 328 20c90.4 0 164 73.6 164 164a162.73 162.73 0 0 1-27.9 91.5 10.07 10.07 0 0 0 .3 11.6l11 40.9-44-11.8a10 10 0 0 0-8.4 1.5 164.32 164.32 0 0 1-151.8 20.2 138.68 138.68 0 0 0-97.1-97.1 164.31 164.31 0 0 1 14.5-143.2 10 10 0 0 0-17-10.6 184 184 0 0 0-19.9 149.6c-4.5-.4-9.1-.7-13.7-.7C61.9 236 0 297.9 0 374a136.88 136.88 0 0 0 22.9 76.1L12.2 490a10 10 0 0 0 12.3 12.3l40.9-11a137.71 137.71 0 0 0 146.5-.8 10 10 0 0 0-10.7-16.9 118.09 118.09 0 0 1-128.6-1.5 9.73 9.73 0 0 0-8.1-1.3L36 478.5l7.4-27.7a10 10 0 0 0-1.5-8.4 117.95 117.95 0 1 1 207-28 10 10 0 0 0 18.8 6.8 137.72 137.72 0 0 0 8.3-47.3 124.44 124.44 0 0 0-.7-13.7 183.93 183.93 0 0 0 155.3-23.6l56.2 15.1a10 10 0 0 0 12.3-12.3zm-246 162.2a10.52 10.52 0 0 0-7.1 2.9 9.73 9.73 0 0 0-2.9 7.1 10.33 10.33 0 0 0 2.9 7.1 9.73 9.73 0 0 0 7.1 2.9 10.52 10.52 0 0 0 7.1-2.9 9.73 9.73 0 0 0 2.9-7.1 9.9 9.9 0 0 0-10-10zM205.3 70.7a10.52 10.52 0 0 0 7.1-2.9 9.73 9.73 0 0 0 2.9-7.1 10.14 10.14 0 0 0-2.9-7.1 9.9 9.9 0 0 0-7.1-2.9 10.52 10.52 0 0 0-7.1 2.9 9.9 9.9 0 0 0-2.9 7.1 10.52 10.52 0 0 0 2.9 7.1 9.9 9.9 0 0 0 7.1 2.9zm-19.4 296.2a9.9 9.9 0 0 0-2.9 7.1 10.33 10.33 0 0 0 2.9 7.1 9.73 9.73 0 0 0 7.1 2.9 10.33 10.33 0 0 0 7.1-2.9 9.73 9.73 0 0 0 2.9-7.1 10.33 10.33 0 0 0-2.9-7.1 9.9 9.9 0 0 0-7.1-2.9 10.33 10.33 0 0 0-7.1 2.9zm210.8-201.1a9.8 9.8 0 0 0 5.2-1.5l1.3-.8a9.92 9.92 0 0 0 3.3-13.7 10.06 10.06 0 0 0-13.8-3.3l-1.3.8a10 10 0 0 0 5.3 18.5zm-68.1 107.4a58 58 0 0 0 57.9-57.9 7 7 0 0 0-7-7H277.7a7 7 0 0 0-7 7 58 58 0 0 0 57.9 57.9zm-43.5-50.9h87.1l-1 3.7a43.93 43.93 0 0 1-85.2 0zm-25.8-56.5a9.8 9.8 0 0 0 5.2-1.5l1.3-.8a9.92 9.92 0 0 0 3.3-13.7 10.06 10.06 0 0 0-13.8-3.3l-1.3.8a10 10 0 0 0 5.3 18.5zM75.9 366.9A9.9 9.9 0 0 0 73 374a10.33 10.33 0 0 0 2.9 7.1A9.73 9.73 0 0 0 83 384a10.33 10.33 0 0 0 7.1-2.9A9.73 9.73 0 0 0 93 374a10.33 10.33 0 0 0-2.9-7.1A9.9 9.9 0 0 0 83 364a10.33 10.33 0 0 0-7.1 2.9z" fill="#4285f4" data-name="Capa 1"/></g></svg>'
146
- );
147
- -webkit-mask-image: @-inline-svg-url;
148
- border-radius: 0;
149
- background-color: @primary-color;
150
- }
151
142
 
152
143
  .mobile {
153
144
  .widget-container {
@@ -416,21 +407,28 @@
416
407
  .chat-button {
417
408
  cursor: pointer;
418
409
  position: relative;
419
- scale: 1;
410
+ transform: scale(1);
420
411
  transition:
421
- filter 250ms ease,
422
- opacity 0.15s ease-in,
423
- scale 0.125s ease-in-out,
424
- transform 0.2s ease-in-out;
412
+ opacity 200ms ease-in,
413
+ transform 250ms cubic-bezier(0.34, 1.5, 0.64, 1);
425
414
 
426
415
  &.hidden {
416
+ visibility: hidden;
427
417
  opacity: 0;
418
+ transform: scale(0.2);
419
+ pointer-events: none;
428
420
  }
429
421
  }
430
422
 
431
- .chat-button:hover {
423
+ @media (prefers-reduced-motion: reduce) {
424
+ .chat-button {
425
+ transition: none !important;
426
+ }
427
+ }
428
+
429
+ .chat-button:not(.hidden):hover {
432
430
  filter: brightness(1.1);
433
- scale: 1.05;
431
+ transform: scale(1.05);
434
432
  }
435
433
 
436
434
  .chat-button--img {
@@ -729,13 +727,12 @@
729
727
  z-index: @z-index-3;
730
728
  background: @white;
731
729
  box-shadow: 0px 5px 30px rgba(0, 0, 0, 0.15);
732
- border: 1px solid @border;
733
730
  border-radius: 15px;
734
731
  max-width: 100%;
735
732
  min-width: 210px;
736
733
  margin-bottom: 15px;
737
734
  padding: 15px 20px;
738
- positive: relative;
735
+ position: relative;
739
736
  cursor: pointer;
740
737
 
741
738
  &.right {
@@ -4,4 +4,4 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
- var _default = exports.default = require('css-loader!less-loader!../../assets/less/notif.less');
7
+ var _default = exports.default = require('css-loader?import=false!less-loader!../../assets/less/notif.less');
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", {
6
6
  exports.default = Buttons;
7
7
  var _index = _interopRequireDefault(require("../util/index.js"));
8
8
  var _preact = require("preact");
9
+ var _url = require("../util/url.js");
9
10
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
10
11
  function Buttons(props) {
11
12
  if (_index.default.size(props.buttons) === 0) return null;
@@ -13,7 +14,7 @@ function Buttons(props) {
13
14
  if (button.type === 'call_button') {
14
15
  return (0, _preact.h)("a", {
15
16
  class: "url-button-attachment",
16
- href: 'tel:' + button.phone_number,
17
+ href: (0, _url.safeUrl)('tel:' + button.phone_number),
17
18
  key: index,
18
19
  title: button.title
19
20
  }, props.t.i18n(button.i18n_title) || props.t.i18n(button.old_i18n_title) || button.title || `${props.t('call')} ${button.phone_number}`);
@@ -21,16 +22,18 @@ function Buttons(props) {
21
22
  if (button.type === 'url_button') {
22
23
  return (0, _preact.h)("a", {
23
24
  class: "url-button-attachment",
24
- href: button.url,
25
+ href: (0, _url.safeUrl)(button.url) || undefined,
25
26
  target: "_blank",
27
+ rel: "noopener noreferrer",
26
28
  key: index,
27
29
  title: button.title
28
30
  }, props.t.i18n(button.i18n_title) || props.t.i18n(button.old_i18n_title) || button.title || button.url);
29
31
  }
30
32
  if (button.type === 'postback_button') {
31
- return (0, _preact.h)("a", {
33
+ return (0, _preact.h)("button", {
34
+ type: "button",
32
35
  class: "url-button-attachment",
33
- href: "javascript:;",
36
+ key: index,
34
37
  onClick: _ => props.onSelect(button)
35
38
  }, props.t.i18n(button.i18n_title) || button.title);
36
39
  }
@@ -11,6 +11,7 @@ var _block = _interopRequireDefault(require("./block.js"));
11
11
  var _preact = require("preact");
12
12
  function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
13
13
  var defaultBubble = require('../../assets/img/bubble_default.svg');
14
+ const dotChatIcon = require('../../assets/img/dot_chat.svg');
14
15
  let defaultAvatar = require('../../assets/img/default_avatar.png');
15
16
  class ChatButton extends _common.Com {
16
17
  constructor(props) {
@@ -345,22 +346,7 @@ class ChatButton extends _common.Com {
345
346
  }, reply.title);
346
347
  })));
347
348
  }
348
- async prepareButtonImage() {
349
- let accountSetting = this.props.plugin.chatbox;
350
- accountSetting = this.fixMissingSetting(accountSetting);
351
- let imgsrc = _index.default.get(accountSetting, 'desktop_button.background_image_url') || _index.default.get(accountSetting, 'desktop_button.background_mask_url') || defaultBubble;
352
- if (this.props.store.isMobile()) {
353
- imgsrc = _index.default.get(accountSetting, 'mobile_button.background_image_url') || _index.default.get(accountSetting, 'mobile_button.background_mask_url') || imgsrc;
354
- }
355
- imgsrc = this.props.store.replaceFileUrl(imgsrc);
356
- await _index.default.preloadImg(imgsrc);
357
- this.setState({
358
- ready: true
359
- });
360
- this.readyGate.open();
361
- }
362
- renderButton() {
363
- if (typeof sbz_info != 'undefined') sbz_info.render_chatbox_button = _index.default.Date.now();
349
+ getButtonAppearance() {
364
350
  let accountSetting = this.props.plugin.chatbox;
365
351
  accountSetting = this.fixMissingSetting(accountSetting);
366
352
  let imgsrc = _index.default.get(accountSetting, 'desktop_button.background_image_url') || _index.default.get(accountSetting, 'desktop_button.background_mask_url') || defaultBubble;
@@ -382,22 +368,93 @@ class ChatButton extends _common.Com {
382
368
  maskurl = mobilemaskurl;
383
369
  }
384
370
  }
371
+ const imageUrl = url => {
372
+ const asset = normalizeButtonImageUrl(this.props.store.replaceFileUrl(url));
373
+ return asset === dotChatIcon ? asset : addVersionParam(asset);
374
+ };
375
+ imgsrc = imageUrl(imgsrc);
376
+ imgurl = imageUrl(imgurl);
377
+ maskurl = imageUrl(maskurl);
378
+ const defaultMask = !imgurl && !maskurl ? DEF_BG_URL : '';
379
+ const urls = [...new Set([imgsrc, imgurl && encodeURI(imgurl), maskurl && encodeURI(maskurl), defaultMask].filter(Boolean))];
380
+ return {
381
+ imgsrc,
382
+ imgurl,
383
+ maskurl,
384
+ background,
385
+ position,
386
+ imgwidth,
387
+ imgheight,
388
+ urls,
389
+ maskAsset: maskurl ? encodeURI(maskurl) : defaultMask,
390
+ key: JSON.stringify([urls, maskurl, defaultMask])
391
+ };
392
+ }
393
+ componentDidUpdate() {
394
+ if (this.getButtonAppearance().key !== this._buttonImageKey) this.prepareButtonImage();
395
+ }
396
+ async prepareButtonImage() {
397
+ const appearance = this.getButtonAppearance();
398
+ const version = this._buttonImageVersion = (this._buttonImageVersion || 0) + 1;
399
+ this._buttonImageKey = appearance.key;
400
+ this.readyGate.close();
401
+ const [loaded, mask] = await Promise.all([Promise.all(appearance.urls.filter(url => url !== appearance.maskAsset).map(url => preloadButtonImage(url))), appearance.maskAsset ? prepareButtonMask(appearance.maskAsset) : Promise.resolve(null)]);
402
+ const stale = () => !this._isMounted || this._buttonImageVersion !== version;
403
+ if (stale()) {
404
+ if (mask) URL.revokeObjectURL(mask);
405
+ return;
406
+ }
407
+ const fallback = loaded.some(success => !success) || !!appearance.maskAsset && !mask;
408
+ const ready = !fallback || (await preloadButtonImage(defaultBubble));
409
+ if (stale()) {
410
+ if (mask) URL.revokeObjectURL(mask);
411
+ return;
412
+ }
413
+ if (this._buttonMaskUrl) URL.revokeObjectURL(this._buttonMaskUrl);
414
+ this._buttonMaskUrl = mask;
415
+ if (this._buttonElement) window.getComputedStyle(this._buttonElement).transform;
416
+ this.setState({
417
+ ready,
418
+ readyImageKey: appearance.key,
419
+ fallbackButtonImage: fallback,
420
+ buttonMaskUrl: mask
421
+ });
422
+ this.readyGate.open();
423
+ }
424
+ componentWillUnmount() {
425
+ if (this._buttonMaskUrl) URL.revokeObjectURL(this._buttonMaskUrl);
426
+ if (this._animateTimeout) clearTimeout(this._animateTimeout);
427
+ }
428
+ renderButton() {
429
+ if (typeof sbz_info != 'undefined') sbz_info.render_chatbox_button = _index.default.Date.now();
430
+ const appearance = this.getButtonAppearance();
431
+ let {
432
+ imgsrc,
433
+ imgurl,
434
+ maskurl,
435
+ background,
436
+ position,
437
+ imgwidth,
438
+ imgheight
439
+ } = appearance;
440
+ if (appearance.maskAsset) {
441
+ maskurl = this.state.readyImageKey === appearance.key ? this.state.buttonMaskUrl : '';
442
+ if (imgsrc === appearance.maskAsset) imgsrc = maskurl || '';
443
+ }
444
+ if (this.state.readyImageKey === appearance.key && this.state.fallbackButtonImage) {
445
+ imgsrc = imgurl = defaultBubble;
446
+ maskurl = '';
447
+ }
385
448
  let whitebgcls = 'chat-button--white-bg';
386
449
  if (!imgurl && maskurl) whitebgcls += ' chat-button--white-bg--mask-only';
387
450
  let imgcontainerstyle = '';
388
- imgurl = this.props.store.replaceFileUrl(imgurl);
389
- imgsrc = this.props.store.replaceFileUrl(imgsrc);
390
- maskurl = this.props.store.replaceFileUrl(maskurl);
391
- imgurl = addVersionParam(imgurl);
392
- imgsrc = addVersionParam(imgsrc);
393
- maskurl = addVersionParam(maskurl);
394
451
  if (!imgurl && !maskurl) {
395
452
  whitebgcls += ' chat-button--white-bg--mask-only';
396
453
  imgcontainerstyle = `
397
- -webkit-mask-image: url("${encodeURI(DEF_BG_URL)}") !important;
398
- -o-mask-image: url("${encodeURI(DEF_BG_URL)}") !important;
399
- -moz-mask-image: url("${encodeURI(DEF_BG_URL)}") !important;
400
- mask-image: url("${encodeURI(DEF_BG_URL)}") !important;
454
+ -webkit-mask-image: none !important;
455
+ -o-mask-image: none !important;
456
+ -moz-mask-image: none !important;
457
+ mask-image: none !important;
401
458
  height: ${imgheight}px !important;
402
459
  width: ${imgwidth}px !important;
403
460
  background: ${background} !important;
@@ -450,9 +507,15 @@ class ChatButton extends _common.Com {
450
507
  height: ${imgheight - 4}px !important;
451
508
 
452
509
  `;
453
- if (!this.state.ready) cls += ' hidden';
454
- return (0, _preact.h)("div", {
510
+ if (!this.state.ready || this.state.readyImageKey !== appearance.key) cls += ' hidden';
511
+ return (0, _preact.h)("button", {
512
+ ref: element => {
513
+ this._buttonElement = element;
514
+ },
515
+ type: "button",
455
516
  class: cls,
517
+ "aria-label": this.props.t('chat'),
518
+ "aria-expanded": !this.props.isShow,
456
519
  onClick: e => this.onClick(e)
457
520
  }, (0, _preact.h)("div", {
458
521
  class: whitebgcls,
@@ -492,7 +555,9 @@ class ChatButton extends _common.Com {
492
555
  return defmsg;
493
556
  }
494
557
  return (0, _preact.h)(_block.default, {
495
- block: block
558
+ block: block,
559
+ store: this.props.store,
560
+ t: this.props.t
496
561
  });
497
562
  }
498
563
  let message = _index.default.get(ev, 'data.message.text', defmsg);
@@ -521,6 +586,10 @@ function randomAgent(agentM) {
521
586
  return agents[Math.floor(Math.random() * _index.default.size(agents))] || {};
522
587
  }
523
588
  const Ms30Mins = 30 * 60 * 1000;
589
+ function normalizeButtonImageUrl(url) {
590
+ if (/^https:\/\/(?:storage\.googleapis\.com\/public-gcs\.subiz-cdn\.com|public-gcs\.subiz-cdn\.com|vcdn\.subiz-cdn\.com)\/dashboard-v4\/public\/img\/bubble\/dot_chat\.svg(?=$|[?#])/.test(url)) return dotChatIcon;
591
+ return url;
592
+ }
524
593
  const DEF_BG_URL = 'https://vcdn.subiz-cdn.com/file/bubble_11.svg?v=5';
525
594
  const DEF_BG = 'linear-gradient(280.16deg, #0053d3 22.03%, #0265ff 78.2%)';
526
595
  function addVersionParam(url, version = 8) {
@@ -535,4 +604,33 @@ function addVersionParam(url, version = 8) {
535
604
  const newUrl = base + (hasQuery ? '&' : '?') + `v=${version}`;
536
605
  return hash ? newUrl + '#' + hash : newUrl;
537
606
  }
607
+ }
608
+ function preloadButtonImage(src, {
609
+ crossOrigin = false
610
+ } = {}) {
611
+ return new Promise(resolve => {
612
+ const image = new Image();
613
+ if (crossOrigin) image.crossOrigin = 'anonymous';
614
+ image.onerror = () => resolve(false);
615
+ image.onload = async () => {
616
+ try {
617
+ if (image.decode) await image.decode();
618
+ resolve(true);
619
+ } catch (_) {
620
+ resolve(false);
621
+ }
622
+ };
623
+ image.src = src;
624
+ });
625
+ }
626
+ async function prepareButtonMask(src) {
627
+ let url;
628
+ try {
629
+ const response = await fetch(src);
630
+ if (!response.ok) return null;
631
+ url = URL.createObjectURL(await response.blob());
632
+ if (await preloadButtonImage(url)) return url;
633
+ } catch (_) {}
634
+ if (url) URL.revokeObjectURL(url);
635
+ return null;
538
636
  }