@jrapps/my_tickets_chat_ui 0.2.1 → 0.2.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.
@@ -69,7 +69,7 @@ var defaultTheme = {
69
69
  buttonRadius: 8,
70
70
  borderRadius: 12
71
71
  };
72
- function buildThemeVars(partial) {
72
+ function buildThemeVars(partial, width, height) {
73
73
  const theme = { ...defaultTheme, ...partial };
74
74
  return {
75
75
  // Colours
@@ -91,8 +91,8 @@ function buildThemeVars(partial) {
91
91
  "--cw-font-family": FONT_FAMILY,
92
92
  "--cw-font-size": FONT_SIZE,
93
93
  "--cw-shadow": SHADOW,
94
- "--cw-width": WIDTH,
95
- "--cw-height": HEIGHT,
94
+ "--cw-width": width !== void 0 ? typeof width === "number" ? `${width}px` : width : WIDTH,
95
+ "--cw-height": height !== void 0 ? typeof height === "number" ? `${height}px` : height : HEIGHT,
96
96
  "--cw-header-height": HEADER_HEIGHT
97
97
  };
98
98
  }
@@ -186,7 +186,7 @@ var import_react2 = require("react");
186
186
  if (typeof document !== "undefined" && !document.getElementById("jrapps-style-ebcf221d")) {
187
187
  const s = document.createElement("style");
188
188
  s.id = "jrapps-style-ebcf221d";
189
- s.textContent = ".cw-footer {\n display: flex;\n align-items: flex-end;\n gap: 8px;\n padding: 10px 12px;\n background-color: var(--cw-background);\n border-top: 1px solid var(--cw-border);\n flex-shrink: 0;\n}\n\n.cw-footer__input {\n flex: 1;\n resize: none;\n border: 1px solid var(--cw-input-border);\n border-radius: var(--cw-button-radius);\n background-color: var(--cw-input-background);\n font-family: var(--cw-font-family);\n font-size: var(--cw-font-size);\n color: inherit;\n padding: 8px 12px;\n line-height: 1.5;\n min-height: 38px;\n max-height: 120px;\n overflow-y: auto;\n transition: border-color 0.15s ease;\n}\n\n.cw-footer__input:focus {\n outline: none;\n border-color: var(--cw-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--cw-primary) 20%, transparent);\n}\n\n.cw-footer__input:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.cw-footer__attach-btn,\n.cw-footer__send-btn {\n background: none;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n transition: background-color 0.15s ease, color 0.15s ease;\n color: var(--cw-primary);\n margin-bottom: 1px;\n}\n\n.cw-footer__attach-btn:hover,\n.cw-footer__send-btn:not(.cw-footer__send-btn--disabled):hover {\n background-color: color-mix(in srgb, var(--cw-primary) 10%, transparent);\n}\n\n.cw-footer__attach-btn:focus-visible,\n.cw-footer__send-btn:focus-visible {\n outline: 2px solid var(--cw-primary);\n outline-offset: 2px;\n}\n\n.cw-footer__attach-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.cw-footer__send-btn--disabled {\n opacity: 0.35;\n cursor: not-allowed;\n}\n\n.cw-footer__file-input {\n display: none;\n}\n";
189
+ s.textContent = ".cw-footer {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 10px 12px;\n background-color: var(--cw-background);\n border-top: 1px solid var(--cw-border);\n flex-shrink: 0;\n}\n\n.cw-footer__controls {\n display: flex;\n align-items: flex-end;\n gap: 8px;\n}\n\n/* \u2500\u2500\u2500 Staged file chips \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.cw-footer__file-list {\n list-style: none;\n margin: 0;\n padding: 0;\n display: flex;\n flex-wrap: wrap;\n gap: 6px;\n}\n\n.cw-footer__file-chip {\n display: flex;\n align-items: center;\n gap: 4px;\n background-color: color-mix(in srgb, var(--cw-primary) 12%, transparent);\n border: 1px solid color-mix(in srgb, var(--cw-primary) 30%, transparent);\n border-radius: 999px;\n padding: 3px 8px 3px 10px;\n font-size: 12px;\n color: var(--cw-primary);\n max-width: 200px;\n}\n\n.cw-footer__file-chip-name {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.cw-footer__file-chip-remove {\n background: none;\n border: none;\n cursor: pointer;\n padding: 2px;\n display: flex;\n align-items: center;\n justify-content: center;\n color: inherit;\n border-radius: 50%;\n flex-shrink: 0;\n opacity: 0.7;\n transition: opacity 0.15s ease, background-color 0.15s ease;\n}\n\n.cw-footer__file-chip-remove:hover {\n opacity: 1;\n background-color: color-mix(in srgb, var(--cw-primary) 15%, transparent);\n}\n\n.cw-footer__file-chip-remove:focus-visible {\n outline: 2px solid var(--cw-primary);\n outline-offset: 1px;\n}\n\n.cw-footer__input {\n flex: 1;\n resize: none;\n border: 1px solid var(--cw-input-border);\n border-radius: var(--cw-button-radius);\n background-color: var(--cw-input-background);\n font-family: var(--cw-font-family);\n font-size: var(--cw-font-size);\n color: inherit;\n padding: 8px 12px;\n line-height: 1.5;\n min-height: 38px;\n max-height: 120px;\n overflow-y: auto;\n transition: border-color 0.15s ease;\n}\n\n.cw-footer__input:focus {\n outline: none;\n border-color: var(--cw-primary);\n box-shadow: 0 0 0 2px color-mix(in srgb, var(--cw-primary) 20%, transparent);\n}\n\n.cw-footer__input:disabled {\n opacity: 0.5;\n cursor: not-allowed;\n}\n\n.cw-footer__attach-btn,\n.cw-footer__send-btn {\n background: none;\n border: none;\n cursor: pointer;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 8px;\n border-radius: 50%;\n flex-shrink: 0;\n transition: background-color 0.15s ease, color 0.15s ease;\n color: var(--cw-primary);\n margin-bottom: 1px;\n}\n\n.cw-footer__attach-btn:hover,\n.cw-footer__send-btn:not(.cw-footer__send-btn--disabled):hover {\n background-color: color-mix(in srgb, var(--cw-primary) 10%, transparent);\n}\n\n.cw-footer__attach-btn:focus-visible,\n.cw-footer__send-btn:focus-visible {\n outline: 2px solid var(--cw-primary);\n outline-offset: 2px;\n}\n\n.cw-footer__attach-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.cw-footer__send-btn--disabled {\n opacity: 0.35;\n cursor: not-allowed;\n}\n\n.cw-footer__file-input {\n display: none;\n}\n";
190
190
  document.head.appendChild(s);
191
191
  }
192
192
 
@@ -194,34 +194,33 @@ if (typeof document !== "undefined" && !document.getElementById("jrapps-style-eb
194
194
  var import_jsx_runtime2 = require("react/jsx-runtime");
195
195
  var Footer = ({ onSend, onAttachment, disabled }) => {
196
196
  const [text, setText] = (0, import_react2.useState)("");
197
+ const [stagedFiles, setStagedFiles] = (0, import_react2.useState)([]);
197
198
  const fileInputRef = (0, import_react2.useRef)(null);
198
199
  const textareaRef = (0, import_react2.useRef)(null);
199
- const isEmpty = text.trim().length === 0;
200
- const handleKeyDown = (0, import_react2.useCallback)(
201
- (e) => {
202
- if (e.key === "Enter" && !e.shiftKey) {
203
- e.preventDefault();
204
- if (!isEmpty && !disabled) {
205
- onSend(text.trim());
206
- setText("");
207
- if (textareaRef.current) {
208
- textareaRef.current.style.height = "auto";
209
- }
210
- }
211
- }
212
- },
213
- [isEmpty, disabled, onSend, text]
214
- );
200
+ const isEmpty = text.trim().length === 0 && stagedFiles.length === 0;
215
201
  const handleSend = (0, import_react2.useCallback)(() => {
216
202
  if (!isEmpty && !disabled) {
217
- onSend(text.trim());
218
- setText("");
203
+ if (text.trim().length > 0) {
204
+ onSend(text.trim());
205
+ setText("");
206
+ }
207
+ stagedFiles.forEach((file) => onAttachment(file));
208
+ setStagedFiles([]);
219
209
  if (textareaRef.current) {
220
210
  textareaRef.current.style.height = "auto";
221
211
  textareaRef.current.focus();
222
212
  }
223
213
  }
224
- }, [isEmpty, disabled, onSend, text]);
214
+ }, [isEmpty, disabled, onSend, text, stagedFiles, onAttachment]);
215
+ const handleKeyDown = (0, import_react2.useCallback)(
216
+ (e) => {
217
+ if (e.key === "Enter" && !e.shiftKey) {
218
+ e.preventDefault();
219
+ handleSend();
220
+ }
221
+ },
222
+ [handleSend]
223
+ );
225
224
  const handleChange = (0, import_react2.useCallback)(
226
225
  (e) => {
227
226
  setText(e.target.value);
@@ -238,90 +237,109 @@ var Footer = ({ onSend, onAttachment, disabled }) => {
238
237
  const handleFileChange = (0, import_react2.useCallback)(
239
238
  (e) => {
240
239
  var _a;
241
- const file = (_a = e.target.files) == null ? void 0 : _a[0];
242
- if (file) {
243
- onAttachment(file);
240
+ const files = Array.from((_a = e.target.files) != null ? _a : []);
241
+ if (files.length > 0) {
242
+ setStagedFiles((prev) => [...prev, ...files]);
244
243
  }
245
244
  if (fileInputRef.current) {
246
245
  fileInputRef.current.value = "";
247
246
  }
248
247
  },
249
- [onAttachment]
248
+ []
250
249
  );
250
+ const handleRemoveStagedFile = (0, import_react2.useCallback)((index) => {
251
+ setStagedFiles((prev) => prev.filter((_, i) => i !== index));
252
+ }, []);
251
253
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("footer", { className: "cw-footer", role: "contentinfo", children: [
252
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
253
- "button",
254
- {
255
- className: "cw-footer__attach-btn",
256
- onClick: handleAttachmentClick,
257
- "aria-label": "Attach file",
258
- type: "button",
259
- disabled,
260
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
261
- "svg",
262
- {
263
- xmlns: "http://www.w3.org/2000/svg",
264
- width: "20",
265
- height: "20",
266
- viewBox: "0 0 24 24",
267
- fill: "none",
268
- stroke: "currentColor",
269
- strokeWidth: "2",
270
- strokeLinecap: "round",
271
- strokeLinejoin: "round",
272
- "aria-hidden": "true",
273
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" })
274
- }
275
- )
276
- }
277
- ),
278
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
279
- "textarea",
280
- {
281
- ref: textareaRef,
282
- className: "cw-footer__input",
283
- value: text,
284
- onChange: handleChange,
285
- onKeyDown: handleKeyDown,
286
- placeholder: "Type a message\u2026",
287
- "aria-label": "Message input",
288
- rows: 1,
289
- disabled
290
- }
291
- ),
292
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
293
- "button",
294
- {
295
- className: `cw-footer__send-btn${isEmpty || disabled ? " cw-footer__send-btn--disabled" : ""}`,
296
- onClick: handleSend,
297
- "aria-label": "Send message",
298
- type: "button",
299
- disabled: isEmpty || disabled,
300
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
301
- "svg",
302
- {
303
- xmlns: "http://www.w3.org/2000/svg",
304
- width: "20",
305
- height: "20",
306
- viewBox: "0 0 24 24",
307
- fill: "currentColor",
308
- "aria-hidden": "true",
309
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" })
310
- }
311
- )
312
- }
313
- ),
314
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
315
- "input",
316
- {
317
- ref: fileInputRef,
318
- type: "file",
319
- className: "cw-footer__file-input",
320
- onChange: handleFileChange,
321
- "aria-hidden": "true",
322
- tabIndex: -1
323
- }
324
- )
254
+ stagedFiles.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("ul", { className: "cw-footer__file-list", "aria-label": "Files to send", children: stagedFiles.map((file, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("li", { className: "cw-footer__file-chip", children: [
255
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "cw-footer__file-chip-name", title: file.name, children: file.name }),
256
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
257
+ "button",
258
+ {
259
+ className: "cw-footer__file-chip-remove",
260
+ onClick: () => handleRemoveStagedFile(i),
261
+ "aria-label": `Remove ${file.name}`,
262
+ type: "button",
263
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("svg", { xmlns: "http://www.w3.org/2000/svg", width: "12", height: "12", viewBox: "0 0 24 24", fill: "currentColor", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z" }) })
264
+ }
265
+ )
266
+ ] }, `${file.name}-${i}`)) }),
267
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "cw-footer__controls", children: [
268
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
269
+ "button",
270
+ {
271
+ className: "cw-footer__attach-btn",
272
+ onClick: handleAttachmentClick,
273
+ "aria-label": "Attach file",
274
+ type: "button",
275
+ disabled,
276
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
277
+ "svg",
278
+ {
279
+ xmlns: "http://www.w3.org/2000/svg",
280
+ width: "20",
281
+ height: "20",
282
+ viewBox: "0 0 24 24",
283
+ fill: "none",
284
+ stroke: "currentColor",
285
+ strokeWidth: "2",
286
+ strokeLinecap: "round",
287
+ strokeLinejoin: "round",
288
+ "aria-hidden": "true",
289
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" })
290
+ }
291
+ )
292
+ }
293
+ ),
294
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
295
+ "textarea",
296
+ {
297
+ ref: textareaRef,
298
+ className: "cw-footer__input",
299
+ value: text,
300
+ onChange: handleChange,
301
+ onKeyDown: handleKeyDown,
302
+ placeholder: "Type a message\u2026",
303
+ "aria-label": "Message input",
304
+ rows: 1,
305
+ disabled
306
+ }
307
+ ),
308
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
309
+ "button",
310
+ {
311
+ className: `cw-footer__send-btn${isEmpty || disabled ? " cw-footer__send-btn--disabled" : ""}`,
312
+ onClick: handleSend,
313
+ "aria-label": "Send message",
314
+ type: "button",
315
+ disabled: isEmpty || disabled,
316
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
317
+ "svg",
318
+ {
319
+ xmlns: "http://www.w3.org/2000/svg",
320
+ width: "20",
321
+ height: "20",
322
+ viewBox: "0 0 24 24",
323
+ fill: "currentColor",
324
+ "aria-hidden": "true",
325
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("path", { d: "M2.01 21L23 12 2.01 3 2 10l15 2-15 2z" })
326
+ }
327
+ )
328
+ }
329
+ ),
330
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
331
+ "input",
332
+ {
333
+ ref: fileInputRef,
334
+ type: "file",
335
+ className: "cw-footer__file-input",
336
+ onChange: handleFileChange,
337
+ "aria-hidden": "true",
338
+ tabIndex: -1,
339
+ multiple: true
340
+ }
341
+ )
342
+ ] })
325
343
  ] });
326
344
  };
327
345
  var Footer_default = Footer;
@@ -1204,7 +1222,7 @@ var SiteChatComponentNew = import_react5.default.forwardRef(({
1204
1222
  onClose
1205
1223
  }, ref) => {
1206
1224
  const { open, openWidget, closeWidget } = useSiteChatComponentNew(defaultOpen);
1207
- const themeVars = buildThemeVars(theme);
1225
+ const themeVars = buildThemeVars(theme, width, height);
1208
1226
  const handleClose = () => {
1209
1227
  closeWidget();
1210
1228
  onClose == null ? void 0 : onClose();
@@ -1240,7 +1258,6 @@ var SiteChatComponentNew = import_react5.default.forwardRef(({
1240
1258
  role: "dialog",
1241
1259
  "aria-modal": "true",
1242
1260
  "aria-label": `${title} chat widget`,
1243
- style: { ...width !== void 0 && { width }, ...height !== void 0 && { height } },
1244
1261
  children: [
1245
1262
  /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
1246
1263
  Header_default,