@nuraly/lumenui 0.2.2 → 0.3.2

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 (41) hide show
  1. package/dist/cdn.js +1 -0
  2. package/dist/nuralyui.bundle.js +2467 -1857
  3. package/dist/nuralyui.bundle.js.gz +0 -0
  4. package/dist/src/components/canvas/bundle.js +569 -204
  5. package/dist/src/components/canvas/bundle.js.gz +0 -0
  6. package/dist/src/components/canvas/canvas.constants.d.ts +1 -1
  7. package/dist/src/components/canvas/canvas.constants.js +1 -1
  8. package/dist/src/components/canvas/workflow-canvas.component.d.ts +7 -0
  9. package/dist/src/components/canvas/workflow-canvas.component.js +46 -2
  10. package/dist/src/components/canvas/workflow-canvas.types.d.ts +8 -1
  11. package/dist/src/components/canvas/workflow-canvas.types.js +157 -0
  12. package/dist/src/components/chat-panel/bundle.js +216 -0
  13. package/dist/src/components/chat-panel/bundle.js.gz +0 -0
  14. package/dist/src/components/chat-panel/chat-panel.component.d.ts +85 -0
  15. package/dist/src/components/chat-panel/chat-panel.component.js +510 -0
  16. package/dist/src/components/chat-panel/chat-panel.style.d.ts +2 -0
  17. package/dist/src/components/chat-panel/chat-panel.style.js +127 -0
  18. package/dist/src/components/chat-panel/chat-panel.types.d.ts +54 -0
  19. package/dist/src/components/chat-panel/chat-panel.types.js +2 -0
  20. package/dist/src/components/chat-panel/index.d.ts +3 -0
  21. package/dist/src/components/chat-panel/index.js +2 -0
  22. package/dist/src/components/chatbot/bundle.js +1 -1
  23. package/dist/src/components/chatbot/bundle.js.gz +0 -0
  24. package/dist/src/components/chatbot/providers/workflow-socket-provider.js +1 -1
  25. package/dist/src/components/presence/bundle.js +69 -42
  26. package/dist/src/components/presence/bundle.js.gz +0 -0
  27. package/dist/src/components/presence/presence-chat.component.d.ts +2 -0
  28. package/dist/src/components/presence/presence-chat.component.js +12 -2
  29. package/dist/src/components/presence/presence.component.d.ts +30 -6
  30. package/dist/src/components/presence/presence.component.js +277 -30
  31. package/dist/src/components/presence/presence.types.d.ts +2 -0
  32. package/dist/src/components/toast/bundle.js +11 -9
  33. package/dist/src/components/toast/bundle.js.gz +0 -0
  34. package/dist/src/components/toast/toast.component.d.ts +8 -0
  35. package/dist/src/components/toast/toast.component.js +17 -7
  36. package/dist/src/components/video/bundle.js +13 -12
  37. package/dist/src/components/video/bundle.js.gz +0 -0
  38. package/dist/src/components/video/video.component.d.ts +15 -1
  39. package/dist/src/components/video/video.component.js +131 -3
  40. package/package.json +5 -10
  41. package/packages/common/dist/VERSIONS.md +1 -1
