@nuraly/lumenui 0.3.5 → 0.3.7

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 (86) hide show
  1. package/dist/nuralyui.bundle.js +2577 -1486
  2. package/dist/nuralyui.bundle.js.gz +0 -0
  3. package/dist/src/components/button/bundle.js +130 -39
  4. package/dist/src/components/button/bundle.js.gz +0 -0
  5. package/dist/src/components/button/button.component.js +7 -4
  6. package/dist/src/components/button/button.style.js +92 -2
  7. package/dist/src/components/canvas/base-canvas.component.d.ts +8 -0
  8. package/dist/src/components/canvas/base-canvas.component.js +75 -3
  9. package/dist/src/components/canvas/bundle.js +2540 -1201
  10. package/dist/src/components/canvas/bundle.js.gz +0 -0
  11. package/dist/src/components/canvas/controllers/collaboration.controller.d.ts +24 -11
  12. package/dist/src/components/canvas/controllers/collaboration.controller.js +176 -120
  13. package/dist/src/components/canvas/controllers/selection.controller.js +20 -0
  14. package/dist/src/components/canvas/interfaces/collaboration.interface.d.ts +8 -0
  15. package/dist/src/components/canvas/templates/index.d.ts +1 -0
  16. package/dist/src/components/canvas/templates/index.js +2 -0
  17. package/dist/src/components/canvas/templates/lock-overlay.template.d.ts +20 -0
  18. package/dist/src/components/canvas/templates/lock-overlay.template.js +33 -0
  19. package/dist/src/components/canvas/workflow-canvas.component.js +52 -24
  20. package/dist/src/components/canvas/workflow-canvas.style.js +62 -1
  21. package/dist/src/components/canvas/workflow-canvas.types.js +50 -4
  22. package/dist/src/components/chat-panel/bundle.js +10 -10
  23. package/dist/src/components/chat-panel/bundle.js.gz +0 -0
  24. package/dist/src/components/chat-panel/chat-panel.component.js +8 -8
  25. package/dist/src/components/chatbot/bundle.js +400 -242
  26. package/dist/src/components/chatbot/bundle.js.gz +0 -0
  27. package/dist/src/components/chatbot/chatbot.style.js +156 -22
  28. package/dist/src/components/chatbot/chatbot.types.d.ts +1 -0
  29. package/dist/src/components/chatbot/core/chatbot-core.controller.js +13 -7
  30. package/dist/src/components/chatbot/plugins/artifact-plugin.js +0 -19
  31. package/dist/src/components/chatbot/plugins/flight-card-plugin.js +0 -35
  32. package/dist/src/components/chatbot/plugins/markdown-plugin.js +0 -4
  33. package/dist/src/components/chatbot/plugins/print-job-card-plugin.js +0 -36
  34. package/dist/src/components/chatbot/plugins/selection-card-plugin.js +0 -34
  35. package/dist/src/components/chatbot/providers/workflow-socket-provider.js +1 -2
  36. package/dist/src/components/chatbot/templates/input-box.template.js +58 -30
  37. package/dist/src/components/chatbot/templates/message.template.js +41 -31
  38. package/dist/src/components/chatbot/templates/thread-sidebar.template.js +38 -39
  39. package/dist/src/components/colorpicker/bundle.js +15 -10
  40. package/dist/src/components/colorpicker/bundle.js.gz +0 -0
  41. package/dist/src/components/colorpicker/color-picker.component.js +15 -10
  42. package/dist/src/components/datepicker/bundle.js +10 -10
  43. package/dist/src/components/datepicker/bundle.js.gz +0 -0
  44. package/dist/src/components/datepicker/datepicker.component.js +14 -22
  45. package/dist/src/components/dropdown/bundle.js +15 -14
  46. package/dist/src/components/dropdown/bundle.js.gz +0 -0
  47. package/dist/src/components/dropdown/dropdown.component.js +10 -9
  48. package/dist/src/components/dropdown/dropdown.style.js +2 -2
  49. package/dist/src/components/file-upload/bundle.js +15 -14
  50. package/dist/src/components/file-upload/bundle.js.gz +0 -0
  51. package/dist/src/components/file-upload/file-upload.component.js +15 -14
  52. package/dist/src/components/icon/bundle.js +7 -7
  53. package/dist/src/components/icon/bundle.js.gz +0 -0
  54. package/dist/src/components/icon/icon-paths.js +15 -0
  55. package/dist/src/components/iconpicker/bundle.js +216 -124
  56. package/dist/src/components/iconpicker/bundle.js.gz +0 -0
  57. package/dist/src/components/iconpicker/icon-picker.component.js +4 -4
  58. package/dist/src/components/menu/bundle.js +5 -2
  59. package/dist/src/components/menu/bundle.js.gz +0 -0
  60. package/dist/src/components/menu/menu.component.js +5 -2
  61. package/dist/src/components/modal/bundle.js +16 -13
  62. package/dist/src/components/modal/bundle.js.gz +0 -0
  63. package/dist/src/components/modal/modal.component.js +16 -13
  64. package/dist/src/components/panel/bundle.js +28 -28
  65. package/dist/src/components/panel/bundle.js.gz +0 -0
  66. package/dist/src/components/popconfirm/bundle.js +135 -41
  67. package/dist/src/components/popconfirm/bundle.js.gz +0 -0
  68. package/dist/src/components/popconfirm/popconfirm.component.d.ts +15 -119
  69. package/dist/src/components/popconfirm/popconfirm.component.js +158 -162
  70. package/dist/src/components/popconfirm/popconfirm.style.js +94 -0
  71. package/dist/src/components/presence/bundle.js +2 -1
  72. package/dist/src/components/presence/bundle.js.gz +0 -0
  73. package/dist/src/components/presence/presence.component.js +2 -1
  74. package/dist/src/components/table/bundle.js +3 -2
  75. package/dist/src/components/table/bundle.js.gz +0 -0
  76. package/dist/src/components/table/table.component.js +3 -2
  77. package/dist/src/components/tabs/bundle.js +3 -3
  78. package/dist/src/components/tabs/bundle.js.gz +0 -0
  79. package/dist/src/components/timepicker/bundle.js +3 -3
  80. package/dist/src/components/timepicker/bundle.js.gz +0 -0
  81. package/package.json +1 -1
  82. package/packages/common/dist/VERSIONS.md +1 -1
  83. package/packages/common/dist/shared/controllers/dropdown.controller.d.ts +4 -0
  84. package/packages/common/dist/shared/controllers/dropdown.controller.d.ts.map +1 -1
  85. package/packages/common/dist/shared/controllers/dropdown.controller.js +29 -3
  86. package/packages/common/dist/shared/controllers/dropdown.controller.js.map +1 -1
