@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.
- package/dist/cdn.js +1 -0
- package/dist/nuralyui.bundle.js +2467 -1857
- package/dist/nuralyui.bundle.js.gz +0 -0
- package/dist/src/components/canvas/bundle.js +569 -204
- package/dist/src/components/canvas/bundle.js.gz +0 -0
- package/dist/src/components/canvas/canvas.constants.d.ts +1 -1
- package/dist/src/components/canvas/canvas.constants.js +1 -1
- package/dist/src/components/canvas/workflow-canvas.component.d.ts +7 -0
- package/dist/src/components/canvas/workflow-canvas.component.js +46 -2
- package/dist/src/components/canvas/workflow-canvas.types.d.ts +8 -1
- package/dist/src/components/canvas/workflow-canvas.types.js +157 -0
- package/dist/src/components/chat-panel/bundle.js +216 -0
- package/dist/src/components/chat-panel/bundle.js.gz +0 -0
- package/dist/src/components/chat-panel/chat-panel.component.d.ts +85 -0
- package/dist/src/components/chat-panel/chat-panel.component.js +510 -0
- package/dist/src/components/chat-panel/chat-panel.style.d.ts +2 -0
- package/dist/src/components/chat-panel/chat-panel.style.js +127 -0
- package/dist/src/components/chat-panel/chat-panel.types.d.ts +54 -0
- package/dist/src/components/chat-panel/chat-panel.types.js +2 -0
- package/dist/src/components/chat-panel/index.d.ts +3 -0
- package/dist/src/components/chat-panel/index.js +2 -0
- package/dist/src/components/chatbot/bundle.js +1 -1
- package/dist/src/components/chatbot/bundle.js.gz +0 -0
- package/dist/src/components/chatbot/providers/workflow-socket-provider.js +1 -1
- package/dist/src/components/presence/bundle.js +69 -42
- package/dist/src/components/presence/bundle.js.gz +0 -0
- package/dist/src/components/presence/presence-chat.component.d.ts +2 -0
- package/dist/src/components/presence/presence-chat.component.js +12 -2
- package/dist/src/components/presence/presence.component.d.ts +30 -6
- package/dist/src/components/presence/presence.component.js +277 -30
- package/dist/src/components/presence/presence.types.d.ts +2 -0
- package/dist/src/components/toast/bundle.js +11 -9
- package/dist/src/components/toast/bundle.js.gz +0 -0
- package/dist/src/components/toast/toast.component.d.ts +8 -0
- package/dist/src/components/toast/toast.component.js +17 -7
- package/dist/src/components/video/bundle.js +13 -12
- package/dist/src/components/video/bundle.js.gz +0 -0
- package/dist/src/components/video/video.component.d.ts +15 -1
- package/dist/src/components/video/video.component.js +131 -3
- package/package.json +5 -10
- 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
|
|
@@ -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
|
|
Binary file
|
|
@@ -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
|
|
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
|
|
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=
|
|
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=
|
|
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
|
|
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
|
-
*/,
|
|
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
|
|
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
|
-
${
|
|
136
|
-
<div class="pa" @click=${()=>this._handleClick(
|
|
137
|
-
<div class="pa-avatar" style="background:${
|
|
138
|
-
${
|
|
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">${
|
|
141
|
+
<span class="pa-tip">${t.displayName}</span>
|
|
142
142
|
</div>
|
|
143
143
|
`)}
|
|
144
|
-
${s>0?
|
|
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=
|
|
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
|
|
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
|
|
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?
|
|
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:
|
|
416
|
+
${this.minimized?i:e`<div class="chat-header-status">Online</div>`}
|
|
417
417
|
</div>
|
|
418
418
|
|
|
419
|
-
${this.minimized?
|
|
419
|
+
${this.minimized?e`
|
|
420
420
|
<button
|
|
421
421
|
class="chat-btn"
|
|
422
422
|
title="Float"
|
|
423
|
-
@mousedown=${
|
|
424
|
-
@click=${
|
|
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
|
-
`:
|
|
433
|
+
`:e`
|
|
434
434
|
<button
|
|
435
435
|
class="chat-btn"
|
|
436
436
|
title="Minimize"
|
|
437
|
-
@mousedown=${
|
|
438
|
-
@click=${
|
|
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=${
|
|
450
|
-
@click=${
|
|
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
|
-
${
|
|
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
|
|
468
|
-
<div class="chat-msg ${
|
|
469
|
-
<div class="chat-bubble">${
|
|
470
|
-
<span class="chat-time">${new Date(
|
|
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
|
-
|
|
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=
|
|
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,
|
|
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=${
|
|
510
|
+
@user-click=${t=>this._openDm(t.detail.user)}
|
|
506
511
|
></nr-presence-avatars>
|
|
507
512
|
|
|
508
|
-
${
|
|
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=${
|
|
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(
|
|
523
|
-
@send=${e=>
|
|
537
|
+
@close=${()=>this._closeChat(t)}
|
|
538
|
+
@send=${e=>this._sendMessage(t,e.detail.text)}
|
|
524
539
|
></nr-presence-chat>
|
|
525
540
|
`})}
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
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};
|
|
Binary file
|
|
@@ -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.
|
|
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
|
|
15
|
-
*
|
|
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
|
-
* .
|
|
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
|
|
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;
|