@@ -0,0 +1,54 @@
1
+ export interface ChatMessage {
2
+ id: string | number;
3
+ from: 'me' | 'them' | 'system' | 'date';
4
+ senderId?: string;
5
+ senderName?: string;
6
+ senderInitials?: string;
7
+ senderColor?: string;
8
+ text: string;
9
+ time?: string;
10
+ status?: 'sent' | 'delivered' | 'read';
11
+ attachment?: ChatAttachment | null;
12
+ replyTo?: {
13
+ text: string;
14
+ from: string;
15
+ } | null;
16
+ reactions?: ChatReaction[];
17
+ edited?: boolean;
18
+ deleted?: boolean;
19
+ encrypted?: boolean;
20
+ }
21
+ export interface ChatAttachment {
22
+ url: string;
23
+ decryptedUrl?: string;
24
+ type: 'image' | 'audio' | 'file' | 'call';
25
+ name?: string;
26
+ fileName?: string;
27
+ mimeType?: string;
28
+ fileSize?: number;
29
+ duration?: string;
30
+ waveform?: number[];
31
+ callType?: 'audio' | 'video';
32
+ callStatus?: 'completed' | 'missed' | 'declined';
33
+ iv?: string;
34
+ }
35
+ export interface ChatReaction {
36
+ emoji: string;
37
+ count: number;
38
+ users: string[];
39
+ }
40
+ export interface ChatParticipant {
41
+ user_id: string;
42
+ username?: string;
43
+ display_name?: string;
44
+ avatar_url?: string;
45
+ color?: string;
46
+ initials?: string;
47
+ }
48
+ export interface ChatUser {
49
+ userId: string;
50
+ name: string;
51
+ initials: string;
52
+ color: string;
53
+ }
54
+ //# sourceMappingURL=chat-panel.types.d.ts.map
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=chat-panel.types.js.map
@@ -0,0 +1,3 @@
1
+ export { NrChatPanelElement } from './chat-panel.component.js';
2
+ export type { ChatMessage, ChatAttachment, ChatReaction, ChatParticipant, ChatUser } from './chat-panel.types.js';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,2 @@
1
+ export { NrChatPanelElement } from './chat-panel.component.js';
2
+ //# sourceMappingURL=index.js.map
@@ -2706,7 +2706,7 @@ var Gt=function(t,e,n,i){return new(n||(n=Promise))(function(o,s){function r(t){
2706
2706
  * @license
2707
2707
  * Copyright 2024 Nuraly, Laabidi Aymen
2708
2708
  * SPDX-License-Identifier: MIT
2709
- */var ve=function(t,e,n,i){return new(n||(n=Promise))(function(o,s){function r(t){try{l(i.next(t))}catch(t){s(t)}}function a(t){try{l(i.throw(t))}catch(t){s(t)}}function l(t){var e;t.done?o(t.value):(e=t.value,e instanceof n?e:new n(function(t){t(e)})).then(r,a)}l((i=i.apply(t,e||[])).next())})},be=function(t){return this instanceof be?(this.v=t,this):new be(t)},ye=function(t,e,n){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var i,o=n.apply(t,e||[]),s=[];return i=Object.create(("function"==typeof AsyncIterator?AsyncIterator:Object).prototype),r("next"),r("throw"),r("return",function(t){return function(e){return Promise.resolve(e).then(t,c)}}),i[Symbol.asyncIterator]=function(){return this},i;function r(t,e){o[t]&&(i[t]=function(e){return new Promise(function(n,i){s.push([t,e,n,i])>1||a(t,e)})},e&&(i[t]=e(i[t])))}function a(t,e){try{(n=o[t](e)).value instanceof be?Promise.resolve(n.value.v).then(l,c):d(s[0][2],n)}catch(t){d(s[0][3],t)}var n}function l(t){a("next",t)}function c(t){a("throw",t)}function d(t,e){t(e),s.shift(),s.length&&a(s[0][0],s[0][1])}};class xe{constructor(){this.id="workflow-socket",this.name="Workflow Socket Provider",this.capabilities={streaming:!0,fileUpload:!0,modules:!0,functions:!1},this.socket=null,this.config=null,this.connected=!1,this.sessionId=`session_${Date.now()}_${Math.random().toString(36).substring(2,11)}`,this.activeExecutions=new Map}connect(t){return ve(this,void 0,void 0,function*(){if(!t.workflowId)throw new Error("Workflow ID is required");this.config=Object.assign({socketUrl:t.socketUrl||("undefined"!=typeof window?window.location.origin:"http://localhost:8000"),socketPath:t.socketPath||"/__nk_socketio/",triggerEndpoint:t.triggerEndpoint||"/api/v1/workflows/{workflowId}/trigger/chat",responseTimeout:t.responseTimeout||6e4},t);const e=`${this.config.socketUrl}/nk/apps/workflows/socket`;return this.socket=h(e,{path:this.config.socketPath,query:{l:JSON.stringify({workflowId:this.config.workflowId})},transports:["websocket","polling"],autoConnect:!0,reconnection:!0,reconnectionAttempts:5}),new Promise((t,e)=>{const n=setTimeout(()=>{e(new Error("Socket connection timeout"))},1e4);this.socket.on("connect",()=>{clearTimeout(n),this.connected=!0,console.log("[WorkflowSocketProvider] Connected:",this.socket.id),this.subscribeToWorkflow(this.config.workflowId),t()}),this.socket.on("connect_error",t=>{clearTimeout(n),console.error("[WorkflowSocketProvider] Connection error:",t),e(t)}),this.socket.on("disconnect",t=>{this.connected=!1,console.log("[WorkflowSocketProvider] Disconnected:",t)}),this.setupEventListeners()})})}subscribeToWorkflow(t){this.socket&&(this.socket.emit("nk:subscribe:workflow",{workflowId:t}),console.log("[WorkflowSocketProvider] Subscribed to workflow:",t))}subscribeToExecution(t){this.socket&&(this.socket.emit("nk:subscribe:execution",{executionId:t}),console.log("[WorkflowSocketProvider] Subscribed to execution:",t))}setupEventListeners(){this.socket&&(this.socket.onAny((t,...e)=>{console.log("[WorkflowSocketProvider] RAW event:",t,e[0])}),this.socket.on("nk:data",t=>{(null==t?void 0:t.event)&&t.data&&this._handleEvent(t.event,t.data)}),this.socket.on("execution:chat-message",t=>this._handleEvent("execution:chat-message",t)),this.socket.on("execution:started",t=>this._handleEvent("execution:started",t)),this.socket.on("execution:completed",t=>this._handleEvent("execution:completed",t)),this.socket.on("execution:failed",t=>this._handleEvent("execution:failed",t)),this.socket.on("execution:node-started",t=>this._handleEvent("execution:node-started",t)),this.socket.on("execution:node-completed",t=>this._handleEvent("execution:node-completed",t)))}_handleEvent(t,e){var n,i,o,s,r;switch(t){case"execution:chat-message":{const t=e.executionId,o=e.message;if(console.log("[WorkflowSocketProvider] Chat message received:",t,o),!t||!o)return;const s=this.activeExecutions.get(t);if(!s)return void(null===(i=null===(n=this.config)||void 0===n?void 0:n.onMessage)||void 0===i||i.call(n,o));s.completed||s.messages.push(o);break}case"execution:started":console.log("[WorkflowSocketProvider] Execution started (event):",e.executionId);break;case"execution:completed":{const t=e.executionId;if(console.log("[WorkflowSocketProvider] Execution completed:",t),!t)return;const n=this.activeExecutions.get(t);if(!n||n.completed)return;n.completed=!0;let i="";if(null===(o=this.config)||void 0===o?void 0:o.extractResponse)i=this.config.extractResponse(e);else if(n.messages.length>0)i=n.messages.join("\n\n");else if(e.outputData)try{const t="string"==typeof e.outputData?JSON.parse(e.outputData):e.outputData;i=t.response||t.message||t.result||JSON.stringify(t)}catch(t){i=e.outputData}n.resolve(i||"Workflow completed"),this.activeExecutions.delete(t);break}case"execution:failed":{const t=e.executionId,n=e.errorMessage||e.error||"Workflow execution failed";if(console.error("[WorkflowSocketProvider] Execution failed:",t,n),!t)return;const i=this.activeExecutions.get(t);if(!i||i.completed)return;i.completed=!0,i.reject(new Error(n)),this.activeExecutions.delete(t);break}case"execution:node-started":console.log("[WorkflowSocketProvider] Node started:",e.nodeName),e.nodeName&&(null===(s=this.onNodeStarted)||void 0===s||s.call(this,e.nodeName));break;case"execution:node-completed":console.log("[WorkflowSocketProvider] Node completed:",e.nodeName),e.nodeName&&(null===(r=this.onNodeCompleted)||void 0===r||r.call(this,e.nodeName))}}disconnect(){return ve(this,void 0,void 0,function*(){var t;this.socket&&((null===(t=this.config)||void 0===t?void 0:t.workflowId)&&this.socket.emit("nk:unsubscribe:workflow",{workflowId:this.config.workflowId}),this.socket.disconnect(),this.socket=null),this.connected=!1,this.activeExecutions.clear(),console.log("[WorkflowSocketProvider] Disconnected")})}isConnected(){var t;return this.connected&&!0===(null===(t=this.socket)||void 0===t?void 0:t.connected)}sendMessage(t,e){return ye(this,arguments,function*(){var n,i;if(!this.connected||!this.socket||!this.config)return yield yield be(this.formatError("Not Connected","Socket is not connected. Please check your connection.")),yield be(void 0);try{const o=this.buildInput(t,e),s=this.config.triggerEndpoint.replace("{workflowId}",this.config.workflowId),r=`${this.config.socketUrl}${s}`;console.log("[WorkflowSocketProvider] Triggering workflow:",r,o);const a=yield be(fetch(r,{method:"POST",headers:Object.assign({"Content-Type":"application/json"},this.config.headers),body:JSON.stringify(o)}));if(!a.ok){const t=yield be(a.text().catch(()=>a.statusText));return yield yield be(this.formatError(`${a.status} ${a.statusText}`,t)),yield be(void 0)}const l=a.headers.get("X-Execution-Id")||(null===(n=yield be(a.json().catch(()=>({}))))||void 0===n?void 0:n.executionId);if(!l)return yield yield be(this.formatError("Execution Error","No execution ID received from server")),yield be(void 0);console.log("[WorkflowSocketProvider] Execution started:",l),(null===(i=this.config)||void 0===i?void 0:i.onExecutionStart)&&this.config.onExecutionStart(l,this.config.workflowId),this.subscribeToExecution(l);const c=new Promise((t,e)=>{this.activeExecutions.set(l,{messages:[],resolve:t,reject:e,completed:!1}),setTimeout(()=>{const n=this.activeExecutions.get(l);n&&!n.completed&&(n.completed=!0,n.messages.length>0?t(n.messages.join("\n\n")):e(new Error("Execution timeout")),this.activeExecutions.delete(l))},this.config.responseTimeout)}),d=this.activeExecutions.get(l);let h=0;const u=setInterval(()=>{d.messages.length>h&&(h=d.messages.length)},100);try{for(;!d.completed;){if(d.messages.length>0){const t=d.messages.join("\n\n");yield yield be(t)}yield be(new Promise(t=>setTimeout(t,200)))}clearInterval(u);const t=yield be(c);yield yield be(t)}catch(t){throw clearInterval(u),t}}catch(t){const e=t instanceof Error?t.message:String(t);yield yield be(this.formatError("Workflow Error",e)),this.onError(t instanceof Error?t:new Error(String(t)))}})}buildInput(t,e){var n,i,o;if(null===(n=this.config)||void 0===n?void 0:n.buildInput)return this.config.buildInput(t,e);console.log("[WorkflowSocketProvider] buildInput context.uploadedFiles:",e.uploadedFiles);const s=(null===(i=e.currentThread)||void 0===i?void 0:i.id)||this.sessionId,r={message:t,threadId:s,modules:e.selectedModules,metadata:e.metadata,files:(null===(o=e.uploadedFiles)||void 0===o?void 0:o.map(t=>{var e;return{id:t.id,name:t.name,type:t.type,mimeType:t.mimeType,url:t.url,base64:null===(e=t.metadata)||void 0===e?void 0:e.base64}}))||[]};return console.log("[WorkflowSocketProvider] buildInput threadId:",s,"files count:",r.files.length),r}setWorkflowId(t){this.config&&(this.socket&&this.config.workflowId&&this.socket.emit("nk:unsubscribe:workflow",{workflowId:this.config.workflowId}),this.config.workflowId=t,this.socket&&this.connected&&this.subscribeToWorkflow(t))}getSocket(){return this.socket}uploadFile(t){return ve(this,void 0,void 0,function*(){const e=`file-${Date.now()}-${Math.random().toString(36).substring(2,9)}`,n=URL.createObjectURL(t),i=yield this.fileToBase64(t),o=t.type||"application/octet-stream",s=this.determineFileType(o);return console.log(`[WorkflowSocketProvider] File prepared: ${t.name} (${t.size} bytes)`),{id:e,name:t.name,size:t.size,type:s,mimeType:o,url:n,previewUrl:s===X.Image?n:void 0,uploadProgress:100,metadata:{provider:"workflow-socket",uploadedAt:(new Date).toISOString(),base64:i}}})}fileToBase64(t){return new Promise((e,n)=>{const i=new FileReader;i.onload=()=>{const t=i.result,n=t.split(",")[1]||t;e(n)},i.onerror=n,i.readAsDataURL(t)})}determineFileType(t){return t.startsWith("image/")?X.Image:t.startsWith("video/")?X.Video:t.startsWith("audio/")?X.Audio:t.startsWith("application/pdf")||t.includes("document")||t.startsWith("text/")?X.Document:t.includes("zip")||t.includes("rar")||t.includes("tar")?X.Archive:t.includes("javascript")||t.includes("json")||t.includes("xml")?X.Code:X.Unknown}formatError(t,e){return`[ERROR_START][ERROR_TITLE_START]${t}[ERROR_TITLE_END]${e}[ERROR_END]`}onError(t){console.error("[WorkflowSocketProvider] Error:",t)}}
2709
+ */var ve=function(t,e,n,i){return new(n||(n=Promise))(function(o,s){function r(t){try{l(i.next(t))}catch(t){s(t)}}function a(t){try{l(i.throw(t))}catch(t){s(t)}}function l(t){var e;t.done?o(t.value):(e=t.value,e instanceof n?e:new n(function(t){t(e)})).then(r,a)}l((i=i.apply(t,e||[])).next())})},be=function(t){return this instanceof be?(this.v=t,this):new be(t)},ye=function(t,e,n){if(!Symbol.asyncIterator)throw new TypeError("Symbol.asyncIterator is not defined.");var i,o=n.apply(t,e||[]),s=[];return i=Object.create(("function"==typeof AsyncIterator?AsyncIterator:Object).prototype),r("next"),r("throw"),r("return",function(t){return function(e){return Promise.resolve(e).then(t,c)}}),i[Symbol.asyncIterator]=function(){return this},i;function r(t,e){o[t]&&(i[t]=function(e){return new Promise(function(n,i){s.push([t,e,n,i])>1||a(t,e)})},e&&(i[t]=e(i[t])))}function a(t,e){try{(n=o[t](e)).value instanceof be?Promise.resolve(n.value.v).then(l,c):d(s[0][2],n)}catch(t){d(s[0][3],t)}var n}function l(t){a("next",t)}function c(t){a("throw",t)}function d(t,e){t(e),s.shift(),s.length&&a(s[0][0],s[0][1])}};class xe{constructor(){this.id="workflow-socket",this.name="Workflow Socket Provider",this.capabilities={streaming:!0,fileUpload:!0,modules:!0,functions:!1},this.socket=null,this.config=null,this.connected=!1,this.sessionId=`session_${Date.now()}_${Math.random().toString(36).substring(2,11)}`,this.activeExecutions=new Map}connect(t){return ve(this,void 0,void 0,function*(){if(!t.workflowId)throw new Error("Workflow ID is required");this.config=Object.assign({socketUrl:t.socketUrl||("undefined"!=typeof window?window.location.origin:"http://localhost:8000"),socketPath:t.socketPath||"/__nk_socketio/",triggerEndpoint:t.triggerEndpoint||"/api/v1/workflows/{workflowId}/trigger/chat",responseTimeout:t.responseTimeout||6e4},t);const e=`${this.config.socketUrl}/nk/apps/workflows/:workflowId`;return this.socket=h(e,{path:this.config.socketPath,query:{l:JSON.stringify({workflowId:this.config.workflowId})},transports:["websocket","polling"],autoConnect:!0,reconnection:!0,reconnectionAttempts:5}),new Promise((t,e)=>{const n=setTimeout(()=>{e(new Error("Socket connection timeout"))},1e4);this.socket.on("connect",()=>{clearTimeout(n),this.connected=!0,console.log("[WorkflowSocketProvider] Connected:",this.socket.id),this.subscribeToWorkflow(this.config.workflowId),t()}),this.socket.on("connect_error",t=>{clearTimeout(n),console.error("[WorkflowSocketProvider] Connection error:",t),e(t)}),this.socket.on("disconnect",t=>{this.connected=!1,console.log("[WorkflowSocketProvider] Disconnected:",t)}),this.setupEventListeners()})})}subscribeToWorkflow(t){this.socket&&(this.socket.emit("nk:subscribe:workflow",{workflowId:t}),console.log("[WorkflowSocketProvider] Subscribed to workflow:",t))}subscribeToExecution(t){this.socket&&(this.socket.emit("nk:subscribe:execution",{executionId:t}),console.log("[WorkflowSocketProvider] Subscribed to execution:",t))}setupEventListeners(){this.socket&&(this.socket.onAny((t,...e)=>{console.log("[WorkflowSocketProvider] RAW event:",t,e[0])}),this.socket.on("nk:data",t=>{(null==t?void 0:t.event)&&t.data&&this._handleEvent(t.event,t.data)}),this.socket.on("execution:chat-message",t=>this._handleEvent("execution:chat-message",t)),this.socket.on("execution:started",t=>this._handleEvent("execution:started",t)),this.socket.on("execution:completed",t=>this._handleEvent("execution:completed",t)),this.socket.on("execution:failed",t=>this._handleEvent("execution:failed",t)),this.socket.on("execution:node-started",t=>this._handleEvent("execution:node-started",t)),this.socket.on("execution:node-completed",t=>this._handleEvent("execution:node-completed",t)))}_handleEvent(t,e){var n,i,o,s,r;switch(t){case"execution:chat-message":{const t=e.executionId,o=e.message;if(console.log("[WorkflowSocketProvider] Chat message received:",t,o),!t||!o)return;const s=this.activeExecutions.get(t);if(!s)return void(null===(i=null===(n=this.config)||void 0===n?void 0:n.onMessage)||void 0===i||i.call(n,o));s.completed||s.messages.push(o);break}case"execution:started":console.log("[WorkflowSocketProvider] Execution started (event):",e.executionId);break;case"execution:completed":{const t=e.executionId;if(console.log("[WorkflowSocketProvider] Execution completed:",t),!t)return;const n=this.activeExecutions.get(t);if(!n||n.completed)return;n.completed=!0;let i="";if(null===(o=this.config)||void 0===o?void 0:o.extractResponse)i=this.config.extractResponse(e);else if(n.messages.length>0)i=n.messages.join("\n\n");else if(e.outputData)try{const t="string"==typeof e.outputData?JSON.parse(e.outputData):e.outputData;i=t.response||t.message||t.result||JSON.stringify(t)}catch(t){i=e.outputData}n.resolve(i||"Workflow completed"),this.activeExecutions.delete(t);break}case"execution:failed":{const t=e.executionId,n=e.errorMessage||e.error||"Workflow execution failed";if(console.error("[WorkflowSocketProvider] Execution failed:",t,n),!t)return;const i=this.activeExecutions.get(t);if(!i||i.completed)return;i.completed=!0,i.reject(new Error(n)),this.activeExecutions.delete(t);break}case"execution:node-started":console.log("[WorkflowSocketProvider] Node started:",e.nodeName),e.nodeName&&(null===(s=this.onNodeStarted)||void 0===s||s.call(this,e.nodeName));break;case"execution:node-completed":console.log("[WorkflowSocketProvider] Node completed:",e.nodeName),e.nodeName&&(null===(r=this.onNodeCompleted)||void 0===r||r.call(this,e.nodeName))}}disconnect(){return ve(this,void 0,void 0,function*(){var t;this.socket&&((null===(t=this.config)||void 0===t?void 0:t.workflowId)&&this.socket.emit("nk:unsubscribe:workflow",{workflowId:this.config.workflowId}),this.socket.disconnect(),this.socket=null),this.connected=!1,this.activeExecutions.clear(),console.log("[WorkflowSocketProvider] Disconnected")})}isConnected(){var t;return this.connected&&!0===(null===(t=this.socket)||void 0===t?void 0:t.connected)}sendMessage(t,e){return ye(this,arguments,function*(){var n,i;if(!this.connected||!this.socket||!this.config)return yield yield be(this.formatError("Not Connected","Socket is not connected. Please check your connection.")),yield be(void 0);try{const o=this.buildInput(t,e),s=this.config.triggerEndpoint.replace("{workflowId}",this.config.workflowId),r=`${this.config.socketUrl}${s}`;console.log("[WorkflowSocketProvider] Triggering workflow:",r,o);const a=yield be(fetch(r,{method:"POST",headers:Object.assign({"Content-Type":"application/json"},this.config.headers),body:JSON.stringify(o)}));if(!a.ok){const t=yield be(a.text().catch(()=>a.statusText));return yield yield be(this.formatError(`${a.status} ${a.statusText}`,t)),yield be(void 0)}const l=a.headers.get("X-Execution-Id")||(null===(n=yield be(a.json().catch(()=>({}))))||void 0===n?void 0:n.executionId);if(!l)return yield yield be(this.formatError("Execution Error","No execution ID received from server")),yield be(void 0);console.log("[WorkflowSocketProvider] Execution started:",l),(null===(i=this.config)||void 0===i?void 0:i.onExecutionStart)&&this.config.onExecutionStart(l,this.config.workflowId),this.subscribeToExecution(l);const c=new Promise((t,e)=>{this.activeExecutions.set(l,{messages:[],resolve:t,reject:e,completed:!1}),setTimeout(()=>{const n=this.activeExecutions.get(l);n&&!n.completed&&(n.completed=!0,n.messages.length>0?t(n.messages.join("\n\n")):e(new Error("Execution timeout")),this.activeExecutions.delete(l))},this.config.responseTimeout)}),d=this.activeExecutions.get(l);let h=0;const u=setInterval(()=>{d.messages.length>h&&(h=d.messages.length)},100);try{for(;!d.completed;){if(d.messages.length>0){const t=d.messages.join("\n\n");yield yield be(t)}yield be(new Promise(t=>setTimeout(t,200)))}clearInterval(u);const t=yield be(c);yield yield be(t)}catch(t){throw clearInterval(u),t}}catch(t){const e=t instanceof Error?t.message:String(t);yield yield be(this.formatError("Workflow Error",e)),this.onError(t instanceof Error?t:new Error(String(t)))}})}buildInput(t,e){var n,i,o;if(null===(n=this.config)||void 0===n?void 0:n.buildInput)return this.config.buildInput(t,e);console.log("[WorkflowSocketProvider] buildInput context.uploadedFiles:",e.uploadedFiles);const s=(null===(i=e.currentThread)||void 0===i?void 0:i.id)||this.sessionId,r={message:t,threadId:s,modules:e.selectedModules,metadata:e.metadata,files:(null===(o=e.uploadedFiles)||void 0===o?void 0:o.map(t=>{var e;return{id:t.id,name:t.name,type:t.type,mimeType:t.mimeType,url:t.url,base64:null===(e=t.metadata)||void 0===e?void 0:e.base64}}))||[]};return console.log("[WorkflowSocketProvider] buildInput threadId:",s,"files count:",r.files.length),r}setWorkflowId(t){this.config&&(this.socket&&this.config.workflowId&&this.socket.emit("nk:unsubscribe:workflow",{workflowId:this.config.workflowId}),this.config.workflowId=t,this.socket&&this.connected&&this.subscribeToWorkflow(t))}getSocket(){return this.socket}uploadFile(t){return ve(this,void 0,void 0,function*(){const e=`file-${Date.now()}-${Math.random().toString(36).substring(2,9)}`,n=URL.createObjectURL(t),i=yield this.fileToBase64(t),o=t.type||"application/octet-stream",s=this.determineFileType(o);return console.log(`[WorkflowSocketProvider] File prepared: ${t.name} (${t.size} bytes)`),{id:e,name:t.name,size:t.size,type:s,mimeType:o,url:n,previewUrl:s===X.Image?n:void 0,uploadProgress:100,metadata:{provider:"workflow-socket",uploadedAt:(new Date).toISOString(),base64:i}}})}fileToBase64(t){return new Promise((e,n)=>{const i=new FileReader;i.onload=()=>{const t=i.result,n=t.split(",")[1]||t;e(n)},i.onerror=n,i.readAsDataURL(t)})}determineFileType(t){return t.startsWith("image/")?X.Image:t.startsWith("video/")?X.Video:t.startsWith("audio/")?X.Audio:t.startsWith("application/pdf")||t.includes("document")||t.startsWith("text/")?X.Document:t.includes("zip")||t.includes("rar")||t.includes("tar")?X.Archive:t.includes("javascript")||t.includes("json")||t.includes("xml")?X.Code:X.Unknown}formatError(t,e){return`[ERROR_START][ERROR_TITLE_START]${t}[ERROR_TITLE_END]${e}[ERROR_END]`}onError(t){console.error("[WorkflowSocketProvider] Error:",t)}}
2710
2710
  /**
2711
2711
  * @license
2712
2712
  * Copyright 2024 Nuraly, Laabidi Aymen
@@ -84,7 +84,7 @@ export class WorkflowSocketProvider {
84
84
  this.config = Object.assign({ socketUrl: config.socketUrl || (typeof window !== 'undefined' ? window.location.origin : 'http://localhost:8000'), socketPath: config.socketPath || '/__nk_socketio/', triggerEndpoint: config.triggerEndpoint || '/api/v1/workflows/{workflowId}/trigger/chat', responseTimeout: config.responseTimeout || 60000 }, config);
85
85
  // Connect to the workflow socket namespace so socket.ts handler runs and
86
86
  // registers this socket in the execution bridge's subscriber map.
87
- const socketNs = `${this.config.socketUrl}/nk/apps/workflows/socket`;
87
+ const socketNs = `${this.config.socketUrl}/nk/apps/workflows/:workflowId`;
88
88
  this.socket = io(socketNs, {
89
89
  path: this.config.socketPath,
90
90
  query: { __params: JSON.stringify({ workflowId: this.config.workflowId }) },
@@ -1,9 +1,9 @@
1
- import{css as e,html as t,nothing as i,LitElement as s}from"lit";import{property as r,customElement as n,state as o}from"lit/decorators.js";
1
+ import{css as t,html as e,nothing as i,LitElement as s}from"lit";import{property as n,customElement as r,state as o}from"lit/decorators.js";
2
2
  /**
3
3
  * @license
4
4
  * Copyright 2023 Nuraly, Laabidi Aymen
5
5
  * SPDX-License-Identifier: MIT
6
- */const a=e=>class extends e{constructor(){super(...arguments),this.handleSystemThemeChange=()=>{this.closest("[data-theme]")||document.documentElement.hasAttribute("data-theme")||this.requestUpdate()}}connectedCallback(){super.connectedCallback(),this.setupThemeObserver(),this.setupDesignSystemObserver(),this.setupSystemThemeListener()}disconnectedCallback(){var e,t,i;super.disconnectedCallback(),null===(e=this.themeObserver)||void 0===e||e.disconnect(),null===(t=this.designSystemObserver)||void 0===t||t.disconnect(),null===(i=this.mediaQuery)||void 0===i||i.removeEventListener("change",this.handleSystemThemeChange)}get currentTheme(){var e,t;const i=(null===(e=this.closest("[data-theme]"))||void 0===e?void 0:e.getAttribute("data-theme"))||document.documentElement.getAttribute("data-theme");return i||((null===(t=window.matchMedia)||void 0===t?void 0:t.call(window,"(prefers-color-scheme: dark)").matches)?"dark":"light")}get currentDesignSystem(){var e;const t=(null===(e=this.closest("[design-system]"))||void 0===e?void 0:e.getAttribute("design-system"))||document.documentElement.getAttribute("design-system");return"carbon"===t?t:"default"}setupThemeObserver(){this.themeObserver=new MutationObserver(()=>{this.requestUpdate()}),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]})}setupDesignSystemObserver(){this.designSystemObserver=new MutationObserver(()=>{this.requestUpdate()}),this.designSystemObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["design-system"]})}setupSystemThemeListener(){window.matchMedia&&(this.mediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.mediaQuery.addEventListener("change",this.handleSystemThemeChange))}},c=()=>{var e;return void 0!==globalThis.litElementVersions||"undefined"!=typeof process&&"development"===(null===(e=process.env)||void 0===e?void 0:e.NODE_ENV)||"undefined"!=typeof window&&("localhost"===window.location.hostname||"127.0.0.1"===window.location.hostname)},h=e=>class extends e{constructor(){super(...arguments),this.requiredComponents=[]}validateDependencies(){if(c())for(const e of this.requiredComponents)if(!this.isComponentAvailable(e))throw new Error(`Required component "${e}" is not registered. Please import and register the component before using ${this.tagName.toLowerCase()}. Example: import '@nuralyui/${e}';`)}validateDependenciesWithHandler(e){if(!c())return!0;let t=!0;for(const i of this.requiredComponents)if(!this.isComponentAvailable(i)){t=!1;const s=new Error(`Required component "${i}" is not registered. Please import and register the component before using ${this.tagName.toLowerCase()}.`);e?e(i,s):console.error(s.message)}return t}isComponentAvailable(e){return!!customElements.get(e)}getMissingDependencies(){return this.requiredComponents.filter(e=>!this.isComponentAvailable(e))}areDependenciesAvailable(){return this.requiredComponents.every(e=>this.isComponentAvailable(e))}addRequiredComponent(e){this.requiredComponents.includes(e)||this.requiredComponents.push(e)}removeRequiredComponent(e){const t=this.requiredComponents.indexOf(e);t>-1&&this.requiredComponents.splice(t,1)}},d=e=>class extends e{dispatchCustomEvent(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}dispatchEventWithMetadata(e,t){var i;const s=Object.assign(Object.assign({},t),{timestamp:Date.now(),componentName:(null===(i=this.tagName)||void 0===i?void 0:i.toLowerCase())||"unknown"});this.dispatchCustomEvent(e,s)}dispatchInputEvent(e,t){const i=Object.assign({target:t.target||this,value:t.value,originalEvent:t.originalEvent},t);this.dispatchCustomEvent(e,i)}dispatchFocusEvent(e,t){const i=Object.assign({target:t.target||this,value:t.value,focused:t.focused,cursorPosition:t.cursorPosition,selectedText:t.selectedText},t);this.dispatchCustomEvent(e,i)}dispatchValidationEvent(e,t){var i;const s=Object.assign({target:t.target||this,value:t.value,isValid:null!==(i=t.isValid)&&void 0!==i&&i,error:t.error},t);this.dispatchCustomEvent(e,s)}dispatchActionEvent(e,t){const i=Object.assign({target:t.target||this,action:t.action,previousValue:t.previousValue,newValue:t.newValue},t);this.dispatchCustomEvent(e,i)}isReadonlyKeyAllowed(e){if(e.ctrlKey||e.metaKey){return["KeyA","KeyC"].includes(e.code)}return["Tab","Escape","ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Home","End","PageUp","PageDown"].includes(e.key)}isActivationKey(e){return"Enter"===e.key||" "===e.key}},l=new Set,p=new Map;
6
+ */const a=t=>class extends t{constructor(){super(...arguments),this.handleSystemThemeChange=()=>{this.closest("[data-theme]")||document.documentElement.hasAttribute("data-theme")||this.requestUpdate()}}connectedCallback(){super.connectedCallback(),this.setupThemeObserver(),this.setupDesignSystemObserver(),this.setupSystemThemeListener()}disconnectedCallback(){var t,e,i;super.disconnectedCallback(),null===(t=this.themeObserver)||void 0===t||t.disconnect(),null===(e=this.designSystemObserver)||void 0===e||e.disconnect(),null===(i=this.mediaQuery)||void 0===i||i.removeEventListener("change",this.handleSystemThemeChange)}get currentTheme(){var t,e;const i=(null===(t=this.closest("[data-theme]"))||void 0===t?void 0:t.getAttribute("data-theme"))||document.documentElement.getAttribute("data-theme");return i||((null===(e=window.matchMedia)||void 0===e?void 0:e.call(window,"(prefers-color-scheme: dark)").matches)?"dark":"light")}get currentDesignSystem(){var t;const e=(null===(t=this.closest("[design-system]"))||void 0===t?void 0:t.getAttribute("design-system"))||document.documentElement.getAttribute("design-system");return"carbon"===e?e:"default"}setupThemeObserver(){this.themeObserver=new MutationObserver(()=>{this.requestUpdate()}),this.themeObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["data-theme"]})}setupDesignSystemObserver(){this.designSystemObserver=new MutationObserver(()=>{this.requestUpdate()}),this.designSystemObserver.observe(document.documentElement,{attributes:!0,attributeFilter:["design-system"]})}setupSystemThemeListener(){window.matchMedia&&(this.mediaQuery=window.matchMedia("(prefers-color-scheme: dark)"),this.mediaQuery.addEventListener("change",this.handleSystemThemeChange))}},c=()=>{var t;return void 0!==globalThis.litElementVersions||"undefined"!=typeof process&&"development"===(null===(t=process.env)||void 0===t?void 0:t.NODE_ENV)||"undefined"!=typeof window&&("localhost"===window.location.hostname||"127.0.0.1"===window.location.hostname)},h=t=>class extends t{constructor(){super(...arguments),this.requiredComponents=[]}validateDependencies(){if(c())for(const t of this.requiredComponents)if(!this.isComponentAvailable(t))throw new Error(`Required component "${t}" is not registered. Please import and register the component before using ${this.tagName.toLowerCase()}. Example: import '@nuralyui/${t}';`)}validateDependenciesWithHandler(t){if(!c())return!0;let e=!0;for(const i of this.requiredComponents)if(!this.isComponentAvailable(i)){e=!1;const s=new Error(`Required component "${i}" is not registered. Please import and register the component before using ${this.tagName.toLowerCase()}.`);t?t(i,s):console.error(s.message)}return e}isComponentAvailable(t){return!!customElements.get(t)}getMissingDependencies(){return this.requiredComponents.filter(t=>!this.isComponentAvailable(t))}areDependenciesAvailable(){return this.requiredComponents.every(t=>this.isComponentAvailable(t))}addRequiredComponent(t){this.requiredComponents.includes(t)||this.requiredComponents.push(t)}removeRequiredComponent(t){const e=this.requiredComponents.indexOf(t);e>-1&&this.requiredComponents.splice(e,1)}},d=t=>class extends t{dispatchCustomEvent(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}dispatchEventWithMetadata(t,e){var i;const s=Object.assign(Object.assign({},e),{timestamp:Date.now(),componentName:(null===(i=this.tagName)||void 0===i?void 0:i.toLowerCase())||"unknown"});this.dispatchCustomEvent(t,s)}dispatchInputEvent(t,e){const i=Object.assign({target:e.target||this,value:e.value,originalEvent:e.originalEvent},e);this.dispatchCustomEvent(t,i)}dispatchFocusEvent(t,e){const i=Object.assign({target:e.target||this,value:e.value,focused:e.focused,cursorPosition:e.cursorPosition,selectedText:e.selectedText},e);this.dispatchCustomEvent(t,i)}dispatchValidationEvent(t,e){var i;const s=Object.assign({target:e.target||this,value:e.value,isValid:null!==(i=e.isValid)&&void 0!==i&&i,error:e.error},e);this.dispatchCustomEvent(t,s)}dispatchActionEvent(t,e){const i=Object.assign({target:e.target||this,action:e.action,previousValue:e.previousValue,newValue:e.newValue},e);this.dispatchCustomEvent(t,i)}isReadonlyKeyAllowed(t){if(t.ctrlKey||t.metaKey){return["KeyA","KeyC"].includes(t.code)}return["Tab","Escape","ArrowLeft","ArrowRight","ArrowUp","ArrowDown","Home","End","PageUp","PageDown"].includes(t.key)}isActivationKey(t){return"Enter"===t.key||" "===t.key}},l=new Set,p=new Map;
7
7
  /**
8
8
  * @license
9
9
  * Copyright 2023 Nuraly, Laabidi Aymen
@@ -14,12 +14,12 @@ import{css as e,html as t,nothing as i,LitElement as s}from"lit";import{property
14
14
  * Copyright 2023 Nuraly, Laabidi Aymen
15
15
  * SPDX-License-Identifier: MIT
16
16
  */