@@ -472,25 +472,31 @@ let WorkflowCanvasElement = class WorkflowCanvasElement extends BaseCanvasElemen
472
472
  const previewNode = this.getPreviewNode();
473
473
  if (!previewNode || !((_a = this.workflow) === null || _a === void 0 ? void 0 : _a.id))
474
474
  return;
475
+ const config = previewNode.configuration || {};
476
+ const httpPath = config.httpPath || '/webhook';
477
+ const httpMethod = (config.httpMethod || 'POST').toUpperCase();
478
+ const methodHasBody = httpMethod !== 'GET' && httpMethod !== 'HEAD' && httpMethod !== 'OPTIONS';
475
479
  this.httpPreviewLoading = true;
476
480
  this.httpPreviewError = '';
477
481
  this.httpPreviewResponse = '';
478
482
  this.nodeStatuses = {};
479
483
  try {
480
- let body;
481
- try {
482
- body = JSON.parse(this.httpPreviewBody);
483
- }
484
- catch (_b) {
485
- throw new Error('Invalid JSON in request body');
484
+ let body = undefined;
485
+ if (methodHasBody) {
486
+ try {
487
+ body = JSON.parse(this.httpPreviewBody);
488
+ }
489
+ catch (_b) {
490
+ throw new Error('Invalid JSON in request body');
491
+ }
486
492
  }
487
493
  const baseUrl = typeof window !== 'undefined' ? window.location.origin : 'http://localhost:8000';
488
- const triggerUrl = `${baseUrl}/api/v1/workflows/${this.workflow.id}/trigger/http`;
489
- console.log('[Canvas] Sending HTTP preview request:', triggerUrl, body);
494
+ const triggerUrl = `${baseUrl}/api/v1/workflows/${this.workflow.id}/trigger${httpPath}`;
495
+ console.log('[Canvas] Sending HTTP preview request:', httpMethod, triggerUrl, body);
490
496
  const response = yield fetch(triggerUrl, {
491
- method: 'POST',
492
- headers: { 'Content-Type': 'application/json' },
493
- body: JSON.stringify(body),
497
+ method: httpMethod,
498
+ headers: methodHasBody ? { 'Content-Type': 'application/json' } : {},
499
+ body: methodHasBody ? JSON.stringify(body) : undefined,
494
500
  });
495
501
  const executionIdHeader = response.headers.get('X-Execution-Id');
496
502
  let responseData;
@@ -1083,8 +1089,21 @@ let WorkflowCanvasElement = class WorkflowCanvasElement extends BaseCanvasElemen
1083
1089
  `;
1084
1090
  }
1085
1091
  renderHttpPreviewPanel(previewNode, panelStyle) {
1092
+ var _a;
1086
1093
  const config = previewNode.configuration || {};
1087
1094
  const httpPath = config.httpPath || '/webhook';
1095
+ const httpMethod = (config.httpMethod || 'POST').toUpperCase();
1096
+ const httpAuth = config.httpAuth || 'none';
1097
+ const wfId = ((_a = this.workflow) === null || _a === void 0 ? void 0 : _a.id) || '{workflowId}';
1098
+ const origin = typeof window !== 'undefined' ? window.location.origin : '';
1099
+ const webhookUrl = `${origin}/api/v1/workflows/${wfId}/trigger${httpPath}`;
1100
+ const methodHasBody = httpMethod !== 'GET' && httpMethod !== 'HEAD' && httpMethod !== 'OPTIONS';
1101
+ const authLabel = {
1102
+ none: '',
1103
+ api_key: `API Key required (header: ${config.httpAuthHeaderName || 'X-API-Key'})`,
1104
+ bearer: 'Bearer token required (Authorization header)',
1105
+ basic: 'Basic auth required (Authorization header)',
1106
+ };
1088
1107
  return html `
1089
1108
  <div class="chatbot-preview-panel http-preview-panel" style=${styleMap(panelStyle)} data-theme=${this.currentTheme}>
1090
1109
  <div class="chatbot-preview-header">
@@ -1098,19 +1117,27 @@ let WorkflowCanvasElement = class WorkflowCanvasElement extends BaseCanvasElemen
1098
1117
  </div>
1099
1118
  <div class="http-preview-content">
1100
1119
  <div class="http-preview-url">
1101
- <span class="http-method">POST</span>
1102
- <span class="http-path">${httpPath}</span>
1103
- </div>
1104
- <div class="http-preview-section">
1105
- <label>Request Body (JSON)</label>
1106
- <textarea
1107
- class="http-request-body"
1108
- .value=${this.httpPreviewBody}
1109
- @input=${(e) => this.httpPreviewBody = e.target.value}
1110
- placeholder='{ "key": "value" }'
1111
- ?disabled=${this.httpPreviewLoading}
1112
- ></textarea>
1120
+ <span class="http-method">${httpMethod}</span>
1121
+ <span class="http-path" title=${webhookUrl}>${webhookUrl}</span>
1113
1122
  </div>
1123
+ ${httpAuth !== 'none' ? html `
1124
+ <div class="http-preview-auth-hint">
1125
+ <nr-icon name="shield" size="small"></nr-icon>
1126
+ <span>${authLabel[httpAuth]}</span>
1127
+ </div>
1128
+ ` : ''}
1129
+ ${methodHasBody ? html `
1130
+ <div class="http-preview-section">
1131
+ <label>Request Body (JSON)</label>
1132
+ <textarea
1133
+ class="http-request-body"
1134
+ .value=${this.httpPreviewBody}
1135
+ @input=${(e) => this.httpPreviewBody = e.target.value}
1136
+ placeholder='{ "key": "value" }'
1137
+ ?disabled=${this.httpPreviewLoading}
1138
+ ></textarea>
1139
+ </div>
1140
+ ` : ''}
1114
1141
  <div class="http-preview-actions">
1115
1142
  <button
1116
1143
  class="http-send-btn"
@@ -1122,7 +1149,7 @@ let WorkflowCanvasElement = class WorkflowCanvasElement extends BaseCanvasElemen
1122
1149
  <span>Sending...</span>
1123
1150
  ` : html `
1124
1151
  <nr-icon name="send" size="small"></nr-icon>
1125
- <span>Send Request</span>
1152
+ <span>Send ${httpMethod}</span>
1126
1153
  `}
1127
1154
  </button>
1128
1155
  </div>
@@ -1441,6 +1468,7 @@ let WorkflowCanvasElement = class WorkflowCanvasElement extends BaseCanvasElemen
1441
1468
  ></workflow-node>
1442
1469
  `;
1443
1470
  })}
