PageSourceSearch

https://circuitdigest.cloud/assets/index-DumCValY.js

js circuitdigest.cloud collected 2026-10-04 16:31:34 UTC 166,853 bytes, 10 lines download raw bytes

1import{j as e,J as aa,bm as Dt,I as j,b9 as za,ba as qa,bH as sa,ag as st,ak as lt,cx as ra,bb as Yt,ch as Qa,ax as Qe,cA as Ot,cj as xt,ah as ia,co as Ya,a1 as pt,ae as Et,cd as Ja,Z as rt,cy as la,K as Xa,aP as Za,aQ as es,M as E,H as na,aS as ts,bI as as,bu as Ve,bw as Ie,bx as ze,by as We,bl as $e,bz as Ke,bc as Oa,aw as l,aD as te,aE as ae,aF as se,aG as re,aH as S,cl as qe,aC as oa,aZ as Se,ce as ca,a6 as ht,bA as tt,ai as Hs,O as Bs,b7 as Us,ci as ss,cK as Gs,cL as zs,cM as qs,b8 as Qs,cN as Ys,bp as Ea,az as Mt,ay as Js,aB as Jt,b6 as Xs,a$ as G,b1 as Zs,cG as Xe,c1 as Ge,S as Ra,a9 as mt,at as Gt,ck as Pa,au as zt,av as er,ad as Ct,m as kt,bU as tr,bV as ar,bW as sr,bX as rr,bY as Aa,di as ir,bZ as Ze,br as lr}from"./index-DRbl4l2O.js";import{r}from"./vendor-recharts-DOYp6jOb.js";import{A as it,S as Rt,P as gt,C as rs,D as nr,l as or,g as qt,b as Xt,c as da,d as ma,T as is,e as Lt,f as cr,F as ls,h as ns,H as dr,i as os,j as Qt,B as St,R as mr,a as ur}from"./dashboardShareService-CPpfVG1C.js";import{sha256 as Fa}from"./sha2-DtKt9EDC.js";import{S as ua}from"./scroll-area-g9iHu1Kd.js";import{T as yt}from"./thermometer-CVhQ-lOK.js";import{T as Pt}from"./type-DCNtLSny.js";import{W as At}from"./waves-DCCqNab_.js";import{T as cs}from"./trending-up-QLND7-nd.js";import{a as hr,P as xr,S as ha,F as pr,W as gr,T as ds}from"./wind-xAFoRHZz.js";import{R as yr}from"./ruler-ClXA6wwQ.js";import{L as xa}from"./lightbulb-EMutqUGq.js";import{B as Ft}from"./battery-Cumb6LX3.js";import{D as pa}from"./droplets-CstNHRtk.js";import{d as ut,f as et,C as fr,p as Va,v as _t,i as De,P as br}from"./iotService-DxYKM30U.js";import{S as ms}from"./sliders-horizontal-BNDU3Bmu.js";import{C as vr}from"./mic-06QOT1tK.js";import{C as Ia}from"./calendar-BTAQSu3y.js";import{L as jr}from"./list-CPrdYVR1.js";import{B as Nr}from"./bell-C448JThb.js";import{C as Zt}from"./circle-check-big-CqNExLnt.js";import{a as ea}from"./layout-grid-BX3z21K2.js";import{H as wr}from"./hash-BhUbwzMm.js";import{L as us}from"./link-2-_dHsjTY6.js";import{L as hs}from"./toggle-right-DoKjx3rK.js";import{u as Cr}from"./useDevices-DUgIryxZ.js";import{P as Wa}from"./pen-line-DBUy4uAm.js";import"./archive-DQjrfkOs.js";import"./minus-C6WBDloz.js";import"./arrow-up-Cm47Dok5.js";import"./arrow-left-DDJ2t-5T.js";import"./ban-B6M3SDui.js";import"./pen-CHOzwckn.js";import"./building-2-SS8n9w-d.js";import"./power-off-rKY5NiTc.js";import"./card-sim-BBPznaWs.js";import"./cloud-download-B7qqVchg.js";import"./chevron-right-C47m6FgX.js";import"./settings-2-D85_8Q8y.js";import"./circle-question-mark-pypzk4th.js";import"./clipboard-copy-Dk11d4Tf.js";import"./cloud-CVcuTeZG.js";import"./move-right-5OEL2mUu.js";import"./rocket-NO0Zha_u.js";import"./copy-check-84I12hOl.js";import"./ellipsis-vertical-C0zpCfsi.js";import"./ellipsis-jsiMJqHY.js";import"./file-check-RnPWvRGd.js";import"./fingerprint-pattern-DgON33Or.js";import"./flask-conical-BpdwPQvL.js";import"./flip-horizontal-BePaBIhK.js";import"./funnel-BvvzoY8B.js";import"./twitter-7PooTTwG.js";import"./image-off-CaT7J7Qe.js";import"./key-round-CHlweL8D.js";import"./network-NA23VnR9.js";import"./pause-bD7of_IX.js";import"./pencil-BAxmdU_g.js";import"./qr-code-DusJTqS2.js";import"./rotate-ccw-DUr6usEi.js";import"./router-CiJz6-zS.js";import"./rss-DG77Wij3.js";import"./save-Cb2w7K6S.js";import"./shield-alert-Uifwc5q7.js";import"./user-check-D5lEsBFO.js";import"./shield-BhRcilRI.js";import"./signal-D7vdMYlU.js";import"./square-pen-CRi75AVc.js";import"./star-vl1q7TtR.js";import"./terminal-DntCKxUK.js";import"./timer-BqlMtNfG.js";import"./undo-2-C_Vje_P8.js";import"./user-x-CGvXS78O.js";import"./wifi-off-sPNXYNwi.js";import"./wrench-DPsDhL3m.js";import"./youtube-SBEqAbkY.js";import"./table-TbIXv9jo.js";import"./switch-CMGsbGsu.js";import"./index-FNGKbkbf.js";function kr(i){let m=0;function k(){return i[m++]}function d(y){if(y<=23)return y;if(y===24)return k();if(y===25)return k()<<8|k();if(y===26){let g=0;for(let x=0;x<4;x++)g=g*256+k();return g}if(y===27){let g=0;for(let x=0;x<8;x++)g=g*256+k();return g}throw new Error(`Unsupported additional info: ${y}`)}function T(){const y=k(),g=k(),x=y>>2&31,R=(y&3)<<8|g;return x===0?(y>>7?-1:1)*R*2**-24:x===31?R?NaN:y>>7?-1/0:1/0:(y>>7?-1:1)*(1+R/1024)*2**(x-15)}function z(){const y=new DataView(i.buffer,i.byteOffset+m,4);return m+=4,y.getFloat32(0,!1)}function F(){const y=new DataView(i.buffer,i.byteOffset+m,8);return m+=8,y.getFloat64(0,!1)}function p(){const y=k(),g=y>>5,x=y&31;if(g===0)return d(x);if(g===1)return-1-d(x);if(g===2){const R=d(x),P=i.slice(m,m+R);return m+=R,P}if(g===3){const R=d(x),P=i.slice(m,m+R);return m+=R,new TextDecoder().decode(P)}if(g===4){const R=d(x),P=[];for(let D=0;D<R;D++)P.push(p());return P}if(g===5){const R=d(x),P={};for(let D=0;D<R;D++){const O=p();P[O]=p()}return P}if(g===7){if(x===25)return T();if(x===26)return z();if(x===27)return F();if(x===20)return!1;if(x===21)return!0;
1if(x===22)return null}throw new Error(`Unsupported CBOR type: major=${g} ai=${x}`)}return p()}const Sr="https://api.ap-in-1.anedya.io/v1",_r=3e3,Tr=5,Lr=new Set([4001,4002,4003,4008]);function $a(i){i&&(i.onmessage=i.onerror=i.onclose=null,i.readyState===WebSocket.CONNECTING?i.onopen=()=>i.close():(i.onopen=null,i.close()))}function Dr(i){return Array.from(i).map(m=>m.toString(16).padStart(2,"0")).join("")}function Ka(i,m,k=""){const d=new TextEncoder,T=Fa(d.encode(k)),z=new Uint8Array(8);new DataView(z.buffer).setBigUint64(0,BigInt(m),!1);const F=new Uint8Array([...T,...z,...d.encode("v1"),...d.encode(i)]);return Dr(Fa(F))}function Ha(i){const m=Array.from(i).map(k=>k.toString(16).padStart(2,"0")).join("");return`${m.slice(0,8)}-${m.slice(8,12)}-${m.slice(12,16)}-${m.slice(16,20)}-${m.slice(20)}`}function Mr({deviceIds:i,enabled:m=!0,onTelemetry:k,onUnknownKey:d,onNodeEvent:T}){const[z,F]=r.useState("idle"),[p,y]=r.useState(null),[g,x]=r.useState({}),[R,P]=r.useState(null),[D,O]=r.useState(0),B=r.useRef(null),J=r.useRef(null),I=r.useRef(null),ue=r.useRef(null),he=r.useRef(0),le=r.useRef({received:0,mapped:0,dropped:0,lastDropReason:void 0}),ve=r.useRef({}),ye=r.useRef({}),we=r.useRef(k);we.current=k;const _e=r.useRef(d);_e.current=d;const de=r.useRef(T);de.current=T;const b=r.useRef(m);b.current=m;const ne=r.useCallback(()=>{he.current=0,O(q=>q+1)},[]),oe=r.useCallback((q,X,n,f)=>{le.current.received++;const ge=`${q}:${X}`,c=`${n}:${f}`;if(ye.current[ge]===c)return;ye.current[ge]=c;const w=ve.current[q]??(ve.current[q]=new Set);w.has(X)||(w.add(X),_e.current?.(q,X)),le.current.mapped++,we.current?.(q,X,{value:n,timestamp:new Date(f).toISOString()})},[]);return r.useEffect(()=>{if(!m||!i){F("idle");return}const q=i.split(",").filter(Boolean);if(q.length===0){F("idle");return}let X=!1;he.current=0,le.current={received:0,mapped:0,dropped:0,lastDropReason:void 0},ye.current={};const n=()=>{X=!0,J.current&&(clearInterval(J.current),J.current=null),I.current&&(clearTimeout(I.current),I.current=null),ue.current&&(clearTimeout(ue.current),ue.current=null),$a(B.current),B.current=null};async function f(W=!1){const s=localStorage.getItem("access_token")??"";try{const v=await fetch(`/api/v1/anedya/streams/connect-info?device_ids=${encodeURIComponent(q.join(","))}`+(W?"&refresh=1":""),{headers:{Authorization:`Bearer ${s}`}});if(!v.ok){const H=await v.text().catch(()=>"");throw new Error(`connect-info HTTP ${v.status}: ${H.slice(0,200)}`)}return await v.json()}catch(v){return console.error("[WS/ACS] connect-info failed:",v),null}}async function ge(){F("connecting"),y(null);const W=await f();if(X)return;if(!W){F("error"),y("Failed to get stream credentials");return}x(W.node_to_device);const s=W.device_to_node&&Object.keys(W.device_to_node).length>0?W.device_to_node:Object.fromEntries(Object.entries(W.node_to_device).map(([v,H])=>[H,v]));if(P({token_id:W.token_id,token:W.token,device_to_node:s,api_base:"https://api.ap-in-1.anedya.io/v1"}),!W.stream_url){F("connected");return}c(W,()=>X)}async function c(W,s){if(s())return;const v=Math.floor(Date.now()/1e3),H=Ka(W.token,v),Y=new URLSearchParams({Authorization:"ANEDYASIGV1","x-anedya-streamid":W.stream_id,"x-anedya-tokenid":W.token_id,"x-anedya-signature":H,"x-anedya-timestamp":String(v),"x-anedya-signatureversion":"v1"}),me=`${W.stream_url}?${Y.toString()}`;console.info("[WS/ACS] Connecting DIRECT to Anedya ACS:",W.stream_id,"ts=",v);const ce=new WebSocket(me);ce.binaryType="arraybuffer",B.current=ce;const t=setTimeout(()=>{ce.readyState===WebSocket.CONNECTING&&($a(ce),B.current=null)},1e4);ce.onopen=()=>{if(clearTimeout(t),s()){ce.close();return}J.current&&(clearInterval(J.current),J.current=null),F("connected"),ue.current&&clearTimeout(ue.current),ue.current=setTimeout(()=>{he.current=0},15e3)},ce.onmessage=C=>{if(s())return;
1if(typeof C.data=="string"){try{const U=JSON.parse(C.data);if(U.type==="init")return;const{nodeId:L,variable:Q,value:Ce,timestamp:je}=U;if(!L||!Q||Ce===void 0)return;const Ne=W.node_to_device[L];if(!Ne)return;let Te=Date.now();typeof je=="number"?Te=je*1e3:typeof je=="string"&&(Te=Date.parse(je)),oe(Ne,Q,Ce,Te)}catch{}return}const M=new Uint8Array(C.data);if(!(M.length<3))try{const U=M.slice(3),L=kr(U);if(M[0]===0&&M[1]===1){const Q=L?.n,Ce=Q instanceof Uint8Array&&Q.length===16?Ha(Q):String(L?.ns?.id??L?.n??""),je=L?.v??L?.key,Ne=L?.d??L?.val,Te=L?.ts;if(!Ce||!je||Ne===void 0)return;const Ye=W.node_to_device[Ce];if(!Ye)return;oe(Ye,je,Ne,Te??Date.now())}else if(M[0]===0&&M[1]===2){const Q=L?.n,Ce=Q instanceof Uint8Array&&Q.length===16?Ha(Q):String(L?.ns?.id??L?.n??""),je=L?.key??L?.v;if(!Ce)return;const Ne=W.node_to_device[Ce];Ne&&de.current?.(Ne,String(je??""),L)}}catch{}},ce.onerror=()=>{clearTimeout(t)},ce.onclose=C=>{if(clearTimeout(t),ue.current&&(clearTimeout(ue.current),ue.current=null),s())return;if(B.current=null,console.warn("[WS/ACS] closed code=%d reason=%s",C.code,C.reason||"(none)"),Lr.has(C.code)){F("error"),y(`ACS stream closed: ${C.reason||`code ${C.code}`}`);return}if(he.current>=Tr){console.warn("[WS/ACS] max reconnects reached  switching to REST pull mode"),w(W,s);return}const M=Math.min(1e3*2**he.current,3e4);he.current++,I.current=setTimeout(async()=>{if(s())return;const U=await f(!0);if(!s())if(U){x(U.node_to_device);const L=U.device_to_node&&Object.keys(U.device_to_node).length>0?U.device_to_node:Object.fromEntries(Object.entries(U.node_to_device).map(([Q,Ce])=>[Ce,Q]));P({token_id:U.token_id,token:U.token,device_to_node:L,api_base:"https://api.ap-in-1.anedya.io/v1"}),c(U,s)}else w(W,s)},M)}}function w(W,s){if(s())return;F("connected"),y(null);const v={};for(const[Y,me]of Object.entries(W.node_to_device)){const ce=W.device_slots[me]??[];for(const t of ce)v[t]||(v[t]={nodeIds:[],deviceIdByNode:{}}),v[t].nodeIds.push(Y),v[t].deviceIdByNode[Y]=me}if(Object.keys(v).length===0)return;async function H(){s()||await Promise.allSettled(Object.entries(v).map(async([Y,{nodeIds:me,deviceIdByNode:ce}])=>{const t=JSON.stringify({nodes:me,variable:Y}),C=Math.floor(Date.now()/1e3),M=Ka(W.token,C,t);try{const U=await fetch(`${Sr}/data/latest`,{method:"POST",headers:{Authorization:"ANEDYASIGV1","x-anedya-SignatureVersion":"v1","x-anedya-TokenId":W.token_id,"x-anedya-Timestamp":String(C),"x-anedya-Signature":M,"Content-Type":"application/json"},body:t});if(!U.ok)return;const Q=(await U.json())?.data;if(!Q)return;for(const[Ce,je]of Object.entries(Q)){const Ne=ce[Ce];!Ne||je?.value===void 0||oe(Ne,Y,je.value,je.timestamp*1e3)}}catch{}}))}J.current=setInterval(H,_r),H()}return ge(),n},[i,m,D,oe]),{status:z,error:p,nodeToDevice:g,controlToken:R,reconnect:ne,diagnostics:le.current}}const ta=new Set(["value","gauge","chart","table","notification","button","toggle","slider","switch","mjpeg_stream","image","colorpicker","webrtc_stream","map"]),Vt=[{id:"temp_celsius",name:"Temperature (Celsius)",description:"Display temperature in Celsius with thermometer gauge",icon:"Thermometer",category:"sensor",widgetType:"temperature",config:{unit:"°C",min:-20,max:50,warningMin:5,warningMax:35,criticalMin:0,criticalMax:40},suggestedVariable:{var_type:"float",min_value:-20,max_value:50,unit:"°C"},defaultLayout:{w:3,h:3}},{id:"temp_fahrenheit",name:"Temperature (Fahrenheit)",description:"Display temperature in Fahrenheit",icon:"Thermometer",category:"sensor",widgetType:"temperature",config:{unit:"°F",min:0,max:120,warningMin:40,warningMax:95,criticalMin:32,criticalMax:104},suggestedVariable:{var_type:"float",min_value:0,max_value:120,unit:"°F"},defaultLayout:{w:3,h:3}},{id:"humidity",name:"Humidity Sensor",description:"Display relative humidity percentage",icon:"Droplets",category:"sensor",widgetType:"humidity",config:{unit:"%",min:0,max:100,warningMin:30,warningMax:70,criticalMin:20,criticalMax:80},suggestedVariable:{var_type:"float",min_value:0,max_value:100,unit:"%"},defaultLayout:{w:3,h:3}},{id:"battery_percent",name:"Battery Monitor",description:"Show battery level with charging indicator",icon:"Battery",category:"sensor",widgetType:"battery",config:{unit:"%",min:0,max:100,lowThreshold:20,criticalThreshold:10},suggestedVariable:{var_type:"float",min_value:0,max_value:100,unit:"%"},defaultLayout:{w:3,h:2}},{id:"light_lux",name:"Light Sensor",description:"Display light intensity in lux",icon:"Lightbulb",category:"sensor",widgetType:"light",config:{unit:"lux",min:0,max:1024},suggestedVariable:{var_type:"integer",min_value:0,max_value:1024,unit:"lux"},defaultLayout:{w:3,h:3}},{id:"pressure_hpa",name:"Barometric Pressure",description:"Display atmospheric pressure in hPa",icon:"Fan",category:"sensor",widgetType:"gauge",config:{metric_key:"pressure-1",unit:"hPa",min:950,max:1050,warningMin:980,warningMax:1030},suggestedVariable:{var_type:"float",min_value:950,max_value:1050,unit:"hPa"},defaultLayout:{w:3,h:3}},{id:"soil_moisture",name:"Soil Moisture",description:"Monitor soil moisture percentage",icon:"Sprout",category:"sensor",widgetType:"gauge",config:{metric_key:"percentage-1",unit:"%",min:0,max:100,warningMin:30,warningMax:80,criticalMin:20,criticalMax:90},suggestedVariable:{var_type:"integer",min_value:0,max_value:100,unit:"%"},defaultLayout:{w:3,h:3}},{id:"distance_cm",name:"Ultrasonic Distance",description:"Display distance in centimeters",icon:"Ruler",category:"sensor",widgetType:"gauge",config:{metric_key:"distance-1",unit:"cm",min:0,max:400},suggestedVariable:{var_type:"float",min_value:0,max_value:400,unit:"cm"},defaultLayout:{w:3,h:3}},{id:"motion_detector",name:"Motion Sensor",description:"Boolean motion detection indicator",icon:"PersonStanding",category:"indicator",widgetType:"status",config:{metric_key:"motion-1",trueLabel:"MOTION DETECTED",falseLabel:"NO MOTION",trueColor:"red",falseColor:"green"},suggestedVariable:{var_type:"boolean"},defaultLayout:{w:3,h:2}},{id:"door_sensor",name:"Door/Window Sensor",description:"Contact sensor for doors/windows",icon:"DoorOpen",category:"indicator",widgetType:"status",config:{metric_key:"door-1",trueLabel:"OPEN",fal
1seLabel:"CLOSED",trueColor:"orange",falseColor:"gray"},suggestedVariable:{var_type:"boolean"},defaultLayout:{w:3,h:2}},{id:"toggle_light",name:"Light Switch",description:"Toggle control for lights",icon:"Lightbulb",category:"control",widgetType:"toggle",config:{commandKey:"light-1",onLabel:"ON",offLabel:"OFF"},suggestedVariable:{var_type:"boolean"},defaultLayout:{w:3,h:3}},{id:"toggle_fan",name:"Fan Control",description:"Toggle control for fans",icon:"Fan",category:"control",widgetType:"toggle",config:{commandKey:"fan-1",onLabel:"RUNNING",offLabel:"STOPPED"},suggestedVariable:{var_type:"boolean"},defaultLayout:{w:3,h:3}},{id:"toggle_pump",name:"Water Pump",description:"Control water pump on/off",icon:"Droplets",category:"control",widgetType:"toggle",config:{commandKey:"pump-1",onLabel:"PUMPING",offLabel:"STOPPED"},suggestedVariable:{var_type:"boolean"},defaultLayout:{w:3,h:3}},{id:"slider_brightness",name:"Brightness Control",description:"Adjust brightness level (0-100%)",icon:"Sun",category:"control",widgetType:"slider",config:{commandKey:"percentage-1",min:0,max:100,step:5,unit:"%"},suggestedVariable:{var_type:"integer",min_value:0,max_value:100,unit:"%"},defaultLayout:{w:4,h:2}},{id:"slider_speed",name:"Motor Speed Control",description:"Adjust motor speed (0-255 PWM)",icon:"Settings",category:"control",widgetType:"slider",config:{commandKey:"speed-1",min:0,max:255,step:1,unit:"PWM"},suggestedVariable:{var_type:"integer",min_value:0,max_value:255,unit:"PWM"},defaultLayout:{w:4,h:2}},{id:"chart_24h_temp",name:"Temperature Chart (24h)",description:"Line chart showing temperature history",icon:"BarChart3",category:"analytics",widgetType:"chart",config:{chartType:"line",timeRange:"24h",metric_keys:["temperature-1"]},suggestedVariable:{var_type:"float",unit:"°C"},defaultLayout:{w:6,h:4}},{id:"chart_7d_humidity",name:"Humidity Chart (7 days)",description:"Area chart showing humidity over 7 days",icon:"TrendingUp",category:"analytics",widgetType:"chart",config:{chartType:"area",timeRange:"7d",metric_keys:["humidity-1"]},suggestedVariable:{var_type:"float",unit:"%"},defaultLayout:{w:6,h:4}},{id:"chart_multi_sensor",name:"Multi-Sensor Chart",description:"Compare multiple sensors on one chart",icon:"LineChart",category:"analytics",widgetType:"chart",config:{chartType:"line",timeRange:"6h",metric_keys:[]},defaultLayout:{w:12,h:4}},{id:"device_online_status",name:"Device Online Status",description:"Shows Live / Offline based on MQTT LWT heartbeat",icon:"Wifi",category:"indicator",widgetType:"status",config:{metric_key:"online",trueLabel:"ONLINE",falseLabel:"OFFLINE",trueColor:"green",falseColor:"red"},defaultLayout:{w:2,h:2}},{id:"alert_threshold",name:"Threshold Alert",description:"Alert when value exceeds limits",icon:"AlertTriangle",category:"indicator",widgetType:"alert",config:{alertLabel:"ALERT",showValue:!0,alertOnWarning:!1},suggestedVariable:{var_type:"float"},defaultLayout:{w:3,h:3}},{id:"speedometer_rpm",name:"Motor RPM Gauge",description:"Speedometer-style RPM indicator",icon:"Zap",category:"indicator",widgetType:"speedometer",config:{metric_key:"rpm-1",unit:"RPM",min:0,max:3e3},suggestedVariable:{var_type:"float",min_value:0,max_value:3e3,unit:"RPM"},defaultLayout:{w:4,h:4}},{id:"speedometer_speed",name:"Vehicle Speed",description:"Speedometer for vehicle tracking",icon:"Car",category:"indicator",widgetType:"speedometer",config:{metric_key:"speed-1",unit:"km/h",min:0,max:200},suggestedVariable:{var_type:"float",min_value:0,max_value:200,unit:"km/h"},defaultLayout:{w:4,h:3}},{id:"signal_strength",name:"Signal Strength",description:"Display WiFi/cellular signal strength",icon:"Wifi",category:"indicator",widgetType:"signal",config:{metric_key:"rssi",unit:"dBm",min:-100,max:0},suggestedVariable:{var_type:"float",min_value:-100,max_value:0,unit:"dBm"},defaultLayout:{w:3,h:2}},{id:"power_consumption",name:"Power Monitor",description:"Display power consumption in watts",icon:"Zap",category:"indicator",widgetType:"power",config:{metric_key:"power-1",unit:"W",min:0,max:3600},suggestedVariable:{var_type:"float",min_value:0,max_value:3600,unit:"W"},defaultLayout:{w:3,h:3}},{id:"log_terminal",name:"System Logs",description:"Terminal-style log viewer with level filtering",icon:"FileText",category:"indicator",widgetType:"log",config:{metric_key:"log",maxLogs:100},suggestedVariable:{var_type:"string"},defaultLayout:{w:6,h:4}},{id:"gps_map",name:"GPS Tracker",description:"Live GPS location on map",icon:"Map",category:"location",widgetType:"map",config:{lat_key:"lat",lng_key:"lng",default_zoom:15},suggestedVariable:{var_type:"float"},defaultLayout:{w:8,h:5}},{id:"geolinker_map",name:"GeoLinker Live Map",description:"Real-time GPS position from a GeoLinker device",icon:"MapPin",category:"location",widgetType:"map",config:{metric_keys:["latitude","longitude"],default_zoom:15},suggestedVariable:{var_type:"float"},defaultLayout:{w:6,h:5}}
1,{id:"coordinates",name:"Lat/Lng Display",description:"Display GPS coordinates as text",icon:"MapPin",category:"location",widgetType:"value",config:{metric_key:"lat",unit:"°"},suggestedVariable:{var_type:"float",unit:"°"},defaultLayout:{w:3,h:2}},{id:"media_image",name:"Static Image",description:"Display an image from a URL or device trigger",icon:"Image",category:"media",widgetType:"image",config:{url:"https://images.unsplash.com/photo-1558346490-a72e53ae2d4f?auto=format&fit=crop&q=80&w=400",fit:"cover",overlay:!0},defaultLayout:{w:4,h:4}},{id:"media_video",name:"Video Player",description:"Play MP4 or WebM video clips",icon:"Video",category:"media",widgetType:"video",config:{url:"https://www.w3schools.com/html/mov_bbb.mp4",autoPlay:!0,loop:!0,muted:!0,controls:!0},defaultLayout:{w:6,h:4}},{id:"media_stream",name:"Live IPCam Stream",description:"Live HLS or MP4 camera feed",icon:"Airplay",category:"media",widgetType:"stream",config:{url:"http://sample.vodobox.net/skate_phantom_flex_4k/skate_phantom_flex_4k.m3u8"},defaultLayout:{w:6,h:5}},{id:"media_webrtc",name:"Live Camera (WebRTC)",description:"Real-time P2P video stream from an ESP32-CAM or browser publisher",icon:"Video",category:"media",widgetType:"webrtc_stream",config:{room_id:"",mode:"webrtc",quality:"med",auto_reconnect:!0},defaultLayout:{w:6,h:5}},{id:"media_mjpeg",name:"MJPEG Snapshot Stream",description:"Low-latency MJPEG relay from a connected camera device",icon:"Airplay",category:"media",widgetType:"mjpeg_stream",config:{room_id:"",mode:"mjpeg",auto_reconnect:!0},defaultLayout:{w:5,h:4}},{id:"level_tank",name:"Liquid Tank Level",description:"Vertical indicator for water tanks or storage",icon:"Waves",category:"sensor",widgetType:"level",config:{min:0,max:100,unit:"%",color:"bg-blue-500",waveColor:"rgba(59, 130, 246, 0.4)"},suggestedVariable:{var_type:"float",min_value:0,max_value:100,unit:"%"},defaultLayout:{w:3,h:6}},{id:"clock_digital",name:"System Clock",description:"Real-time digital clock and date",icon:"Clock",category:"indicator",widgetType:"clock",config:{label:"System Time",showSeconds:!0,format24h:!1},defaultLayout:{w:4,h:2}},{id:"scene_modes",name:"Mode Selector",description:"Switch between device operating modes",icon:"Layout",category:"control",widgetType:"scene",config:{options:[{label:"Eco",payload:{mode:"eco"}},{label:"Auto",payload:{mode:"auto"}},{label:"Turbo",payload:{mode:"turbo"}},{label:"Off",payload:{mode:"off"}}]},defaultLayout:{w:4,h:3}},{id:"note_info",name:"Dashboard Note",description:"Fixed text/instructions for dashboard users",icon:"StickyNote",category:"indicator",widgetType:"note",config:{content:`Instructions:
21. Check tank levels daily
32. Monitor stream for alerts
43. Set mode to 'Eco' at night`,bgColor:"bg-yellow-500/10",textColor:"text-yellow-700 dark:text-yellow-400 font-medium"},defaultLayout:{w:4,h:4}},{id:"battery_progress",name:"Battery Level",description:"Linear progress bar for battery or charge level",icon:"Activity",category:"indicator",widgetType:"progress",config:{min:0,max:100,unit:"%",color:"bg-green-500"},suggestedVariable:{var_type:"float",min_value:0,max_value:100,unit:"%"},defaultLayout:{w:4,h:2}},{id:"event_timeline",name:"Event Timeline",description:"Compact list of recent state changes",icon:"History",category:"analytics",widgetType:"timeline",config:{limit:5},defaultLayout:{w:4,h:4}},{id:"dashboard_header",name:"Section Header",description:"Visual separator for dashboard organization",icon:"Type",category:"indicator",widgetType:"label",config:{text:"SYSTEM OVERVIEW",size:"text-xs",color:"text-primary/40"},defaultLayout:{w:12,h:1}}];function Ba(i){return Vt.filter(m=>m.category===i)}function Or(i){const m=i.toLowerCase();return Vt.filter(k=>k.name.toLowerCase().includes(m)||k.description.toLowerCase().includes(m)||k.category.toLowerCase().includes(m)||k.widgetType.toLowerCase().includes(m))}function Er(){return["sensor","control","analytics","indicator","location","media"]}const Rr={Thermometer:yt,Droplets:pa,Battery:Ft,Lightbulb:xa,Fan:pr,Sprout:ha,Ruler:yr,PersonStanding:xr,DoorOpen:nr,Sun:hr,Settings:ra,BarChart3:lt,TrendingUp:cs,LineChart:rs,AlertTriangle:la,Zap:rt,Car:Ja,Wifi:Et,FileText:pt,Map:Ya,MapPin:sa,Activity:st,Gauge:ia,Image:xt,Video:Ot,Airplay:it,Waves:At,Clock:Qe,Layout:gt,StickyNote:Rt,History:Qa,Type:Pt},Ua={sensor:{label:"Sensors",Icon:yt},control:{label:"Controls",Icon:ra},analytics:{label:"Analytics",Icon:lt},indicator:{label:"Indicators",Icon:st},location:{label:"Location",Icon:sa},media:{label:"Media",Icon:it}};function Pr({selectedPresetIds:i,onToggle:m}){const[k,d]=r.useState(""),[T,z]=r.useState("sensor"),p=Er().filter(g=>Ba(g).some(x=>ta.has(x.widgetType))),y=(k.trim()!==""?Or(k):Ba(T)).filter(g=>ta.has(g.widgetType));return e.jsxs("div",{className:"space-y-4",children:[e.jsxs("div",{className:"flex items-center gap-2 text-sm text-muted-foreground",children:[e.jsx(aa,{className:"h-4 w-4"}),e.jsx("span",{children:"Select one or more presets to add at once"})]}),e.jsxs("div",{className:"relative",children:[e.jsx(Dt,{className:"absolute left-3 top-1/2 -translate-y-1/2 h-4 w-4 text-muted-foreground"}),e.jsx(j,{placeholder:"Search presets (e.g., temperature, battery, pump...)",value:k,onChange:g=>d(g.target.value),className:"pl-9"})]}),k.trim()===""&&e.jsx(za,{value:T,onValueChange:z,className:"w-full",children:e.jsx(qa,{className:"grid w-full grid-cols-5",children:p.map(g=>{const x=Ua[g]?.Icon;return e.jsxs(Yt,{value:g,className:"text-xs",children:[x&&e.jsx(x,{className:"h-3.5 w-3.5 mr-1 text-primary"}),Ua[g]?.label]},g)})})}),e.jsxs(ua,{className:"h-[320px] pr-4",children:[e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:y.map(g=>{const x=i.includes(g.id);return e.jsxs("button",{onClick:()=>m(g),className:`group relative p-3 border rounded-lg text-left transition-all hover:shadow-md ${x?"border-primary bg-primary/5 shadow-md ring-2 ring-primary":"border-border hover:border-primary/50"}`,children:[e.jsxs("div",{className:"flex items-start gap-3 mb-2",children:[(()=>{const R=Rr[g.icon];
4return R?e.jsx(R,{className:"h-6 w-6 shrink-0 text-primary"}):e.jsx("div",{className:"h-6 w-6 shrink-0"})})(),e.jsxs("div",{className:"flex-1 min-w-0",children:[e.jsxs("div",{className:"flex items-center justify-between gap-2",children:[e.jsx("h4",{className:"font-semibold text-sm truncate",children:g.name}),x&&e.jsx("div",{className:"h-5 w-5 rounded-full bg-primary flex items-center justify-center shrink-0",children:e.jsx(Xa,{className:"h-3 w-3 text-primary-foreground"})})]}),e.jsx("p",{className:"text-xs text-muted-foreground mt-0.5 line-clamp-2",children:g.description})]})]}),e.jsxs("div",{className:"flex items-center justify-between text-xs text-muted-foreground",children:[e.jsx("span",{className:"capitalize",children:g.widgetType}),g.defaultLayout&&e.jsxs("span",{className:"opacity-60",children:[g.defaultLayout.w,"×",g.defaultLayout.h]})]}),g.config&&Object.keys(g.config).length>0&&e.jsx("div",{className:"mt-2 pt-2 border-t text-[10px] text-muted-foreground",children:e.jsxs("div",{className:"flex flex-wrap gap-1",children:[g.config.unit&&e.jsx("span",{className:"px-1.5 py-0.5 rounded bg-muted",children:g.config.unit}),g.config.min!==void 0&&g.config.max!==void 0&&e.jsxs("span",{className:"px-1.5 py-0.5 rounded bg-muted",children:[g.config.min,"–",g.config.max]}),g.config.onLabel&&e.jsx("span",{className:"px-1.5 py-0.5 rounded bg-muted",children:g.config.onLabel})]})})]},g.id)})}),y.length===0&&e.jsxs("div",{className:"flex flex-col items-center justify-center h-64 text-muted-foreground",children:[e.jsx(Dt,{className:"h-12 w-12 mb-3 text-primary/30"}),e.jsx("p",{className:"text-sm",children:"No presets found"}),e.jsx("p",{className:"text-xs mt-1",children:"Try a different search term or category"})]})]}),i.length>0&&e.jsxs("div",{className:"text-xs text-muted-foreground bg-muted/30 p-3 rounded-md",children:[e.jsxs("strong",{children:[i.length," preset",i.length>1?"s":""," selected:"]})," ",i.map(g=>Vt.find(x=>x.id===g)?.name).filter(Boolean).join(", "),e.jsx("br",{}),"Each preset will be added with its recommended settings using your first available device. You can customize them after adding."]})]})}function at({value:i,onChange:m,placeholder:k="Select icon",suggestions:d}){const[T,z]=r.useState(!1),[F,p]=r.useState(""),y=r.useMemo(()=>or(),[]),g=r.useMemo(()=>{const D=F.trim().toLowerCase();return D?y.filter(O=>O.includes(D)).slice(0,240):y.slice(0,240)},[y,F]),x=qt(i),R=d&&d.length>0&&!F,P=D=>{m(D),z(!1)};return e.jsxs(Za,{open:T,onOpenChange:z,children:[e.jsx(es,{asChild:!0,children:e.jsxs(E,{variant:"outline",size:"sm",className:"justify-between gap-2 min-w-[160px]",children:[e.jsxs("span",{className:"flex items-center gap-2 truncate",children:[x?e.jsx(x,{className:"h-5 w-5"}):null,e.jsx("span",{className:"text-xs truncate",children:i||k})]}),e.jsx(na,{className:"h-3 w-3 opacity-60 shrink-0"})]})}),e.jsxs(ts,{className:"w-[320px] p-2",align:"start",children:[i&&x&&e.jsxs("div",{className:"flex items-center gap-2 px-2 py-1.5 mb-2 bg-primary/8 rounded-md border border-primary/20",children:[e.jsx(x,{className:"h-7 w-7 text-primary shrink-0"}),e.jsx("span",{className:"text-xs font-medium text-primary truncate",children:i}),e.jsx("button",{type:"button","aria-label":"Clear icon",onClick:()=>{m(null),z(!1)},className:"ml-auto h-5 w-5 rounded hover:bg-primary/20 flex items-center justify-center shrink-0",children:e.jsx(as,{className:"h-3 w-3 text-primary"})})]}),e.jsxs("div",{className:"relative mb-2",children:[e.jsx(Dt,{className:"absolute left-2 top-1/2 -translate-y-1/2 h-3.5 w-3.5 text-muted-foreground"}),e.jsx(j,{value:F,onChange:D=>p(D.target.value),placeholder:"Search icons…",className:"h-8 pl-7 text-xs",autoFocus:!0})]}),R&&e.jsxs("div",{className:"mb-2",children:[e.jsxs("div",{className:"flex items-center gap-1 mb-1.5 px-0.5",children:[e.jsx(aa,{className:"h-3 w-3 text-primary/60"}),e.jsx("span",{className:"text-[10px] font-semibold text-primary/60 uppercase tracking-wider",children:"Suggested"})]}),e.jsx("div",{className:"flex flex-wrap gap-1",children:d.map(D=>{const O=qt(D);if(!O)return null;const B=D===i;return e.jsx("button",{type:"button",title:D,onClick:()=>P(D),className:`flex items-center justify-center h-9 w-9 rounded-lg border transition-colors ${B?"bg-primary/15 text-primary border-primary/40 ring-1 ring-primary":"border-border/60 hover:bg-primary/8 hover:border-primary/30 text-slate-600 dar
4k:text-slate-400"}`,children:e.jsx(O,{className:"h-4.5 w-4.5"})},D)})}),e.jsx("div",{className:"mt-2 mb-1 h-px bg-border/50"})]}),e.jsxs(ua,{className:"h-[240px]",children:[e.jsx("div",{className:"grid grid-cols-6 gap-1",children:g.map(D=>{const O=qt(D);if(!O)return null;const B=D===i;return e.jsx("button",{type:"button",title:D,onClick:()=>P(D),className:`flex items-center justify-center h-10 w-10 rounded transition-colors ${B?"bg-primary/15 text-primary ring-2 ring-primary ring-offset-1":"hover:bg-muted text-slate-600 dark:text-slate-400"}`,children:e.jsx(O,{className:"h-5 w-5"})},D)})}),g.length===0&&e.jsxs("div",{className:"text-center text-xs text-muted-foreground py-6",children:['No icons match "',F,'"']})]})]})]})}const Ar=[["tl","tc","tr"],["ml","mc","mr"],["bl","bc","br"]];function xs({value:i,onChange:m}){return e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"grid grid-cols-3 gap-1 p-1.5 rounded-lg border border-border bg-muted/30",children:Ar.flat().map(k=>e.jsx("button",{type:"button",title:Fr[k],onClick:()=>m(k),className:`w-7 h-7 rounded flex items-center justify-center border transition-all duration-150 ${i===k?"bg-primary border-primary shadow-sm":"border-border/60 bg-background hover:border-primary/50 hover:bg-primary/5"}`,children:e.jsx("div",{className:`rounded-full transition-all ${i===k?"w-2 h-2 bg-white":"w-1.5 h-1.5 bg-muted-foreground/30"}`})},k))}),e.jsx("button",{type:"button",onClick:()=>m("off"),className:`text-[11px] font-medium px-2.5 py-1.5 rounded-md border transition-all duration-150 ${i==="off"?"bg-primary border-primary text-primary-foreground":"border-border text-muted-foreground hover:border-primary/50 hover:text-foreground"}`,children:"Hide"})]})}const Fr={tl:"Top left",tc:"Top center",tr:"Top right",ml:"Middle left",mc:"Middle center",mr:"Middle right",bl:"Bottom left",bc:"Bottom center",br:"Bottom right"},Ga=[{id:"display",name:"Display & Visualization",icon:e.jsx(gt,{className:"h-4 w-4"})},{id:"content",name:"Content & Information",icon:e.jsx(pt,{className:"h-4 w-4"})},{id:"environmental",name:"Environmental Sensors",icon:e.jsx(yt,{className:"h-4 w-4"})},{id:"energy",name:"Energy & Power",icon:e.jsx(Ft,{className:"h-4 w-4"})},{id:"connectivity",name:"Connectivity & Location",icon:e.jsx(Et,{className:"h-4 w-4"})},{id:"controls",name:"Controls & Inputs",icon:e.jsx(ms,{className:"h-4 w-4"})},{id:"media",name:"Media & Camera",icon:e.jsx(xt,{className:"h-4 w-4"})}],Tt=[{value:"value",label:"Value Display",description:"Large number display for key metrics",icon:e.jsxs("svg",{viewBox:"0 0 10 18",fill:"currentColor",className:"h-5 w-5 text-primary","aria-hidden":"true",children:[e.jsx("rect",{x:"1.5",y:"0",width:"7",height:"1.8",rx:"0.9"}),e.jsx("rect",{x:"0",y:"1.5",width:"1.8",height:"6",rx:"0.9"}),e.jsx("rect",{x:"8.2",y:"1.5",width:"1.8",height:"6",rx:"0.9"}),e.jsx("rect",{x:"1.5",y:"8.1",width:"7",height:"1.8",rx:"0.9"}),e.jsx("rect",{x:"0",y:"10.5",width:"1.8",height:"6",rx:"0.9"}),e.jsx("rect",{x:"8.2",y:"10.5",width:"1.8",height:"6",rx:"0.9"}),e.jsx("rect",{x:"1.5",y:"16.2",width:"7",height:"1.8",rx:"0.9"})]}),category:"display"},{value:"gauge",label:"Gauge",description:"Circular gauge with min/max ranges",icon:e.jsx(da,{className:"h-5 w-5 text-primary"}),category:"display"},{value:"chart",label:"Time Series Chart",description:"Line chart with historical data",icon:e.jsx(lt,{className:"h-5 w-5 text-primary"}),category:"display"},{value:"status",label:"Status Indicator",description:"Device online/offline status",icon:e.jsx(Hs,{className:"h-5 w-5 text-primary"}),category:"display"},{value:"speedometer",label:"Speedometer",description:"Speed/RPM gauge with needle indicator",icon:e.jsx(ia,{className:"h-5 w-5 text-primary"}),category:"display"},{value:"trend",label:"Trend Indicator",description:"Show metric trend with up/down arrows",icon:e.jsx(cs,{className:"h-5 w-5 text-primary"}),category:"display"},{value:"barchart",label:"Bar Chart",description:"Compare multiple metrics in bars",icon:e.jsx(vr,{className:"h-5 w-5 text-primary"}),category:"display"},{value:"piechart",label:"Pie Chart",description:"Distribution breakdown in pie slices",icon:e.jsx(cr,{className:"h-5 w-5 text-primary"}),category:"display"},{value:"level",label:"Level Indicator",description:"Vertical tank level with wave animation",icon:e.jsx(At,{className:"h-5 w-5 text-primary"}),category:"display"},{value:"progress",label:"Progress Bar",description:"Horizontal bar for battery or completion",icon:e.jsx(st,{className:"h-5 w-5 text-primary"}),category:"display"},{value:"markdown",label:"Markdown/HTML Card",description:"Render markdown or HTML content with variables",icon:e.jsx(pt,{className:"h-5 w-5 text-primary"}),category:"content"},{value:"note",label:"Text Note",description:"Sticky note for instructions or labels",icon:e.jsx(Rt,{className:"h-5 w-5 text-primary"}),category:"content"},{value:"label",label:"Section Label",description:"Header text for organizing your dashboard",icon:e.jsx(Pt,{className:"h-5 w-5 text-primary"}),category:"content"},{value:"clock",label:"Digital Clock",description:"Real-time system time and date display",icon:e.jsx(Qe,{className:"h-5 w-5 text-primary"}),category:"content"},{value:"table",label:"Data Table",description:"Tabular view of current latest data",icon:e.jsx(is,{className:"h-5 w-5 text-primary"}),category:"content"},{value:"history_table",label:"History Table",description:"Scrollable table of historical values",icon:e.jsx(Ia,{className:"h-5 w-5 text-primary"}),category:"content"},{value:"log",label:"Event Log",description:"Scrollable list of recent events",icon:e.jsx(jr,{className:"h-5 w-5 text-primary"}),category:"content"},{value:"timeline",label:"Event Timeline",description:"Compact list of recent logs/events",icon:e.jsx(Qa,{className:"h-5 w-5 text-primary"}),category:"content"}
4,{value:"message",label:"Message Display",description:"Show text messages from devices",icon:e.jsx(Bs,{className:"h-5 w-5 text-primary"}),category:"content"},{value:"alert",label:"Alert Widget",description:"Warning/error alerts with severity levels",icon:e.jsx(la,{className:"h-5 w-5 text-primary"}),category:"content"},{value:"notification",label:"Notifications",description:"Recent notifications feed",icon:e.jsx(Nr,{className:"h-5 w-5 text-primary"}),category:"content"},{value:"healthcheck",label:"Health Check",description:"Device health status with pass/fail",icon:e.jsx(Zt,{className:"h-5 w-5 text-primary"}),category:"content"},{value:"schedule",label:"Schedule/Timer",description:"Device schedule and automation timer",icon:e.jsx(Ia,{className:"h-5 w-5 text-primary"}),category:"content"},{value:"temperature",label:"Temperature",description:"Temperature with color scale",icon:e.jsx(yt,{className:"h-5 w-5 text-primary"}),category:"environmental"},{value:"humidity",label:"Humidity",description:"Humidity percentage with droplets",icon:e.jsx(pa,{className:"h-5 w-5 text-primary"}),category:"environmental"},{value:"airquality",label:"Air Quality",description:"AQI with health indicators",icon:e.jsx(gr,{className:"h-5 w-5 text-primary"}),category:"environmental"},{value:"power",label:"Power Monitor",description:"Real-time power consumption meter",icon:e.jsx(rt,{className:"h-5 w-5 text-primary"}),category:"energy"},{value:"battery",label:"Battery Level",description:"Battery status with charging indicator",icon:e.jsx(Ft,{className:"h-5 w-5 text-primary"}),category:"energy"},{value:"light",label:"Light Status",description:"Visual status indicator for a light (ON/OFF display only)",icon:e.jsx(xa,{className:"h-5 w-5 text-primary"}),category:"energy"},{value:"map",label:"Location Map",description:"GPS coordinates on interactive map",icon:e.jsx(sa,{className:"h-5 w-5 text-primary"}),category:"connectivity"},{value:"signal",label:"Signal Strength",description:"WiFi/cellular signal quality indicator",icon:e.jsx(Et,{className:"h-5 w-5 text-primary"}),category:"connectivity"},{value:"uptime",label:"Uptime Monitor",description:"Device uptime and last seen timestamp",icon:e.jsx(Qe,{className:"h-5 w-5 text-primary"}),category:"connectivity"},{value:"toggle",label:"Toggle Switch",description:"ON/OFF toggle control",icon:e.jsx(ds,{className:"h-5 w-5 text-primary"}),category:"controls"},{value:"slider",label:"Slider",description:"Continuous value adjustment (0-100)",icon:e.jsx(ms,{className:"h-5 w-5 text-primary"}),category:"controls"},{value:"colorpicker",label:"Color Picker",description:"RGB color selection for LED control",icon:e.jsx(Xt,{className:"h-5 w-5 text-primary"}),category:"controls"},{value:"dropdown",label:"Dropdown",description:"Select from predefined options",icon:e.jsx(na,{className:"h-5 w-5 text-primary"}),category:"controls"},{value:"stepper",label:"Stepper",description:"Increment/decrement value",icon:e.jsx(ca,{className:"h-5 w-5 text-primary"}),category:"controls"},{value:"joystick",label:"Joystick",description:"2D directional control (X/Y axis)",icon:e.jsx(Us,{className:"h-5 w-5 text-primary"}),category:"controls"},{value:"scene",label:"Scene Selector",description:"Multi-state button group for mode selection",icon:e.jsx(gt,{className:"h-5 w-5 text-primary"}),category:"controls"},{value:"image",label:"Image",description:"Display static images from a URL or base64 data",icon:e.jsx(xt,{className:"h-5 w-5 text-primary"}),category:"media"},{value:"video",label:"Video",description:"Play MP4/WebM video clips directly on the dashboard",icon:e.jsx(Ot,{className:"h-5 w-5 text-primary"}),category:"media"},{value:"stream",label:"Live Stream",description:"Connect to live HLS, Dash, or RTSP camera feeds",icon:e.jsx(it,{className:"h-5 w-5 text-primary"}),category:"media"},{value:"webrtc_stream",label:"Live Camera (WebRTC)",description:"Real-time P2P video from an ESP32-CAM via WebRTC signaling",icon:e.jsx(ma,{className:"h-5 w-5 text-primary"}),category:"media"},{value:"mjpeg_stream",label:"MJPEG Snapshot Stream",description:"Low-latency MJPEG relay from a connected camera device",icon:e.jsx(it,{className:"h-5 w-5 text-primary"}),category:"media"}];function Vr({open:i,onOpenChange:m,onAdd:k,onAddMultiple:d,devices:T,isLoading:z,initialVariablesByDevice:F}){const[p,y]=r.useState(null),[g,x]=r.useState(""),[R,P]=r.useState(""),[D,O]=r.useState(""),[B,J]=r.useState([]),[I,ue]=r.useState(""),[he,le]=r.useState(""),[ve,ye]=r.useState(null),[we,_e]=r.useState(""),[de,b]=r.useState([]),[ne,oe]=r.useState(!1),[q,X]=r.useState([]),[n,f]=r.useState({}),[ge,c]=r.useState(!1),w=r.useRef({});r.useEffect(()=>{F&&(w.current={...F,...w.current})},[F]),r.useEffect(()=>{if(!I){b([]),O(""),J([]);return}const t=w.current[I];t&&b(t),O(""),J([]),(async()=>{t||oe(!0);try{const M=await ut.list(I,{active_only:!0});w.current[I]=M.variables,b(M.variables)}catch(M){console.error("Failed to load variables",M),t||b([])}finally{oe(!1)}})()},[I]),r.useEffect(()=>{i||(y(null),x(""),P(""),O(""),J([]),ue(""),le(""),ye(null),_e(""),b([]),X([]),f({}),c(!1))},[i]),r.useEffect(()=>{p==="table"&&f(t=>t.rowCount==null?{...t,rowCount:5}:t)},[p]);const W=t=>{X(C=>C.includes(t.id)?C.filter(M=>M!==t.id):[...C,t.id])},s=async()=>
4{if(!d||q.length===0)return;const t=T[0],C=q.map(M=>{const U=Vt.find(L=>L.id===M);return{type:U.widgetType,title:U.name,device_id:t?.id??void 0,config:U.config??{},layout:{x:0,y:0,w:4,h:3,...U.defaultLayout??{}},refresh_mode:"realtime"}});try{await d(C),X([]),m(!1)}catch(M){console.error("Add Presets error:",M)}},v=t=>{let C=Tt.filter(M=>M.category===t&&ta.has(M.value));if(we.trim()){const M=we.toLowerCase();C=C.filter(U=>U.label.toLowerCase().includes(M)||U.description.toLowerCase().includes(M))}return C},H=["chart","trend","barchart","piechart","table","history_table","map"].includes(p||""),Y=["status","clock","note","label","image","video","stream","scene","markdown","webrtc_stream","mjpeg_stream"].includes(p||""),me=["clock","note","label","image","video","stream","markdown","webrtc_stream","mjpeg_stream"].includes(p||""),ce=async()=>{if(!p)return;if(!g.trim()){P("Widget label is required");return}if(P(""),p==="map"&&B.length<2||H&&B.length===0||!H&&!D&&!Y||(p==="webrtc_stream"||p==="mjpeg_stream")&&!n.room_id)return;let C={...n};if(p==="scene"&&C.options&&(C.options=C.options.map(L=>{if(typeof L.payload=="string")try{return{...L,payload:JSON.parse(L.payload)}}catch{return console.warn("Failed to parse scene payload JSON:",L.payload),L}return L})),p==="map"){const L=T.find(Q=>Q.id===I);L&&(C={...C,device_name:L.device_name})}if(H){const L=de.filter(Q=>B.includes(Q.id));C={...C,metric_keys:L.map(Q=>Q.key)}}else if(!Y){const L=de.find(Q=>Q.id===D);C={...C,metric_key:L?.key,commandKey:L?.key,...he?{unit:he}:L?.unit?{unit:L.unit}:{}}}const M=H?B[0]:D,U={type:p,title:g,...M?{variable_id:M}:{},device_id:I||void 0,config:C,layout:{x:0,y:0,w:4,h:3},refresh_mode:"realtime"};try{console.log("[AddWidget] Attempting to add widget:",{type:p,title:g,deviceId:I,isNoVariableType:Y}),await k(U),y(null),x(""),O(""),J([]),ue(""),le(""),b([]),f({})}catch(L){console.error("Add Widget error in dialog:",L)}};return e.jsx(Ve,{open:i,onOpenChange:m,children:e.jsxs(Ie,{className:"sm:max-w-[650px] max-h-[90vh] overflow-y-auto",children:[e.jsxs(ze,{children:[e.jsxs(We,{className:"flex items-center gap-2",children:[e.jsx($e,{className:"h-5 w-5 text-primary"}),"Add Widget"]}),e.jsx(Ke,{children:"Choose a widget type and configure it for your dashboard."})]}),e.jsx("div",{className:"space-y-3 py-2",children:p?e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs(l,{className:"flex items-center gap-1.5 text-xs",children:["Device",!me&&e.jsx("span",{className:"text-destructive",children:"*"})]}),e.jsxs(te,{value:I,onValueChange:ue,children:[e.jsx(ae,{className:"border-primary/20 bg-primary/5 h-9",children:e.jsx(se,{placeholder:"Select device"})}),e.jsxs(re,{children:[T.filter(t=>t.id).map(t=>e.jsx(S,{value:t.id,children:t.device_name},t.id)),e.jsx("div",{className:"border-t mt-1 pt-1",children:e.jsxs("a",{href:"/devices",target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-1.5 px-2 py-1.5 text-xs font-medium text-primary hover:bg-primary/5 rounded-sm",children:[e.jsx($e,{className:"h-3.5 w-3.5"}),"Add new device"]})})]})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs(l,{htmlFor:"widget-title",className:"text-xs",children:["Widget Label ",e.jsx("span",{className:"text-destructive",children:"*"})]}),e.jsx(j,{id:"widget-title",placeholder:"e.g. Room Lamp",value:g,onChange:t=>{x(t.target.value),t.target.value.trim()&&P("")},onBlur:()=>{g.trim()||P("Widget label is required")},className:`h-9 ${R?"border-destructive focus-visible:ring-destructive":""}`,"aria-invalid":!!R}),R&&e.jsx("p",{className:"text-[11px] text-destructive flex items-center gap-1",children:R})]})]}),e.jsxs("div",{className:"p-2.5 border rounded-md bg-muted/30 flex items-center gap-3",children:[Tt.find(t=>t.value===p)?.icon,e.jsxs("div",{className:"flex flex-col flex-1",children:[e.jsx("span",{className:"text-sm font-medium",children:Tt.find(t=>t.value===p)?.label}),e.jsx("span",{className:"text-[10px] text-muted-foreground line-clamp-1",children:Tt.find(t=>t.value===p)?.description})]}),e.jsx(E,{variant:"ghost",size:"sm",className:"ml-auto text-[10px] h-7 shrink-0",onClick:()=>y(null),children:"Change"})]}),!Y&&I&&p!=="value"&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(l,{className:"text-xs",children:[H?"Variables":"Variable"," ",e.jsxs("span",{className:"text-muted-foreground font-normal",children:["(data point",H&&"s",")"]})]}),ne&&e.jsx(qe,{className:"h-3 w-3 animate-spin text-primary"})]}),e.jsxs("div",{className:"flex items-center gap-1",children:[e.jsxs(E,{type:"button",variant:"ghost",size:"sm",className:"h-6 text-[10px]",onClick:async()=>{oe(!0);try{const t=await ut.list(I,{active_only:!0});w.current[I]=t.variables,b(t.variables)}catch(t){console.error("Failed to reload variables",t)}finally{oe(!1)}},disabled:ne,children:[e.jsx(oa,{className:"h-3 w-3 mr-1"}),"Refresh"]}),e.jsxs("a",{href:`/iot-dashboard/variables?add=1&device=${I}`,target:"_blank",rel:"noopener noreferrer",className:"flex items-center gap-1 h-6 px-1.5 text-[10px] font-medium text-primary hover:bg-primary/5 rounded-sm",children:[e.jsx($e,{className:"h-3 w-3"}),"Add variable"]})]})]}),ne?e.jsxs("div",{className:"flex items-center justify-center gap-2 text-sm text-muted-foreground py-4 border rounded-md bg-muted/10",children:[e.jsx(qe,{className:"h-4 w-4 animate-spin text-primary"}),e.jsx("span",{children:"Loading variables..."})]}):de.length===0?e.jsxs("div",{className:"text-sm text-muted-foreground py-3 px-4 border rounded-md bg-yellow-500/10 border-yellow-500/20",children:[e.jsx("p",{className:"font-medium text-yellow-700 dark:text-yellow-500 mb-1",children:"No Variables Found"}),e.jsxs("p",{className:"text-xs",children:["This device has no variables."," ",e.jsx("a",{href:`/iot-dashboard/variables?add=1&device=${I}`,target:"_blank",rel:"noopener noreferrer",className:"font-medium text-primary underline underline-offset-2",children:"Add one in a new tab"}),", then hit Refresh."]})]}):H?e.jsx("div",{className:"flex flex-col gap-2 max-h-[120px] overflow-y-auto p-2 border rounded-md custom-scrollbar bg-muted/20",children:de.map(t=>{const C=B.includes(t.id);return e.jsxs("div",{className:`flex items-center space-x-3 p-2 rounded-md cursor-pointer text-sm transition-colors ${C?"bg-primary/10 border border-primary/30":"hover:bg-muted border border-transparent"}`,onClick:()=>{J(C?B.filter(M=>M!==t.id):[...B,t.id])},children:[e.jsx(Se,{checked:C,onCheckedChange:M=>{J(M?[...B,t.id]:B.filter(U=>U!==t.id))}}),e.jsxs("div",{className:"flex-1",children:[e.jsx("span",{className:"font-medium mr-2",children:t.name}),e.jsx("span",{className:"text-[10px] text-muted-foreground bg-muted px-1.5 py-0.5 rounded",children:t.key})]})]},t.id)})}):e.jsxs(te,{value:D,onValueChange:O,children:[e.jsx(ae,{children:e.jsx(se,{placeholder:"Select variable"})}),e.jsx(re,{children:de.map(t=>e.jsx(S,{value:t.id,children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{children:t.name}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:["(",t.key,")"]})]})},t.id))})]})]}),p==="value"&&I&&e.jsxs("div",{className:"grid grid-cols-2 gap-3 items-start",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs(l,{className:"text-xs",children:["Variable ",e.jsx("span",{className:"text-muted-foreground font-normal",children:"(data point)"})]}),ne&&e.jsx(qe,{className:"h-3 w-3 animate-spin text-primary"})]}),ne?e.jsxs("div",{className:"flex items-center gap-2 text-xs text-muted-foreground py-2 px-3 border rounded-md bg-muted/10",children:[e.jsx(qe,{className:"h-3 w-3 animate-spin text-primary"}
4),"Loading..."]}):de.length===0?e.jsxs("div",{className:"text-xs py-2 px-3 border rounded-md bg-yellow-500/10 border-yellow-500/20 text-yellow-700 dark:text-yellow-500",children:["No variables."," ",e.jsx("a",{href:`/iot-dashboard/variables?add=1&device=${I}`,target:"_blank",rel:"noopener noreferrer",className:"underline underline-offset-2",children:"Add one"}),", then"," ",e.jsx("button",{type:"button",className:"underline underline-offset-2",onClick:async()=>{oe(!0);try{const t=await ut.list(I,{active_only:!0});w.current[I]=t.variables,b(t.variables)}catch{}finally{oe(!1)}},children:"refresh"}),"."]}):e.jsxs(te,{value:D,onValueChange:O,children:[e.jsx(ae,{children:e.jsx(se,{placeholder:"Select variable"})}),e.jsx(re,{children:de.map(t=>e.jsx(S,{value:t.id,children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{children:t.name}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:["(",t.key,")"]})]})},t.id))})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs(l,{htmlFor:"widget-unit",className:"text-xs",children:["Unit ",e.jsx("span",{className:"text-muted-foreground font-normal",children:"(optional)"})]}),e.jsx(j,{id:"widget-unit",placeholder:"e.g. °C, %, V",value:he,onChange:t=>le(t.target.value)})]})]}),p==="gauge"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(da,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Gauge Options"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{htmlFor:"gauge-unit",className:"text-xs",children:"Unit (optional)"}),e.jsx(j,{id:"gauge-unit",placeholder:"e.g. °C, %, rpm",value:he,onChange:t=>le(t.target.value),className:"h-8"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"gauge-min",className:"text-[10px]",children:"Min Value"}),e.jsx(j,{id:"gauge-min",type:"number",placeholder:"0",value:n.min??"",onChange:t=>f({...n,min:t.target.value?parseFloat(t.target.value):0}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"gauge-max",className:"text-[10px]",children:"Max Value"}),e.jsx(j,{id:"gauge-max",type:"number",placeholder:"100",value:n.max??"",onChange:t=>f({...n,max:t.target.value?parseFloat(t.target.value):100}),className:"h-8 text-xs"})]})]}),e.jsx("p",{className:"text-[10px] text-muted-foreground",children:"Set the range for the gauge needle"}),e.jsxs("div",{className:"pt-2 border-t space-y-2",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Se,{id:"add-active-range",checked:!!n.activeRange,onCheckedChange:t=>f({...n,activeRange:!!t})}),e.jsx(l,{htmlFor:"add-active-range",className:"text-xs",children:"Active Range Colors"})]}),!!n.activeRange&&e.jsxs("div",{className:"grid grid-cols-3 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px] text-green-600",children:"Low → Medium"}),e.jsx(j,{type:"number",placeholder:"e.g. 30",value:n.rangeLow??"",onChange:t=>f({...n,rangeLow:t.target.value?parseFloat(t.target.value):void 0}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px] text-amber-600",children:"Medium → High"}),e.jsx(j,{type:"number",placeholder:"e.g. 60",value:n.rangeMid??"",onChange:t=>f({...n,rangeMid:t.target.value?parseFloat(t.target.value):void 0}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px] text-orange-600",children:"High → Critical"}),e.jsx(j,{type:"number",placeholder:"e.g. 80",value:n.rangeHigh??"",onChange:t=>f({...n,rangeHigh:t.target.value?parseFloat(t.target.value):void 0}),className:"h-8 text-xs"})]})]}),!!n.activeRange&&e.jsx("p",{className:"text-[10px] text-muted-foreground",children:"Leave blank to auto-split into equal quarters (green → amber → orange → red)."})]})]}),p==="chart"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(lt,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Chart Options"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{htmlFor:"chart-datapoints",className:"text-xs",children:"Data Points"}),e.jsx(j,{id:"chart-datapoints",type:"number",placeholder:"50",value:n.dataPoints||"50",onChange:t=>f({...n,dataPoints:parseInt(t.target.value)||50}),className:"h-8"})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{className:"text-xs font-semibold",children:"Y-Axis"}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"y-min",className:"text-[10px]",children:"Min"}),e.jsx(j,{id:"y-min",type:"number",placeholder:"Auto",value:n.yMin??"",onChange:t=>f({...n,yMin:t.target.value?parseFloat(t.target.value):void 0}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"y-max",className:"text-[10px]",children:"Max"}),e.jsx(j,{id:"y-max",type:"number",placeholder:"Auto",value:n.yMax??"",onChange:t=>f({...n,yMax:t.target.value?parseFloat(t.target.value):void 0}),className:"h-8 text-xs"})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"y-label",className:"text-[10px]",children:"Label"}),e.jsx(j,{id:"y-label",placeholder:"e.g. Temp (°C)",value:n.yLabel||"",onChange:t=>f({...n,yLabel:t.target.value}),className:"h-8 text-xs"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{className:"text-xs font-semibold",children:"X-Axis"}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"x-type",className:"text-[10px]",children:"Type"}),e.jsxs(te,{value:n.xType||"time",onValueChange:t=>f({...n,xType:t}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"time",children:"Time Series"}),e.jsx(S,{value:"linear",children:"Linear"}),e.jsx(S,{value:"category",children:"Category"})]})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"x-label",className:"text-[10px]",children:"Label"}),e.jsx(j,{id:"x-label",placeholder:"e.g. Time",value:n.xLabel||"",onChange:t=>f({...n,xLabel:t.target.value}),className:"h-8 text-xs"})]})]})]})]}),p==="image"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(xt,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Image Options"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-xs",children:"Display Mode"}),e.jsxs(te,{value:n.mode||"latest",onValueChange:t=>f({...n,mode:t}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"latest",children:"Latest image only"}),e.jsx(S,{value:"slideshow",children:"Slideshow  all images"})]})]}),e.jsx("p",{className:"text-[10px] text-muted-foreground italic",children:(n.mode||"latest")==="slideshow"?"Loads the last 10 images from telemetry history and shows them as a carousel.":"Shows only the most recent image sent by the device."})]}),(n.mode||"latest")==="latest"&&e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(l,{htmlFor:"image-url",className:"text-xs",children:"Image URL"}),I&&e.jsx(E,{variant:"link",size:"sm",className:"h-auto p-0 text-[10px] text-primary",onClick:()=>{f({...n,url:`https://www.circuitdigest.cloud/api/v1/devices/mqtt_u_${I}/image/content`})},children:"Use Device Latest"})]}),e.jsx(j,{id:"image-url",placeholder:"https://example.com/image.jpg",value:n.url||"",onChange:t=>f({...n,url:t.target.value}),className:"h-8"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-xs",children:"Scaling"}),e.jsxs(te,{value:n.fit||"cover",onValueChange:t=>f({...n,fit:t}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"cover",children:"Cover (Fill)"}),e.jsx(S,{value:"contain",children:"Contain (Fit)"})]})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-xs",children:"Capture Trigger Variable"}
4),e.jsxs(te,{value:n.captureVariableKey||"none",onValueChange:t=>f({...n,captureVariableKey:t==="none"?void 0:t}),disabled:!I,children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{placeholder:"None"})}),e.jsxs(re,{children:[e.jsx(S,{value:"none",children:"None (capture button hidden)"}),de.filter(t=>t.key?.startsWith("capture-")).map(t=>e.jsx(S,{value:t.key,children:t.name||t.key},t.id))]})]}),e.jsx("p",{className:"text-[10px] text-muted-foreground italic",children:'Optional. Adds a Capture button that pulses this variable to trigger the device camera. Requires a "capture-N" variable on this device.'})]})]}),(p==="video"||p==="stream")&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[p==="video"?e.jsx(Ot,{className:"h-4 w-4 text-primary"}):e.jsx(it,{className:"h-4 w-4 text-primary"}),e.jsxs(l,{className:"text-sm font-semibold",children:[p==="video"?"Video":"Stream"," Options"]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{htmlFor:"media-url",className:"text-xs",children:"Source URL"}),e.jsx(j,{id:"media-url",placeholder:p==="video"?"MP4/WebM URL":"HLS/RTSP URL",value:n.url||"",onChange:t=>f({...n,url:t.target.value}),className:"h-8"})]}),p==="video"&&e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Se,{id:"auto-play",checked:n.autoPlay!==!1,onCheckedChange:t=>f({...n,autoPlay:!!t})}),e.jsx(l,{htmlFor:"auto-play",className:"text-xs",children:"Auto-play & Loop"})]})]}),(p==="webrtc_stream"||p==="mjpeg_stream")&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(ma,{className:"h-4 w-4 text-primary"}),e.jsxs(l,{className:"text-sm font-semibold",children:[p==="webrtc_stream"?"WebRTC Camera":"MJPEG Stream"," Options"]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs(l,{htmlFor:"room-id",className:"text-xs",children:["Room ID ",e.jsx("span",{className:"text-destructive",children:"*"})]}),e.jsx(j,{id:"room-id",placeholder:"e.g. esp32cam-living-room",value:n.room_id||"",onChange:t=>f({...n,room_id:t.target.value.trim()}),className:"h-8 font-mono text-xs"}),e.jsxs("p",{className:"text-[10px] text-muted-foreground",children:["Must match the ",e.jsx("code",{className:"text-[9px] bg-muted px-1 rounded",children:"room_id"})," your device publishes to."]})]}),p==="webrtc_stream"&&e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-xs",children:"Quality"}),e.jsxs(te,{value:n.quality||"med",onValueChange:t=>f({...n,quality:t}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"low",children:"Low (240p)"}),e.jsx(S,{value:"med",children:"Medium (480p)"}),e.jsx(S,{value:"high",children:"High (720p)"})]})]})]}),e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Se,{id:"auto-reconnect",checked:n.auto_reconnect!==!1,onCheckedChange:t=>f({...n,auto_reconnect:!!t})}),e.jsx(l,{htmlFor:"auto-reconnect",className:"text-xs",children:"Auto-reconnect on disconnect"})]})]}),p==="note"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(Rt,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Note Content"})]}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(E,{type:"button",variant:n.mode!=="html"?"default":"outline",size:"sm",onClick:()=>f({...n,mode:"text"}),className:"h-7 text-[10px]",children:"Plain Text"}),e.jsx(E,{type:"button",variant:n.mode==="html"?"default":"outline",size:"sm",onClick:()=>f({...n,mode:"html"}),className:"h-7 text-[10px]",children:"Static HTML"})]}),n.mode==="html"?e.jsxs("div",{className:"space-y-1.5",children:[e.jsx("textarea",{className:"w-full h-28 p-2 text-xs border rounded bg-background font-mono",placeholder:"<p>Hello <b>world</b></p>",value:n.html||"",onChange:t=>f({...n,html:t.target.value})}),e.jsx("p",{className:"text-[10px] text-muted-foreground",children:"Scripts and event handlers are stripped automatically."})]}):e.jsx("textarea",{className:"w-full h-24 p-2 text-xs border rounded bg-background",placeholder:"Enter your dashboard note here...",value:n.text||n.content||"",onChange:t=>f({...n,text:t.target.value})})]}),p==="label"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(Pt,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Label Styling"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px]",children:"Font Size"}),e.jsxs(te,{value:n.fontSize||"medium",onValueChange:t=>f({...n,fontSize:t}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"small",children:"Small"}),e.jsx(S,{value:"medium",children:"Medium"}),e.jsx(S,{value:"large",children:"Large"})]})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px]",children:"Alignment"}),e.jsxs(te,{value:n.align||"left",onValueChange:t=>f({...n,align:t}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"left",children:"Left"}),e.jsx(S,{value:"center",children:"Center"})]})]})]})]})]}),p==="clock"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(Qe,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Clock Options"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Se,{id:"show-seconds",checked:n.showSeconds!==!1,onCheckedChange:t=>f({...n,showSeconds:!!t})}),e.jsx(l,{htmlFor:"show-seconds",className:"text-xs",children:"Show Seconds"})]}),e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Se,{id:"format-24h",checked:n.format24h===!0,onCheckedChange:t=>f({...n,format24h:!!t})}),e.jsx(l,{htmlFor:"format-24h",className:"text-xs",children:"24-hour Format"})]})]})]}),p==="level"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(At,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Level Options"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"level-min",className:"text-[10px]",children:"Min Value"}),e.jsx(j,{id:"level-min",type:"number",placeholder:"0",value:n.min??"",onChange:t=>f({...n,min:parseFloat(t.target.value)||0}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"level-max",className:"text-[10px]",children:"Max Value"}),e.jsx(j,{id:"level-max",type:"number",placeholder:"100",value:n.max??"",onChange:t=>f({...n,max:parseFloat(t.target.value)||100}),className:"h-8 text-xs"})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{htmlFor:"level-unit",className:"text-xs",children:"Unit"}),e.jsx(j,{id:"level-unit",placeholder:"e.g. %, Liters",value:n.unit||"",onChange:t=>le(t.target.value),className:"h-8 text-xs"})]})]}),p==="progress"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(st,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Progress Options"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"progress-min",className:"text-[10px]",children:"Min"}),e.jsx(j,{id:"progress-min",type:"number",placeholder:"0",value:n.min??"",onChange:t=>f({...n,min:parseFloat(t.target.value)||0}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"progress-max",className:"text-[10px]",children:"Max"}),e.jsx(j,{id:"progress-max",type:"number",placeholder:"100",value:n.max??"",onChange:t=>f({...n,max:parseFloat(t.target.value)||100}),className:"h-8 text-xs"})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px]",children:"Bar Color"}),e.jsxs(te,{value:n.color||"bg-blue-500",onValueChange:t=>f({...n,color:t}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"bg-blue-500",children:"Blue"}),e.jsx(S,{value:"bg-green-500",children:"Green"}),e.jsx(S,{value:"bg-amber-500",children:"Amber"}),e.jsx(S,{value:"bg-rose-500",children:"Rose"})]})]})]})]}),p==="markdown"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(pt,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Markdown/HTML Content"})]}),e.jsx("div",{className:"space-y-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(l,{className:"text-xs",children:"Content Mode"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(E,{type:"button",variant:n.mode!=="html"?"default":"outline",size:"sm",onClick:()=>f({...n,mode:"markdown"}),className:"h-7 text-[10px]",children:"Markdown"}),e.jsx(E,{type:"button",variant:n.mode==="html"?"default":"outline",size:"sm",onClick:()=>f({...n,mode:"html"}),className:"h-7 text-[10px]",children:"HTML"})]})]})}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs(l,{className:"text-xs",children:["Content ",n.mode==="html"?"(HTML)":"(Mark
4down)"]}),e.jsx("textarea",{className:"w-full h-40 p-2 text-xs border rounded bg-background font-mono",placeholder:n.mode==="html"?`<div style="text-align: center;">
5  <h2>Dashboard Stats</h2>
6  <p>Temperature: \${temp}°C</p>
7</div>`:"# Dashboard Title\n\n**Current Temperature:** ${temp}°C\n\nUse `${variable_name}` for substitution.",value:n.content||"",onChange:t=>f({...n,content:t.target.value})}),e.jsxs("p",{className:"text-[10px] text-muted-foreground italic",children:["Use ",e.jsx("code",{className:"text-[9px] bg-muted px-1 py-0.5 rounded",children:"${variable_name}"})," to insert live device data"]})]})]}),p==="table"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(is,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Table Options"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px]",children:"Rows to show (1–20)"}),e.jsx(j,{type:"number",min:1,max:20,placeholder:"5",value:n.rowCount??5,onChange:t=>f({...n,rowCount:Math.max(1,Math.min(20,Number(t.target.value)||5))}),className:"h-8 text-xs"})]}),e.jsx("div",{className:"flex items-end pb-1",children:e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Se,{id:"add-show-ts",checked:n.showTimestamp!==!1,onCheckedChange:t=>f({...n,showTimestamp:!!t})}),e.jsx(l,{htmlFor:"add-show-ts",className:"text-xs",children:"Show timestamp"})]})})]}),e.jsx("p",{className:"text-[10px] text-muted-foreground",children:"Select up to 5 variables above. Each row = one historical reading."})]}),p==="scene"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center justify-between pb-2 border-b",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(gt,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Scene Buttons"})]}),e.jsxs(E,{type:"button",variant:"outline",size:"sm",onClick:()=>{const t=n.options||[{label:"Eco",payload:{mode:"eco"}},{label:"Auto",payload:{mode:"auto"}},{label:"Turbo",payload:{mode:"turbo"}}];f({...n,options:[...t,{label:"New Scene",payload:{}}]})},className:"h-7 text-[10px]",children:[e.jsx(ca,{className:"h-3 w-3 mr-1"})," Add Button"]})]}),e.jsx("div",{className:"space-y-3 max-h-[200px] overflow-y-auto pr-1 custom-scrollbar",children:(n.options||[{label:"Eco",payload:{mode:"eco"}},{label:"Auto",payload:{mode:"auto"}},{label:"Turbo",payload:{mode:"turbo"}}]).map((t,C)=>e.jsxs("div",{className:"p-2 border rounded-md bg-background/50 relative group",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-2 pr-6",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px]",children:"Button Label"}),e.jsx(j,{value:t.label,onChange:M=>{const L=[...n.options||[{label:"Eco",payload:{mode:"eco"}},{label:"Auto",payload:{mode:"auto"}},{label:"Turbo",payload:{mode:"turbo"}}]];L[C]={...L[C],label:M.target.value},f({...n,options:L})},className:"h-8 text-xs",placeholder:"e.g. Eco"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px]",children:"Payload (JSON)"}),e.jsx(j,{value:typeof t.payload=="object"?JSON.stringify(t.payload):t.payload,onChange:M=>{const L=[...n.options||[{label:"Eco",payload:{mode:"eco"}},{label:"Auto",payload:{mode:"auto"}},{label:"Turbo",payload:{mode:"turbo"}}]];L[C]={...L[C],payload:M.target.value},f({...n,options:L})},className:"h-8 text-xs font-mono",placeholder:'{"mode": "eco"}'})]})]}),e.jsx(E,{type:"button",variant:"ghost",size:"icon",className:"absolute right-1 top-1/2 -translate-y-1/2 h-6 w-6 text-muted-foreground hover:text-destructive",onClick:()=>{const U=(n.options||[{label:"Eco",payload:{mode:"eco"}},{label:"Auto",payload:{mode:"auto"}},{label:"Turbo",payload:{mode:"turbo"}}]).filter((L,Q)=>Q!==C);f({...n,options:U})},children:e.jsx(ht,{className:"h-4 w-4"})})]},C))}),e.jsx("p",{className:"text-[10px] text-muted-foreground italic text-center",children:"Each scene button sends a specific MQTT payload to the device."})]}),p&&!["clock","note","label","image","video","stream","colorpicker"].includes(p)&&e.jsxs("div",{className:"p-3 border rounded-lg bg-muted/20",children:[e.jsxs("button",{type:"button",className:"flex items-center justify-between w-full",onClick:()=>c(t=>
7!t),children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Xt,{className:"h-4 w-4 text-primary"}),e.jsx("span",{className:"text-sm font-semibold",children:"Icon & Appearance"})]}),e.jsx(na,{className:`h-4 w-4 text-muted-foreground transition-transform duration-200 ${ge?"rotate-180":""}`})]}),ge&&e.jsx("div",{className:"space-y-3 mt-3 pt-3 border-t",children:["toggle","switch","status","healthcheck"].includes(p)?e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-[10px]",children:"Icon when ON"}),e.jsx(at,{value:n.iconOn??null,onChange:t=>f({...n,iconOn:t}),placeholder:"Auto",suggestions:Lt(p,n.metric_key)})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-[10px]",children:"Icon when OFF"}),e.jsx(at,{value:n.iconOff??null,onChange:t=>f({...n,iconOff:t}),placeholder:"Auto",suggestions:Lt(p,n.metric_key)})]})]}):e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-[10px]",children:"Widget Icon"}),e.jsx(at,{value:n.icon??null,onChange:t=>f({...n,icon:t}),placeholder:"Auto (by type)",suggestions:Lt(p,n.metric_key)})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-[10px]",children:"Icon Position"}),e.jsx(xs,{value:n.iconPosition||"off",onChange:t=>f({...n,iconPosition:t})})]}),e.jsxs("div",{className:"space-y-1.5 col-span-2",children:[e.jsx(l,{className:"text-[10px]",children:"Icon Size"}),e.jsx("div",{className:"flex gap-1",children:["sm","md","lg","xl"].map(t=>e.jsx("button",{type:"button",onClick:()=>f({...n,iconSize:t}),className:`flex-1 py-1.5 text-xs font-medium rounded border transition-all ${(n.iconSize||"md")===t?"bg-primary text-primary-foreground border-primary":"border-border text-muted-foreground hover:border-primary/50 hover:text-foreground"}`,children:t.toUpperCase()},t))})]})]})})]})]}):e.jsxs(za,{defaultValue:"manual",className:"w-full",children:[e.jsxs(qa,{className:"grid w-full grid-cols-2 mb-4",children:[e.jsxs(Yt,{value:"manual",className:"gap-1.5",children:[e.jsx(Xt,{className:"h-3.5 w-3.5 text-primary"}),"All Widget Types"]}),e.jsxs(Yt,{value:"presets",className:"gap-1.5",children:[e.jsx(rt,{className:"h-3.5 w-3.5 text-primary"}),"Quick Start (Presets)"]})]}),e.jsxs(Oa,{value:"manual",className:"mt-0 space-y-3",children:[e.jsxs("div",{className:"relative",children:[e.jsx(Dt,{className:"absolute left-2.5 top-2.5 h-4 w-4 text-muted-foreground"}),e.jsx(j,{placeholder:"Search widgets...",className:"pl-9",value:we,onChange:t=>_e(t.target.value)})]}),e.jsxs("div",{className:"flex flex-wrap gap-2 pb-3 border-b",children:[e.jsx(E,{variant:ve===null?"default":"outline",size:"sm",onClick:()=>ye(null),className:"h-8 text-xs",children:"All Widgets"}),Ga.filter(t=>v(t.id).length>0).map(t=>e.jsxs(E,{variant:ve===t.id?"default":"outline",size:"sm",onClick:()=>ye(t.id),className:"h-8 text-xs gap-1.5",children:[t.icon,t.name]},t.id))]}),e.jsx("div",{className:"max-h-[450px] overflow-y-auto pr-2 space-y-4",children:ve===null?Ga.map(t=>{const C=v(t.id);return C.length===0?null:e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center gap-2 px-2 py-1 bg-muted/50 rounded-md",children:[t.icon,e.jsx("h3",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wide",children:t.name}),e.jsxs("span",{className:"ml-auto text-[10px] text-muted-foreground",children:[C.length," widget",C.length!==1?"s":""]})]}),e.jsx("div",{className:"grid grid-cols-2 gap-2",children:C.map(M=>e.jsxs("button",{type:"button",onClick:()=>y(M.value),className:"flex flex-col items-start gap-1.5 p-3 border rounded-lg hover:border-primary hover:bg-primary/5 transition-all text-left group",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[M.icon,e.jsx("span",{className:"font-medium text-sm",children:M.label})]}),e.jsx("span",{className:"text-xs text-muted-foreground line-clamp-2",children:M.description})]},M.value))})]},t.id)}):e.jsx("div",{className:"grid grid-cols-2 gap-3",children:v(ve).map(t=>e.jsxs("button",{type:"button",onClick:()=>y(t.value),className:"flex flex-col items-start gap-1.5 p-3 border rounded-lg hover:border-primary hover:bg-primary/5 transition-all text-left group",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[t.icon,e.jsx("span",{className:"font-medium text-sm",children:t.label})]}),e.jsx("span",{className:"text-xs text-muted-foreground line-clamp-2",children:t.description})]},t.value))})})]}),e.jsxs(Oa,{value:"presets",className:"mt-0 space-y-3",children:[e.jsx(Pr,{selectedPresetIds:q,onToggle:W}),q.length>0&&e.jsxs(E,{className:"w-full h-11 text-sm",onClick:s,disabled:z,children:[e.jsx($e,{className:"h-4 w-4 mr-2"}),"Add ",q.length," Widget",q.length>
71?"s":""]})]})]})}),e.jsxs(tt,{children:[e.jsx(E,{variant:"outline",onClick:()=>m(!1),children:"Cancel"}),e.jsx(E,{onClick:ce,disabled:!p||!g||!I&&!me||p==="map"&&B.length<2||H&&B.length===0||!H&&!Y&&!D||(p==="webrtc_stream"||p==="mjpeg_stream")&&!n.room_id||z,children:z?"Adding...":"Add Widget"})]})]})})}const ps=[{id:"smart_home",name:"Smart Home",description:"Monitor temperature, humidity, and control lights/appliances",icon:"",category:"home",widgets:[{type:"temperature",title:"Living Room Temperature",variableKey:"temp",variableType:"float",config:{metric_key:"temp",unit:"°C",min:10,max:35},layout:{x:0,y:0,w:3,h:3}},{type:"humidity",title:"Humidity",variableKey:"humidity",variableType:"float",config:{metric_key:"humidity",unit:"%",min:0,max:100},layout:{x:3,y:0,w:3,h:3}},{type:"toggle",title:"Living Room Light",variableKey:"light",variableType:"boolean",config:{commandKey:"light",onLabel:"ON",offLabel:"OFF"},layout:{x:6,y:0,w:3,h:3}},{type:"toggle",title:"Fan Control",variableKey:"fan",variableType:"boolean",config:{commandKey:"fan",onLabel:"ON",offLabel:"OFF"},layout:{x:9,y:0,w:3,h:3}},{type:"chart",title:"Temperature History (24h)",variableKey:"temp",variableType:"float",config:{chartType:"line",timeRange:"24h",metric_keys:["temp"]},layout:{x:0,y:3,w:6,h:4}},{type:"chart",title:"Humidity History (24h)",variableKey:"humidity",variableType:"float",config:{chartType:"area",timeRange:"24h",metric_keys:["humidity"]},layout:{x:6,y:3,w:6,h:4}}]},{id:"weather_station",name:"Weather Station",description:"Track temperature, humidity, pressure, wind speed, and UV index",icon:"",category:"environmental",widgets:[{type:"temperature",title:"Outdoor Temperature",variableKey:"temp",variableType:"float",config:{metric_key:"temp",unit:"°C",min:-20,max:50},layout:{x:0,y:0,w:3,h:3}},{type:"humidity",title:"Humidity",variableKey:"humidity",variableType:"float",config:{metric_key:"humidity",unit:"%",min:0,max:100},layout:{x:3,y:0,w:3,h:3}},{type:"gauge",title:"Barometric Pressure",variableKey:"pressure",variableType:"float",config:{metric_key:"pressure",unit:"hPa",min:950,max:1050},layout:{x:6,y:0,w:3,h:3}},{type:"gauge",title:"Wind Speed",variableKey:"wind_speed",variableType:"float",config:{metric_key:"wind_speed",unit:"km/h",min:0,max:100},layout:{x:9,y:0,w:3,h:3}},{type:"value",title:"UV Index",variableKey:"uv",variableType:"float",config:{metric_key:"uv",unit:"index"},layout:{x:0,y:3,w:3,h:2}},{type:"value",title:"Rainfall",variableKey:"rain",variableType:"float",config:{metric_key:"rain",unit:"mm"},layout:{x:3,y:3,w:3,h:2}},{type:"chart",title:"Temperature & Humidity (7 days)",variableKey:"temp",variableType:"float",config:{chartType:"line",timeRange:"7d",metric_keys:["temp","humidity"]},layout:{x:0,y:5,w:12,h:4}}]},{id:"industrial_monitor",name:"Industrial Monitor",description:"Track motor RPM, vibration, temperature, current, and power consumption",icon:"",category:"industrial",widgets:[{type:"speedometer",title:"Motor RPM",variableKey:"motor_rpm",variableType:"float",config:{metric_key:"motor_rpm",unit:"RPM",min:0,max:3e3},layout:{x:0,y:0,w:4,h:4}},{type:"gauge",title:"Vibration Level",variableKey:"vibration",variableType:"float",config:{metric_key:"vibration",unit:"g",min:0,max:10},layout:{x:4,y:0,w:4,h:4}},{type:"temperature",title:"Motor Temperature",variableKey:"temp",variableType:"float",config:{metric_key:"temp",unit:"°C",min:0,max:100},layout:{x:8,y:0,w:4,h:4}},{type:"power",title:"Current Draw",variableKey:"current",variableType:"float",config:{metric_key:"current",unit:"A",min:0,max:30},layout:{x:0,y:4,w:3,h:3}},{type:"power",title:"Power Consumption",variableKey:"power",variableType:"float",config:{metric_key:"power",unit:"W",min:0,max:3600},layout:{x:3,y:4,w:3,h:3}},{type:"alert",title:"System Alert",variableKey:"alert",variableType:"boolean",config:{criticalMax:1,alertLabel:"SYSTEM FAULT",showValue:!1},layout:{x:6,y:4,w:3,h:3}},{type:"status",title:"Equipment Status",variableKey:"status",variableType:"string",config:{metric_key:"status"},layout:{x:9,y:4,w:3,h:3}},{type:"chart",title:"RPM & Temperature Trend",variableKey:"motor_rpm",variableType:"float",config:{chartType:"line",timeRange:"6h",metric_keys:["motor_rpm","temp"]},layout:{x:0,y:7,w:12,h:4}}]},{id:"agriculture",name:"Smart Greenhouse",description:"Monitor soil moisture, temperature, humidity, light, and pH levels",icon:"",category:"agriculture",widgets:[{type:"gauge",title:"Soil Moisture",variableKey:"soil",variableType:"integer",config:{metric_key:"soil",unit:"%",min:0,max:100},layout:{x:0,y:0,w:3,h:3}},{type:"temperature",title:"Air Temperature",variableKey:"temp",variableType:"float",config:{metric_key:"temp",unit:"°C",min:0,max:50},layout:{x:3,y:0,w:3,h:3}},{type:"humidity",title:"Air Humidity",variableKey:"humidity",variableType:"float",config:{metric_key:"humidity",unit:"%",min:0,max:100},layout:{x:6,y:0,w:3,h:3}},{type:"light",title:"Light Intensity",variableKey:"light",variableType:"integer",config:{metric_key:"light",unit:"lux",min:0,max:1024},layout:{x:9,y:0,w:3,h:3}},{type:"value",title:"pH Level",variableKey:"ph",variableType:"float",config:{metric_key:"ph",unit:"pH"},layout:{x:0,y:3,w:3,h:2}},{type:"toggle",title:"Water Pump",variableKey:"pump",variableType:"boolean",config:{commandKey:"pump",onLabel:"PUMPING",offLabel:"STOPPED"},layout:{x:3,y:3,w:3,h:2}},{type:"toggle",title:"Grow Light",variableKey:"grow_light",variableType:"boolean",config:{commandKey:"grow_light",onLabel:"ON",offLabel:"OFF"},layout:{x:6,y:3,w:3,h:2}},{type:"toggle",title:"Ventilation Fan",variableKey:"fan",variableType:"boolean",config:{commandKey:"fan",onLabel:"ON",offLabel:"OFF"},layout:{x:9,y:3,w:3,h:2}},{type:"chart",title:"Soil Moisture & Temperature",variableKey:"soil",variableType:"integer",config:{chartType:"area",timeRange:"24h",metric_keys:["soil","temp"]},layout:{x:0,y:5,w:12,h:4}}]},{id:"vehicle_tracker",name:"Vehicle Tracker",description:"Track GPS location, speed, battery, and engine status",icon:"",category:"home",widgets:[{type:"map",t
7itle:"Live GPS Location",variableKey:"lat",variableType:"float",config:{latKey:"lat",lngKey:"lng",zoom:15},layout:{x:0,y:0,w:8,h:5}},{type:"speedometer",title:"Current Speed",variableKey:"speed",variableType:"float",config:{metric_key:"speed",unit:"km/h",min:0,max:200},layout:{x:8,y:0,w:4,h:3}},{type:"battery",title:"Battery Level",variableKey:"battery",variableType:"float",config:{metric_key:"battery",unit:"%",min:0,max:100},layout:{x:8,y:3,w:4,h:2}},{type:"value",title:"Latitude",variableKey:"lat",variableType:"float",config:{metric_key:"lat",unit:"°"},layout:{x:0,y:5,w:3,h:2}},{type:"value",title:"Longitude",variableKey:"lng",variableType:"float",config:{metric_key:"lng",unit:"°"},layout:{x:3,y:5,w:3,h:2}},{type:"status",title:"Engine Status",variableKey:"engine",variableType:"string",config:{metric_key:"engine"},layout:{x:6,y:5,w:3,h:2}},{type:"signal",title:"GPS Signal",variableKey:"rssi",variableType:"float",config:{metric_key:"rssi",unit:"dBm",min:-100,max:0},layout:{x:9,y:5,w:3,h:2}},{type:"chart",title:"Speed History (24h)",variableKey:"speed",variableType:"float",config:{chartType:"area",timeRange:"24h",metric_keys:["speed"]},layout:{x:0,y:7,w:12,h:4}}]}];function Ir(i){return ps.filter(m=>m.category===i)}const Wr={home:"bg-blue-500/10 text-blue-600 border-blue-500/30",industrial:"bg-orange-500/10 text-orange-600 border-orange-500/30",environmental:"bg-green-500/10 text-green-600 border-green-500/30",agriculture:"bg-emerald-500/10 text-emerald-600 border-emerald-500/30",healthcare:"bg-pink-500/10 text-pink-600 border-pink-500/30"},$r={smart_home:{Icon:ss,className:"text-blue-500"},weather_station:{Icon:ns,className:"text-cyan-500"},industrial_monitor:{Icon:ls,className:"text-orange-500"},agriculture:{Icon:ha,className:"text-emerald-500"},vehicle_tracker:{Icon:Ja,className:"text-violet-500"}},Kr=[{value:"all",label:"All Templates",Icon:ea,className:"text-muted-foreground"},{value:"home",label:"Smart Home",Icon:ss,className:"text-blue-500"},{value:"industrial",label:"Industrial",Icon:ls,className:"text-orange-500"},{value:"environmental",label:"Environmental",Icon:ns,className:"text-green-500"},{value:"agriculture",label:"Agriculture",Icon:ha,className:"text-emerald-500"},{value:"healthcare",label:"Healthcare",Icon:dr,className:"text-pink-500"}],Hr={temperature:yt,humidity:pa,gauge:lt,chart:rs,toggle:ds,map:Ya,speedometer:ia,light:xa,battery:Ft,value:wr,alert:la,status:os,power:rt,signal:Et};function Br({open:i,onOpenChange:m,onApply:k,isLoading:d}){const[T,z]=r.useState(null),[F,p]=r.useState(null),y=()=>{T&&(k(T),m(!1),z(null))},g=F?Ir(F):ps;return e.jsx(Ve,{open:i,onOpenChange:m,children:e.jsx(Ie,{className:"max-w-4xl w-[95vw] h-[85vh] p-0 overflow-hidden border-border/60 shadow-2xl rounded-2xl bg-background",children:e.jsxs("div",{className:"flex flex-col h-full",children:[e.jsxs("div",{className:"px-8 py-6 border-b flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-4",children:[e.jsx("div",{className:"h-10 w-10 rounded-xl bg-primary/10 flex items-center justify-center",children:e.jsx(aa,{className:"h-5 w-5 text-primary"})}),e.jsxs("div",{children:[e.jsx(We,{className:"text-xl font-bold",children:"Choose a Blueprint"}),e.jsx(Ke,{className:"text-sm",children:"Select a template to instantly configure your dashboard layout."})]})]}),e.jsx(E,{variant:"ghost",size:"icon",onClick:()=>m(!1),className:"rounded-full",children:e.jsx(as,{className:"h-4 w-4"})})]}),e.jsxs("div",{className:"flex flex-1 overflow-hidden",children:[e.jsxs("div",{className:"w-56 border-r bg-muted/5 p-4 flex flex-col shrink-0",children:[e.jsx("div",{className:"text-[10px] font-bold text-muted-foreground uppercase tracking-widest px-3 mb-3",children:"Categories"}),e.jsx("div",{className:"space-y-1",children:Kr.map(x=>{const R=x.Icon,P=F===x.value||!F&&x.value==="all";return e.jsxs("button",{className:`w-full flex items-center gap-3 h-10 px-3 rounded-xl text-sm transition-all ${P?"bg-primary text-primary-foreground font-semibold":"text-muted-foreground hover:bg-muted"}`,onClick:()=>
7p(x.value==="all"?null:x.value),children:[e.jsx(R,{className:"h-4 w-4 shrink-0"}),e.jsx("span",{className:"truncate",children:x.label})]},x.value)})})]}),e.jsx("div",{className:"flex-1 overflow-hidden",children:e.jsx(ua,{className:"h-full",children:e.jsxs("div",{className:"p-6 space-y-4",children:[g.map(x=>{const R=$r[x.id],P=R?.Icon??ea,D=R?.className??"text-muted-foreground",O=T?.id===x.id;return e.jsxs("button",{onClick:()=>z(x),className:`w-full group flex items-start gap-6 p-5 rounded-2xl border transition-all ${O?"border-primary bg-primary/3 ring-1 ring-primary/20 shadow-md":"border-border bg-card hover:border-primary/40 hover:shadow-sm"}`,children:[e.jsx("div",{className:`h-16 w-16 rounded-2xl border flex items-center justify-center shrink-0 transition-all ${O?"bg-primary/20 border-primary/30":"bg-muted/50 border-border"}`,children:e.jsx(P,{className:`h-8 w-8 ${D}`})}),e.jsxs("div",{className:"flex-1 min-w-0 py-1",children:[e.jsxs("div",{className:"flex items-center justify-between mb-1",children:[e.jsx("h3",{className:`font-bold text-lg truncate ${O?"text-primary":""}`,children:x.name}),e.jsx("span",{className:`px-2 py-0.5 rounded-full text-[9px] font-black border uppercase tracking-tighter ${Wr[x.category]}`,children:x.category})]}),e.jsx("p",{className:"text-sm text-muted-foreground leading-snug line-clamp-2 mb-4",children:x.description}),e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[x.widgets.slice(0,5).map((B,J)=>{const I=Hr[B.type]??os;return e.jsx("div",{className:"h-6 w-6 rounded-md border bg-background flex items-center justify-center shadow-xs",title:B.type,children:e.jsx(I,{className:"h-3 w-3 text-muted-foreground/70"})},J)}),x.widgets.length>5&&e.jsxs("span",{className:"text-[10px] text-muted-foreground font-medium",children:["+",x.widgets.length-5," others"]})]}),O&&e.jsxs("div",{className:"flex items-center gap-2 text-primary",children:[e.jsx("span",{className:"text-xs font-bold uppercase tracking-widest",children:"Selected"}),e.jsx(Zt,{className:"h-4 w-4"})]})]})]})]},x.id)}),g.length===0&&e.jsxs("div",{className:"flex flex-col items-center justify-center h-64 text-muted-foreground/30",children:[e.jsx(ea,{className:"h-12 w-12 mb-2"}),e.jsx("p",{className:"text-sm",children:"No blueprints match this category"})]})]})})})]}),e.jsxs("div",{className:"p-6 border-t bg-muted/20 flex items-center justify-between gap-6",children:[e.jsx("div",{className:"flex-1",children:T?e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx("div",{className:"h-8 w-8 rounded-lg bg-primary/10 flex items-center justify-center text-primary",children:e.jsx(Zt,{className:"h-4 w-4"})}),e.jsxs("div",{children:[e.jsxs("h4",{className:"text-sm font-bold",children:[T.name," Ready"]}),e.jsxs("p",{className:"text-[11px] text-muted-foreground",children:["Contains ",T.widgets.length," elements to be deployed."]})]})]}):e.jsx("p",{className:"text-sm text-muted-foreground",children:"Select a blueprint to begin setup."})}),e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(E,{variant:"outline",onClick:()=>m(!1),className:"rounded-xl h-10 px-6",children:"Cancel"}),e.jsx(E,{onClick:y,disabled:!T||d,className:"rounded-xl h-10 px-8 font-bold shadow-lg shadow-primary/20",children:d?e.jsx(qe,{className:"h-4 w-4 animate-spin"}):"Deploy Blueprint"})]})]})]})})})}const Ur={value:"Displays a single numeric or string value with an optional unit.",temperature:"Specific display optimized for temperature readings.",humidity:"Specific display optimized for humidity percentage.",power:"Displays power consumption in Watts.",battery:"Shows battery level with a percentage indicator.",light:"Specific display for light intensity or state.",signal:"Displays signal strength (RSSI) with an icon.",airquality:"Monitors air quality indices.",uptime:"Shows how long the device has been active.",speedometer:"Classic circular dial for speed or RPM.",gauge:"A radial dial showing a numeric value within a defined range.",status:"A colored indicator (Green/Red) showing online/offline status.",healthcheck:"Monitors system health and diagnostic flags.",alert:"A high-visibility indicator that flashes during critical states.",notification:"Displays alert messages or system notifications.",log:"A scrolling terminal view for text messages and debugging.",message:"Displays incoming text messages from the device.",chart:"A live line chart showing telemetry data over time.",trend:"Area chart showing data trends and history.",barchart:"Compares multiple data points using bars.",piechart:"Visualizes data distribution as a pie chart.",table:"Displays current values of multiple variables in a table.",history_table:"Shows a log of past values for selected variables.",map:"Real-time GPS tracker. Requires 2 variables: Latitude and Longitude.",button:"A momentary button to trigger functions on your device.",toggle:"A simple button to send ON/OFF commands.",switch:"A classic switch for persistent ON/OFF states.",slider:"Sliding control to send numeric values (0-100, etc.).",colorpicker:"Choose a color and send its packed RGB integer (0xRRGGBB) to your device.",dropdown:"Select from a list of predefined options.",stepper:"Increment/decrement values with +/- buttons.",joystick:"2D control for motors or navigation.",webrtc_stream:"Real-time P2P video stream from an ESP32-CAM or browser. Requires a room_id.",mjpeg_stream:"Low-latency MJPEG relay from a connected camera device. Requires a room_id."};function Gr({widget:i,open:m,onOpenChange:k,onUpdate:d,devices:T,isLoading:z}){const[F,p]=r.useState(""),[y,g]=r.useState(""),[x,R]=r.useState(""),[P,D]=r.useState([]),[O,B]=r.useState(""),[J,I]=r.useState(""),[ue,he]=r.useState(""),[le,ve]=r.useState(""),[ye,we]=r.useState(""),[_e,de]=r.useState(""),[b,ne]=r.useState(""),[oe,q]=r.useState(""),[X,n]=r.useState([]),[f,ge]=r.useState(!1),[c,w]=r.useState({});r.useEffect(()=>
7{i&&(p(i.title),g(""),R(i.variable_id||""),B(i.device_id||"none"),I(i.config?.unit||""),he(i.config?.commandKey||""),ve(i.config?.buttonLabel||""),we(i.config?.commandValue||""),de(String(i.config?.min??"")),ne(String(i.config?.max??"")),q(String(i.config?.step??"")),w(i.config||{}),i.config?.metric_keys)},[i]),r.useEffect(()=>{if(i?.config?.metric_keys&&X.length>0){const s=i.config.metric_keys.map(v=>X.find(Y=>Y.key===v)?.id).filter(Boolean);D(s)}else if(i?.config?.metric_key&&X.length>0){const s=X.find(v=>v.key===i.config?.metric_key);s&&D([s.id])}},[X,i]),r.useEffect(()=>{if(!O||O==="none"){n([]);return}(async()=>{ge(!0);try{const v=await ut.list(O,{active_only:!0});n(v.variables)}catch(v){console.error("Failed to load variables",v),n([])}finally{ge(!1)}})()},[O]);const W=()=>{if(!i)return;if(!F.trim()){g("Widget label is required");return}const s=X.find(t=>t.id===x),v={...c},H=["status","clock","note","label","image","video","stream","scene","markdown","webrtc_stream","mjpeg_stream"].includes(i.type),Y=["chart","trend","barchart","piechart","table","history_table","map"].includes(i.type);if(i.type==="scene"&&v.options&&(v.options=v.options.map(t=>{if(typeof t.payload=="string")try{return{...t,payload:JSON.parse(t.payload)}}catch{return console.warn("Failed to parse scene payload JSON:",t.payload),t}return t})),Y){const t=X.filter(C=>P.includes(C.id));v.metric_keys=t.map(C=>C.key),delete v.metric_key,delete v.commandKey}else!H&&s&&(v.metric_key=s.key,v.commandKey=s.key);J?v.unit=J:s?.unit&&(v.unit=s.unit),i.type==="button"&&ue&&(v.commandKey=ue),le&&(v.buttonLabel=le),ye&&(v.commandValue=ye),(i.type==="slider"||i.type==="stepper")&&(_e&&(v.min=Number(_e)),b&&(v.max=Number(b)),oe&&(v.step=Number(oe)));const me=Y?P[0]:x,ce={title:F,variable_id:me||void 0,device_id:O&&O!=="none"?O:void 0,config:v};d(i.id,ce)};return i?e.jsx(Ve,{open:m,onOpenChange:k,children:e.jsxs(Ie,{className:"sm:max-w-[650px] max-h-[90vh] overflow-y-auto",children:[e.jsxs(ze,{children:[e.jsxs(We,{className:"flex items-center gap-2",children:[e.jsx(st,{className:"h-5 w-5 text-primary"}),"Edit Widget"]}),e.jsx(Ke,{children:"Update widget configuration and settings."})]}),e.jsxs("div",{className:"space-y-3 py-2",children:[e.jsx("div",{className:"p-2.5 border rounded-md bg-muted/30 flex items-center gap-3",children:e.jsxs("div",{className:"flex flex-col flex-1",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(l,{className:"text-xs text-muted-foreground",children:"Widget Type"}),e.jsx(Gs,{children:e.jsxs(zs,{children:[e.jsx(qs,{asChild:!0,children:e.jsx(Qs,{className:"h-3.5 w-3.5 text-muted-foreground cursor-help"})}),e.jsx(Ys,{side:"right",className:"max-w-[200px]",children:e.jsx("p",{className:"text-xs",children:Ur[i.type]||"The type of this widget."})})]})})]}),e.jsx("span",{className:"text-sm font-medium",children:i.type})]})}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{className:"text-xs",children:"Device"}),e.jsxs(te,{value:O,onValueChange:B,children:[e.jsx(ae,{className:"border-primary/20 bg-primary/5 h-9",children:e.jsx(se,{placeholder:"Select device"})}),e.jsxs(re,{children:[e.jsx(S,{value:"none",children:"None"}),T.filter(s=>s.id).map(s=>e.jsx(S,{value:s.id,children:s.device_name},s.id))]})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsxs(l,{htmlFor:"edit-widget-title",className:"text-xs",children:["Widget Label ",e.jsx("span",{className:"text-destructive",children:"*"})]}),e.jsx(j,{id:"edit-widget-title",placeholder:"e.g. Room Lamp",value:F,onChange:s=>{p(s.target.value),s.target.value.trim()&&g("")},onBlur:()=>{F.trim()||g("Widget label is required")},"aria-invalid":!!y,className:`h-9 ${y?"border-destructive focus-visible:ring-destructive":""}`}),y&&e.jsx("p",{className:"text-xs text-destructive",children:y})]})]}),!["status","clock","note","label","image","video","stream","scene","markdown","webrtc_stream","mjpeg_stream"].includes(i.type)&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsxs(l,{className:"text-xs",children:[["chart","trend","barchart","piechart","table","history_table","map"].includes(i.type)?"Variables":"Variable"," ",e.jsxs("span",{className:"text-muted-foreground font-normal",children:["(data point",["chart","trend","barchart","piechart","table","history_table","map"].includes(i.type)&&"s",")"]})]}),f&&e.jsx(qe,{className:"h-3 w-3 animate-spin text-primary"})]}),O&&O!=="none"&&e.jsxs(E,{type:"button",variant:"ghost",size:"sm",className:"h-6 text-[10px]",onClick:async()=>{ge(!0);try{const s=await ut.list(O,{active_only:!0});n(s.variables)}catch(s){console.error("Failed to reload variables",s)}finally{ge(!1)}},disabled:f,children:[e.jsx(oa,{className:"h-3 w-3 mr-1"}),"Refresh"]})]}),f?e.jsxs("div",{className:"flex items-center justify-center gap-2 text-sm text-muted-foreground py-4 border rounded-md bg-muted/10",children:[e.jsx(qe,{className:"h-4 w-4 animate-spin text-primary"}),e.jsx("span",{children:"Loading variables..."})]}):X.length===0?e.jsxs("div",{className:"text-sm text-muted-foreground py-3 px-4 border rounded-md bg-yellow-500/10 border-yellow-500/20",children:[e.jsx("p",{className:"font-medium text-yellow-700 dark:text-yellow-500 mb-1",children:"No Variables Found"}),e.jsx("p",{className:"text-xs",children:O&&O!=="none"?"This device has no variables. Please add variables first from the Variables page.":"Select a device above to load its variables."})]}):["chart","trend","barchart","piechart","table","history_table","map"].includes(i.type)?e.jsx("div",{className:"flex flex-col gap-2 max-h-[120px] overflow-y-auto p-2 border rounded-md custom-scrollbar bg-muted/20",children:X.map(s=>
7{const v=P.includes(s.id);return e.jsxs("div",{className:`flex items-center space-x-3 p-2 rounded-md cursor-pointer text-sm transition-colors ${v?"bg-primary/10 border border-primary/30":"hover:bg-muted border border-transparent"}`,onClick:()=>{D(v?P.filter(H=>H!==s.id):[...P,s.id])},children:[e.jsx(Se,{checked:v,onCheckedChange:H=>{D(H?[...P,s.id]:P.filter(Y=>Y!==s.id))}}),e.jsxs("div",{className:"flex-1",children:[e.jsx("span",{className:"font-medium mr-2",children:s.name}),e.jsx("span",{className:"text-[10px] text-muted-foreground bg-muted px-1.5 py-0.5 rounded",children:s.key})]})]},s.id)})}):e.jsxs(te,{value:x,onValueChange:R,children:[e.jsx(ae,{children:e.jsx(se,{placeholder:"Select variable"})}),e.jsx(re,{children:X.map(s=>e.jsx(S,{value:s.id,children:e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx("span",{children:s.name}),e.jsxs("span",{className:"text-xs text-muted-foreground",children:["(",s.key,")"]})]})},s.id))})]})]}),i.type==="value"&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs(l,{htmlFor:"edit-widget-unit",children:["Unit"," ",e.jsx("span",{className:"text-muted-foreground text-xs",children:"(optional)"})]}),e.jsx(j,{id:"edit-widget-unit",placeholder:"e.g. °C, %, V",value:J,onChange:s=>I(s.target.value)})]}),i.type==="gauge"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(da,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Gauge Options"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{htmlFor:"gauge-unit",className:"text-xs",children:"Unit (optional)"}),e.jsx(j,{id:"gauge-unit",placeholder:"e.g. °C, %, rpm",value:J,onChange:s=>I(s.target.value),className:"h-8"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"gauge-min",className:"text-[10px]",children:"Min Value"}),e.jsx(j,{id:"gauge-min",type:"number",placeholder:"0",value:c.min??"",onChange:s=>w({...c,min:s.target.value?parseFloat(s.target.value):0}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"gauge-max",className:"text-[10px]",children:"Max Value"}),e.jsx(j,{id:"gauge-max",type:"number",placeholder:"100",value:c.max??"",onChange:s=>w({...c,max:s.target.value?parseFloat(s.target.value):100}),className:"h-8 text-xs"})]})]}),e.jsx("p",{className:"text-[10px] text-muted-foreground",children:"Set the range for the gauge needle"}),e.jsxs("div",{className:"pt-2 border-t space-y-2",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Se,{id:"edit-active-range",checked:!!c.activeRange,onCheckedChange:s=>w({...c,activeRange:!!s})}),e.jsx(l,{htmlFor:"edit-active-range",className:"text-xs",children:"Active Range Colors"})]}),!!c.activeRange&&e.jsxs("div",{className:"grid grid-cols-3 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px] text-green-600",children:"Low → Medium"}),e.jsx(j,{type:"number",placeholder:"e.g. 30",value:c.rangeLow??"",onChange:s=>w({...c,rangeLow:s.target.value?parseFloat(s.target.value):void 0}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px] text-amber-600",children:"Medium → High"}),e.jsx(j,{type:"number",placeholder:"e.g. 60",value:c.rangeMid??"",onChange:s=>w({...c,rangeMid:s.target.value?parseFloat(s.target.value):void 0}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px] text-orange-600",children:"High → Critical"}),e.jsx(j,{type:"number",placeholder:"e.g. 80",value:c.rangeHigh??"",onChange:s=>w({...c,rangeHigh:s.target.value?parseFloat(s.target.value):void 0}),className:"h-8 text-xs"})]})]}),!!c.activeRange&&e.jsx("p",{className:"text-[10px] text-muted-foreground",children:"Leave blank to auto-split the range into equal quarters (green → amber → orange → red)."})]})]}),i.type==="chart"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(lt,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Chart Options"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{htmlFor:"chart-datapoints",className:"text-xs",children:"Data Points"}),e.jsx(j,{id:"chart-datapoints",type:"number",placeholder:"50",value:c.dataPoints||"50",onChange:s=>w({...c,dataPoints:parseInt(s.target.value)||50}),className:"h-8"})]}),e.jsxs("div",{className:"grid grid-cols-1 md:grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{className:"text-xs font-semibold",children:"Y-Axis"}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"y-min",className:"text-[10px]",children:"Min"}),e.jsx(j,{id:"y-min",type:"number",placeholder:"Auto",value:c.yMin??"",onChange:s=>w({...c,yMin:s.target.value?parseFloat(s.target.value):void 0}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"y-max",className:"text-[10px]",children:"Max"}),e.jsx(j,{id:"y-max",type:"number",placeholder:"Auto",value:c.yMax??"",onChange:s=>w({...c,yMax:s.target.value?parseFloat(s.target.value):void 0}),className:"h-8 text-xs"})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"y-label",className:"text-[10px]",children:"Label"}),e.jsx(j,{id:"y-label",placeholder:"e.g. Temp (°C)",value:c.yLabel||"",onChange:s=>w({...c,yLabel:s.target.value}),className:"h-8 text-xs"})]})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{className:"text-xs font-semibold",children:"X-Axis"}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"x-type",className:"text-[10px]",children:"Type"}),e.jsxs(te,{value:c.xType||"time",onValueChange:s=>w({...c,xType:s}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"time",children:"Time Series"}),e.jsx(S,{value:"linear",children:"Linear"}),e.jsx(S,{value:"category",children:"Category"})]})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"x-label",className:"text-[10px]",children:"Label"}),e.jsx(j,{id:"x-label",placeholder:"e.g. Time",value:c.xLabel||"",onChange:s=>w({...c,xLabel:s.target.value}),className:"h-8 text-xs"})]})]})]})]}),i.type==="image"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(xt,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Image Options"})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-xs",children:"Display Mode"}),e.jsxs(te,{value:c.mode||"latest",onValueChange:s=>w({...c,mode:s}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"latest",children:"Latest image only"}),e.jsx(S,{value:"slideshow",children:"Slideshow  all images"})]})]}),e.jsx("p",{className:"text-[10px] text-muted-foreground italic",children:(c.mode||"latest")==="slideshow"?"Loads the last 10 images from telemetry history and shows them as a carousel.":"Shows only the most recent image sent by the device."})]}),(c.mode||"latest")==="latest"&&e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(l,{htmlFor:"image-url",className:"text-xs",children:"Image URL"}),O&&O!=="none"&&e.jsx(E,{variant:"link",size:"sm",className:"h-auto p-0 text-[10px] text-primary",onClick:()=>{w({...c,url:`https://www.circuitdigest.cloud/api/v1/devices/mqtt_u_${O}/image/content`})},children:"Use Device Latest"})]}),e.jsx(j,{id:"image-url",placeholder:"https://example.com/image.jpg",value:c.url||"",onChange:s=>w({...c,url:s.target.value}),className:"h-8"}),e.jsx("p",{className:"text-[10px] text-muted-foreground italic",children:"Allows static URLs or dynamic device images (ESP32-CAM)."})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-xs",children:"Scaling"}),e.jsxs(te,{value:c.fit||"cover",onValueChange:s=>w({...c,fit:s}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"cover",children:"Cover (Fill)"}),e.jsx(S,{value:"contain",children:"Contain (Fit)"})]})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-xs",children:"Capture Trigger Variable"}
7),e.jsxs(te,{value:c.captureVariableKey||"none",onValueChange:s=>w({...c,captureVariableKey:s==="none"?void 0:s}),disabled:!O||O==="none",children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{placeholder:"None"})}),e.jsxs(re,{children:[e.jsx(S,{value:"none",children:"None (capture button hidden)"}),X.filter(s=>s.key?.startsWith("capture-")).map(s=>e.jsx(S,{value:s.key,children:s.name||s.key},s.id))]})]}),e.jsx("p",{className:"text-[10px] text-muted-foreground italic",children:'Optional. Adds a Capture button that pulses this variable to trigger the device camera. Requires a "capture-N" variable on this device.'})]})]}),(i.type==="video"||i.type==="stream")&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[i.type==="video"?e.jsx(Ot,{className:"h-4 w-4 text-primary"}):e.jsx(it,{className:"h-4 w-4 text-primary"}),e.jsxs(l,{className:"text-sm font-semibold",children:[i.type==="video"?"Video":"Stream"," Options"]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{htmlFor:"media-url",className:"text-xs",children:"Source URL"}),e.jsx(j,{id:"media-url",placeholder:i.type==="video"?"MP4/WebM URL":"HLS/RTSP URL",value:c.url||"",onChange:s=>w({...c,url:s.target.value}),className:"h-8"})]}),i.type==="video"&&e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Se,{id:"auto-play",checked:c.autoPlay!==!1,onCheckedChange:s=>w({...c,autoPlay:!!s})}),e.jsx(l,{htmlFor:"auto-play",className:"text-xs",children:"Auto-play & Loop"})]})]}),(i.type==="webrtc_stream"||i.type==="mjpeg_stream")&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(ma,{className:"h-4 w-4 text-primary"}),e.jsxs(l,{className:"text-sm font-semibold",children:[i.type==="webrtc_stream"?"WebRTC Camera":"MJPEG Stream"," Options"]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs(l,{htmlFor:"edit-room-id",className:"text-xs",children:["Room ID ",e.jsx("span",{className:"text-destructive",children:"*"})]}),e.jsx(j,{id:"edit-room-id",placeholder:"e.g. esp32cam-living-room",value:c.room_id||"",onChange:s=>w({...c,room_id:s.target.value.trim()}),className:"h-8 font-mono text-xs"}),e.jsxs("p",{className:"text-[10px] text-muted-foreground",children:["Must match the ",e.jsx("code",{className:"text-[9px] bg-muted px-1 rounded",children:"room_id"})," your device publishes to."]})]}),i.type==="webrtc_stream"&&e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-xs",children:"Quality"}),e.jsxs(te,{value:c.quality||"med",onValueChange:s=>w({...c,quality:s}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"low",children:"Low (240p)"}),e.jsx(S,{value:"med",children:"Medium (480p)"}),e.jsx(S,{value:"high",children:"High (720p)"})]})]})]}),e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Se,{id:"edit-auto-reconnect",checked:c.auto_reconnect!==!1,onCheckedChange:s=>w({...c,auto_reconnect:!!s})}),e.jsx(l,{htmlFor:"edit-auto-reconnect",className:"text-xs",children:"Auto-reconnect on disconnect"})]})]}),i.type==="note"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(Rt,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Note Content"})]}),e.jsx("div",{className:"space-y-1.5",children:e.jsx("textarea",{className:"w-full h-24 p-2 text-xs border rounded bg-background",placeholder:"Enter your dashboard note here...",value:c.content||"",onChange:s=>w({...c,content:s.target.value})})})]}),i.type==="markdown"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(pt,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Markdown/HTML Content"})]}),e.jsx("div",{className:"space-y-2",children:e.jsxs("div",{className:"flex items-center justify-between",children:[e.jsx(l,{className:"text-xs",children:"Content Mode"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsx(E,{type:"button",variant:c.mode!=="html"?"default":"outline",size:"sm",onClick:()=>w({...c,mode:"markdown"}),className:"h-7 text-[10px]",children:"Markdown"}),e.jsx(E,{type:"button",variant:c.mode==="html"?"default":"outline",size:"sm",onClick:()=>w({...c,mode:"html"}),className:"h-7 text-[10px]",children:"HTML"})]})]})}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsxs(l,{className:"text-xs",children:["Content ",c.mode==="html"?"(HTML)":"(Mark
7down)"]}),e.jsx("textarea",{className:"w-full h-40 p-2 text-xs border rounded bg-background font-mono",placeholder:c.mode==="html"?`<div style="text-align: center;">
8  <h2>Dashboard Stats</h2>
9  <p>Temperature: \${temp}°C</p>
10</div>`:"# Dashboard Title\n\n**Current Temperature:** ${temp}°C\n\nUse `${variable_name}` for substitution.",value:c.content||"",onChange:s=>w({...c,content:s.target.value})}),e.jsxs("p",{className:"text-[10px] text-muted-foreground italic",children:["Use ",e.jsx("code",{className:"text-[9px] bg-muted px-1 py-0.5 rounded",children:"${variable_name}"})," to insert live device data"]})]})]}),i.type==="label"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(Pt,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Label Styling"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px]",children:"Font Size"}),e.jsxs(te,{value:c.fontSize||"medium",onValueChange:s=>w({...c,fontSize:s}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"small",children:"Small"}),e.jsx(S,{value:"medium",children:"Medium"}),e.jsx(S,{value:"large",children:"Large"})]})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px]",children:"Alignment"}),e.jsxs(te,{value:c.align||"left",onValueChange:s=>w({...c,align:s}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"left",children:"Left"}),e.jsx(S,{value:"center",children:"Center"})]})]})]})]})]}),i.type==="clock"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(Qe,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Clock Options"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-4",children:[e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Se,{id:"show-seconds",checked:c.showSeconds!==!1,onCheckedChange:s=>w({...c,showSeconds:!!s})}),e.jsx(l,{htmlFor:"show-seconds",className:"text-xs",children:"Show Seconds"})]}),e.jsxs("div",{className:"flex items-center space-x-2",children:[e.jsx(Se,{id:"format-24h",checked:c.format24h===!0,onCheckedChange:s=>w({...c,format24h:!!s})}),e.jsx(l,{htmlFor:"format-24h",className:"text-xs",children:"24-hour Format"})]})]})]}),i.type==="level"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(At,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Level Options"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"level-min",className:"text-[10px]",children:"Min Value"}),e.jsx(j,{id:"level-min",type:"number",placeholder:"0",value:c.min??"",onChange:s=>w({...c,min:parseFloat(s.target.value)||0}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"level-max",className:"text-[10px]",children:"Max Value"}),e.jsx(j,{id:"level-max",type:"number",placeholder:"100",value:c.max??"",onChange:s=>w({...c,max:parseFloat(s.target.value)||100}),className:"h-8 text-xs"})]})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{htmlFor:"level-unit",className:"text-xs",children:"Unit"}),e.jsx(j,{id:"level-unit",placeholder:"e.g. %, Liters",value:c.unit||"",onChange:s=>w({...c,unit:s.target.value}),className:"h-8 text-xs"})]})]}),i.type==="progress"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center gap-2 pb-2 border-b",children:[e.jsx(st,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Progress Options"})]}),e.jsxs("div",{className:"grid grid-cols-2 gap-2",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"progress-min",className:"text-[10px]",children:"Min"}),e.jsx(j,{id:"progress-min",type:"number",placeholder:"0",value:c.min??"",onChange:s=>w({...c,min:parseFloat(s.target.value)||0}),className:"h-8 text-xs"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{htmlFor:"progress-max",className:"text-[10px]",children:"Max"}),e.jsx(j,{id:"progress-max",type:"number",placeholder:"100",value:c.max??"",onChange:s=>w({...c,max:parseFloat(s.target.value)||100}),className:"h-8 text-xs"})]})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px]",children:"Bar Color"}),e.jsxs(te,{value:c.color||"bg-blue-500",onValueChange:s=>w({...c,color:s}),children:[e.jsx(ae,{className:"h-8 text-xs",children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"bg-blue-500",children:"Blue"}),e.jsx(S,{value:"bg-green-500",children:"Green"}),e.jsx(S,{value:"bg-amber-500",children:"Amber"}),e.jsx(S,{value:"bg-rose-500",children:"Rose"})]})]})]})]}),i.type==="scene"&&e.jsxs("div",{className:"space-y-3 p-3 border rounded-lg bg-muted/20",children:[e.jsxs("div",{className:"flex items-center justify-between pb-2 border-b",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(gt,{className:"h-4 w-4 text-primary"}),e.jsx(l,{className:"text-sm font-semibold",children:"Scene Buttons"})]}),e.jsxs(E,{type:"button",variant:"outline",size:"sm",onClick:()=>{const s=c.options||[{label:"Eco",payload:{mode:"eco"}},{label:"Auto",payload:{mode:"auto"}},{label:"Turbo",payload:{mode:"turbo"}}];w({...c,options:[...s,{label:"New Scene",payload:{}}]})},className:"h-7 text-[10px]",children:[e.jsx(ca,{className:"h-3 w-3 mr-1"})," Add Button"]})]}),e.jsx("div",{className:"space-y-3 max-h-[200px] overflow-y-auto pr-1 custom-scrollbar",children:(c.options||[{label:"Eco",payload:{mode:"eco"}},{label:"Auto",payload:{mode:"auto"}},{label:"Turbo",payload:{mode:"turbo"}}]).map((s,v)=>e.jsxs("div",{className:"p-2 border rounded-md bg-background/50 relative group",children:[e.jsxs("div",{className:"grid grid-cols-2 gap-2 pr-6",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px]",children:"Button Label"}),e.jsx(j,{value:s.label,onChange:H=>{const me=[...c.options||[{label:"Eco",payload:{mode:"eco"}},{label:"Auto",payload:{mode:"auto"}},{label:"Turbo",payload:{mode:"turbo"}}]];me[v]={...me[v],label:H.target.value},w({...c,options:me})},className:"h-8 text-xs",placeholder:"e.g. Eco"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-[10px]",children:"Payload (JSON)"}),e.jsx(j,{value:typeof s.payload=="object"?JSON.stringify(s.payload):s.payload,onChange:H=>{const me=[...c.options||[{label:"Eco",payload:{mode:"eco"}},{label:"Auto",payload:{mode:"auto"}},{label:"Turbo",payload:{mode:"turbo"}}]];me[v]={...me[v],payload:H.target.value},w({...c,options:me})},className:"h-8 text-xs font-mono",placeholder:'{"mode": "eco"}'})]})]}),e.jsx(E,{type:"button",variant:"ghost",size:"icon",className:"absolute right-1 top-1/2 -translate-y-1/2 h-6 w-6 text-muted-foreground hover:text-destructive",onClick:()=>{const Y=(c.options||[{label:"Eco",payload:{mode:"eco"}},{label:"Auto",payload:{mode:"auto"}},{label:"Turbo",payload:{mode:"turbo"}}]).filter((me,ce)=>ce!==v);w({...c,options:Y})},children:e.jsx(ht,{className:"h-4 w-4"})})]},v))}),e.jsx("p",{className:"text-[10px] text-muted-foreground italic text-center",children:"Each scene button sends a specific MQTT payload to the device."})]}),["button","toggle","slider","switch","colorpicker","dropdown","stepper","joystick"].includes(i.type)&&e.jsxs(e.Fragment,{children:[i.type==="button"&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{className:"space-y-2",children:[e.jsxs(l,{htmlFor:"edit-command-key",children:["Command Key"," ",e.jsx("span",{className:"text-muted-foreground text-xs",children:"(MQTT payload key)"})]}),e.jsx(j,{id:"edit-command-key",placeholder:"e.g. led, motor, state",value:ue,onChange:s=>he(s.target.value)})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{htmlFor:"edit-button-label",children:"Button Label"}),e.jsx(j,{id:"edit-button-label",placeholder:"e.g. Turn ON, Trigger",value:le,onChange:s=>ve(s.target.value)})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{htmlFor:"edit-command-value",children:"Command Value"}),e.jsx(j,{id:"edit-command-value",placeholder:"e.g. 1, trigger, on",value:ye,onChange:s=>we(s.target.value)})]})]}),(i.type==="slider"||i.type==="stepper")&&e.jsxs("div",{className:"grid grid-cols-3 gap-2",children:[e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{htmlFor:"edit-min",children:"Min"}),e.jsx(j,{id:"edit-min",type:"number",placeholder:"0",value:_e,onChange:s=>de(s.target.value)})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{htmlFor:"edit-max",children:"Max"}),e.jsx(j,{id:"edit-max",type:"number",placeholder:"100",value:b,onChange:s=>ne(s.target.value)})]}),e.jsxs("div",{className:"space-y-2",children:[e.jsx(l,{htmlFor:"edit-step",children:"Step"}),e.jsx(j,{id:"edit-step",type:"number",placeholder:"1",value:oe,onChange:s=>q(s.target.value)})]})]})]}),e.jsx(qr,{widget:i,config:c,onChange:w})]}),e.jsxs(tt,{children:[e.jsx(E,{variant:"outline",onClick:()=>k(!1),children:"Cancel"}),e.jsx(E,{onClick:W,disabled:!F.trim()||z,children:z?"Updating...":"Update Widget"})]})]})}):null}const zr=new Set(["value","temperature","humidity","power","battery","light","signal","airquality","uptime"]);function qr({widget:i,config:m,onChange:k}){const d=y=>k({...m,...y}),T=i.type,z=T!=="map"&&T!=="joystick"&&T!=="colorpicker",F=T==="status"||T==="toggle"||T==="switch"||T==="healthcheck",p=Lt(T,m.metric_key);return e.jsxs("div",{className:"border-t pt-3 mt-2 space-y-3",children:[e.jsx("h4",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wider",children:"Appearance & Behavior"}),z&&!F&&e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-xs",children:"Icon"}),e.jsx(at,{value:m.icon,onChange:y=>
10d({icon:y??void 0}),placeholder:"Default for type",suggestions:p})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-xs",children:"Icon position"}),e.jsx(xs,{value:m.iconPosition||"off",onChange:y=>d({iconPosition:y})})]}),e.jsxs("div",{className:"space-y-1 col-span-2",children:[e.jsx(l,{className:"text-xs",children:"Icon size"}),e.jsx("div",{className:"flex gap-1",children:["sm","md","lg","xl"].map(y=>e.jsx("button",{type:"button",onClick:()=>d({iconSize:y}),className:`flex-1 py-1.5 text-xs font-medium rounded border transition-all ${(m.iconSize||"md")===y?"bg-primary text-primary-foreground border-primary":"border-border text-muted-foreground hover:border-primary/50 hover:text-foreground"}`,children:y.toUpperCase()},y))})]})]}),F&&e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-xs",children:"Icon (ON state)"}),e.jsx(at,{value:m.iconOn,onChange:y=>d({iconOn:y??void 0}),placeholder:"None"})]}),e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-xs",children:"Icon (OFF state)"}),e.jsx(at,{value:m.iconOff,onChange:y=>d({iconOff:y??void 0}),placeholder:"None"})]})]}),zr.has(T)&&e.jsx("div",{className:"space-y-2",children:e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-xs",children:"Last value"}),e.jsxs(te,{value:m.lastValueMode||"off",onValueChange:y=>d({lastValueMode:y}),children:[e.jsx(ae,{children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"off",children:"Hidden"}),e.jsx(S,{value:"dynamic",children:"Dynamic (previous reading)"}),e.jsx(S,{value:"constant",children:"Constant (fixed text)"})]})]})]}),m.lastValueMode==="constant"&&e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-xs",children:"Constant last value"}),e.jsx(j,{value:m.staticLastValue||"",onChange:y=>d({staticLastValue:y.target.value}),placeholder:"e.g. 24.5 °C"})]})]})}),T==="note"&&e.jsxs("div",{className:"space-y-2",children:[e.jsx("div",{className:"grid grid-cols-2 gap-3",children:e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-xs",children:"Content type"}),e.jsxs(te,{value:m.mode||"text",onValueChange:y=>d({mode:y}),children:[e.jsx(ae,{children:e.jsx(se,{})}),e.jsxs(re,{children:[e.jsx(S,{value:"text",children:"Plain text"}),e.jsx(S,{value:"html",children:"Static HTML (sanitized)"})]})]})]})}),m.mode==="html"?e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-xs",children:"HTML content"}),e.jsx(Ea,{value:m.html||"",onChange:y=>d({html:y.target.value}),rows:5,placeholder:"<p>Hello <b>world</b></p>",className:"font-mono text-xs"}),e.jsx("p",{className:"text-[10px] text-muted-foreground",children:"Scripts and event handlers are stripped automatically for safety."})]}):e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-xs",children:"Text"}),e.jsx(Ea,{value:m.text||m.content||"",onChange:y=>d({text:y.target.value}),rows:4,placeholder:"Note content"})]})]}),T==="table"&&e.jsxs("div",{className:"grid grid-cols-2 gap-3",children:[e.jsxs("div",{className:"space-y-1",children:[e.jsx(l,{className:"text-xs",children:"Row count (1-20)"}),e.jsx(j,{type:"number",min:1,max:20,value:m.rowCount??5,onChange:y=>d({rowCount:Math.max(1,Math.min(20,Number(y.target.value)||5))})})]}),e.jsxs("div",{className:"flex items-end gap-2",children:[e.jsx(Se,{id:"show-timestamp",checked:m.showTimestamp!==!1,onCheckedChange:y=>d({showTimestamp:y===!0})}),e.jsx(l,{htmlFor:"show-timestamp",className:"text-xs",children:"Show timestamp column"})]}),e.jsx("p",{className:"col-span-2 text-[10px] text-muted-foreground",children:"Up to 5 variables shown as columns. Select more in the Variables field above and only the first 5 will be used."})]})]})}const Qr=[{label:"Never",value:"never"},{label:"1 hour",value:"1h"},{label:"24 hours",value:"24h"},{label:"7 days",value:"7d"},{label:"30 days",value:"30d"},{label:"Custom…",value:"custom"}];function Yr(i,m){if(!i||i==="never")return null;if(i==="custom")return m||null;
10const k=new Date,d={"1h":3600*1e3,"24h":1440*60*1e3,"7d":10080*60*1e3,"30d":720*60*60*1e3};return new Date(k.getTime()+d[i]).toISOString()}function Jr({v:i}){return i==="public"?e.jsx(Mt,{className:"h-3.5 w-3.5 text-green-500"}):i==="password"?e.jsx(hs,{className:"h-3.5 w-3.5 text-amber-500"}):e.jsx(us,{className:"h-3.5 w-3.5 text-blue-500"})}function Xr({v:i}){const m={public:"Public",link:"Link Only",password:"Password"};return e.jsx("span",{children:m[i]})}function Zr({open:i,onClose:m,dashboardId:k,dashboardName:d}){const[T,z]=r.useState([]),[F,p]=r.useState(!1),[y,g]=r.useState(!1),x=b=>`${window.location.origin}/shared/${b}`,[R,P]=r.useState("link"),[D,O]=r.useState(""),[B,J]=r.useState("never"),[I,ue]=r.useState(""),[he,le]=r.useState(null),ve=async()=>{p(!0);try{const b=await Qt.list(k);z(b)}catch{G.error("Failed to load shares")}finally{p(!1)}};r.useEffect(()=>{i&&ve()},[i,k]);const ye=async()=>{if(R==="password"&&!D){G.error("Enter a password for this share");return}g(!0);try{const b=Yr(B,I),ne=await Qt.create(k,{visibility:R,password:R==="password"?D:void 0,expires_at:b});z(oe=>[ne,...oe]),O(""),G.success("Share link created!")}catch(b){G.error(b.message||"Failed to create share")}finally{g(!1)}},we=async b=>{if(confirm("Delete this share link? Anyone with the link will lose access."))try{await Qt.delete(b),z(ne=>ne.filter(oe=>oe.token!==b)),G.success("Share deleted")}catch{G.error("Failed to delete share")}},_e=(b,ne)=>{const oe=()=>{le(ne),G.success("Link copied!"),setTimeout(()=>le(null),2e3)};if(navigator.clipboard?.writeText)navigator.clipboard.writeText(b).then(oe).catch(()=>{G.error("Failed to copy link")});else try{const q=document.createElement("textarea");q.value=b,q.style.position="fixed",q.style.opacity="0",document.body.appendChild(q),q.select(),document.execCommand("copy"),document.body.removeChild(q),oe()}catch{G.error("Copy not supported in this browser")}},de=T.filter(b=>b.is_active);return e.jsx(Ve,{open:i,onOpenChange:m,children:e.jsxs(Ie,{className:"sm:max-w-[520px] max-h-[90vh] overflow-y-auto",children:[e.jsxs(ze,{children:[e.jsxs(We,{className:"flex items-center gap-2",children:[e.jsx(Mt,{className:"h-5 w-5 text-blue-500"}),"Share Dashboard"]}),e.jsxs(Ke,{children:["Create a public link to ",e.jsx("span",{className:"font-medium text-foreground",children:d}),". Visitors can view live data without logging in."]})]}),e.jsxs("div",{className:"rounded-lg border border-dashed border-border/70 bg-muted/30 p-4 space-y-4",children:[e.jsx("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wide",children:"New Share Link"}),e.jsx("div",{className:"grid grid-cols-3 gap-2",children:["link","public","password"].map(b=>e.jsxs("button",{type:"button",onClick:()=>P(b),className:`flex flex-col items-center gap-1.5 rounded-lg border px-3 py-3 text-xs font-medium transition-colors ${R===b?"border-primary bg-primary/5 text-primary":"border-border/50 bg-background text-muted-foreground hover:bg-muted/50"}`,children:[b==="public"&&e.jsx(Mt,{className:"h-4 w-4"}),b==="link"&&e.jsx(us,{className:"h-4 w-4"}),b==="password"&&e.jsx(hs,{className:"h-4 w-4"}),e.jsx("span",{children:b==="link"?"Link Only":b==="public"?"Public":"Password"})]},b))}),e.jsxs("p",{className:"text-xs text-muted-foreground -mt-1",children:[R==="public"&&"Anyone can find and view this dashboard.",R==="link"&&"Anyone with the link can view. Not indexed publicly.",R==="password"&&"Visitors must enter the password before viewing."]}),R==="password"&&e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-xs",children:"Password"}),e.jsx(j,{type:"password",placeholder:"Set a password…",className:"h-8 text-sm",value:D,onChange:b=>O(b.target.value)})]}),e.jsxs("div",{className:"space-y-1.5",children:[e.jsx(l,{className:"text-xs",children:"Expiry"}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(te,{value:B,onValueChange:J,children:[e.jsx(ae,{className:"h-8 text-xs flex-1",children:e.jsx(se,{placeholder:"Never expires"})}),e.jsx(re,{children:Qr.map(b=>e.jsx(S,{value:b.value,children:b.label},b.value))})]}),B==="custom"&&e.jsx(j,{type:"datetime-local",className:"h-8 text-xs flex-1",value:I,onChange:b=>ue(b.target.value)})]})]}),e.jsxs(E,{className:"w-full h-8 text-sm",onClick:ye,disabled:y,children:[y?e.jsx(oa,{className:"h-3.5 w-3.5 mr-2 animate-spin"}):e.jsx($e,{className:"h-3.5 w-3.5 mr-2"}),"Generate Link"]})]}),de.length>0&&e.jsxs("div",{className:"space-y-2",children:[e.jsxs("p",{className:"text-xs font-semibold text-muted-foreground uppercase tracking-wide",children:["Active Links (",de.length,")"]}),e.jsx("div",{className:"space-y-2",children:de.map(b=>{const ne=b.expires_at&&new Date(b.expires_at)<new Date;return e.jsxs("div",{className:`rounded-lg border p-3 space-y-2 ${ne?"opacity-50 border-dashed":"border-border/60"}`,children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Jr,{v:b.visibility}),e.jsx("span",{className:"text-xs font-medium",children:e.jsx(Xr,{v:b.visibility})}),ne&&e.jsx(Js,{variant:"secondary",className:"text-[10px] bg-destructive/10 text-destructive",children:"Expired"}),e.jsx("div",{className:"flex-1"}),e.jsxs("div",{className:"flex items-center gap-1 text-[10px] text-muted-foreground",children:[e.jsx(Jt,{className:"h-3 w-3"}),b.view_count]})]}),e.jsxs("div",{className:"flex items-center gap-1.5",children:[e.jsx("code",{className:"flex-1 text-[10px] bg-muted px-2 py-1 rounded truncate text-muted-foreground",children:x(b.token)}),e.jsx(E,{variant:"ghost",size:"sm",className:"h-7 w-7 p-0 shrink-0",onClick:()=>_e(x(b.token),b.token),children:he===b.token?e.jsx(Xa,{className:"h-3.5 w-3.5 text-green-500"}):e.jsx(Xs,{className:"h-3.5 w-3.5"})}),e.jsx(E,{variant:"ghost",size:"sm",className:"h-7 w-7 p-0 shrink-0 text-destructive hover:text-destructive",onClick:()=>we(b.token),children:e.jsx(ht,{className:"h-3.5 w-3.5"})})]}),b.expires_at&&e.jsxs("div",{className:"flex items-center gap-1 text-[10px] text-muted-foreground",children:[e.jsx(Qe,{className:"h-3 w-3"}
10),ne?"Expired":"Expires"," ",new Date(b.expires_at).toLocaleString()]})]},b.token)})})]})]})})}function ei(i){if(!i)return"never";const m=Math.floor((Date.now()-i*1e3)/6e4);if(m<1)return"just now";if(m<60)return`${m}m ago`;const k=Math.floor(m/60);return k<24?`${k}h ago`:`${Math.floor(k/24)}d ago`}function ti(){const[i,m]=r.useState(new Date);return r.useEffect(()=>{const k=setInterval(()=>m(new Date),1e3);return()=>clearInterval(k)},[]),e.jsxs("div",{className:"live-tick flex items-center gap-1.5 ml-2 pl-2 border-l text-sm text-muted-foreground shrink-0",children:[e.jsx(Qe,{className:"h-3.5 w-3.5 shrink-0"}),e.jsx("span",{className:"font-medium text-foreground hidden md:inline",children:i.toLocaleDateString(void 0,{weekday:"short",month:"short",day:"numeric"})}),e.jsx("span",{className:"text-muted-foreground/50 hidden md:inline",children:"·"}),e.jsx("span",{className:"font-mono inline-block text-left min-w-[9ch]",children:i.toLocaleTimeString(void 0,{hour:"2-digit",minute:"2-digit",second:"2-digit"})})]})}function ai(){const i=r.useRef(null),[m,k]=r.useState(1200);r.useEffect(()=>{const a=i.current;if(!a)return;const o=new ResizeObserver(h=>{const u=h[0]?.contentRect.width;if(u===void 0)return;const N=Math.round(u);k(A=>A===N?A:N)});return o.observe(a),()=>o.disconnect()},[]);const[d,T]=r.useState(null),[z,F]=r.useState([]),{data:p=[]}=Cr(),[y,g]=r.useState(!0),[x,R]=r.useState(!1),[P,D]=r.useState(null),[O,B]=r.useState(!1),[J,I]=r.useState(!1),[ue,he]=r.useState(!1),[le,ve]=r.useState(""),[ye,we]=r.useState(!1),[_e,de]=r.useState(!1),[b,ne]=r.useState(null),[oe,q]=r.useState(!1),[X,n]=r.useState(!1),[f,ge]=r.useState({}),[c,w]=r.useState({}),[W,s]=r.useState(!1),[,v]=r.useState(null),[H,Y]=r.useState({}),[me,ce]=r.useState({}),[t,C]=r.useState({}),[M,U]=r.useState({}),L=r.useRef(null),Q=r.useRef({});L.current=d,Q.current=t;const[Ce,je]=r.useState({}),[Ne]=r.useState(1e4),[Te]=r.useState(!0),Ye=r.useRef(null),ga=r.useRef(void 0),gs=r.useRef(!1),ft=r.useRef(new Set),ys=r.useRef(!1),Je=r.useRef({cache:{},timestamps:{},dirty:!1}),Me=r.useRef(null),bt=r.useRef({}),ya=r.useRef(new Set),It=r.useRef(new Set),[fs,nt]=r.useState(!1),[Wt,fa]=r.useState(""),[ba,va]=r.useState(!1),[bs,ot]=r.useState(!1),[ja,Na]=r.useState(!1),[vs,wa]=r.useState(!1),[js,He]=r.useState(!1),[Re,$t]=r.useState(""),[Ca,ka]=r.useState(!1),[Pe,Kt]=r.useState(null);r.useEffect(()=>{(async()=>{try{const o=await De.list();if(F(o.dashboards),o.dashboards.length>0){const h=await De.get(o.dashboards[0].id);T(h)}}catch(o){console.error("Failed to load dashboards",o)}finally{g(!1)}})()},[]);const Oe=r.useMemo(()=>d?.widgets?.length?[...new Set(d.widgets.map(a=>a.device_id).filter(Boolean))].sort().join(","):"",[d?.widgets]),Ht=r.useCallback(async(a,o)=>{const h=a.filter(K=>["chart","timeline","history_table","table"].includes(K.type)&&K.device_id&&K.variable_id);if(h.length===0)return{};const N=`dash-hist:${h.map(K=>`${K.device_id}:${o[K.variable_id]?.key??K.variable_id}`).sort().join("|")}`,A=et.get(N);if(A)return A;const $=Math.floor(Date.now()/1e3),ee=$-900,fe=await Promise.allSettled(h.map(K=>{const Z=o[K.variable_id]?.key;return Z?Xe.getHistory({device_id:K.device_id,variable:Z,from_sec:ee,to_sec:$,limit:200,order:"asc"}):Promise.resolve(null)})),V={};return h.forEach((K,Z)=>{const xe=fe[Z];if(xe.status==="fulfilled"&&xe.value?.data){const _=o[K.variable_id]?.key??K.variable_id??"";V[`${K.device_id}__${_}`]=xe.value.data.map(pe=>({...pe,timestamp:new Date(pe.timestamp*1e3).toISOString()}))}}),et.set(N,V,fr.HISTORY),V},[]);r.useEffect(()=>{if(!Oe)return;const a=Oe.split(",").filter(Boolean);if(a.length===0)return;const o={};for(const u of a){const N=Va.get(`iot:telem:${u}`);N&&(o[u]=N)}Object.keys(o).length>0&&ge(o),(async()=>{try{const u=await Promise.all(a.map(_=>_t.list(_,{active_only:!0}))),N={},A={};u.forEach((_,pe)=>
10{A[a[pe]]=_.variables,_.variables.forEach(be=>{N[be.id]=be})}),C(N),U(A);const $={};Object.entries(A).forEach(([_,pe])=>{$[_]={},pe.forEach(be=>{be.anedya_slot&&($[_][be.anedya_slot]=be.key)})}),bt.current=$;const ee={};Object.values(N).forEach(_=>{_.last_value!==null&&_.last_value!==void 0&&(ee[_.device_id]||(ee[_.device_id]={}),ee[_.device_id][_.key]=_.last_value)}),ge(ee);const fe=[...new Set(Object.values(N).map(_=>_.key))],V={...ee},K={};if(fe.length>0)try{const _=`init-latest:${Oe}`,be=et.get(_)??await(async()=>{const ie=await Xe.getLatestBatchMulti(a,fe);return et.set(_,ie,6e4),ie})();Object.entries(be.data).forEach(([ie,Le])=>{V[ie]||(V[ie]={}),K[ie]||(K[ie]={}),Object.entries(Le).forEach(([ke,Ee])=>{V[ie][ke]=Ee.value,K[ie][ke]=new Date(Ee.timestamp*1e3).toISOString()})})}catch(_){console.warn("[dashboard] fetchInitial latest-multi failed:",_)}ge(V),w(K),v(new Date),a.forEach(_=>{V[_]&&Va.set(`iot:telem:${_}`,V[_],br.TELEMETRY)});try{const _=`init-health:${Oe}`,be=et.get(_)??await(async()=>{const ke=await Xe.getHealth(a);return et.set(_,ke,6e4),ke})(),ie={},Le={};Object.entries(be.health).forEach(([ke,Ee])=>{ie[ke]=Ee.online,Ee.lastHeartbeat&&(Le[ke]=Ee.lastHeartbeat)}),Y(ie),ce(Le)}catch{}const Z=L.current?.widgets??[],xe=await Ht(Z,N);je(xe)}catch(u){console.error("[dashboard] fetchInitial failed:",u)}})()},[Oe,Ht]);const Bt=r.useMemo(()=>p.map(a=>a.id).sort().join(","),[p]);r.useEffect(()=>{if(!Bt)return;const a=Bt.split(",");let o=!1;const h=async()=>{try{const{health:N}=await Xe.getHealth(a);if(o)return;Y(A=>{const $={...A};for(const[ee,fe]of Object.entries(N))$[ee]=fe.online;return $}),ce(A=>{const $={...A};for(const[ee,fe]of Object.entries(N))fe.lastHeartbeat&&($[ee]=fe.lastHeartbeat);return $})}catch{}};h();const u=setInterval(h,3e4);return()=>{o=!0,clearInterval(u)}},[Bt]);const Sa=r.useCallback(async(a,o)=>{const h=`${a}:${o}`;if(!(ya.current.has(h)||It.current.has(h))){It.current.add(h);try{const u=await Xe.backfillVariables(a,[o]);if(ya.current.add(h),!u.created?.length)return;_t.invalidateCache(a);const N=await _t.list(a,{active_only:!0});U($=>({...$,[a]:N.variables})),C($=>{const ee={...$};
10return N.variables.forEach(fe=>{ee[fe.id]=fe}),ee});const A={...bt.current};A[a]={},N.variables.forEach($=>{$.anedya_slot&&(A[a][$.anedya_slot]=$.key)}),bt.current=A,G.success(`Detected ${u.created.length} new variable${u.created.length>1?"s":""} from your device`)}catch(u){console.warn("[backfill] failed:",u)}finally{It.current.delete(h)}}},[]),_a=r.useRef(Sa);_a.current=Sa;const Ns=r.useCallback((a,o,h)=>{const N=bt.current[a]?.[o]??o;ft.current.delete(`${a}:${N}`);const A=Je.current;A.cache[a]||(A.cache[a]={}),A.timestamps[a]||(A.timestamps[a]={}),A.cache[a][N]=h.value,A.timestamps[a][N]=h.timestamp,A.dirty=!0,Me.current===null&&(Me.current=requestAnimationFrame(()=>{Me.current=null;const{cache:$,timestamps:ee,dirty:fe}=Je.current;fe&&(Je.current={cache:{},timestamps:{},dirty:!1},ge(V=>{const K={...V};return Object.entries($).forEach(([Z,xe])=>{K[Z]={...K[Z]||{},...xe}}),K}),w(V=>{const K={...V};return Object.entries(ee).forEach(([Z,xe])=>{K[Z]={...K[Z]||{},...xe}}),K}),v(new Date))}))},[]),ws=r.useCallback((a,o)=>{_a.current(a,o)},[]),Cs=r.useCallback((a,o)=>{const h=o==="connected"||o==="heartbeat"||o==="online";Y(u=>u[a]===h?u:{...u,[a]:h}),h&&ce(u=>({...u,[a]:Math.floor(Date.now()/1e3)}))},[]),Ta=Te,{status:Be,error:vt,reconnect:La,diagnostics:ct,controlToken:Da,nodeToDevice:ks}=Mr({deviceIds:Ta&&Oe||"",enabled:Ta,onTelemetry:Ns,onUnknownKey:ws,onNodeEvent:Cs}),jt=Be==="connected";ys.current=jt,r.useEffect(()=>{if(!(!Oe||Oe.split(",").filter(Boolean).length===0))return clearInterval(ga.current),()=>{clearInterval(ga.current),gs.current=!1,Me.current!==null&&(cancelAnimationFrame(Me.current),Me.current=null)}},[Oe,Te]);const Nt=async()=>{if(le.trim()){we(!0);try{const o={...await De.create({name:le.trim()}),widgets:[]};F(h=>[...h,o]),T(o),ve(""),de(!1),G.success("Dashboard created!")}catch(a){G.error(a.message||"Failed to create dashboard")}finally{we(!1)}}},Ss=async a=>{g(!0);try{const o=await De.get(a);ge({}),La(),T(o),R(!1)}catch{G.error("Failed to load dashboard")}finally{g(!1)}},_s=()=>{d&&(fa(d.name),nt(!0))},Ts=async()=>{if(!(!d||!Wt.trim())){va(!0);try{const a=await De.update(d.id,{name:Wt.trim()}),o={...a,widgets:d.widgets};T(o),F(h=>h.map(u=>u.id===a.id?o:u)),nt(!1),G.success("Dashboard updated!")}catch(a){G.error(a.message||"Failed to update dashboard")}finally{va(!1)}}},Ls=async()=>{if(d){Na(!0);try{await De.delete(d.id);const a=z.filter(o=>o.id!==d.id);if(F(a),a.length>0){const o=await De.get(a[0].id);T(o)}else T(null);ot(!1),G.success("Dashboard deleted")}catch(a){G.error(a.message||"Failed to delete dashboard")}finally{Na(!1)}}},Ds=a=>a.length?{x:0,y:Math.max(...a.map(h=>(h.layout?.y??0)+(h.layout?.h??3)))}:{x:0,y:0},Ms=async a=>{if(d){he(!0);try{const o=Ds(d.widgets),h={...a,layout:{w:a.layout?.w??4,h:a.layout?.h??3,x:o.x,y:o.y}},u=await De.addWidget(d.id,h);T(N=>N&&{...N,widgets:[...N.widgets,u]}),B(!1),G.success("Widget added!"),["chart","timeline","history_table","table"].includes(u.type)&&u.device_id&&u.variable_id&&Ht([u],Q.current).then(N=>{Object.keys(N).length>0&&je(A=>({...A,...N}))}).catch(()=>{})}catch(o){console.error("Add Widget error:",o),console.error("Error details:",{message:o?.message,detail:o?.detail,status:o?.status,response:o?.response});const h=o?.message||o?.detail||(typeof o=="string"?o:"Failed to add widget. Please check the browser console for details.");G.error(h)}finally{he(!1)}}},Os=a=>a.includes("light")||a.includes("lamp")||a.includes("bulb")?{iconOn:"lightbulb",iconOff:"lightbulb-off"}:a.includes("fan")||a.includes("ventil")?{iconOn:"fan",iconOff:"fan-off"}:a.includes("heat")||a.includes("boiler")||a.includes("furnace")?{iconOn:"flame",iconOff:"flame"}:a.includes("cool")||a.includes("aircon")||a.includes("ac")?{iconOn:"snowflake",iconOff:"snowflake"}:a.includes("pump")||a.includes("valve")?{iconOn:"droplets",iconOff:"droplets"}:a.includes("lock")?{iconOn:"lock-open",iconOff:"lock"}:a.includes("door")||a.includes("gate")?{iconOn:"door-open",iconOff:"door-closed"}:a.includes("motor")||a.includes("engine")?{iconOn:"rotate-cw",iconOff:"circle-power"}:a.includes("alarm")||a.includes("siren")?{iconOn:"bell-ring",iconOff:"bell-off"}:a.includes("power")||a.includes("relay")?{iconOn:"power",iconOff:"power"}:a.includes("wifi")||a.includes("connect")||a.includes("online")?{iconOn:"wifi",iconOff:"wifi-off"}:a.includes("water")||a.includes("liquid")?{iconOn:"droplets",iconOff:"droplets"}:{iconOn:"toggle-right",iconOff:"toggle-left"},Es=a=>{d&&(Kt(a),I(!1),He(!0))},Ae=10,Ut=async(a,o)=>{const h=[];for(const u of o){const N=await De.addWidget(a,u);h.push(N)}return h},Rs=async()=>
10{if(!d||!Re)return;const a=d.widgets.length,o=Ae-a;if(o<=0){G.error(`Dashboard is full (${Ae} widgets max). Remove some widgets first.`);return}ka(!0);try{let h=M[Re]||[];if(h.length===0&&(h=(await _t.list(Re,{active_only:!0})).variables),Pe){const V=Pe.widgets.map(_=>{const pe=_.variableKey?h.find(be=>be.key===_.variableKey||be.key.toLowerCase().includes(_.variableKey.toLowerCase())||be.name.toLowerCase().includes(_.variableKey.toLowerCase())):void 0;return{type:_.type,title:_.title,device_id:Re,variable_id:pe?.id,config:{..._.config,...pe&&{metric_key:pe.key,commandKey:pe.key,unit:pe.unit||_.config.unit}},layout:_.layout,refresh_mode:"realtime"}}),K=V.slice(0,o),Z=V.length-K.length,xe=await Ut(d.id,K);T(_=>_&&{..._,widgets:[..._.widgets,...xe]}),He(!1),$t(""),Kt(null),G.success(Z>0?`Applied "${Pe.name}" — ${K.length} widgets added (${Z} skipped, dashboard at capacity)`:`Applied "${Pe.name}" — ${K.length} widgets created!`);return}if(h.length===0){G.error("No variables found for this device");return}let u=0,N=0;const A=[];h.forEach((V,K)=>{const Z=V.direction==="output"||V.direction==="bidirectional",xe=V.var_type==="integer"||V.var_type==="float",_=V.var_type==="boolean",pe=V.name.toLowerCase(),be={metric_key:V.key,commandKey:V.key,unit:V.unit||void 0,min:0,max:_?1:100};let ie="value",Le=3,ke=3;Z&&_?(ie="toggle",Le=3,ke=3):Z&&xe?(ie="slider",Le=4,ke=3):_?(ie="status",Le=2,ke=2):xe&&(ie="value",Le=3,ke=3),Z||(pe.includes("temp")?ie="temperature":pe.includes("humid")?ie="humidity":pe.includes("batt")?ie="battery":pe.includes("light")?ie="light":pe.includes("power")&&(ie="power")),u+Le>12&&(u=0,N+=4);const Ee={...be};(ie==="toggle"||ie==="status")&&Object.assign(Ee,Os(pe)),A.push({type:ie,title:V.name,variable_id:V.id,device_id:Re,config:Ee,layout:{x:u,y:N,w:Le,h:ke},refresh_mode:"realtime"}),u+=Le;let Fe=null,Ue=4,dt=4;if(xe){const Ma=K%3;Ma===0?(Fe="chart",Ue=6,dt=4):Ma===1?(Fe="gauge",Ue=3,dt=4):(Fe="progress",Ue=4,dt=3)}else _&&(Fe="timeline",Ue=5,dt=4);Fe&&(u+Ue>12&&(u=0,N+=4),A.push({type:Fe,title:`${V.name} ${Fe==="chart"?"History":"Details"}`,variable_id:V.id,device_id:Re,config:Fe==="timeline"?{...be,metric_keys:[V.key]}:be,layout:{x:u,y:N,w:Ue,h:dt},refresh_mode:"realtime"}),u+=Ue)});const $=A.slice(0,o),ee=A.length-$.length,fe=await Ut(d.id,$);T(V=>V&&{...V,widgets:[...V.widgets,...fe]}),He(!1),$t(""),G.success(ee>0?`Added ${$.length} widgets (${ee} skipped  dashboard at ${Ae} widget capacity)`:`Created ${$.length} widgets!`)}catch(h){G.error(h.message||"Failed to create widgets")}finally{ka(!1)}},Ps=r.useCallback(a=>{const o=d?.widgets.find(h=>h.id===a);o&&(ne(o),q(!0))},[d]),As=async(a,o)=>{n(!0);try{const h=await De.updateWidget(a,o);T(u=>u&&{...u,widgets:u.widgets.map(N=>N.id===a?h:N)}),q(!1),ne(null),G.success("Widget updated!")}catch(h){G.error(h.message||"Failed to update widget")}finally{n(!1)}},Fs=r.useCallback(async a=>{try{await De.deleteWidget(a),T(o=>o&&{...o,widgets:o.widgets.filter(h=>h.id!==a)}),G.success("Widget removed")}catch(o){G.error(o.message||"Failed to delete widget")}},[]),Vs=r.useRef(Da);Vs.current=Da;const Is=r.useRef({});Is.current=Object.fromEntries(Object.entries(ks).map(([a,o])=>[o,a]));const Ws=r.useCallback(async(a,o)=>{const h=Object.keys(o).map(u=>`${a}:${u}`);h.forEach(u=>{ft.current.add(u)});try{const u=await Xe.setControl(a,o);if(u.failed?.length){const A=!u.set?.length;G.error(A?"Control failed":"Partial control",{description:u.failed.map($=>`${$.key}: ${$.error??"rejected"}`).join("; ")})}const N=u.set??[];if(N.length>0){const A=new Date().toISOString(),$=Je.current;$.cache[a]||($.cache[a]={}),$.timestamps[a]||($.timestamps[a]={});for(const ee of N)$.cache[a][ee]=o[ee],$.timestamps[a][ee]=A,ft.current.delete(`${a}:${ee}`);$.dirty=!0,Me.current===null&&(Me.current=requestAnimationFrame(()=>{Me.current=null;const{cache:ee,timestamps:fe,dirty:V}=Je.current;V&&(Je.current={cache:{},timestamps:{},dirty:!1},ge(K=>{const Z={...K};return Object.entries(ee).forEach(([xe,_])=>{Z[xe]={...Z[xe]||{},..._}}),Z}),w(K=>{const Z={...K};return Object.entries(fe).forEach(([xe,_])=>{Z[xe]={...Z[xe]||{},..._}}),Z}))}))}return u}catch(u){return G.error("Control failed",{description:u.message||"Check device connection"}),{set:[],failed:Object.keys(o).map(N=>({key:N,error:u.message||"Control failed"}))}}finally{h.forEach(u=>{ft.current.delete(u)})}},[]),$s=r.useCallback(a=>
10{if(!d||!x&&!P)return;const o=a.map(h=>({widget_id:h.i,x:h.x,y:h.y,w:h.w,h:h.h}));T(h=>h&&{...h,widgets:h.widgets.map(u=>{const N=o.find(A=>A.widget_id===u.id);return N?{...u,layout:{x:N.x,y:N.y,w:N.w,h:N.h}}:u})}),Ye.current&&clearTimeout(Ye.current),Ye.current=setTimeout(()=>{De.updateLayout(d.id,o).catch(h=>{console.error("Failed to save layout",h),G.error("Failed to save layout")})},1500)},[d,x,P]),wt=r.useMemo(()=>(d?.widgets||[]).map(a=>{const o=x||a.id===P;return{i:a.id,x:a.layout?.x??0,y:a.layout?.y??0,w:a.layout?.w??4,h:a.layout?.h??3,minW:2,minH:2,static:!o}}),[d?.widgets,x,P]);if(r.useEffect(()=>{if(!P)return;const a=o=>{const h=o.target;h&&(h.closest("[data-widget-card]")||D(null))};return document.addEventListener("mousedown",a),()=>document.removeEventListener("mousedown",a)},[P]),r.useEffect(()=>{x&&D(null)},[x]),y)return e.jsxs("div",{className:"flex flex-col gap-6 -m-4 p-4 md:-m-6 md:p-6 lg:-m-8 lg:p-8",children:[e.jsxs("div",{className:"flex items-center justify-between gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Ge,{className:"h-7 w-36 rounded-md"}),e.jsx(Ge,{className:"h-9 w-44 rounded-md"}),e.jsx(Ge,{className:"h-9 w-9 rounded-md"}),e.jsx(Ge,{className:"h-9 w-9 rounded-md"})]}),e.jsxs("div",{className:"flex items-center gap-2",children:[e.jsx(Ge,{className:"h-9 w-24 rounded-full"}),e.jsx(Ge,{className:"h-9 w-28 rounded-md"})]})]}),e.jsx("div",{className:"grid grid-cols-2 lg:grid-cols-4 gap-3",children:Array.from({length:6}).map((a,o)=>e.jsx(Ge,{className:`rounded-xl ${o<2?"h-40":"h-32"}`},o))})]});if(!d)return e.jsxs("div",{className:"flex flex-col gap-6 max-w-2xl mx-auto py-4",children:[e.jsx(Ra,{title:"IoT Dashboard",description:"Monitor and control your connected microcontroller devices (ESP32, ESP8266, Arduino) in real-time. Custom widgets for charts, gauges, indicators, and control buttons.",keywords:"iot dashboard, real-time monitoring, esp32 dashboard, arduino control panel, sensor visualizer, mqtt dashboard"}),e.jsxs(mt,{className:"w-full",children:[e.jsxs(Gt,{className:"text-center pb-3",children:[e.jsx("div",{className:"mx-auto bg-blue-500/10 rounded-full p-3 w-12 h-12 flex items-center justify-center mb-1",children:e.jsx(Pa,{className:"h-6 w-6 text-blue-500"})}),e.jsx(zt,{className:"text-lg",children:"Create Your Dashboard"}),e.jsx(er,{className:"text-sm",children:"Name your dashboard to start adding widgets and visualizing device data."})]}),e.jsxs(Ct,{className:"space-y-3 max-w-sm mx-auto w-full",children:[e.jsx(j,{placeholder:"e.g. Home Sensors, Factory Floor",value:le,onChange:a=>ve(a.target.value),onKeyDown:a=>a.key==="Enter"&&Nt()}),e.jsx(E,{className:"w-full",onClick:Nt,disabled:!le.trim()||ye,children:ye?"Creating...":"Create Dashboard"}),e.jsxs(kt,{to:"/iot-dashboard/get-started",className:"flex items-center justify-center gap-1.5 text-xs text-muted-foreground hover:text-primary transition-colors pt-1",children:[e.jsx(St,{className:"h-3.5 w-3.5"}),"View setup docs & code examples"]})]})]}),e.jsxs("div",{children:[e.jsx("p",{className:"text-sm font-medium text-muted-foreground mb-2",children:"Project Tutorials"}),e.jsx("div",{className:"grid grid-cols-1 sm:grid-cols-2 gap-3",children:[{title:"AI-based Air Quality Monitor using ESP32",description:"Track PM2.5, PM10 & AQI in real time with cloud dashboard and WhatsApp alerts.",image:"https://circuitdigest.com/sites/default/files/projectimage_mic/AI-Based-Air-Quality-Monitor-Using-ESP32_0.jpg",link:"https://circuitdigest.com/microcontroller-projects/esp32-air-quality-monitor"},{title:"IoT Indoor Weather Station",description:"Monitor temperature, humidity, pressure & light live on CircuitDigest Cloud.",image:"https://circuitdigest.com/sites/default/files/projectimage_mic/IoT-Indoor-Weather-Station.jpg",link:"https://circuitdigest.com/microcontroller-projects/iot-indoor-weather-station-using-circuitdigest-cloud"}].map((a,o)=>e.jsx("a",{href:a.link,target:"_blank",rel:"noopener noreferrer",className:"block h-full",children:e.jsxs(mt,{className:"p-0 gap-0 overflow-hidden hover:shadow-lg transition-all duration-300 hover:scale-[1.01] group flex flex-col h-full cursor-pointer",children:[e.jsx("div",{className:"aspect-video overflow-hidden bg-muted",children:e.jsx("img",{src:a.image,alt:a.title,className:"w-full h-full object-cover transition-transform duration-500 group-hover:scale-105",loading:"lazy"})}),e.jsxs(Gt,{className:"p-3 pb-2 flex-1",children:[e.jsx(zt,{className:"text-sm group-hover:text-primary transition-colors line-clamp-2 leading-tight",children:a.title}),e.jsx("p",{className:"text-[11px] text-muted-foreground line-clamp-2 mt-1 leading-snug",children:a.description})]})]})},o))})]})]});const Ks=[...new Set(d.widgets.map(a=>
10a.device_id).filter(Boolean))];return e.jsxs("div",{className:"flex flex-col gap-8 min-h-screen -m-4 p-4 md:-m-6 md:p-6 lg:-m-8 lg:p-8 bg-white",children:[e.jsx(Ra,{title:"IoT Dashboard",description:"Monitor and control your connected microcontroller devices (ESP32, ESP8266, Arduino) in real-time. Custom widgets for charts, gauges, indicators, and control buttons.",keywords:"iot dashboard, real-time monitoring, esp32 dashboard, arduino control panel, sensor visualizer, mqtt dashboard"}),e.jsxs("div",{className:"flex flex-col gap-6",children:[e.jsxs("div",{className:"flex flex-col sm:flex-row sm:items-center justify-between gap-4",children:[e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[e.jsx("h1",{className:"text-2xl font-bold tracking-tight shrink-0",children:"My Dashboard"}),z.length>0&&d&&e.jsxs(te,{value:d.id,onValueChange:Ss,children:[e.jsx(ae,{className:"w-[200px] h-9 font-semibold",children:e.jsx(se,{placeholder:"Select dashboard"})}),e.jsx(re,{children:z.filter(a=>a.id).map(a=>e.jsx(S,{value:a.id,children:a.name},a.id))})]}),e.jsx(E,{variant:"outline",size:"sm",className:"h-9 w-9 p-0",title:"New Dashboard",onClick:()=>de(!0),children:e.jsx($e,{className:"h-4 w-4"})}),e.jsx(E,{variant:x?"default":"outline",size:"sm",className:"h-9 w-9 p-0",title:x?"Lock Layout":"Edit Layout",onClick:()=>R(!x),children:e.jsx(Wa,{className:"h-4 w-4"})}),d&&e.jsxs(tr,{children:[e.jsx(ar,{asChild:!0,children:e.jsx(E,{variant:"outline",size:"sm",className:"h-9 w-9 p-0",title:"Settings",children:e.jsx(ra,{className:"h-4 w-4"})})}),e.jsxs(sr,{align:"start",className:"w-56",children:[e.jsx(rr,{children:"Dashboard Settings"}),e.jsx(Aa,{}),e.jsxs(ir,{children:[e.jsxs(Ze,{onClick:_s,children:[e.jsx(Wa,{className:"h-4 w-4 mr-2"}),"Edit Name"]}),e.jsxs(Ze,{onClick:()=>wa(!0),children:[e.jsx(Mt,{className:"h-4 w-4 mr-2"}),"Share Dashboard"]}),e.jsxs(Ze,{onClick:()=>He(!0),children:[e.jsx(rt,{className:"h-4 w-4 mr-2"}),"Quick Create Widgets"]}),e.jsxs(Ze,{onClick:()=>s(!W),children:[W?e.jsx(lr,{className:"h-4 w-4 mr-2"}):e.jsx(Jt,{className:"h-4 w-4 mr-2"}),W?"Hide Debug":"Show Debug"]}),e.jsx(Ze,{asChild:!0,children:e.jsxs(kt,{to:"/iot-dashboard/get-started",children:[e.jsx(St,{className:"h-4 w-4 mr-2"}),"View Docs"]})})]}),e.jsx(Aa,{}),e.jsxs(Ze,{className:"text-destructive focus:text-destructive",onClick:()=>ot(!0),children:[e.jsx(ht,{className:"h-4 w-4 mr-2"}),"Delete Dashboard"]})]})]}),e.jsx(ti,{})]}),e.jsxs("div",{className:"flex items-center gap-2 flex-wrap",children:[p.length>0&&(()=>{const a=p.filter(u=>H[u.id]===!0).length,o=p.filter(u=>H[u.id]===!1).length,h=p.filter(u=>H[u.id]===void 0).length;return e.jsxs(Za,{children:[e.jsx(es,{asChild:!0,children:e.jsxs("button",{type:"button",title:"Click for device heartbeats",className:"flex items-center gap-1.5 shrink-0 border-r pr-3 text-[11px] transition-opacity hover:opacity-70",children:[e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-green-500"}),e.jsx("span",{className:"font-medium text-green-700 dark:text-green-400",children:a})]}),e.jsx("span",{className:"text-muted-foreground/40",children:"·"}),e.jsxs("span",{className:"flex items-center gap-1",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-red-500"}),e.jsx("span",{className:"font-medium text-red-600 dark:text-red-400",children:o})]}),h>0&&e.jsxs(e.Fragment,{children:[e.jsx("span",{className:"text-muted-foreground/40",children:"·"}),e.jsxs("span",{className:"flex items-center gap-1 text-muted-foreground",children:[e.jsx("span",{className:"w-2 h-2 rounded-full bg-muted-foreground/30"}),h]})]})]})}),e.jsxs(ts,{align:"start",className:"w-72 p-0",children:[e.jsxs("div",{className:"px-3 py-2 border-b",children:[e.jsx("p",{className:"text-xs font-semibold",children:"Device Heartbeats"}),e.jsx("p",{className:"text-[10px] text-muted-foreground",children:"Last check-in with the cloud"})]}),e.jsx("div",{className:"max-h-72 overflow-y-auto py-1",children:p.map(u=>{const N=H[u.id]===!0,A=H[u.id]!==void 0;return e.jsxs("div",{className:"flex items-center justify-between gap-2 px-3 py-1.5 text-xs",children:[e.jsxs("div",{className:"flex items-center gap-2 min-w-0",children:[e.jsx("span",{className:`w-2 h-2 rounded-full shrink-0 ${N?"bg-green-500 animate-pulse":A?"bg-red-500":"bg-muted-foreground
10/30"}`}),e.jsx("span",{className:"font-medium truncate",children:u.device_name})]}),e.jsx("span",{className:"text-muted-foreground shrink-0 tabular-nums",children:ei(me[u.id])})]},u.id)})})]})]})})(),e.jsx("div",{className:"flex items-center gap-1 shrink-0",children:e.jsxs("div",{className:`flex items-center gap-1.5 rounded-full px-3 h-7 text-[11px] font-semibold border select-none ${Be==="connected"?"bg-green-500/10 text-green-700 dark:text-green-400 border-green-500/30":Be==="error"?"bg-red-500/10 text-red-700 dark:text-red-400 border-red-500/30":"bg-amber-500/10 text-amber-700 dark:text-amber-400 border-amber-500/30"}`,children:[e.jsx("span",{className:`h-1.5 w-1.5 rounded-full shrink-0 ${Be==="connected"?"bg-green-500 animate-pulse":Be==="error"?"bg-red-500":"bg-amber-400 animate-pulse"}`}),Be==="connected"?"Live":Be==="error"?"Error":"Connecting…"]})}),e.jsxs(E,{variant:"outline",size:"sm",className:"h-9 text-xs font-semibold px-4 shrink-0",onClick:()=>B(!0),children:[e.jsx($e,{className:"h-3.5 w-3.5 mr-1.5"}),"Add Widget"]})]})]}),e.jsxs("p",{className:"text-muted-foreground text-sm -mt-4",children:["Monitor sensors, control devices, and view live data."," ",e.jsx(kt,{to:"/iot-dashboard/get-started",className:"text-primary underline underline-offset-2",children:"Get Started"})]}),W&&e.jsxs(mt,{className:"border-yellow-500/50 bg-yellow-500/5",children:[e.jsx(Gt,{className:"pb-3",children:e.jsxs(zt,{className:"text-sm flex items-center gap-2",children:[e.jsx(Jt,{className:"h-4 w-4"}),"Debug Info"]})}),e.jsxs(Ct,{className:"space-y-2 text-xs font-mono",children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Mode:"})," ",e.jsx("span",{className:jt?"text-green-600":Te?"text-yellow-500":"text-blue-500",children:Te?jt?"Live (WebSocket connected)":"Live (connecting…)":"Polling"})]}),Te&&e.jsxs(e.Fragment,{children:[e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Stream msgs:"})," ","received=",ct.received," mapped=",ct.mapped," dropped=",ct.dropped,ct.lastDropReason&&e.jsxs("span",{className:"ml-1 text-yellow-500",children:["(",ct.lastDropReason,")"]})]}),vt&&e.jsxs("div",{className:"text-red-500",children:[e.jsx("span",{className:"text-muted-foreground",children:"Stream error:"})," ",vt]})]}),!Te&&e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Refresh interval:"})," ",Ne>=6e4?`${Ne/6e4} min`:`${Ne/1e3}s`]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Devices in dashboard:"})," ",Ks.length]}),e.jsxs("div",{children:[e.jsx("span",{className:"text-muted-foreground",children:"Telemetry cache:"})," ",Object.keys(f).length," devices"]}),e.jsxs("details",{className:"mt-2",children:[e.jsx("summary",{className:"cursor-pointer text-blue-600 hover:text-blue-700",children:"View cached data"}),e.jsx("pre",{className:"mt-2 p-2 bg-muted rounded text-[10px] overflow-auto max-h-40",children:JSON.stringify(f,null,2)})]})]})]}),Te&&!jt&&vt&&e.jsxs("div",{className:"flex items-center gap-3 rounded-md border border-red-500/40 bg-red-500/10 px-4 py-2.5 text-sm",children:[e.jsx("span",{className:"text-red-600 font-medium shrink-0",children:"Stream error:"}),e.jsx("span",{className:"text-red-700 dark:text-red-400 flex-1 truncate",children:vt}),e.jsx("span",{className:"text-muted-foreground text-xs shrink-0",children:"Retrying…"}),e.jsx(E,{variant:"ghost",size:"sm",className:"h-7 px-2 text-xs shrink-0",onClick:La,children:"Reconnect now"})]}),e.jsx("div",{ref:i,children:d.widgets?.length?e.jsx(mr,{className:"layout",width:m,layouts:{lg:wt,md:wt,sm:wt,xs:wt},breakpoints:{lg:900,md:700,sm:500,xs:0},cols:{lg:12,md:12,sm:6,xs:4},rowHeight:65,isDraggable:x||P!==null,isResizable:x||P!==null,onLayoutChange:$s,draggableHandle:".drag-handle",draggableCancel:".no-drag",containerPadding:[8,0],margin:[12,12],children:d.widgets.map(a=>{const o=a.id===P;return e.jsx("div",{"data-widget-card":a.id,className:`relative group rounded-xl overflow-hidden transition-all duration-300 ${o?"shadow-[0_0_0_2px_rgba(25,71,136,0.4),0_4px_16px_rgba(25,71,136,0.12)]":"shadow-sm hover:shadow-lg"}`,children:e.jsx(ur,{widget:a,variable:a.variable_id?t[a.variable_id]:void 0,latestPayload:a.device_id?f[a.device_id]:null,metricTimestamps:a.device_id?c[a.device_id]:null,telemetryHistory:a.device_id?(()=>{const h=a.variable_id?t[a.variable_id]?.key:void 0,u=h?`${a.device_id}__${h}`:null;return u?Ce[u]??null:null})():null,onEdit:Ps,onDelete:Fs,onSendCommand:Ws,isEditing:x,isUnlocked:o,onUnlock:D,showDebug:W,isOnline:a.device_id?H[a.device_id]??null:null,keyToName:a.device_id?Object.fromEntries((M[a.device_id]??[]).map(h=>[h.key,h.name])):void 0})},a.id)})}):e.jsx(mt,{className:"border-dashed",children:e.jsxs(Ct,{className:"flex flex-col items-center justify-center py-16 text-center",children:[e.jsx(Pa,{className:"h-12 w-12 text-muted-foreground opacity-30 mb-4"}),e.jsx("h2",{className:"text-lg font-semibold mb-1",children:"Welcome to your AIOT Dashboard"}),e.jsx("p",{className:"text-muted-foreground mb-4 max-w-md",children:"Monitor sensors, control devices, create automations, and integrate WhatsApp, SMS, email, and AI all from one place."}),e.jsxs("div",{className:"flex gap-2",children:[e.jsxs(E,{onClick:()=>B(!0),children:[e.jsx($e,{className:"h-4 w-4 mr-2"}),"Add Widget"]}),e.jsxs(E,{variant:"outline",onClick:()=>He(!0),children:[e.jsx(rt,{className:"h-4 w-4 mr-2"}),"Quick Create"]})]})]})})}),!d.widgets?.length&&e.jsx(mt,{className:"border-dashed",children:e.jsxs(Ct,{className:"flex flex-col sm:flex-row items-center justify-between gap-3 py-5",children:[e.jsxs("div",{className:"flex items-center gap-3",children:[e.jsx(St,{className:"h-8 w-8 text-muted-foreground opacity-50 shrink-0"}),e.jsxs("div",{children:[e.jsx("p",{className:"font-medium",children:"New here?"}),e.jsx("p",{className:"text-sm text-muted-foreground",children:"Getting started only takes minutes. Checkout our Getting Started guide."})]})]}),e.jsx(E,{variant:"outline",asChild:!0,className:"shrink-0",children:e.jsxs(kt,{to:"/iot-dashboard/get-started",children:[e.jsx(St,{className:"h-4 w-4 mr-2"}),"Getting Started Guide"]})})]})}),e.jsx(Ve,{open:fs,onOpenChange:nt,children:e.jsxs(Ie,{className:"sm:max-w-[425px]",children:[e.jsxs(ze,{children:[e.jsx(We,{children:"Edit Dashboard"}),e.jsx(Ke,{children:"Update your dashboard settings or delete it entirely."})]}),e.jsx("div",{className:"grid gap-4 py-4",children:e.jsxs("div",{className:"grid gap-2",children:[e.jsx(l,{htmlFor:"dashboard-name",children:"Name"}
10),e.jsx(j,{id:"dashboard-name",value:Wt,onChange:a=>fa(a.target.value)})]})}),e.jsxs(tt,{className:"flex-col sm:flex-row gap-2",children:[e.jsxs(E,{variant:"destructive",className:"sm:mr-auto",onClick:()=>{nt(!1),ot(!0)},children:[e.jsx(ht,{className:"h-4 w-4 mr-2"}),"Delete"]}),e.jsxs("div",{className:"flex gap-2 justify-end",children:[e.jsx(E,{variant:"outline",onClick:()=>nt(!1),children:"Cancel"}),e.jsx(E,{onClick:Ts,disabled:ba,children:ba?"Saving...":"Save Changes"})]})]})]})}),e.jsx(Ve,{open:bs,onOpenChange:ot,children:e.jsxs(Ie,{className:"sm:max-w-[425px]",children:[e.jsxs(ze,{children:[e.jsx(We,{className:"text-destructive",children:"Delete Dashboard?"}),e.jsxs(Ke,{children:["This will permanently delete the dashboard"," ",e.jsx("b",{children:d?.name})," and all its widgets. This action cannot be undone."]})]}),e.jsxs(tt,{children:[e.jsx(E,{variant:"outline",onClick:()=>ot(!1),children:"Cancel"}),e.jsx(E,{variant:"destructive",onClick:Ls,disabled:ja,children:ja?"Deleting...":"Confirm Delete"})]})]})}),e.jsx(Ve,{open:js,onOpenChange:a=>{He(a),a||Kt(null)},children:e.jsxs(Ie,{children:[e.jsxs(ze,{children:[e.jsx(We,{children:Pe?`Apply Template: ${Pe.name}`:"Quick Create Widgets"}),e.jsx(Ke,{children:Pe?`Select a device to map "${Pe.name}" variables to.`:"Automatically create widgets for all variables of a device"})]}),e.jsxs("div",{className:"space-y-4 py-4",children:[e.jsxs("div",{children:[e.jsx(l,{children:"Select Device"}),e.jsxs(te,{value:Re,onValueChange:$t,children:[e.jsx(ae,{children:e.jsx(se,{placeholder:"Choose a device..."})}),e.jsx(re,{children:p.map(a=>e.jsx(S,{value:a.id,children:a.device_name},a.id))})]})]}),d&&e.jsxs("div",{className:`flex items-center justify-between text-xs px-3 py-2 rounded-md ${d.widgets.length>=Ae?"bg-destructive/10 text-destructive":"bg-muted/60 text-muted-foreground"}`,children:[e.jsx("span",{children:"Dashboard capacity"}),e.jsxs("span",{className:"font-semibold tabular-nums",children:[d.widgets.length," / ",Ae," widgets",d.widgets.length<Ae&&e.jsxs("span",{className:"text-green-600 ml-1",children:["(",Ae-d.widgets.length," slots free)"]})]})]})]}),e.jsxs(tt,{children:[e.jsx(E,{variant:"outline",onClick:()=>He(!1),children:"Cancel"}),e.jsx(E,{onClick:Rs,disabled:!Re||Ca,children:Ca?"Creating...":"Create Widgets"})]})]})}),e.jsx(Ve,{open:_e,onOpenChange:de,children:e.jsxs(Ie,{className:"sm:max-w-[425px]",children:[e.jsxs(ze,{children:[e.jsx(We,{children:"Create Dashboard"}),e.jsx(Ke,{children:"Give your new dashboard a name."})]}),e.jsx("div",{className:"grid gap-4 py-4",children:e.jsx(j,{placeholder:"e.g. My Smart Home",value:le,onChange:a=>ve(a.target.value),onKeyDown:a=>a.key==="Enter"&&Nt()})}),e.jsx(tt,{children:e.jsx(E,{onClick:Nt,disabled:!le.trim()||ye,children:ye?"Creating...":"Create"})})]})}),e.jsx(Vr,{open:O,onOpenChange:B,onAdd:Ms,onAddMultiple:async a=>{if(d){he(!0);try{const o=Ae-d.widgets.length,h=a.slice(0,o),u=a.length-h.length,N=await Ut(d.id,h);T(A=>A&&{...A,widgets:[...A.widgets,...N]}),u>0?G.warning(`Added ${N.length} widget${N.length>1?"s":""}. ${u} skipped  widget limit reached.`):G.success(`Added ${N.length} widget${N.length>1?"s":""}`)}catch(o){G.error(o?.message||"Failed to add widgets")}finally{he(!1)}}},devices:p,isLoading:ue,initialVariablesByDevice:M}),e.jsx(Gr,{widget:b,open:oe,onOpenChange:a=>{q(a),a||ne(null)},onUpdate:As,devices:p,isLoading:X}),e.jsx(Br,{open:J,onOpenChange:I,onApply:Es,isLoading:!1}),d&&e.jsx(Zr,{open:vs,onClose:()=>wa(!1),dashboardId:d.id,dashboardName:d.name})]})]})}const Tl=()=>e.jsx(Zs,{children:e.jsx(ai,{})});export{Tl as component};

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.