17
- const u=e=>{class t extends e{constructor(){super(...arguments),this.t=null}createRenderRoot(){return this.constructor.useShadowDom?super.createRenderRoot():this}connectedCallback(){const e=this.constructor.useShadowDom;if(!e&&null===this.t)for(this.t=[];this.firstChild;)this.t.push(this.removeChild(this.firstChild));if(super.connectedCallback(),!e){const e=this.constructor,t=this.tagName.toLowerCase(),i=e.styles;if(i){const e=m(i);e&&function(e,t,i){var s;if(!p.has(e)){const i=new CSSStyleSheet;i.replaceSync(t),p.set(e,i)}const r=p.get(e),n=`doc:${e}`;if(l.has(n)||(document.adoptedStyleSheets=[...document.adoptedStyleSheets,r],l.add(n)),i){let t=i;for(;t;){const i=t.getRootNode();if(!(i instanceof ShadowRoot))break;{const n=`shadow:${((null===(s=i.host)||void 0===s?void 0:s.tagName)||"").toLowerCase()}:${e}`;l.has(n)||(i.adoptedStyleSheets=[...i.adoptedStyleSheets,r],l.add(n)),t=i.host}}}}(t,e,this)}}}get lightChildren(){return this.t?this.t.filter(e=>!(e instanceof Element&&e.hasAttribute("slot"))):[]}lightChildrenNamed(e){return this.t?this.t.filter(t=>t instanceof Element&&t.getAttribute("slot")===e):[]}}return t.useShadowDom=!1,t},f=e=>h(a(d(u(e))));function m(e){return Array.isArray(e)?e.map(e=>m(e)).filter(Boolean).join("\n"):e&&"string"==typeof e.cssText?e.cssText:"string"==typeof e?e:""}
17
+ const u=t=>{class e extends t{constructor(){super(...arguments),this.t=null}createRenderRoot(){return this.constructor.useShadowDom?super.createRenderRoot():this}connectedCallback(){const t=this.constructor.useShadowDom;if(!t&&null===this.t)for(this.t=[];this.firstChild;)this.t.push(this.removeChild(this.firstChild));if(super.connectedCallback(),!t){const t=this.constructor,e=this.tagName.toLowerCase(),i=t.styles;if(i){const t=f(i);t&&function(t,e,i){var s;if(!p.has(t)){const i=new CSSStyleSheet;i.replaceSync(e),p.set(t,i)}const n=p.get(t),r=`doc:${t}`;if(l.has(r)||(document.adoptedStyleSheets=[...document.adoptedStyleSheets,n],l.add(r)),i){let e=i;for(;e;){const i=e.getRootNode();if(!(i instanceof ShadowRoot))break;{const r=`shadow:${((null===(s=i.host)||void 0===s?void 0:s.tagName)||"").toLowerCase()}:${t}`;l.has(r)||(i.adoptedStyleSheets=[...i.adoptedStyleSheets,n],l.add(r)),e=i.host}}}}(e,t,this)}}}get lightChildren(){return this.t?this.t.filter(t=>!(t instanceof Element&&t.hasAttribute("slot"))):[]}lightChildrenNamed(t){return this.t?this.t.filter(e=>e instanceof Element&&e.getAttribute("slot")===t):[]}}return e.useShadowDom=!1,e},v=t=>h(a(d(u(t))));function f(t){return Array.isArray(t)?t.map(t=>f(t)).filter(Boolean).join("\n"):t&&"string"==typeof t.cssText?t.cssText:"string"==typeof t?t:""}
18
18
  /**
19
19
  * @license
20
20
  * Copyright 2024 Nuraly, Laabidi Aymen
21
21
  * SPDX-License-Identifier: MIT
22
- */const v=e`
22
+ */const m=t`
23
23
  :host {
24
24
  display: contents;
25
25
  }