1471
+ ${this.renderNodeLockOverlays()}
1444
1472
  </div>
1445
1473
  </div>
1446
1474
 
@@ -567,6 +567,24 @@ export const workflowCanvasStyles = css `
567
567
  background: rgba(0, 0, 0, 0.05);
568
568
  }
569
569
 
570
+ .config-panel-help {
571
+ background: none;
572
+ border: none;
573
+ color: #8d8d8d;
574
+ cursor: pointer;
575
+ padding: 0.125rem;
576
+ display: flex;
577
+ align-items: center;
578
+ justify-content: center;
579
+ border-radius: 4px;
580
+ transition: all 0.15s ease;
581
+ }
582
+
583
+ .config-panel-help:hover {
584
+ color: #0f62fe;
585
+ background: rgba(15, 98, 254, 0.08);
586
+ }
587
+
570
588
  .config-panel-content {
571
589
  flex: 1;
572
590
  overflow-y: auto;
@@ -1788,7 +1806,7 @@ export const workflowCanvasStyles = css `
1788
1806
  .canvas-wrapper[data-theme="default"] .node-palette,
1789
1807
  .canvas-wrapper[data-theme="default"] .context-menu,
1790
1808
  .canvas-wrapper[data-theme="default"] .config-panel {
1791
- background: #f4f4f4;
1809
+ background: rgb(255 255 255);
1792
1810
  border-color: #e0e0e0;
1793
1811
  }
1794
1812
 
@@ -2119,6 +2137,23 @@ export const workflowCanvasStyles = css `
2119
2137
 
2120
2138
  .http-path {
2121
2139
  color: #525252;
2140
+ overflow: hidden;
2141
+ text-overflow: ellipsis;
2142
+ white-space: nowrap;
2143
+ min-width: 0;
2144
+ flex: 1;
2145
+ }
2146
+
2147
+ .http-preview-auth-hint {
2148
+ display: flex;
2149
+ align-items: center;
2150
+ gap: 0.375rem;
2151
+ padding: 0.375rem 0.625rem;
2152
+ background: #fff8e1;
2153
+ border: 1px solid #ffe082;
2154
+ border-radius: 4px;
2155
+ font-size: 0.75rem;
2156
+ color: #8a6d3b;
2122
2157
  }
2123
2158
 
2124
2159
  .http-preview-section {
@@ -2934,6 +2969,32 @@ export const workflowCanvasStyles = css `
2934
2969
  box-shadow: 0 1px 3px rgba(0, 0, 0, 0.2);
2935
2970
  }
2936
2971
 
2972
+ /* ========================================
2973
+ * COLLABORATION: NODE LOCK PILL
2974
+ * ======================================== */
2975
+
2976
+ .node-lock-pill {
2977
+ position: absolute;
2978
+ pointer-events: none;
2979
+ display: inline-flex;
2980
+ align-items: center;
2981
+ gap: 4px;
2982
+ padding: 3px 8px;
2983
+ border-radius: 10px;
2984
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
2985
+ font-size: 11px;
2986
+ font-weight: 600;
2987
+ color: #ffffff;
2988
+ white-space: nowrap;
2989
+ box-shadow: 0 2px 6px rgba(0, 0, 0, 0.2);
2990
+ z-index: 20;
2991
+ }
2992
+
2993
+ .node-lock-pill svg {
2994
+ display: block;
2995
+ flex: none;
2996
+ }
2997
+
2937
2998
  /* ========================================
2938
2999
  * COLLABORATION: PRESENCE BAR
2939
3000
  * ======================================== */