@@ -28,7 +28,7 @@ const u=e=>{class t extends e{constructor(){super(...arguments),this.t=null}crea
28
28
  * @license
29
29
  * Copyright 2024 Nuraly, Laabidi Aymen
30
30
  * SPDX-License-Identifier: MIT
31
- */,b=e`
31
+ */,g=t`
32
32
  :host { display: flex; align-items: center; }
33
33
 
34
34
  .presence {
@@ -130,30 +130,30 @@ const u=e=>{class t extends e{constructor(){super(...arguments),this.t=null}crea
130
130
  * @license
131
131
  * Copyright 2024 Nuraly, Laabidi Aymen
132
132
  * SPDX-License-Identifier: MIT
133
- */;var g=function(e,t,i,s){for(var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s,a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o};let x=class extends(f(s)){constructor(){super(...arguments),this.users=[],this.max=5}_handleClick(e){this.dispatchEvent(new CustomEvent("user-click",{detail:{user:e},bubbles:!0,composed:!0}))}render(){const e=this.users.slice(0,this.max),s=Math.max(0,this.users.length-this.max);return t`
133
+ */;var b=function(t,e,i,s){for(var n,r=arguments.length,o=r<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s,a=t.length-1;a>=0;a--)(n=t[a])&&(o=(r<3?n(o):r>3?n(e,i,o):n(e,i))||o);return r>3&&o&&Object.defineProperty(e,i,o),o};let x=class extends(v(s)){constructor(){super(...arguments),this.users=[],this.max=5}_handleClick(t){this.dispatchEvent(new CustomEvent("user-click",{detail:{user:t},bubbles:!0,composed:!0}))}render(){const t=this.users.slice(0,this.max),s=Math.max(0,this.users.length-this.max);return e`
134
134
  <div class="presence">
135
- ${e.map(e=>t`
136
- <div class="pa" @click=${()=>this._handleClick(e)}>
137
- <div class="pa-avatar" style="background:${e.color}">
138
- ${e.avatarUrl?t`<img src="${e.avatarUrl}" alt="${e.displayName}">`:e.initials||(e.displayName||"?")[0].toUpperCase()}
135
+ ${t.map(t=>e`
136
+ <div class="pa" @click=${()=>this._handleClick(t)}>
137
+ <div class="pa-avatar" style="background:${t.color}">
138
+ ${t.avatarUrl?e`<img src="${t.avatarUrl}" alt="${t.displayName}">`:t.initials||(t.displayName||"?")[0].toUpperCase()}
139
139
  </div>
140
140
  <span class="pa-dot"></span>
141
- <span class="pa-tip">${e.displayName}</span>
141
+ <span class="pa-tip">${t.displayName}</span>
142
142
  </div>
143
143
  `)}
144
- ${s>0?t`
144
+ ${s>0?e`
145
145
  <div class="pa pa-extra">
146
146
  <div class="pa-avatar" title="${s} more">+${s}</div>
147
147
  </div>
148
148
  `:i}
149
149
  </div>
150
- `}};x.styles=b,x.useShadowDom=!0,g([r({type:Array})],x.prototype,"users",void 0),g([r({type:Number})],x.prototype,"max",void 0),x=g([n("nr-presence-avatars")],x);
150
+ `}};x.styles=g,x.useShadowDom=!0,b([n({type:Array})],x.prototype,"users",void 0),b([n({type:Number})],x.prototype,"max",void 0),x=b([r("nr-presence-avatars")],x);
151
151
  /**
152
152
  * @license
153
153
  * Copyright 2024 Nuraly, Laabidi Aymen
154
154
  * SPDX-License-Identifier: MIT
155
155
  */
156
- const w=e`
156
+ const y=t`
157
157
  :host {
158
158
  position: fixed;
159
159
  display: block;
@@ -398,7 +398,7 @@ const w=e`
398
398
  * @license
399
399
  * Copyright 2024 Nuraly, Laabidi Aymen
400
400
  * SPDX-License-Identifier: MIT
401
- */;var y=function(e,t,i,s){for(var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s,a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o};let k=class extends(f(s)){constructor(){super(...arguments),this.user={displayName:"",color:"#7c3aed"},this.x=300,this.y=200,this.z=100,this.minimized=!1,this.minimizedIndex=0,this.messages=[],this._draft=""}_emit(e,t){this.dispatchEvent(new CustomEvent(e,{detail:t,bubbles:!0,composed:!0}))}_onHeaderMousedown(e){if(this.minimized)return;const t=this.getBoundingClientRect();this._emit("drag-start",{offsetX:e.clientX-t.left,offsetY:e.clientY-t.top}),e.preventDefault()}_onHeaderClick(){this.minimized&&this._emit("restore")}_onSend(){const e=this._draft.trim();e&&(this._emit("send",{text:e}),this._draft="")}_onInputKeydown(e){"Enter"===e.key&&this._onSend(),"Escape"===e.key&&this._emit("close")}updated(){this.style.position="fixed",this.style.display="block",this.style.width="300px",this.minimized?(this.style.right=12+212*this.minimizedIndex+"px",this.style.bottom="0",this.style.top="auto",this.style.left="auto"):(this.style.left=`${this.x}px`,this.style.top=`${this.y}px`,this.style.right="auto",this.style.bottom="auto"),this.style.zIndex=String(this.z)}render(){return t`
401
+ */;var w=function(t,e,i,s){for(var n,r=arguments.length,o=r<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s,a=t.length-1;a>=0;a--)(n=t[a])&&(o=(r<3?n(o):r>3?n(e,i,o):n(e,i))||o);return r>3&&o&&Object.defineProperty(e,i,o),o};let k=class extends(v(s)){constructor(){super(...arguments),this.user={displayName:"",color:"#7c3aed"},this.x=300,this.y=200,this.z=100,this.minimized=!1,this.minimizedIndex=0,this.messages=[],this.loading=!1,this._draft=""}_emit(t,e){this.dispatchEvent(new CustomEvent(t,{detail:e,bubbles:!0,composed:!0}))}_onHeaderMousedown(t){if(this.minimized)return;const e=this.getBoundingClientRect();this._emit("drag-start",{offsetX:t.clientX-e.left,offsetY:t.clientY-e.top}),t.preventDefault()}_onHeaderClick(){this.minimized&&this._emit("restore")}_onSend(){const t=this._draft.trim();t&&(this._emit("send",{text:t}),this._draft="")}_onInputKeydown(t){"Enter"===t.key&&this._onSend(),"Escape"===t.key&&this._emit("close")}updated(){this.style.position="fixed",this.style.display="block",this.style.width="300px",this.minimized?(this.style.right=12+212*this.minimizedIndex+"px",this.style.bottom="0",this.style.top="auto",this.style.left="auto"):(this.style.left=`${this.x}px`,this.style.top=`${this.y}px`,this.style.right="auto",this.style.bottom="auto"),this.style.zIndex=String(this.z)}render(){return e`
402
402
  <div
403
403
  class="chat-panel${this.minimized?" minimized":""}"
404
404
  @mousedown=${()=>this._emit("focus")}
@@ -409,19 +409,19 @@ const w=e`
409
409
  @click=${this._onHeaderClick}
410
410
  >
411
411
  <div class="chat-header-avatar" style="background:${this.user.color}">
412
- ${this.user.avatarUrl?t`<img src="${this.user.avatarUrl}" alt="${this.user.displayName}">`:this.user.initials||(this.user.displayName||"?")[0].toUpperCase()}
412
+ ${this.user.avatarUrl?e`<img src="${this.user.avatarUrl}" alt="${this.user.displayName}">`:this.user.initials||(this.user.displayName||"?")[0].toUpperCase()}
413
413
  </div>
414
414
  <div class="chat-header-info">
415
415
  <div class="chat-header-name">${this.user.displayName}</div>
416
- ${this.minimized?i:t`<div class="chat-header-status">Online</div>`}
416
+ ${this.minimized?i:e`<div class="chat-header-status">Online</div>`}
417
417
  </div>
418
418
 
419
- ${this.minimized?t`
419
+ ${this.minimized?e`
420
420
  <button
421
421
  class="chat-btn"
422
422
  title="Float"
423
- @mousedown=${e=>e.stopPropagation()}
424
- @click=${e=>{e.stopPropagation(),this._emit("float")}}
423
+ @mousedown=${t=>t.stopPropagation()}
424
+ @click=${t=>{t.stopPropagation(),this._emit("float")}}
425
425
  >
426
426
  <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
427
427
  <polyline points="15 3 21 3 21 9"/>
@@ -430,12 +430,12 @@ const w=e`
430
430
  <line x1="3" y1="21" x2="10" y2="14"/>
431
431
  </svg>
432
432
  </button>
433
- `:t`
433
+ `:e`
434
434
  <button
435
435
  class="chat-btn"
436
436
  title="Minimize"
437
- @mousedown=${e=>e.stopPropagation()}
438
- @click=${e=>{e.stopPropagation(),this._emit("minimize")}}
437
+ @mousedown=${t=>t.stopPropagation()}
438
+ @click=${t=>{t.stopPropagation(),this._emit("minimize")}}
439
439
  >
440
440
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
441
441
  <line x1="5" y1="12" x2="19" y2="12"/>
@@ -446,8 +446,8 @@ const w=e`
446
446
  <button
447
447
  class="chat-btn"
448
448
  title="Close"
449
- @mousedown=${e=>e.stopPropagation()}
450
- @click=${e=>{e.stopPropagation(),this._emit("close")}}
449
+ @mousedown=${t=>t.stopPropagation()}
450
+ @click=${t=>{t.stopPropagation(),this._emit("close")}}
451
451
  >
452
452
  <svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
453
453
  <path d="M18 6 6 18M6 6l12 12"/>
@@ -456,7 +456,11 @@ const w=e`
456
456
  </div>
457
457
 
458
458
  <div class="chat-messages">
459
- ${0===this.messages.length?t`
459
+ ${this.loading?e`
460
+ <div class="chat-empty">
461
+ <span>Loading...</span>
462
+ </div>
463
+ `:0===this.messages.length?e`
460
464
  <div class="chat-empty">
461
465
  <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
462
466
  <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
@@ -464,10 +468,10 @@ const w=e`
464
468
  <span>No messages yet</span>
465
469
  <span style="font-size:11px">Say hi to ${this.user.displayName}!</span>
466
470
  </div>
467
- `:this.messages.map(e=>t`
468
- <div class="chat-msg ${e.me?"me":"other"}">
469
- <div class="chat-bubble">${e.text}</div>
470
- <span class="chat-time">${new Date(e.timestamp).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}</span>
471
+ `:this.messages.map(t=>e`
472
+ <div class="chat-msg ${t.me?"me":"other"}">
473
+ <div class="chat-bubble">${t.text}</div>
474
+ <span class="chat-time">${new Date(t.timestamp).toLocaleTimeString([],{hour:"2-digit",minute:"2-digit"})}</span>
471
475
  </div>
472
476
  `)}
473
477
  </div>
@@ -478,12 +482,13 @@ const w=e`
478
482
  class="chat-input"
479
483
  placeholder="Type a message..."
480
484
  .value=${this._draft}
481
- @input=${e=>{this._draft=e.target.value}}
485
+ ?disabled=${this.loading}
486
+ @input=${t=>{this._draft=t.target.value}}
482
487
  @keydown=${this._onInputKeydown}
483
488
  >
484
489
  <button
485
490
  class="chat-send"
486
- ?disabled=${!this._draft.trim()}
491
+ ?disabled=${!this._draft.trim()||this.loading}
487
492
  @click=${this._onSend}
488
493
  >
489
494
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
@@ -493,19 +498,28 @@ const w=e`
493
498
  </button>
494
499
  </div>
495
500
  </div>
496
- `}};k.styles=w,k.useShadowDom=!0,y([r({type:Object})],k.prototype,"user",void 0),y([r({type:Number})],k.prototype,"x",void 0),y([r({type:Number})],k.prototype,"y",void 0),y([r({type:Number})],k.prototype,"z",void 0),y([r({type:Boolean})],k.prototype,"minimized",void 0),y([r({type:Number})],k.prototype,"minimizedIndex",void 0),y([r({type:Array})],k.prototype,"messages",void 0),y([o()],k.prototype,"_draft",void 0),k=y([n("nr-presence-chat")],k);
501
+ `}};k.styles=y,k.useShadowDom=!0,w([n({type:Object})],k.prototype,"user",void 0),w([n({type:Number})],k.prototype,"x",void 0),w([n({type:Number})],k.prototype,"y",void 0),w([n({type:Number})],k.prototype,"z",void 0),w([n({type:Boolean})],k.prototype,"minimized",void 0),w([n({type:Number})],k.prototype,"minimizedIndex",void 0),w([n({type:Array})],k.prototype,"messages",void 0),w([n({type:Boolean})],k.prototype,"loading",void 0),w([o()],k.prototype,"_draft",void 0),k=w([r("nr-presence-chat")],k);
497
502
  /**
498
503
  * @license
499
504
  * Copyright 2024 Nuraly, Laabidi Aymen
500
505
  * SPDX-License-Identifier: MIT
501
506
  */
502
- var $=function(e,t,i,s){for(var r,n=arguments.length,o=n<3?t:null===s?s=Object.getOwnPropertyDescriptor(t,i):s,a=e.length-1;a>=0;a--)(r=e[a])&&(o=(n<3?r(o):n>3?r(t,i,o):r(t,i))||o);return n>3&&o&&Object.defineProperty(t,i,o),o},z=function(e,t,i,s){return new(i||(i=Promise))(function(r,n){function o(e){try{c(s.next(e))}catch(e){n(e)}}function a(e){try{c(s.throw(e))}catch(e){n(e)}}function c(e){var t;e.done?r(e.value):(t=e.value,t instanceof i?t:new i(function(e){e(t)})).then(o,a)}c((s=s.apply(e,t||[])).next())})};let C=class extends(f(s)){constructor(){super(...arguments),this.namespace="",this.socketPath="/__nk_socketio/",this.resourceId="",this.userId="",this.currentUser=null,this.extraUsers=[],this._viewers=[],this._socket=null,this._chats=new Map,this._chatZ=100,this._drag=null,this._boundDragMove=e=>this._onDragMove(e),this._boundDragEnd=()=>this._onDragEnd(),this._boundEscape=e=>this._onEscape(e)}connectedCallback(){super.connectedCallback(),document.addEventListener("keydown",this._boundEscape),this._connect()}disconnectedCallback(){var e;super.disconnectedCallback(),document.removeEventListener("keydown",this._boundEscape),document.removeEventListener("mousemove",this._boundDragMove),document.removeEventListener("mouseup",this._boundDragEnd),null===(e=this._socket)||void 0===e||e.disconnect(),this._socket=null}_connect(){return z(this,void 0,void 0,function*(){if(this.userId&&this.resourceId&&this.namespace)try{const{io:e}=yield import("socket.io-client");this._socket=e(this.namespace,{path:this.socketPath,query:{i:JSON.stringify({userId:this.userId,resourceId:this.resourceId})}}),this._socket.on("nk:data",e=>{var t;const i=e.event;"presence:viewers"!==i&&"presence:joined"!==i&&"presence:left"!==i||(this._viewers=(null===(t=e.data)||void 0===t?void 0:t.viewers)||[],this.dispatchEvent(new CustomEvent("presence-changed",{detail:{viewers:this._viewers},bubbles:!0,composed:!0})))})}catch(e){console.error("[nr-presence] Connection failed:",e)}})}_openChat(e){const t=e.userId||e.displayName;if(this._chats.has(t))this._chats.get(t).z=++this._chatZ;else{const i=24*this._chats.size,s=window.innerWidth-324-i,r=56+i;this._chats.set(t,{user:e,x:s,y:r,savedX:s,savedY:r,z:++this._chatZ,minimized:!1,messages:[],draftText:""})}this.requestUpdate()}_closeChat(e){this._chats.delete(e),this.requestUpdate()}_onEscape(e){if("Escape"!==e.key||0===this._chats.size)return;let t="",i=-1;for(const[e,s]of this._chats)s.z>i&&(i=s.z,t=e);if(!t)return;const s=this._chats.get(t);s.minimized?this._closeChat(t):(s.savedX=s.x,s.savedY=s.y,s.minimized=!0,this.requestUpdate())}_onDragStart(e,t,i){const s=this._chats.get(e);s&&(s.z=++this._chatZ,this._drag={userId:e,ox:t,oy:i},document.addEventListener("mousemove",this._boundDragMove),document.addEventListener("mouseup",this._boundDragEnd))}_onDragMove(e){if(!this._drag)return;const t=this._chats.get(this._drag.userId);t&&(t.x=Math.max(0,Math.min(window.innerWidth-300,e.clientX-this._drag.ox)),t.y=Math.max(0,Math.min(window.innerHeight-60,e.clientY-this._drag.oy)),this.requestUpdate())}_onDragEnd(){this._drag=null,document.removeEventListener("mousemove",this._boundDragMove),document.removeEventListener("mouseup",this._boundDragEnd)}render(){const e=this.currentUser,s=[...e?[e]:[],...this._viewers.filter(t=>!e||t.userId!==e.userId),...this.extraUsers],r=[...this._chats.entries()].filter(([,e])=>e.minimized);return t`
507
+ var $=function(t,e,i,s){for(var n,r=arguments.length,o=r<3?e:null===s?s=Object.getOwnPropertyDescriptor(e,i):s,a=t.length-1;a>=0;a--)(n=t[a])&&(o=(r<3?n(o):r>3?n(e,i,o):n(e,i))||o);return r>3&&o&&Object.defineProperty(e,i,o),o},z=function(t,e,i,s){return new(i||(i=Promise))(function(n,r){function o(t){try{c(s.next(t))}catch(t){r(t)}}function a(t){try{c(s.throw(t))}catch(t){r(t)}}function c(t){var e;t.done?n(t.value):(e=t.value,e instanceof i?e:new i(function(t){t(e)})).then(o,a)}c((s=s.apply(t,e||[])).next())})};const S="__group__";let C=class extends(v(s)){constructor(){super(...arguments),this.namespace="",this.socketPath="/__nk_socketio/",this.resourceId="",this.resourceType="",this.resourceName="",this.userId="",this.currentUser=null,this.extraUsers=[],this.globalSocket=null,this._viewers=[],this._hasUnreadGroup=!1,this._socket=null,this._connecting=!1,this._chats=new Map,this._chatZ=100,this._drag=null,this._boundDragMove=t=>this._onDragMove(t),this._boundDragEnd=()=>this._onDragEnd(),this._boundEscape=t=>this._onEscape(t),this._boundOnMessage=t=>this._onSocketMessage(t),this._groupConversationId=null}connectedCallback(){super.connectedCallback(),document.addEventListener("keydown",this._boundEscape),this._connect(),this._attachGlobalSocket()}disconnectedCallback(){var t;super.disconnectedCallback(),document.removeEventListener("keydown",this._boundEscape),document.removeEventListener("mousemove",this._boundDragMove),document.removeEventListener("mouseup",this._boundDragEnd),null===(t=this._socket)||void 0===t||t.disconnect(),this._socket=null,this._detachGlobalSocket()}updated(t){t.has("globalSocket")&&(this._detachGlobalSocket(t.get("globalSocket")),this._attachGlobalSocket()),!this._socket&&(t.has("userId")||t.has("resourceId")||t.has("namespace"))&&this.userId&&this.resourceId&&this.namespace&&this._connect()}_attachGlobalSocket(){this.globalSocket&&this.globalSocket.on("nk:data",this._boundOnMessage)}_detachGlobalSocket(t){const e=t||this.globalSocket;e&&e.off("nk:data",this._boundOnMessage)}_onSocketMessage(t){if("message:new"!==t.event)return;const e=t.data;if((null==e?void 0:e.conversationId)&&e.senderId!==this.userId){for(const[,t]of this._chats)if(t.conversationId===e.conversationId)return t.messages=[...t.messages,{id:String(e.id),senderId:e.senderId,text:e.content,timestamp:new Date(e.createdAt).getTime(),me:!1}],void this.requestUpdate();this._groupConversationId&&e.conversationId===this._groupConversationId&&(this._hasUnreadGroup=!0)}}_connect(){return z(this,void 0,void 0,function*(){if(!this._socket&&!this._connecting&&this.userId&&this.resourceId&&this.namespace){this._connecting=!0;try{const{io:t}=yield import("socket.io-client");this._socket=t(this.namespace,{path:this.socketPath,query:{i:JSON.stringify({userId:this.userId,resourceId:this.resourceId})}}),this._socket.on("nk:data",t=>{var e;const i=t.event;"presence:viewers"!==i&&"presence:joined"!==i&&"presence:left"!==i||(this._viewers=(null===(e=t.data)||void 0===e?void 0:e.viewers)||[],this.dispatchEvent(new CustomEvent("presence-changed",{detail:{viewers:this._viewers},bubbles:!0,composed:!0})))})}catch(t){console.error("[nr-presence] Connection failed:",t)}finally{this._connecting=!1}}})}_openGroupChat(){return z(this,void 0,void 0,function*(){var t;if(this._chats.has(S)){const t=this._chats.get(S);return t.minimized=!1,t.z=++this._chatZ,this._hasUnreadGroup=!1,void this.requestUpdate()}const e=window.innerWidth-324;this._chats.set(S,{user:{displayName:this.resourceName||`${this.resourceType} chat`,color:"#7c3aed",initials:"#"},conversationId:null,loading:!0,x:e,y:56,savedX:e,savedY:56,z:++this._chatZ,minimized:!1,messages:[],draftText:""}),this._hasUnreadGroup=!1,this.requestUpdate();try{const e=yield fetch("/api/conversations/resource",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({resourceType:this.resourceType,resourceId:this.resourceId,resourceName:this.resourceName})}),i=yield e.json(),s=this._chats.get(S);if(!s||!i.conversationId)return s&&(s.loading=!1),void this.requestUpdate();s.conversationId=i.conversationId,this._groupConversationId=i.conversationId,(null===(t=this.globalSocket)||void 0===t?void 0:t.connected)&&this.globalSocket.emit("nk:conversation:join",{conversationId:i.conversationId}),yield this._loadMessages(s)}catch(t){console.error("[nr-presence] Failed to open group chat:",t);const e=this._chats.get(S);e&&(e.loading=!1)}this.requestUpdate()})}_openDm(t){return z(this,void 0,void 0,function*(){var e;const i=t.userId||t.displayName;if(i===this.userId)return void this._openGroupChat();if(this._chats.has(i))return this._chats.get(i).z=++this._chatZ,void this.requestUpdate();const s=[...this._chats.keys()].filter(t=>t!==S).length,n=window.innerWidth-324-24*(s+1),r=56+24*(s+1);if(this._chats.set(i,{user:t,conversationId:null,loading:!0,x:n,y:r,savedX:n,savedY:r,z:++this._chatZ,minimized:!1,messages:[],draftText:""}),this.requestUpdate(),t.userId){try{const s=yield fetch("/api/conversations/dm",{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({targetUserId:t.userId})}),n=yield s.json(),r=this._chats.get(i);if(!r||!n.conversationId)return r&&(r.loading=!1),void this.requestUpdate();r.conversationId=n.conversationId,(null===(e=this.globalSocket)||void 0===e?void 0:e.connected)&&this.globalSocket.emit("nk:conversation:join",{conversationId:n.conversationId}),yield this._loadMessages(r)}catch(t){console.error("[nr-presence] Failed to open DM:",t);const e=this._chats.get(i);e&&(e.loading=!1)}this.requestUpdate()}})}_loadMessages(t){return z(this,void 0,void 0,function*(){var e;if(t.conversationId){try{const i=yield fetch(`/api/conversations/${t.conversationId}/messages`),s=yield i.json();(null===(e=s.messages)||void 0===e?void 0:e.length)&&(t.messages=s.messages.map(t=>({id:String(t.id),senderId:t.sender_id,text:t.content,timestamp:new Date(t.created_at).getTime(),me:t.sender_id===this.userId})))}catch(t){console.error("[nr-presence] Failed to load messages:",t)}t.loading=!1}})}_sendMessage(t,e){var i;const s=this._chats.get(t);(null==s?void 0:s.conversationId)&&(s.messages=[...s.messages,{id:crypto.randomUUID(),senderId:this.userId,text:e,timestamp:Date.now(),me:!0}],this.requestUpdate(),(null===(i=this.globalSocket)||void 0===i?void 0:i.connected)&&this.globalSocket.emit("nk:message:send",{conversationId:s.conversationId,content:e,type:"text"}))}_closeChat(t){this._chats.delete(t),this.requestUpdate()}_onEscape(t){if("Escape"!==t.key||0===this._chats.size)return;let e="",i=-1;for(const[t,s]of this._chats)s.z>i&&(i=s.z,e=t);if(!e)return;const s=this._chats.get(e);s.minimized?this._closeChat(e):(s.savedX=s.x,s.savedY=s.y,s.minimized=!0,this.requestUpdate())}_onDragStart(t,e,i){const s=this._chats.get(t);s&&(s.z=++this._chatZ,this._drag={userId:t,ox:e,oy:i},document.addEventListener("mousemove",this._boundDragMove),document.addEventListener("mouseup",this._boundDragEnd))}_onDragMove(t){if(!this._drag)return;const e=this._chats.get(this._drag.userId);e&&(e.x=Math.max(0,Math.min(window.innerWidth-300,t.clientX-this._drag.ox)),e.y=Math.max(0,Math.min(window.innerHeight-60,t.clientY-this._drag.oy)),this.requestUpdate())}_onDragEnd(){this._drag=null,document.removeEventListener("mousemove",this._boundDragMove),document.removeEventListener("mouseup",this._boundDragEnd)}render(){const t=this.currentUser,s=[...t?[t]:[],...this._viewers.filter(e=>!t||e.userId!==t.userId),...this.extraUsers],n=[...this._chats.entries()].filter(([,t])=>t.minimized);return e`
503
508
  <nr-presence-avatars
504
509
  .users=${s}
505
- @user-click=${e=>this._openChat(e.detail.user)}
510
+ @user-click=${t=>this._openDm(t.detail.user)}
506
511
  ></nr-presence-avatars>
507
512
 
508
- ${[...this._chats.entries()].map(([e,i])=>{const s=r.findIndex(([t])=>t===e);return t`
513
+ ${this.resourceType?e`
514
+ <button class="group-chat-btn" title="Team chat" @click=${()=>this._openGroupChat()}>
515
+ <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
516
+ <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
517
+ </svg>
518
+ ${this._hasUnreadGroup?e`<span class="unread-dot"></span>`:i}
519
+ </button>
520
+ `:i}
521
+
522
+ ${[...this._chats.entries()].map(([t,i])=>{const s=n.findIndex(([e])=>e===t);return e`
509
523
  <nr-presence-chat
510
524
  .user=${i.user}
511
525
  .x=${i.x}
@@ -514,15 +528,28 @@ var $=function(e,t,i,s){for(var r,n=arguments.length,o=n<3?t:null===s?s=Object.g
514
528
  .minimized=${i.minimized}
515
529
  .minimizedIndex=${s>=0?s:0}
516
530
  .messages=${i.messages}
531
+ .loading=${i.loading}
517
532
  @focus=${()=>{i.z=++this._chatZ,this.requestUpdate()}}
518
- @drag-start=${t=>this._onDragStart(e,t.detail.offsetX,t.detail.offsetY)}
533
+ @drag-start=${e=>this._onDragStart(t,e.detail.offsetX,e.detail.offsetY)}
519
534
  @minimize=${()=>{i.savedX=i.x,i.savedY=i.y,i.minimized=!0,this.requestUpdate()}}
520
535
  @restore=${()=>{i.x=Math.max(0,window.innerWidth-(12+212*s)-300),i.y=Math.max(0,window.innerHeight-420-56),i.minimized=!1,i.z=++this._chatZ,this.requestUpdate()}}
521
536
  @float=${()=>{i.minimized=!1,i.x=i.savedX,i.y=i.savedY,i.z=++this._chatZ,this.requestUpdate()}}
522
- @close=${()=>this._closeChat(e)}
523
- @send=${e=>{i.messages=[...i.messages,{id:crypto.randomUUID(),senderId:this.userId,text:e.detail.text,timestamp:Date.now(),me:!0}],this.requestUpdate()}}
537
+ @close=${()=>this._closeChat(t)}
538
+ @send=${e=>this._sendMessage(t,e.detail.text)}
524
539
  ></nr-presence-chat>
525
540
  `})}
526
-
527
- ${this._chats.size,i}
528
- `}};C.styles=v,C.useShadowDom=!0,$([r({type:String})],C.prototype,"namespace",void 0),$([r({type:String,attribute:"socket-path"})],C.prototype,"socketPath",void 0),$([r({type:String,attribute:"resource-id"})],C.prototype,"resourceId",void 0),$([r({type:String,attribute:"user-id"})],C.prototype,"userId",void 0),$([r({type:Object})],C.prototype,"currentUser",void 0),$([r({type:Array})],C.prototype,"extraUsers",void 0),$([o()],C.prototype,"_viewers",void 0),C=$([n("nr-presence")],C);export{x as NrPresenceAvatarsElement,k as NrPresenceChatElement,C as NrPresenceElement};
541
+ `}};C.styles=[m,t`
542
+ .group-chat-btn {
543
+ display: flex; align-items: center; justify-content: center;
544
+ width: 28px; height: 28px; border-radius: 50%; border: 2px solid var(--bg, #fff);
545
+ background: var(--accent, #7c3aed); color: #fff; cursor: pointer;
546
+ margin-left: 4px; transition: transform 120ms, background 120ms;
547
+ position: relative;
548
+ }
549
+ .group-chat-btn:hover { transform: scale(1.1); background: var(--accent-hover, #6d28d9); }
550
+ .group-chat-btn svg { width: 14px; height: 14px; }
551
+ .unread-dot {
552
+ position: absolute; top: -2px; right: -2px; width: 8px; height: 8px;
553
+ border-radius: 50%; background: #ef4444; border: 2px solid var(--bg, #fff);
554
+ }
555
+ `],C.useShadowDom=!0,$([n({type:String})],C.prototype,"namespace",void 0),$([n({type:String,attribute:"socket-path"})],C.prototype,"socketPath",void 0),$([n({type:String,attribute:"resource-id"})],C.prototype,"resourceId",void 0),$([n({type:String,attribute:"resource-type"})],C.prototype,"resourceType",void 0),$([n({type:String,attribute:"resource-name"})],C.prototype,"resourceName",void 0),$([n({type:String,attribute:"user-id"})],C.prototype,"userId",void 0),$([n({type:Object})],C.prototype,"currentUser",void 0),$([n({type:Array})],C.prototype,"extraUsers",void 0),$([n({type:Object})],C.prototype,"globalSocket",void 0),$([o()],C.prototype,"_viewers",void 0),$([o()],C.prototype,"_hasUnreadGroup",void 0),C=$([r("nr-presence")],C);export{x as NrPresenceAvatarsElement,k as NrPresenceChatElement,C as NrPresenceElement};
@@ -35,6 +35,8 @@ export declare class NrPresenceChatElement extends NrPresenceChatElement_base {
35
35
  minimizedIndex: number;
36
36
  /** Chat messages array */
37
37
  messages: PresenceChatMessage[];
38
+ /** Loading state (while DM is being created/loaded) */
39
+ loading: boolean;
38
40
  private _draft;
39
41
  private _emit;
40
42
  private _onHeaderMousedown;
@@ -42,6 +42,8 @@ let NrPresenceChatElement = class NrPresenceChatElement extends NuralyUIBaseMixi
42
42
  this.minimizedIndex = 0;
43
43
  /** Chat messages array */
44
44
  this.messages = [];
45
+ /** Loading state (while DM is being created/loaded) */
46
+ this.loading = false;
45
47
  this._draft = '';
46
48
  }
47
49
  _emit(type, detail) {
@@ -155,7 +157,11 @@ let NrPresenceChatElement = class NrPresenceChatElement extends NuralyUIBaseMixi
155
157
  </div>
156
158
 
157
159
  <div class="chat-messages">
158
- ${this.messages.length === 0 ? html `
160
+ ${this.loading ? html `
161
+ <div class="chat-empty">
162
+ <span>Loading...</span>
163
+ </div>
164
+ ` : this.messages.length === 0 ? html `
159
165
  <div class="chat-empty">
160
166
  <svg width="32" height="32" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5">
161
167
  <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/>
@@ -177,12 +183,13 @@ let NrPresenceChatElement = class NrPresenceChatElement extends NuralyUIBaseMixi
177
183
  class="chat-input"
178
184
  placeholder="Type a message..."
179
185
  .value=${this._draft}
186
+ ?disabled=${this.loading}
180
187
  @input=${(e) => { this._draft = e.target.value; }}
181
188
  @keydown=${this._onInputKeydown}
182
189
  >
183
190
  <button
184
191
  class="chat-send"
185
- ?disabled=${!this._draft.trim()}
192
+ ?disabled=${!this._draft.trim() || this.loading}
186
193
  @click=${this._onSend}
187
194
  >
188
195
  <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5">
@@ -218,6 +225,9 @@ __decorate([
218
225
  __decorate([
219
226
  property({ type: Array })
220
227
  ], NrPresenceChatElement.prototype, "messages", void 0);
228
+ __decorate([
229
+ property({ type: Boolean })
230
+ ], NrPresenceChatElement.prototype, "loading", void 0);
221
231
  __decorate([
222
232
  state()
223
233
  ], NrPresenceChatElement.prototype, "_draft", void 0);
@@ -11,8 +11,12 @@ declare const NrPresenceElement_base: (new (...args: any[]) => import("@nuralyui
11
11
  /**
12
12
  * Top-level presence orchestrator.
13
13
  *
14
- * Owns the socket connection, viewer list, and chat panel manager.
15
- * Renders `nr-presence-avatars` + one `nr-presence-chat` per open chat.
14
+ * Owns the resource socket for viewer tracking, and uses the global messages
15
+ * socket (`.globalSocket`) for real-time chat.
16
+ *
17
+ * Two chat modes:
18
+ * - **Group chat**: One conversation per resource. Opened via the chat button.
19
+ * - **DM**: Private 1-on-1 conversation. Opened by clicking a viewer's avatar.
16
20
  *
17
21
  * @example
18
22
  * ```html
@@ -20,41 +24,61 @@ declare const NrPresenceElement_base: (new (...args: any[]) => import("@nuralyui
20
24
  * namespace="/nk/apps/workflows/socket"
21
25
  * socket-path="/__nk_socketio/"
22
26
  * resource-id="workflow-abc123"
27
+ * resource-type="workflow"
28
+ * resource-name="My Workflow"
23
29
  * user-id="user-xyz"
24
30
  * .currentUser=${{ displayName, initials, color, avatarUrl }}
25
- * .extraUsers=${[...mockUsers]}
31
+ * .globalSocket=${globalSocket}
26
32
  * ></nr-presence>
27
33
  * ```
28
34
  *
29
35
  * @fires presence-changed - Fires when viewer list updates. Detail: `{ viewers: PresenceUser[] }`
30
36
  */
31
37
  export declare class NrPresenceElement extends NrPresenceElement_base {
32
- static styles: import("lit").CSSResult;
38
+ static styles: import("lit").CSSResult[];
33
39
  static useShadowDom: boolean;
34
- /** Socket.io namespace */
40
+ /** Socket.io namespace for presence tracking */
35
41
  namespace: string;
36
42
  /** Socket.io path */
37
43
  socketPath: string;
38
44
  /** The resource being viewed (workflow id, doc id, etc.) */
39
45
  resourceId: string;
46
+ /** Resource type for group conversation (e.g. 'workflow', 'whiteboard') */
47
+ resourceType: string;
48
+ /** Resource name (used as group conversation name) */
49
+ resourceName: string;
40
50
  /** Current user's id */
41
51
  userId: string;
42
52
  /** Current user object (shown first in avatar strip) */
43
53
  currentUser: PresenceUser | null;
44
54
  /** Additional users to show (e.g. mocks for demo) */
45
55
  extraUsers: PresenceUser[];
56
+ /** Global messages socket (from layout's /nk/messages connection) for real-time chat */
57
+ globalSocket: any;
46
58
  private _viewers;
59
+ private _hasUnreadGroup;
47
60
  private _socket;
61
+ private _connecting;
48
62
  private _chats;
49
63
  private _chatZ;
50
64
  private _drag;
51
65
  private _boundDragMove;
52
66
  private _boundDragEnd;
53
67
  private _boundEscape;
68
+ private _boundOnMessage;
54
69
  connectedCallback(): void;
55
70
  disconnectedCallback(): void;
71
+ updated(changed: Map<string, unknown>): void;
72
+ private _attachGlobalSocket;
73
+ private _detachGlobalSocket;
74
+ /** Handle incoming messages from the global /nk/messages socket */
75
+ private _onSocketMessage;
56
76
  private _connect;
57
- private _openChat;
77
+ private _groupConversationId;
78
+ private _openGroupChat;
79
+ private _openDm;
80
+ private _loadMessages;
81
+ private _sendMessage;
58
82
  private _closeChat;
59
83
  private _onEscape;
60
84
  private _onDragStart;