@@ -1751,7 +1751,17 @@ export const NODE_TEMPLATES = [
1751
1751
  icon: NODE_ICONS[WorkflowNodeType.SLACK_SOCKET],
1752
1752
  color: NODE_COLORS[WorkflowNodeType.SLACK_SOCKET],
1753
1753
  category: 'trigger',
1754
- defaultConfig: { appToken: '', botToken: '' },
1754
+ defaultConfig: {
1755
+ appTokenPath: '',
1756
+ botTokenPath: '',
1757
+ eventTypes: [],
1758
+ interactionTypes: [],
1759
+ slashCommands: '',
1760
+ allowedTeamIds: '',
1761
+ allowedChannelIds: '',
1762
+ allowedUserIds: '',
1763
+ ignoreBots: true,
1764
+ },
1755
1765
  defaultPorts: {
1756
1766
  inputs: [],
1757
1767
  outputs: [
@@ -1767,7 +1777,15 @@ export const NODE_TEMPLATES = [
1767
1777
  icon: NODE_ICONS[WorkflowNodeType.DISCORD_BOT],
1768
1778
  color: NODE_COLORS[WorkflowNodeType.DISCORD_BOT],
1769
1779
  category: 'trigger',
1770
- defaultConfig: { botToken: '' },
1780
+ defaultConfig: {
1781
+ botTokenPath: '',
1782
+ intents: ['GUILDS', 'GUILD_MESSAGES', 'MESSAGE_CONTENT'],
1783
+ eventTypes: [],
1784
+ allowedGuildIds: '',
1785
+ allowedChannelIds: '',
1786
+ allowedUserIds: '',
1787
+ ignoreBots: true,
1788
+ },
1771
1789
  defaultPorts: {
1772
1790
  inputs: [],
1773
1791
  outputs: [
@@ -1783,7 +1801,17 @@ export const NODE_TEMPLATES = [
1783
1801
  icon: NODE_ICONS[WorkflowNodeType.WHATSAPP_WEBHOOK],
1784
1802
  color: NODE_COLORS[WorkflowNodeType.WHATSAPP_WEBHOOK],
1785
1803
  category: 'trigger',
1786
- defaultConfig: {},
1804
+ defaultConfig: {
1805
+ phoneNumberId: '',
1806
+ businessAccountId: '',
1807
+ accessTokenPath: '',
1808
+ appSecretPath: '',
1809
+ verifyToken: '',
1810
+ webhookFields: ['messages'],
1811
+ messageTypes: [],
1812
+ allowedSenders: '',
1813
+ ignoreStatusUpdates: false,
1814
+ },
1787
1815
  defaultPorts: {
1788
1816
  inputs: [],
1789
1817
  outputs: [
@@ -1799,7 +1827,25 @@ export const NODE_TEMPLATES = [
1799
1827
  icon: NODE_ICONS[WorkflowNodeType.CUSTOM_WEBSOCKET],
1800
1828
  color: NODE_COLORS[WorkflowNodeType.CUSTOM_WEBSOCKET],
1801
1829
  category: 'trigger',
1802
- defaultConfig: { url: '' },
1830
+ defaultConfig: {
1831
+ url: '',
1832
+ subprotocol: '',
1833
+ authMode: 'none',
1834
+ tokenPath: '',
1835
+ username: '',
1836
+ passwordPath: '',
1837
+ headerName: '',
1838
+ headerValuePath: '',
1839
+ queryParamName: 'token',
1840
+ queryParamValuePath: '',
1841
+ initialMessage: '',
1842
+ autoReconnect: true,
1843
+ reconnectDelayMs: 5000,
1844
+ maxReconnectAttempts: 0,
1845
+ pingIntervalSec: 30,
1846
+ messageFormat: 'json',
1847
+ filterExpression: '',
1848
+ },
1803
1849
  defaultPorts: {
1804
1850
  inputs: [],
1805
1851
  outputs: [
@@ -127,9 +127,9 @@ import{css as t,html as e,LitElement as i,nothing as o}from"lit";import{property
127
127
  * @license
128
128
  * Copyright 2024 Nuraly, Laabidi Aymen
129
129
  * SPDX-License-Identifier: MIT
130
- */;var d=function(t,e,i,o){for(var s,n=arguments.length,a=n<3?e:null===o?o=Object.getOwnPropertyDescriptor(e,i):o,r=t.length-1;r>=0;r--)(s=t[r])&&(a=(n<3?s(a):n>3?s(e,i,a):s(e,i))||a);return n>3&&a&&Object.defineProperty(e,i,a),a};const l=[{key:"👍",label:"Like"},{key:"❤️",label:"Love"},{key:"😂",label:"Haha"},{key:"😮",label:"Wow"},{key:"😢",label:"Sad"},{key:"🔥",label:"Fire"}],c=["😀","😂","🥰","😎","🤔","🎉","✨","🙏","💯","🚀","👏","😍","🤣","💪","😊","🥳","😤","💀","🫡","👀","💜","🤝","⭐","🙌"],p=e`<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>`,g=e`<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 6 7 17 2 12"/><polyline points="23 6 12 17" opacity="0.5"/></svg>`,u=e`<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#7c3aed" stroke-width="2"><polyline points="18 6 7 17 2 12"/><polyline points="23 6 12 17"/></svg>`,h=e`<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>`,x=e`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>`,m=e`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>`,v=e`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>`,b=e`<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>`,f=e`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07 19.5 19.5 0 01-6-6 19.79 19.79 0 01-3.07-8.67A2 2 0 014.11 2h3a2 2 0 012 1.72c.127.96.361 1.903.7 2.81a2 2 0 01-.45 2.11L8.09 9.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0122 16.92z"/></svg>`,y=e`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2" ry="2"/></svg>`,w=e`<svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>`,k=e`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48"/></svg>`,$=e`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>`;let j=class extends i{constructor(){super(...arguments),this.messages=[],this.currentUser=null,this.conversationId="",this.isGroup=!1,this.loading=!1,this.compact=!1,this.emptyText="No messages yet",this.hideInput=!1,this._showEmoji=!1,this._contextMenu=null,this._replyTo=null,this._editingIdx=null,this._typing=[],this._typingTimer=null,this._longPressTimer=null,this._touchMoved=!1}updated(t){t.has("messages")&&requestAnimationFrame(()=>{var t;const e=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector(".chat-messages");e&&(e.scrollTop=e.scrollHeight)})}addTyping(t){this._typing.includes(t)||(this._typing=[...this._typing,t])}removeTyping(t){this._typing=this._typing.filter(e=>e!==t)}_sendMessage(){var t;const e=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector(".chat-input textarea");if(!(null==e?void 0:e.value.trim()))return;const i=e.value.trim();e.value="",e.focus(),this.dispatchEvent(new CustomEvent("message-send",{detail:{text:i,replyTo:this._replyTo||void 0},bubbles:!0,composed:!0})),this._replyTo=null,this._showEmoji=!1,this._playSound()}_onInputKeydown(t){if("Enter"===t.key&&!t.shiftKey)return t.preventDefault(),void this._sendMessage();this.dispatchEvent(new CustomEvent("typing-start",{bubbles:!0,composed:!0})),clearTimeout(this._typingTimer),this._typingTimer=setTimeout(()=>{this.dispatchEvent(new CustomEvent("typing-stop",{bubbles:!0,composed:!0}))},2e3)}_toggleEmoji(){this._showEmoji=!this._showEmoji}_insertEmoji(t){var e;const i=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector(".chat-input textarea");i&&(i.value+=t,i.focus()),this._showEmoji=!1}_menuPos(t){const e=t.closest(".msg-bubble")||t.closest(".msg-row");if(!e)return{y:0,left:0};const i=e.getBoundingClientRect(),o=!!t.closest(".msg-row.me"),s=o?140:80,n=i.top>s+12?i.top-s-4:i.bottom+4;return o?{y:n,right:Math.max(8,window.innerWidth-i.right)}:{y:n,left:Math.max(8,i.left)}}_showContextMenuHandler(t,e){t.preventDefault(),this._contextMenu=Object.assign({msgIdx:e},this._menuPos(t.target))}_onTouchStart(t,e){this._touchMoved=!1,this._longPressTimer=setTimeout(()=>{var i;t.preventDefault(),null===(i=window.getSelection())||void 0===i||i.removeAllRanges(),this._contextMenu=Object.assign({msgIdx:e},this._menuPos(t.target)),this._touchMoved=!0},500)}_onTouchEnd(){clearTimeout(this._longPressTimer)}_onTouchMove(){this._touchMoved=!0,clearTimeout(this._longPressTimer)}_onMsgTap(t,e){if(!window.matchMedia("(max-width: 640px)").matches)return;if(this._touchMoved)return;const i=t.target;i.closest(".reaction")||i.closest(".audio-play-btn")||i.closest(".file-card")||i.closest(".edit-inline")||(t.stopPropagation(),this._contextMenu=Object.assign({msgIdx:e},this._menuPos(i)))}_hideContextMenu(){this._contextMenu=null}_deleteMsg(t){const e=this.messages[t];(null==e?void 0:e.id)&&this.dispatchEvent(new CustomEvent("message-delete",{detail:{messageId:e.id},bubbles:!0,composed:!0})),this._contextMenu=null}_replyMsg(t){var e,i;const o=this.messages[t];o&&(this._replyTo={text:o.text,from:o.from},null===(i=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector(".chat-input textarea"))||void 0===i||i.focus()),this._contextMenu=null}_editMsg(t){this._editingIdx=t,this._contextMenu=null,requestAnimationFrame(()=>{var t;const e=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector(".edit-input");e&&(e.focus(),e.select())})}_confirmEdit(t){var e;const i=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector(".edit-input"),o=null==i?void 0:i.value.trim();if(!o)return void(this._editingIdx=null);const s=this.messages[t];(null==s?void 0:s.id)&&this.dispatchEvent(new CustomEvent("message-edit",{detail:{messageId:s.id,content:o},bubbles:!0,composed:!0})),this._editingIdx=null}_onEditKeydown(t,e){"Enter"!==t.key||t.shiftKey?"Escape"===t.key&&(this._editingIdx=null):(t.preventDefault(),this._confirmEdit(e))}_reactMsg(t,e){const i=this.messages[t];(null==i?void 0:i.id)&&this.dispatchEvent(new CustomEvent("message-react",{detail:{messageId:i.id,emoji:e},bubbles:!0,composed:!0})),this._contextMenu=null}_toggleAudioPlay(t){var e;const i=t.currentTarget.closest(".audio-msg"),o=null==i?void 0:i.querySelector("audio");o&&(o.paused?(null===(e=this.shadowRoot)||void 0===e||e.querySelectorAll(".audio-msg audio").forEach(t=>{t===o||t.paused||(t.pause(),t.currentTime=0)}),o.play().catch(()=>{})):o.pause())}_onAudioTimeUpdate(t){const e=t.target,i=e.closest(".audio-msg");if(!i||!e.duration)return;const o=i.querySelectorAll(".a-bar"),s=e.currentTime/e.duration,n=Math.floor(s*o.length);o.forEach((t,e)=>t.classList.toggle("played",e<=n))}_onAudioEnded(t){const e=t.target.closest(".audio-msg");null==e||e.querySelectorAll(".a-bar").forEach(t=>t.classList.remove("played"))}_pickFile(t=!1){const e=document.createElement("input");e.type="file",t&&(e.accept="image/jpeg,image/png,image/gif,image/webp,image/heic,image/heif"),e.style.cssText="position:fixed;top:-9999px;left:-9999px;opacity:0",document.body.appendChild(e),e.onchange=()=>{var i;const o=null===(i=e.files)||void 0===i?void 0:i[0];o&&this.dispatchEvent(new CustomEvent("file-select",{detail:{file:o,imageOnly:t},bubbles:!0,composed:!0}));try{document.body.removeChild(e)}catch(t){}},e.click()}_playSound(){try{const t=new AudioContext,e=t.createGain();e.connect(t.destination),e.gain.value=.12;const i=t.createOscillator();i.connect(e),i.type="sine",i.frequency.setValueAtTime(600,t.currentTime),i.frequency.setValueAtTime(900,t.currentTime+.08),e.gain.exponentialRampToValueAtTime(.001,t.currentTime+.15),i.start(t.currentTime),i.stop(t.currentTime+.15),setTimeout(()=>t.close(),500)}catch(t){}}render(){return this.loading?e`<div class="loading">Loading...</div>`:e`
130
+ */;var d=function(t,e,i,o){for(var s,n=arguments.length,a=n<3?e:null===o?o=Object.getOwnPropertyDescriptor(e,i):o,r=t.length-1;r>=0;r--)(s=t[r])&&(a=(n<3?s(a):n>3?s(e,i,a):s(e,i))||a);return n>3&&a&&Object.defineProperty(e,i,a),a};const l=[{key:"👍",label:"Like"},{key:"❤️",label:"Love"},{key:"😂",label:"Haha"},{key:"😮",label:"Wow"},{key:"😢",label:"Sad"},{key:"🔥",label:"Fire"}],c=["😀","😂","🥰","😎","🤔","🎉","✨","🙏","💯","🚀","👏","😍","🤣","💪","😊","🥳","😤","💀","🫡","👀","💜","🤝","⭐","🙌"],p=e`<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="20 6 9 17 4 12"/></svg>`,u=e`<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><polyline points="18 6 7 17 2 12"/><polyline points="23 6 12 17" opacity="0.5"/></svg>`,g=e`<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="#7c3aed" stroke-width="2"><polyline points="18 6 7 17 2 12"/><polyline points="23 6 12 17"/></svg>`,h=e`<svg width="18" height="18" viewBox="0 0 24 24" fill="currentColor"><path d="M2.01 21L23 12 2.01 3 2 10l15 2-15 2z"/></svg>`,x=e`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><circle cx="12" cy="12" r="10"/><path d="M8 14s1.5 2 4 2 4-2 4-2"/><line x1="9" y1="9" x2="9.01" y2="9"/><line x1="15" y1="9" x2="15.01" y2="9"/></svg>`,m=e`<svg width="14" height="14" viewBox="0 0 24 24" fill="currentColor"><polygon points="5 3 19 12 5 21 5 3"/></svg>`,v=e`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M14 2H6a2 2 0 00-2 2v16a2 2 0 002 2h12a2 2 0 002-2V8z"/><polyline points="14 2 14 8 20 8"/></svg>`,b=e`<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M21 15v4a2 2 0 01-2 2H5a2 2 0 01-2-2v-4"/><polyline points="7 10 12 15 17 10"/><line x1="12" y1="15" x2="12" y2="3"/></svg>`,f=e`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M22 16.92v3a2 2 0 01-2.18 2 19.79 19.79 0 01-8.63-3.07 19.5 19.5 0 01-6-6 19.79 19.79 0 01-3.07-8.67A2 2 0 014.11 2h3a2 2 0 012 1.72c.127.96.361 1.903.7 2.81a2 2 0 01-.45 2.11L8.09 9.91a16 16 0 006 6l1.27-1.27a2 2 0 012.11-.45c.907.339 1.85.573 2.81.7A2 2 0 0122 16.92z"/></svg>`,y=e`<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><polygon points="23 7 16 12 23 17 23 7"/><rect x="1" y="5" width="15" height="14" rx="2" ry="2"/></svg>`,w=e`<svg width="36" height="36" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1"><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></svg>`,k=e`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><path d="M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48"/></svg>`,$=e`<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"><rect x="3" y="3" width="18" height="18" rx="2" ry="2"/><circle cx="8.5" cy="8.5" r="1.5"/><polyline points="21 15 16 10 5 21"/></svg>`;let j=class extends i{constructor(){super(...arguments),this.messages=[],this.currentUser=null,this.conversationId="",this.isGroup=!1,this.loading=!1,this.compact=!1,this.emptyText="No messages yet",this.hideInput=!1,this._showEmoji=!1,this._contextMenu=null,this._replyTo=null,this._editingIdx=null,this._typing=[],this._typingTimer=null,this._longPressTimer=null,this._touchMoved=!1}updated(t){t.has("messages")&&requestAnimationFrame(()=>{var t;const e=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector(".chat-messages");e&&(e.scrollTop=e.scrollHeight)})}addTyping(t){this._typing.includes(t)||(this._typing=[...this._typing,t])}removeTyping(t){this._typing=this._typing.filter(e=>e!==t)}_sendMessage(){var t;const e=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector(".chat-input textarea");if(!(null==e?void 0:e.value.trim()))return;const i=e.value.trim();e.value="",e.focus(),this.dispatchEvent(new CustomEvent("message-send",{detail:{text:i,replyTo:this._replyTo||void 0},bubbles:!0,composed:!0})),this._replyTo=null,this._showEmoji=!1,this._playSound()}_onInputKeydown(t){if("Enter"===t.key&&!t.shiftKey)return t.preventDefault(),void this._sendMessage();this.dispatchEvent(new CustomEvent("typing-start",{bubbles:!0,composed:!0})),clearTimeout(this._typingTimer),this._typingTimer=setTimeout(()=>{this.dispatchEvent(new CustomEvent("typing-stop",{bubbles:!0,composed:!0}))},2e3)}_toggleEmoji(){this._showEmoji=!this._showEmoji}_insertEmoji(t){var e;const i=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector(".chat-input textarea");i&&(i.value+=t,i.focus()),this._showEmoji=!1}_menuPos(t){const e=t.closest(".msg-bubble")||t.closest(".msg-row");if(!e)return{y:0,left:0};const i=e.getBoundingClientRect(),o=!!t.closest(".msg-row.me"),s=o?140:80,n=i.top>s+12?i.top-s-4:i.bottom+4;return o?{y:n,right:Math.max(8,window.innerWidth-i.right)}:{y:n,left:Math.max(8,i.left)}}_showContextMenuHandler(t,e){t.preventDefault(),this._contextMenu=Object.assign({msgIdx:e},this._menuPos(t.target))}_onTouchStart(t,e){this._touchMoved=!1,this._longPressTimer=setTimeout(()=>{var i;t.preventDefault(),null===(i=window.getSelection())||void 0===i||i.removeAllRanges(),this._contextMenu=Object.assign({msgIdx:e},this._menuPos(t.target)),this._touchMoved=!0},500)}_onTouchEnd(){clearTimeout(this._longPressTimer)}_onTouchMove(){this._touchMoved=!0,clearTimeout(this._longPressTimer)}_onMsgTap(t,e){if(!window.matchMedia("(max-width: 640px)").matches)return;if(this._touchMoved)return;const i=t.target;i.closest(".reaction")||i.closest(".audio-play-btn")||i.closest(".file-card")||i.closest(".edit-inline")||(t.stopPropagation(),this._contextMenu=Object.assign({msgIdx:e},this._menuPos(i)))}_hideContextMenu(){this._contextMenu=null}_deleteMsg(t){const e=this.messages[t];(null==e?void 0:e.id)&&this.dispatchEvent(new CustomEvent("message-delete",{detail:{messageId:e.id},bubbles:!0,composed:!0})),this._contextMenu=null}_replyMsg(t){var e,i;const o=this.messages[t];o&&(this._replyTo={text:o.text,from:o.from},null===(i=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector(".chat-input textarea"))||void 0===i||i.focus()),this._contextMenu=null}_editMsg(t){this._editingIdx=t,this._contextMenu=null,requestAnimationFrame(()=>{var t;const e=null===(t=this.shadowRoot)||void 0===t?void 0:t.querySelector(".edit-input");e&&(e.focus(),e.select())})}_confirmEdit(t){var e;const i=null===(e=this.shadowRoot)||void 0===e?void 0:e.querySelector(".edit-input"),o=null==i?void 0:i.value.trim();if(!o)return void(this._editingIdx=null);const s=this.messages[t];(null==s?void 0:s.id)&&this.dispatchEvent(new CustomEvent("message-edit",{detail:{messageId:s.id,content:o},bubbles:!0,composed:!0})),this._editingIdx=null}_onEditKeydown(t,e){"Enter"!==t.key||t.shiftKey?"Escape"===t.key&&(this._editingIdx=null):(t.preventDefault(),this._confirmEdit(e))}_reactMsg(t,e){const i=this.messages[t];(null==i?void 0:i.id)&&this.dispatchEvent(new CustomEvent("message-react",{detail:{messageId:i.id,emoji:e},bubbles:!0,composed:!0})),this._contextMenu=null}_toggleAudioPlay(t){var e;const i=t.currentTarget.closest(".audio-msg"),o=null==i?void 0:i.querySelector("audio");o&&(o.paused?(null===(e=this.shadowRoot)||void 0===e||e.querySelectorAll(".audio-msg audio").forEach(t=>{t===o||t.paused||(t.pause(),t.currentTime=0)}),o.play().catch(()=>{})):o.pause())}_onAudioTimeUpdate(t){const e=t.target,i=e.closest(".audio-msg");if(!i||!e.duration)return;const o=i.querySelectorAll(".a-bar"),s=e.currentTime/e.duration,n=Math.floor(s*o.length);o.forEach((t,e)=>t.classList.toggle("played",e<=n))}_onAudioEnded(t){const e=t.target.closest(".audio-msg");null==e||e.querySelectorAll(".a-bar").forEach(t=>t.classList.remove("played"))}_pickFile(t=!1){const e=document.createElement("input");e.type="file",t&&(e.accept="image/jpeg,image/png,image/gif,image/webp,image/heic,image/heif"),e.style.cssText="position:fixed;top:-9999px;left:-9999px;opacity:0",document.body.appendChild(e),e.onchange=()=>{var i;const o=null===(i=e.files)||void 0===i?void 0:i[0];o&&this.dispatchEvent(new CustomEvent("file-select",{detail:{file:o,imageOnly:t},bubbles:!0,composed:!0}));try{document.body.removeChild(e)}catch(t){}},e.click()}_playSound(){try{const t=new AudioContext,e=t.createGain();e.connect(t.destination),e.gain.value=.12;const i=t.createOscillator();i.connect(e),i.type="sine",i.frequency.setValueAtTime(600,t.currentTime),i.frequency.setValueAtTime(900,t.currentTime+.08),e.gain.exponentialRampToValueAtTime(.001,t.currentTime+.15),i.start(t.currentTime),i.stop(t.currentTime+.15),setTimeout(()=>t.close(),500)}catch(t){}}render(){return this.loading?e`<div class="loading">Loading...</div>`:e`
131
131
  ${0===this.messages.length?e`<div class="empty-state">${w}<span>${this.emptyText}</span></div>`:e`
132
- <div class="chat-messages" @click=${()=>this._hideContextMenu()} @touchstart=${()=>{this._contextMenu&&this._hideContextMenu()}}>
132
+ <div class="chat-messages" part="messages" @click=${()=>this._hideContextMenu()} @touchstart=${()=>{this._contextMenu&&this._hideContextMenu()}}>
133
133
  ${this.messages.map((t,e,i)=>this._renderMessage(t,e,i))}
134
134
  </div>
135
135
  `}
@@ -137,7 +137,7 @@ import{css as t,html as e,LitElement as i,nothing as o}from"lit";import{property
137
137
  ${this._contextMenu?this._renderContextMenu():o}
138
138
  ${this._typing.length>0?e`<div class="typing-indicator">${this._typing.join(", ")} typing...</div>`:o}
139
139
  ${this._replyTo?e`
140
- <div class="reply-bar">
140
+ <div class="reply-bar" part="reply-bar">
141
141
  <span class="reply-text">Replying to: ${this._replyTo.text}</span>
142
142
  <button @click=${()=>{this._replyTo=null}}>✕</button>
143
143
  </div>
@@ -159,7 +159,7 @@ import{css as t,html as e,LitElement as i,nothing as o}from"lit";import{property
159
159
  ${this._editingIdx===i?e`<div class="edit-inline"><input class="edit-input" type="text" .value=${t.text||""} @keydown=${t=>this._onEditKeydown(t,i)}><button class="edit-confirm" @click=${()=>this._confirmEdit(i)}>✓</button><button class="edit-cancel" @click=${()=>{this._editingIdx=null}}>✕</button></div>`:t.text?e`<div class="msg ${t.from}">${t.text}${t.edited?e` <span class="msg-edited">(edited)</span>`:o}${t.encrypted?e`<span class="msg-e2e" title="End-to-end encrypted">🔒</span>`:o}</div>`:o}
160
160
  <div class="msg-footer ${t.from}">
161
161
  <span class="msg-time">${t.time||""}</span>
162
- ${"me"===t.from?e`<span class="msg-read">${"read"===t.status?u:"delivered"===t.status?g:p}</span>`:o}
162
+ ${"me"===t.from?e`<span class="msg-read">${"read"===t.status?g:"delivered"===t.status?u:p}</span>`:o}
163
163
  </div>
164
164
  ${(null===(n=t.reactions)||void 0===n?void 0:n.length)?e`
165
165
  <div class="msg-reactions">
@@ -186,7 +186,7 @@ import{css as t,html as e,LitElement as i,nothing as o}from"lit";import{property
186
186
  <div style="flex:1;min-width:0"><div style="font-weight:600;white-space:nowrap;overflow:hidden;text-overflow:ellipsis">${s.name||"File"}</div>${s.fileSize?e`<div style="font-size:10px;color:var(--text-secondary);margin-top:1px">${(s.fileSize/1024).toFixed(0)} KB</div>`:o}</div>
187
187
  ${b}
188
188
  </a></div>`}_renderContextMenu(){const t=this._contextMenu,i=this.messages[t.msgIdx],s="me"===(null==i?void 0:i.from);return e`
189
- <div class="ctx-menu" @mousedown=${t=>t.preventDefault()} @touchstart=${t=>t.stopPropagation()} style="top:${t.y}px;${null!=t.right?`right:${t.right}px`:`left:${t.left}px`}">
189
+ <div class="ctx-menu" part="context-menu" @mousedown=${t=>t.preventDefault()} @touchstart=${t=>t.stopPropagation()} style="top:${t.y}px;${null!=t.right?`right:${t.right}px`:`left:${t.left}px`}">
190
190
  <div class="ctx-reactions">
191
191
  ${l.map(i=>e`<button @click=${()=>this._reactMsg(t.msgIdx,i.key)} title=${i.label}>${i.key}</button>`)}
192
192
  </div>
@@ -195,7 +195,7 @@ import{css as t,html as e,LitElement as i,nothing as o}from"lit";import{property
195
195
  ${s&&!(null==i?void 0:i.deleted)?e`<button class="danger" @click=${()=>this._deleteMsg(t.msgIdx)}>🗑 Delete</button>`:o}
196
196
  </div>
197
197
  `}_renderEmojiPicker(){return e`
198
- <div class="emoji-picker" @mousedown=${t=>t.preventDefault()}>
198
+ <div class="emoji-picker" part="emoji-picker" @mousedown=${t=>t.preventDefault()}>
199
199
  <div class="emoji-quick">
200
200
  ${l.map(t=>e`<button @click=${()=>this._insertEmoji(t.key)} title=${t.label}>${t.key}</button>`)}
201
201
  </div>
@@ -204,13 +204,13 @@ import{css as t,html as e,LitElement as i,nothing as o}from"lit";import{property
204
204
  </div>
205
205
  </div>
206
206
  `}_renderInputBar(){return e`
207
- <div class="chat-input">
208
- <div class="input-tools">
207
+ <div class="chat-input" part="input">
208
+ <div class="input-tools" part="input-tools">
209
209
  <button @click=${()=>this._pickFile()} title="Attach file">${k}</button>
210
210
  <button @click=${()=>this._pickFile(!0)} title="Send image">${$}</button>
211
211
  <button @click=${()=>this._toggleEmoji()} title="Emoji">${x}</button>
212
212
  </div>
213
- <textarea rows="1" placeholder="Type a message..." @keydown=${t=>this._onInputKeydown(t)}></textarea>
214
- <button class="send-btn" @mousedown=${t=>t.preventDefault()} @click=${()=>this._sendMessage()} title="Send">${h}</button>
213
+ <textarea rows="1" placeholder="Type a message..." part="textarea" @keydown=${t=>this._onInputKeydown(t)}></textarea>
214
+ <button class="send-btn" part="send-button" @mousedown=${t=>t.preventDefault()} @click=${()=>this._sendMessage()} title="Send">${h}</button>
215
215
  </div>
216
216
  `}};j.styles=r,d([s({type:Array})],j.prototype,"messages",void 0),d([s({type:Object})],j.prototype,"currentUser",void 0),d([s({type:String,attribute:"conversation-id"})],j.prototype,"conversationId",void 0),d([s({type:Boolean})],j.prototype,"isGroup",void 0),d([s({type:Boolean})],j.prototype,"loading",void 0),d([s({type:Boolean,reflect:!0})],j.prototype,"compact",void 0),d([s({type:String,attribute:"empty-text"})],j.prototype,"emptyText",void 0),d([s({type:Boolean,attribute:"hide-input"})],j.prototype,"hideInput",void 0),d([n()],j.prototype,"_showEmoji",void 0),d([n()],j.prototype,"_contextMenu",void 0),d([n()],j.prototype,"_replyTo",void 0),d([n()],j.prototype,"_editingIdx",void 0),d([n()],j.prototype,"_typing",void 0),j=d([a("nr-chat-panel")],j);export{j as NrChatPanelElement};
@@ -328,7 +328,7 @@ let NrChatPanelElement = class NrChatPanelElement extends LitElement {
328
328
  ${this.messages.length === 0
329
329
  ? html `<div class="empty-state">${svgChat}<span>${this.emptyText}</span></div>`
330
330
  : html `
331
- <div class="chat-messages" @click=${() => this._hideContextMenu()} @touchstart=${() => { if (this._contextMenu)
331
+ <div class="chat-messages" part="messages" @click=${() => this._hideContextMenu()} @touchstart=${() => { if (this._contextMenu)
332
332
  this._hideContextMenu(); }}>
333
333
  ${this.messages.map((m, i, arr) => this._renderMessage(m, i, arr))}
334
334
  </div>
@@ -337,7 +337,7 @@ let NrChatPanelElement = class NrChatPanelElement extends LitElement {
337
337
  ${this._contextMenu ? this._renderContextMenu() : nothing}
338
338
  ${this._typing.length > 0 ? html `<div class="typing-indicator">${this._typing.join(', ')} typing...</div>` : nothing}
339
339
  ${this._replyTo ? html `
340
- <div class="reply-bar">
340
+ <div class="reply-bar" part="reply-bar">
341
341
  <span class="reply-text">Replying to: ${this._replyTo.text}</span>
342
342
  <button @click=${() => { this._replyTo = null; }}>✕</button>
343
343
  </div>
@@ -427,7 +427,7 @@ let NrChatPanelElement = class NrChatPanelElement extends LitElement {
427
427
  const msg = this.messages[cm.msgIdx];
428
428
  const isMe = (msg === null || msg === void 0 ? void 0 : msg.from) === 'me';
429
429
  return html `
430
- <div class="ctx-menu" @mousedown=${(e) => e.preventDefault()} @touchstart=${(e) => e.stopPropagation()} style="top:${cm.y}px;${cm.right != null ? `right:${cm.right}px` : `left:${cm.left}px`}">
430
+ <div class="ctx-menu" part="context-menu" @mousedown=${(e) => e.preventDefault()} @touchstart=${(e) => e.stopPropagation()} style="top:${cm.y}px;${cm.right != null ? `right:${cm.right}px` : `left:${cm.left}px`}">
431
431
  <div class="ctx-reactions">
432
432
  ${REACTIONS.map(r => html `<button @click=${() => this._reactMsg(cm.msgIdx, r.key)} title=${r.label}>${r.key}</button>`)}
433
433
  </div>
@@ -439,7 +439,7 @@ let NrChatPanelElement = class NrChatPanelElement extends LitElement {
439
439
  }
440
440
  _renderEmojiPicker() {
441
441
  return html `
442
- <div class="emoji-picker" @mousedown=${(e) => e.preventDefault()}>
442
+ <div class="emoji-picker" part="emoji-picker" @mousedown=${(e) => e.preventDefault()}>
443
443
  <div class="emoji-quick">
444
444
  ${REACTIONS.map(r => html `<button @click=${() => this._insertEmoji(r.key)} title=${r.label}>${r.key}</button>`)}
445
445
  </div>
@@ -451,14 +451,14 @@ let NrChatPanelElement = class NrChatPanelElement extends LitElement {
451
451
  }
452
452
  _renderInputBar() {
453
453
  return html `
454
- <div class="chat-input">
455
- <div class="input-tools">
454
+ <div class="chat-input" part="input">
455
+ <div class="input-tools" part="input-tools">
456
456
  <button @click=${() => this._pickFile()} title="Attach file">${svgAttach}</button>
457
457
  <button @click=${() => this._pickFile(true)} title="Send image">${svgImage}</button>
458
458
  <button @click=${() => this._toggleEmoji()} title="Emoji">${svgSmile}</button>
459
459
  </div>
460
- <textarea rows="1" placeholder="Type a message..." @keydown=${(e) => this._onInputKeydown(e)}></textarea>
461
- <button class="send-btn" @mousedown=${(e) => e.preventDefault()} @click=${() => this._sendMessage()} title="Send">${svgSend}</button>
460
+ <textarea rows="1" placeholder="Type a message..." part="textarea" @keydown=${(e) => this._onInputKeydown(e)}></textarea>
461
+ <button class="send-btn" part="send-button" @mousedown=${(e) => e.preventDefault()} @click=${() => this._sendMessage()} title="Send">${svgSend}</button>
462
462
  </div>
463
463
  `;
464
464
  }