tassello 0.2.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +38 -0
- package/README.md +112 -8
- package/dist/server/behavior_tree_files.d.ts +0 -1
- package/dist/server/behavior_tree_files.js +2 -25
- package/dist/server/diagnostics.d.ts +16 -0
- package/dist/server/diagnostics.js +200 -0
- package/dist/server/diagnostics_state.d.ts +23 -0
- package/dist/server/diagnostics_state.js +146 -0
- package/dist/server/disks.d.ts +14 -0
- package/dist/server/disks.js +152 -0
- package/dist/server/file_manager.d.ts +25 -0
- package/dist/server/file_manager.js +717 -0
- package/dist/server/http.js +248 -5
- package/dist/server/netpbm.d.ts +3 -0
- package/dist/server/netpbm.js +69 -0
- package/dist/server/pty.d.ts +26 -0
- package/dist/server/pty.js +150 -0
- package/dist/server/server.js +9 -2
- package/dist/server/session.d.ts +7 -1
- package/dist/server/session.js +67 -1
- package/dist/server/terminal_output.d.ts +25 -0
- package/dist/server/terminal_output.js +108 -0
- package/dist/server/terminals.d.ts +32 -0
- package/dist/server/terminals.js +366 -0
- package/dist/server/util.d.ts +4 -0
- package/dist/server/util.js +45 -1
- package/dist/shared/file_manager.d.ts +130 -0
- package/dist/shared/file_manager.js +7 -0
- package/dist/shared/protocol.d.ts +87 -2
- package/dist/shared/protocol.js +8 -0
- package/dist/types/client/api.d.ts +22 -0
- package/dist/types/client/connection.d.ts +22 -1
- package/dist/types/client/icons.d.ts +27 -0
- package/dist/types/client/sdk/index.d.ts +4 -3
- package/dist/types/shared/file_manager.d.ts +130 -0
- package/dist/types/shared/protocol.d.ts +87 -2
- package/dist/www/assets/Joystick.js +1 -1
- package/dist/www/assets/RobotModelView.js +2 -2
- package/dist/www/assets/TerminalView.css +1 -0
- package/dist/www/assets/TerminalView.js +17 -0
- package/dist/www/assets/dialogs.js +1 -0
- package/dist/www/assets/icons.js +1 -1
- package/dist/www/assets/index.css +1 -1
- package/dist/www/assets/index.js +59 -19
- package/dist/www/assets/keys.js +3 -0
- package/dist/www/assets/shared/tassello-sdk.js +1 -1
- package/dist/www/index.html +2 -0
- package/docs/plugins.md +20 -0
- package/package.json +6 -2
package/dist/www/assets/index.js
CHANGED
|
@@ -1,29 +1,69 @@
|
|
|
1
|
-
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/RobotModelView.js","assets/rolldown-runtime.js","assets/react.js","assets/icons.js","assets/jsx-runtime.js"])))=>i.map(i=>d[i]);
|
|
2
|
-
import{n as e}from"./rolldown-runtime.js";import{t}from"./react.js";import{t as n}from"./client.js";import{$ as r,A as i,C as a,D as o,E as s,F as c,G as l,H as u,I as d,J as f,L as p,M as m,N as h,O as g,P as _,Q as v,R as y,S as b,T as x,U as S,V as C,W as w,X as T,Y as E,Z as D,_ as ee,a as O,at as k,b as A,c as j,d as M,et as N,f as P,g as F,h as I,i as L,it as R,j as te,k as z,l as B,m as ne,n as re,nt as V,o as ie,ot as ae,p as oe,q as se,r as H,rt as ce,s as le,st as ue,tt as de,u as U,ut as fe,v as pe,w as me,x as he,y as W,z as ge}from"./icons.js";import{a as G,c as _e,i as K,l as q,o as ve,r as J,s as ye,t as be,u as xe}from"./Joystick.js";import{t as Se}from"./jsx-runtime.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var Ce=e(n(),1),Y=e(t(),1),X=e(Se(),1),we={start:`Starting…`,stop:`Stopping…`,restart:`Restarting…`};function Te(e){let t=Math.max(0,Math.round(e/1e3));return t<60?`${t} s`:t<3600?`${Math.floor(t/60)} min`:t<86400?`${Math.floor(t/3600)} h ${Math.floor(t%3600/60)} min`:`${Math.floor(t/86400)} d`}function Ee(e,t){let n=e.since?` · ${Te(t-e.since)}`:``;if(e.load===`not-found`)return{text:`Not installed`,tone:`off`};switch(e.active){case`active`:return e.sub===`running`?{text:`Running${n}`,tone:`on`}:{text:`Active (${e.sub})${n}`,tone:`on`};case`activating`:return{text:`Starting…`,tone:`busy`};case`deactivating`:return{text:`Stopping…`,tone:`busy`};case`reloading`:return{text:`Reloading…`,tone:`busy`};case`failed`:return{text:`Failed (${e.result})${n}`,tone:`failed`};default:return{text:`Stopped`,tone:`off`}}}function De(e,t){let n=e.replace(/\.service$/,``),r=t.trim().replace(/[*?[].*$/,``).replace(/\.service$/,``);return(r&&n.startsWith(r)?n.slice(r.length).replace(/^[-_.]+/,``):``)||n}function Oe({service:e}){let[t,n]=(0,Y.useState)(``),r=(0,Y.useRef)(null),{unit:i,scope:a}=e;return(0,Y.useEffect)(()=>(n(``),R.subscribeLogs({unit:i,scope:a},({text:e,reset:t})=>n(n=>(t?e:n+e).slice(-16e3)))),[i,a]),(0,Y.useEffect)(()=>{let e=r.current;e&&(e.scrollTop=e.scrollHeight)},[t]),(0,X.jsx)(`pre`,{ref:r,className:`command-output service-output`,children:t||`No output yet`})}function ke({config:e}){let t=_e(),[n,i]=(0,Y.useState)(null),[a,o]=(0,Y.useState)(new Set),[s,c]=(0,Y.useState)({}),[,u]=(0,Y.useState)(0),d=e.services.trim();(0,Y.useEffect)(()=>{if(i(null),d)return R.subscribeServices({pattern:d},i)},[d]),(0,Y.useEffect)(()=>{let e=setInterval(()=>u(e=>e+1),1e3);return()=>clearInterval(e)},[]);let f=e=>`${e.scope} ${e.unit}`,p=async(n,r)=>{let i=De(n.unit,d);if(r!==`start`&&e.confirmStop&&!await t.confirm({title:`${r===`stop`?`Stop`:`Restart`} ${i}?`,message:n.self?`This is the dashboard itself: the page loses its server until it is running again.`:`${n.unit}: ${n.description}`,confirmLabel:r===`stop`?`Stop`:`Restart`,danger:!0}))return;c(e=>({...e,[f(n)]:r}));let a=await R.serviceAction(n.unit,n.scope,r);c(({[f(n)]:e,...t})=>t),a&&G(`Could not ${r} ${i}: ${a}`,`error`)};if(!d)return(0,X.jsx)(`div`,{className:`widget-message`,children:`No services: set their name in edit mode`});if(!n)return(0,X.jsx)(`div`,{className:`widget-message`,children:`Listing the services…`});if(n.services.length===0)return(0,X.jsx)(`div`,{className:`widget-message${n.error?` error`:``}`,children:n.error??`No service matches “${d}”`});let m=new Set(n.services.map(e=>e.scope)),h=R.serverNow();return(0,X.jsx)(`ul`,{className:`services`,children:n.services.map(e=>{let t=f(e),n=s[t],i=n?{text:we[n],tone:`busy`}:Ee(e,h),c=[`active`,`activating`,`reloading`].includes(e.active),u=a.has(t);return(0,X.jsxs)(`li`,{className:`service`,children:[(0,X.jsxs)(`div`,{className:`service-row`,children:[(0,X.jsx)(`span`,{className:`service-dot ${i.tone}`,"aria-hidden":`true`}),(0,X.jsxs)(`div`,{className:`service-text`,title:`${e.unit}: ${e.description}`,children:[(0,X.jsxs)(`span`,{className:`service-name`,children:[De(e.unit,d),e.self&&(0,X.jsx)(`span`,{className:`service-tag`,children:`this dashboard`}),e.enabled===`enabled`&&(0,X.jsx)(`span`,{className:`service-tag`,children:`at boot`}),m.size>1&&(0,X.jsx)(`span`,{className:`service-tag`,children:e.scope})]}),(0,X.jsx)(`span`,{className:`service-state ${i.tone}`,children:i.text})]}),(0,X.jsxs)(`div`,{className:`service-actions`,children:[c?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(`button`,{type:`button`,className:`service-button`,title:`Restart`,"aria-label":`Restart ${e.unit}`,disabled:!!n,onClick:()=>p(e,`restart`),children:(0,X.jsx)(l,{width:16,height:16})}),(0,X.jsx)(`button`,{type:`button`,className:`service-button stop`,title:`Stop`,"aria-label":`Stop ${e.unit}`,disabled:!!n,onClick:()=>p(e,`stop`),children:(0,X.jsx)(T,{width:16,height:16})})]}):(0,X.jsx)(`button`,{type:`button`,className:`service-button start`,title:`Start`,"aria-label":`Start ${e.unit}`,disabled:!!n||e.load===`not-found`,onClick:()=>p(e,`start`),children:(0,X.jsx)(y,{width:16,height:16})}),(0,X.jsx)(`button`,{type:`button`,className:`service-button`,title:u?`Hide the output`:`Show the output`,"aria-label":`Output of ${e.unit}`,"aria-pressed":u,onClick:()=>o(e=>{let n=new Set(e);return n.delete(t)||n.add(t),n}),children:(0,X.jsx)(r,{width:16,height:16})})]})]}),u&&(0,X.jsx)(Oe,{service:e})]},t)})})}var Ae=J({type:`applications`,name:`Application Manager`,description:`The robot’s systemd services: their state, start and stop them, see their output.`,icon:re,defaultSize:{w:6,h:6},minSize:{w:4,h:2},component:ke,properties:[{key:`services`,label:`Services`,kind:`string`,default:``,placeholder:`myrobot`,help:`The start of their names (myrobot: myrobot*.service), or a glob (myrobot-nav*)`},{key:`confirmStop`,label:`Ask before stopping`,kind:`boolean`,default:!0,help:`And before restarting`}]}),je={x:0,y:0,z:0},Z=.06;function Me(e){return`${(e*180/Math.PI).toFixed(1).replace(/^-(0\.0)$/,`$1`)}°`}function Ne(e){return e.split(/[\s,]+/).filter(Boolean)}function Pe({disabled:e,onChange:t}){let n=(0,Y.useRef)(null),r=(0,Y.useRef)(null),[i,a]=(0,Y.useState)(0),[o,s]=(0,Y.useState)(!1),c=(0,Y.useRef)(t);c.current=t;let l=e=>{a(e);let t=Math.max(0,(Math.abs(e)-Z)/.94);c.current(Math.sign(e)*t*t)},u=e=>{let t=n.current.getBoundingClientRect(),r=t.width/2;l(Math.max(-1,Math.min(1,(e.clientX-(t.left+r))/r)))},d=e=>{r.current===null||e&&e.pointerId!==r.current||(r.current=null,s(!1),l(0))},f=(0,Y.useRef)(d);return f.current=d,(0,Y.useEffect)(()=>{let e=()=>document.hidden&&f.current();return document.addEventListener(`visibilitychange`,e),()=>document.removeEventListener(`visibilitychange`,e)},[]),(0,Y.useEffect)(()=>{e&&f.current()},[e]),(0,X.jsxs)(`div`,{ref:n,className:`jog-slider${o?` active`:``}${e?` disabled`:``}`,onPointerDown:t=>{e||r.current!==null||t.button!==0||(r.current=t.pointerId,s(!0),t.currentTarget.setPointerCapture(t.pointerId),u(t))},onPointerMove:e=>e.pointerId===r.current&&u(e),onPointerUp:d,onPointerCancel:d,onLostPointerCapture:d,children:[(0,X.jsx)(`div`,{className:`jog-slider-track`}),(0,X.jsx)(`div`,{className:`jog-slider-knob`,style:{left:`${50+i*46}%`}})]})}function Fe({joint:e}){let{position:t,lower:n,upper:r}=e;if(t===null||n===null||r===null||r<=n)return(0,X.jsx)(`div`,{className:`arm-range empty`});let i=e=>`${Math.max(0,Math.min(100,(e-n)/(r-n)*100))}%`;return(0,X.jsxs)(`div`,{className:`arm-range`,title:`${Me(n)} … ${Me(r)}`,children:[n<0&&r>0&&(0,X.jsx)(`div`,{className:`arm-range-zero`,style:{left:i(0)}}),(0,X.jsx)(`div`,{className:`arm-range-position`,style:{left:i(t)}})]})}function Ie({joint:e,disabled:t,onChange:n}){let r=e.drivable?``:e.located?`Not driven by the hardware`:`Not located: calibrate it`;return(0,X.jsxs)(`div`,{className:`arm-joint${e.drivable?``:` undriven`}`,title:r,children:[(0,X.jsx)(`span`,{className:`arm-joint-name`,children:e.name}),(0,X.jsx)(Pe,{disabled:t||!e.drivable,onChange:n}),(0,X.jsxs)(`div`,{className:`arm-joint-readout`,children:[(0,X.jsx)(`span`,{className:e.located?``:`relative`,children:e.position===null?`–`:Me(e.position)}),(0,X.jsx)(Fe,{joint:e})]})]})}function Le({config:e,editing:t}){let n=ae()===`open`,[r,i]=(0,Y.useState)(null),a=(0,Y.useRef)(null),o=(0,Y.useRef)(e);o.current=e;let s=(0,Y.useRef)({}),c=(0,Y.useRef)(je),l=(0,Y.useRef)(!1),{controllers:u,jointStatesTopic:d,descriptionTopic:f,calibrationTopic:p}=e;(0,Y.useEffect)(()=>{i(null);let{id:e,unsubscribe:t}=R.subscribeArm({controllers:Ne(u),jointStatesTopic:d,descriptionTopic:f,calibrationTopic:p},i);return a.current=e,()=>{a.current=null,t()}},[u,d,f,p]);let m=(0,Y.useCallback)(()=>{let{jointSpeed:e,cartesianSpeed:t,group:n,link:r,frameId:i}=o.current;if(a.current===null)return;let l={};for(let[t,n]of Object.entries(s.current))l[t]=n*e;let u=c.current;R.send({type:`arm.jog`,id:a.current,joints:l,cartesian:{x:u.x*t,y:u.y*t,z:u.z*t},ik:{group:n,link:r,frameId:i}})},[]),h=(0,Y.useCallback)(()=>{let e=Object.values(s.current).some(e=>e!==0)||Object.values(c.current).some(e=>e!==0);e!==l.current&&(l.current=e,m())},[m]);(0,Y.useEffect)(()=>{let t=setInterval(()=>l.current&&m(),1e3/Math.min(50,Math.max(1,e.rate)));return()=>clearInterval(t)},[e.rate,m]);let g=(0,Y.useCallback)(()=>{s.current={},c.current=je,l.current&&(l.current=!1,m())},[m]);(0,Y.useEffect)(()=>g,[e.cartesian,g]);let _=(e,t)=>{s.current={...s.current,[e]:t},h()},v=e=>{c.current={...c.current,...e},h()},y=t||!n,b=r?.joints??[],x=Ne(e.controllers)[0],S=e.cartesian?b.filter(e=>e.controller!==x):b,C=b.some(e=>e.drivable),w;return w=n?r?r.jog.state===`blocked`?{text:r.jog.message,className:`error`}:r.problems.length>0?{text:r.problems.join(` · `),className:`error`}:r.jog.state===`moving`?{text:`Moving…`,className:`active`}:{text:e.cartesian?`Pads: x forward, y left, z up (${e.frameId}). Release to stop`:`Hold a slider off centre to move its joint, release to stop`,className:``}:{text:`Connecting…`,className:``}:{text:`Disconnected`,className:`error`},(0,X.jsxs)(`div`,{className:`arm-teleop`,children:[r?.calibrating&&(0,X.jsx)(`div`,{className:`arm-banner`,children:`Calibrating: the joints' limits are lifted`}),e.cartesian&&(0,X.jsxs)(`div`,{className:`teleop-pads two arm-pads`,children:[(0,X.jsx)(be,{axes:`xy`,label:`x · y`,disabled:y||!C,onMove:(e,t)=>v({x:t,y:-e})}),(0,X.jsx)(be,{axes:`y`,label:`z`,disabled:y||!C,onMove:(e,t)=>v({z:t})})]}),S.length>0&&(0,X.jsx)(`div`,{className:`arm-joints${e.cartesian?` compact`:``}`,children:S.map(e=>(0,X.jsx)(Ie,{joint:e,disabled:y,onChange:t=>_(e.name,t)},e.name))}),r&&b.length===0&&r.problems.length===0&&(0,X.jsxs)(`div`,{className:`widget-message`,children:[`No joints in `,e.controllers]}),(0,X.jsx)(`div`,{className:`arm-status ${w.className}`,title:w.text,children:w.text})]})}var Re=J({type:`arm-teleop`,name:`Arm Teleop`,description:`Jog the arm: a slider per joint, or the end effector along x, y and z.`,icon:H,defaultSize:{w:5,h:5},minSize:{w:3,h:3},component:Le,properties:[{key:`cartesian`,label:`Cartesian mode`,kind:`boolean`,default:!1,help:`Pads moving the end effector along x, y and z, through MoveIt. Otherwise a slider per joint`},{key:`controllers`,label:`Trajectory controllers`,kind:`string`,default:`arm_controller`,help:`Their joints get a slider each. In Cartesian mode the pads move the first one, the others keep their sliders`},{key:`jointSpeed`,label:`Joint speed (rad/s)`,kind:`number`,default:.3,min:.01,max:2,step:.05,help:`With a slider at its end; slower nearer the centre`},{key:`cartesianSpeed`,label:`Cartesian speed (m/s)`,kind:`number`,default:.03,min:.005,max:.3,step:.005,visible:e=>e.cartesian},{key:`group`,label:`Planning group`,kind:`string`,default:`arm`,visible:e=>e.cartesian},{key:`link`,label:`End effector link`,kind:`string`,default:`tool0`,help:`The IK tip of the planning group, whose position the pads move (keeping its orientation free)`,visible:e=>e.cartesian},{key:`frameId`,label:`Frame of the pads`,kind:`string`,default:`base_link`,visible:e=>e.cartesian},{key:`rate`,label:`Rate (Hz)`,kind:`number`,default:20,min:5,max:50,step:1,help:`How often the jog is sent while held`},{key:`jointStatesTopic`,label:`Joint states topic`,kind:`topic`,default:`/joint_states`,topicTypes:[`sensor_msgs/msg/JointState`]},{key:`descriptionTopic`,label:`Robot description topic`,kind:`topic`,default:`/robot_description`,topicTypes:[`std_msgs/msg/String`],help:`The joints' limits, unless the calibration state gives them`},{key:`calibrationTopic`,label:`Calibration state topic`,kind:`topic`,default:``,placeholder:`none`,topicTypes:[`std_msgs/msg/String`],help:`Optional: a hardware interface's calibration state (JSON, see the README), whose limits replace the URDF's`}]}),ze={Action:`action`,Condition:`condition`,Control:`control`,Decorator:`decorator`,SubTree:`subtree`,SubTreePlus:`subtree`},Be={Action:`action`,Condition:`condition`,Control:`control`,Decorator:`decorator`,SubTree:`subtree`},Ve={input_port:`input`,output_port:`output`,inout_port:`inout`};function He(e){let t=[];for(let n of e.children.filter(e=>e.name===`TreeNodesModel`))for(let e of n.children){let n=Be[e.name];if(!n||!e.attributes.ID)continue;let r=[];for(let t of e.children){let e=Ve[t.name];e&&t.attributes.name&&r.push({name:t.attributes.name,direction:e,type:t.attributes.type??``,default:t.attributes.default??null,description:(t.attributes.description??t.text).trim()})}t.push({id:e.attributes.ID,kind:n,ports:r,description:(e.attributes.description??``).trim()})}return t}var Q=(e,t,n,r=null,i=`input`)=>({name:e,direction:i,type:t,default:r,description:n}),$=(e,t,n,r=[],i)=>({id:e,kind:t,ports:r,description:n,format:i}),Ue=e=>[Q(`variable`,`std::string`,`The value compared to the cases`),...Array.from({length:e},(e,t)=>Q(`case_${t+1}`,`std::string`,`Ticks child ${t+1} if equal`))],We=(e,t)=>$(`Loop${e}`,`decorator`,`Ticks its child once for each value of a queue, popped from it`,[Q(`queue`,`std::shared_ptr<std::deque<${t}>>`,`The queue of values`),Q(`if_empty`,`NodeStatus`,`What it returns when the queue is empty`,`SUCCESS`),Q(`value`,t,`The value popped`,null,`output`)],4),Ge=[$(`Sequence`,`control`,`Ticks its children in order while they succeed; restarts from the first after a failure`),$(`ReactiveSequence`,`control`,`As Sequence, but ticks again from the first child each time: conditions are checked while an action runs`),$(`SequenceWithMemory`,`control`,`As Sequence, but resumes from the child that failed`,[],4),$(`SequenceStar`,`control`,`As Sequence, but resumes from the child that failed`,[],3),$(`Fallback`,`control`,`Ticks its children in order until one succeeds`),$(`ReactiveFallback`,`control`,`As Fallback, but ticks again from the first child each time`),$(`Parallel`,`control`,`Ticks all its children at once, until enough succeed or fail`,[Q(`success_count`,`int`,`Successes needed to succeed; -1: all`,`-1`),Q(`failure_count`,`int`,`Failures needed to fail; -1: all`,`1`)],4),$(`Parallel`,`control`,`Ticks all its children at once, until enough succeed or fail`,[Q(`success_threshold`,`int`,`Successes needed to succeed; -1: all`),Q(`failure_threshold`,`int`,`Failures needed to fail; -1: all`,`1`)],3),$(`ParallelAll`,`control`,`Ticks all its children at once until they are all done`,[Q(`max_failures`,`int`,`Failures that make it fail; -1: all`,`1`)],4),$(`IfThenElse`,`control`,`Ticks its second child if its first succeeds, else its third`),$(`WhileDoElse`,`control`,`Reactive: ticks its second child while its first succeeds, else its third`),...[2,3,4,5,6].map(e=>$(`Switch${e}`,`control`,`Ticks the child of the case equal to the variable, else the last (default) of its ${e+1}`,Ue(e))),$(`Inverter`,`decorator`,`Succeeds when its child fails, and fails when it succeeds`),$(`ForceSuccess`,`decorator`,`Succeeds when its child is done, however it ends`),$(`ForceFailure`,`decorator`,`Fails when its child is done, however it ends`),$(`Repeat`,`decorator`,`Ticks its child again each time it succeeds, num_cycles times`,[Q(`num_cycles`,`int`,`Times to repeat; -1: forever`)]),$(`RetryUntilSuccessful`,`decorator`,`Ticks its child again each time it fails, up to num_attempts times`,[Q(`num_attempts`,`int`,`Attempts; -1: forever`)]),$(`KeepRunningUntilFailure`,`decorator`,`Ticks its child again each time it succeeds, until it fails`),$(`Delay`,`decorator`,`Ticks its child after a delay`,[Q(`delay_msec`,`unsigned int`,`The delay, ms`)]),$(`Timeout`,`decorator`,`Halts its child, and fails, if it runs longer than msec`,[Q(`msec`,`unsigned int`,`The time allowed, ms`)]),$(`RunOnce`,`decorator`,`Ticks its child once only; then returns what it returned, or skips`,[Q(`then_skip`,`bool`,`Skips once done, else returns its result again`,`true`)],4),$(`Precondition`,`decorator`,`Ticks its child if the script is true, else returns else`,[Q(`if`,`std::string`,`The condition, a script`),Q(`else`,`NodeStatus`,`What it returns if the condition is false`,`FAILURE`)],4),$(`SkipUnlessUpdated`,`decorator`,`Skips its child unless the blackboard entry changed since its last tick`,[Q(`entry`,`std::string`,`The blackboard entry`)],4),$(`WaitValueUpdate`,`decorator`,`Runs until the blackboard entry changes, then ticks its child`,[Q(`entry`,`std::string`,`The blackboard entry`)],4),We(`Int`,`int`),We(`Double`,`double`),We(`String`,`std::string`),We(`Bool`,`bool`),...[`Int`,`Double`,`String`].map(e=>$(`BlackboardCheck${e}`,`decorator`,`Ticks its child if the two values are equal, else returns return_on_mismatch`,[Q(`value_A`,`std::string`,`A value, or a blackboard entry`),Q(`value_B`,`std::string`,`A value, or a blackboard entry`),Q(`return_on_mismatch`,`NodeStatus`,`What it returns if they differ`,`FAILURE`)],3)),$(`AlwaysSuccess`,`action`,`Succeeds`),$(`AlwaysFailure`,`action`,`Fails`),$(`Script`,`action`,`Runs a script on the blackboard`,[Q(`code`,`std::string`,`The script, e.g. counter += 1`)],4),$(`SetBlackboard`,`action`,`Writes a value into a blackboard entry`,[Q(`value`,`std::string`,`The value, or another entry`),Q(`output_key`,`std::string`,`The entry written`,null,`inout`)]),$(`UnsetBlackboard`,`action`,`Removes a blackboard entry`,[Q(`key`,`std::string`,`The entry`)],4),$(`Sleep`,`action`,`Runs for a while, then succeeds`,[Q(`msec`,`unsigned int`,`How long, ms`)],4),$(`ScriptCondition`,`condition`,`Succeeds if the script is true`,[Q(`code`,`std::string`,`The condition, a script`)],4),$(`WasEntryUpdated`,`condition`,`Succeeds if the blackboard entry changed since its last tick`,[Q(`entry`,`std::string`,`The blackboard entry`)],4)];function Ke(e){return Ge.filter(t=>!t.format||t.format===e).map(({format:e,...t})=>t)}var qe=new Map([...Ge.map(e=>[e.id,e.kind]),...[`Sequence`,`SequenceStar`,`SequenceWithMemory`,`ReactiveSequence`,`Fallback`,`ReactiveFallback`,`Parallel`,`ParallelAll`,`IfThenElse`,`WhileDoElse`,`ManualSelector`,`TryCatch`,`AsyncSequence`,`AsyncFallback`,`PipelineSequence`,`RecoveryNode`,`RoundRobin`,`NonblockingSequence`,`PersistentSequence`,`PauseResumeController`].map(e=>[e,`control`]),...[`RetryUntilSuccesful`,`RateController`,`DistanceController`,`SpeedController`,`GoalUpdater`,`PathLongerOnApproach`,`SingleTrigger`,`GoalUpdatedController`].map(e=>[e,`decorator`]),...[`GoalReached`,`GoalUpdated`,`GloballyUpdatedGoal`,`InitialPoseReceived`,`IsStuck`,`TransformAvailable`,`DistanceTraveled`,`TimeExpired`,`IsBatteryLow`,`IsBatteryCharging`,`IsPathValid`,`PathExpiringTimer`,`AreErrorCodesPresent`,`WouldAControllerRecoveryHelp`,`WouldAPlannerRecoveryHelp`,`WouldASmootherRecoveryHelp`].map(e=>[e,`condition`])]),Je=/^(Is|Are|Has|Was|Would|Can|Check)[A-Z]|Condition/;function Ye(e,t){return qe.get(e)||(t>1?`control`:t===1?`decorator`:Je.test(e)?`condition`:`action`)}var Xe={image:{title:`Choose an image of the robot`,none:`No folder nor image here`,icon:`🖼`},"behavior-tree":{title:`Choose a behavior tree of the robot`,none:`No folder nor XML file here`,icon:`🌳`},bag:{title:`Choose a rosbag of the robot`,none:`No folder nor rosbag here`,icon:`🎞`},folder:{title:`Choose a folder of the robot`,none:`No folder here`,icon:`📁`}},Ze={image:{placeholder:`~/pictures/map.png`,accept:`image/*`},"behavior-tree":{placeholder:`package://my_robot/behavior_trees/main.xml`,accept:`.xml,text/xml,application/xml`}};function Qe({kind:e,children:t,...n}){let[r,i]=(0,Y.useState)(!1),[a,o]=(0,Y.useState)(!1),s=(0,Y.useRef)(null),c=e===`image`?xe(n.value):null,l=async e=>{if(e){o(!0);try{n.onCommit(await q.uploadFile(e))}catch(t){G(`Could not upload ${e.name}: ${t instanceof Error?t.message:t}`,`error`)}finally{o(!1)}}};return(0,X.jsxs)(`div`,{className:`file-input`,children:[t({...n,placeholder:n.placeholder??Ze[e].placeholder}),(0,X.jsxs)(`div`,{className:`file-input-actions`,children:[(0,X.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>i(!0),children:`Browse the robot…`}),(0,X.jsx)(`button`,{type:`button`,className:`button`,disabled:a,onClick:()=>s.current?.click(),children:a?`Uploading…`:`Upload…`}),(0,X.jsx)(`input`,{ref:s,type:`file`,accept:Ze[e].accept,hidden:!0,onChange:e=>{l(e.target.files?.[0]),e.target.value=``}})]}),c&&(0,X.jsx)(`img`,{className:`file-input-preview`,src:c,alt:``,onError:e=>e.currentTarget.hidden=!0},c),r&&(0,X.jsx)($e,{kind:e,start:n.value,onChoose:e=>{i(!1),n.onCommit(e)},onClose:()=>i(!1)})]})}function $e({kind:e,start:t,onChoose:n,onClose:r}){let[i,a]=(0,Y.useState)(()=>!t.startsWith(`/`)&&!t.startsWith(`~/`)?`~`:e!==`folder`&&/\.[A-Za-z0-9]+$/.test(t)?t.replace(/\/[^/]*$/,``)||`/`:t),[o,s]=(0,Y.useState)(null),[c,l]=(0,Y.useState)(null),[u,d]=(0,Y.useState)(null),f=(0,Y.useRef)(!1),{title:p,none:m,icon:h}=Xe[e],g=e===`image`,_=e===`folder`;(0,Y.useEffect)(()=>{let t=!0;return l(null),d(null),q.listFiles(i,e).then(e=>{t&&(f.current=!0,s(e))},e=>{t&&(l(e instanceof Error?e.message:String(e)),!f.current&&i!==`~`&&a(_&&i.lastIndexOf(`/`)>0?i.replace(/\/[^/]*$/,``):`~`))}),()=>{t=!1}},[i,e,_]);let v=e=>`${o.dir.replace(/\/$/,``)}/${e}`,y=_?o?.dir??null:u;return(0,X.jsx)(ye,{title:p,onClose:r,wide:!0,resizable:!0,children:(0,X.jsxs)(`div`,{className:`modal-body file-browser`,children:[(0,X.jsxs)(`div`,{className:`file-browser-path`,children:[(0,X.jsx)(`button`,{type:`button`,className:`button`,disabled:!o?.parent,onClick:()=>o?.parent&&a(o.parent),children:`Up`}),(0,X.jsx)(`code`,{children:o?.dir??i})]}),c&&(0,X.jsx)(`p`,{className:`field-help error`,children:c}),(0,X.jsxs)(`div`,{className:`file-browser-body${g?``:` single`}`,children:[(0,X.jsxs)(`ul`,{className:`file-browser-list`,children:[o?.entries.length===0&&(0,X.jsx)(`li`,{className:`file-browser-empty`,children:m}),o?.entries.map(e=>(0,X.jsx)(`li`,{children:(0,X.jsxs)(`button`,{type:`button`,title:e.name,className:`file-browser-entry${u===v(e.name)?` selected`:``}`,onClick:()=>e.kind===`dir`?a(v(e.name)):d(v(e.name)),onDoubleClick:()=>e.kind!==`dir`&&n(v(e.name)),children:[(0,X.jsx)(`span`,{"aria-hidden":`true`,children:e.kind===`dir`?`📁`:h}),e.name]})},e.name))]}),g&&(0,X.jsx)(`div`,{className:`file-browser-preview`,children:u?(0,X.jsx)(`img`,{src:xe(u)??``,alt:u}):(0,X.jsx)(`span`,{children:`Select an image to preview it`})})]}),(0,X.jsx)(`p`,{className:`file-browser-chosen`,children:y??`Nothing selected`}),(0,X.jsxs)(`div`,{className:`modal-actions`,children:[(0,X.jsx)(`button`,{type:`button`,className:`button`,onClick:r,children:`Cancel`}),(0,X.jsx)(`button`,{type:`button`,className:`button primary`,disabled:!y,onClick:()=>y&&n(y),children:_?`Choose this folder`:`Choose`})]})]})})}function et(e,t){let n=[0],r={left:[...e[0].left],right:[...e[0].right]};for(let i=1;i<e.length;i++){let{left:a,right:o}=e[i],s=-1/0;for(let e=0;e<Math.min(r.right.length,a.length);e++)s=Math.max(s,r.right[e]-a[e]+t);n.push(s);for(let e=0;e<a.length;e++)e<r.left.length?(r.left[e]=Math.min(r.left[e],a[e]+s),r.right[e]=Math.max(r.right[e],o[e]+s)):(r.left.push(a[e]+s),r.right.push(o[e]+s))}return{offsets:n,outline:r}}var tt=e=>Math.round(e*10)/10;function nt(e,t,n,r,i,a){let o=(e,t)=>a?`${tt(t)},${tt(e)}`:`${tt(e)},${tt(t)}`;if(Math.abs(n-e)<.5)return`M${o(t,e)}L${o(r,n)}`;let s=Math.min(6,Math.abs(n-e)/2,i-t,r-i),c=Math.sign(n-e);return`M${o(t,e)}L${o(i-s,e)}Q${o(i,e)} ${o(i,e+c*s)}L${o(i,n-c*s)}Q${o(i,n)} ${o(i+s,n)}L${o(r,n)}`}function rt(e,t,n,r,i){let a=r===`vertical`,o=e=>a?n(e).width:n(e).height,s=e=>a?n(e).height:n(e).width,c=new Map,l=new Map,u=[],d=(e,n)=>{l.set(e,n),u[n]=Math.max(u[n]??0,s(e));let r=o(e)/2,a=t(e);if(a.length===0)return{left:[-r],right:[r]};let f=et(a.map(e=>d(e,n+1)),i.siblings),p=(f.offsets[0]+f.offsets[f.offsets.length-1])/2;return a.forEach((e,t)=>c.set(e,f.offsets[t]-p)),{left:[-r,...f.outline.left.map(e=>e-p)],right:[r,...f.outline.right.map(e=>e-p)]}};if(e.length===0)return{boxes:new Map,links:[],width:0,height:0};let f=et(e.map(e=>d(e,0)),i.siblings*2);e.forEach((e,t)=>c.set(e,f.offsets[t]));let p=Math.min(...f.outline.left),m=Math.max(...f.outline.right)-p,h=[],g=0;for(let e of u)h.push(g),g+=e+i.levels;g-=i.levels;let _=new Map,v=[],y=(e,r)=>{let o=r+c.get(e),s=l.get(e),{width:u,height:d}=n(e),f=o-p,m=a?{x:f-u/2,y:h[s],width:u,height:d}:{x:h[s],y:f-d/2,width:u,height:d};_.set(e,m);let g=t(e);if(g.length===0)return;let b=h[s+1]-i.levels/2;for(let t of g){y(t,o);let n=_.get(t);v.push({parent:e,child:t,d:a?nt(f,m.y+d,n.x+n.width/2,n.y,b,!0):nt(f,m.x+u,n.y+n.height/2,n.x,b,!1)})}};return e.forEach(e=>y(e,0)),{boxes:_,links:v,width:a?m:g,height:a?g:m}}var it={received:!1,version:0,treeId:``,nodes:[],treeSize:0,children:[],depths:[],states:[],transitions:[],nextId:0,error:null,warnings:[],mismatch:null};function at(e,t){return e.received&&e.treeId===t.treeId&&e.treeSize===t.nodes.length&&t.nodes.every((t,n)=>{let r=e.nodes[n];return r.name===t.name&&r.type===t.type&&r.parent===t.parent&&JSON.stringify(r.ports)===JSON.stringify(t.ports)})}function ot(e,t){let n=t.map(()=>[]),r=[];return t.forEach((e,t)=>{r.push(e.parent<0?0:r[e.parent]+1),e.parent>=0&&n[e.parent].push(t)}),{...e,nodes:t,children:n,depths:r}}function st(e,t){switch(t.type){case`reset`:return{...it,version:e.version+1};case`tree`:{let{treeId:n,nodes:r,error:i,warnings:a}=t.tree;return at(e,t.tree)?{...e,error:i,warnings:a}:ot({...it,received:!0,version:e.version+1,treeId:n,treeSize:r.length,error:i,warnings:a},r)}case`update`:{let{reset:n,added:r,states:i,transitions:a,mismatch:o}=t.update,s=e;(n||r.length>0)&&(s=ot(e,[...e.nodes.slice(0,n?e.treeSize:void 0),...r]));let c=n?[]:[...e.states];for(let e of i)c[e.node]=e;let l=a.map((t,n)=>({...t,id:e.nextId+n}));return{...s,states:c,transitions:(n?l:[...e.transitions,...l]).slice(-500),nextId:e.nextId+a.length,mismatch:o}}}}function ct(e){switch(e){case`RUNNING`:return`running`;case`SUCCESS`:return`success`;case`FAILURE`:return`failure`;case`SKIPPED`:return`skipped`;default:return`idle`}}function lt(e){return e.charAt(0)+e.slice(1).toLowerCase()}function ut(e,t=e=>e){let n=new Set;return e.states.forEach((r,i)=>{r?.status===`RUNNING`&&!e.children[i].some(t=>e.states[t]?.status===`RUNNING`)&&n.add(t(i))}),[...n]}function dt(e){return e.name===e.type?e.type:`${e.type} · ${e.name}`}function ft(e){let t=Math.max(0,Math.round(e/1e3));return t<60?`${t} s`:t<3600?`${Math.floor(t/60)} min ${t%60} s`:`${Math.floor(t/3600)} h ${Math.floor(t%3600/60)} min`}function pt(e){let t=new Date(e),n=(e,t=2)=>String(e).padStart(t,`0`);return`${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}.${n(t.getMilliseconds(),3)}`}var mt=.1,ht=2.5,gt=.55,_t=16,vt=54,yt=5,bt=24,xt=280,St=36,Ct=14,wt=()=>window.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches??!1;function Tt(e){let{layout:t,root:n,vertical:r,covered:i,version:a}=e,o=(0,Y.useRef)(e);o.current=e;let s=(0,Y.useRef)(null),c=(0,Y.useRef)(null),l=(0,Y.useRef)(null),u=(0,Y.useRef)(!1),d=(0,Y.useRef)(0),f=(0,Y.useRef)(0),p=(0,Y.useRef)(new Map),m=(0,Y.useRef)(null),h=(0,Y.useRef)(null),g=(0,Y.useCallback)(()=>{let e=l.current,t=c.current,n=s.current;if(!e||!t||!n)return;t.style.transform=`translate(${e.x}px, ${e.y}px) scale(${e.k})`;let r=bt*e.k;for(;r<12;)r*=2;n.style.backgroundSize=`${r}px ${r}px`,n.style.backgroundPosition=`${e.x}px ${e.y}px`},[]),_=()=>{cancelAnimationFrame(d.current),d.current=0},v=(0,Y.useCallback)(e=>{_();let t=l.current;if(!t||wt()){l.current=e,g();return}let n=performance.now(),r=i=>{let a=Math.min(1,(i-n)/xt),o=1-(1-a)**3;l.current={x:t.x+(e.x-t.x)*o,y:t.y+(e.y-t.y)*o,k:t.k+(e.k-t.k)*o},g(),d.current=a<1?requestAnimationFrame(r):0};d.current=requestAnimationFrame(r)},[g]),y=(0,Y.useCallback)(e=>{let i=s.current;if(!i||t.width===0)return;let[a,o]=[i.clientWidth,i.clientHeight],c=Math.min(1,Math.max(mt,Math.min((a-32)/t.width,(o-vt-_t)/t.height)));u.current=!1,_();let d=n===void 0?void 0:t.boxes.get(n);if(e||c>=gt||!d)l.current={k:c,x:(a-t.width*c)/2,y:vt+Math.max(0,(o-vt-_t-t.height*c)/2)};else{let e=gt;l.current=r?{k:e,x:a/2-(d.x+d.width/2)*e,y:vt}:{k:e,x:_t,y:(vt+o)/2-(d.y+d.height/2)*e}}g()},[t,n,r,g]),b=(0,Y.useCallback)((e,n)=>{let r=s.current,a=l.current,o=e.flatMap(e=>t.boxes.get(e)??[]);if(!r||!a||o.length===0)return;u.current=!0;let c=Math.min(...o.map(e=>e.x)),d=Math.min(...o.map(e=>e.y)),f=Math.max(...o.map(e=>e.x+e.width)),p=Math.max(...o.map(e=>e.y+e.height)),m=r.clientWidth-i,h=r.clientHeight,{x:g,y:_,k:y}=a;c*y+g>=_t&&f*y+g<=m-_t&&d*y+_>=vt&&p*y+_<=h-_t&&!n||v({k:y,x:m/2-(c+f)/2*y,y:(vt+h-_t)/2-(d+p)/2*y})},[t,i,v]),x=(0,Y.useCallback)(e=>{let n=t.boxes.get(e),r=l.current;n&&r&&(h.current={node:e,x:n.x*r.k+r.x,y:n.y*r.k+r.y})},[t]),S=(0,Y.useCallback)(e=>{let t=s.current,n=l.current;if(!t||!n)return null;let r=t.getBoundingClientRect();return e.x<r.left||e.x>r.right||e.y<r.top||e.y>r.bottom?null:{x:(e.x-r.left-n.x)/n.k,y:(e.y-r.top-n.y)/n.k}},[]);(0,Y.useLayoutEffect)(()=>{u.current=!1},[a]),(0,Y.useLayoutEffect)(()=>{let e=h.current;h.current=null;let n=e&&t.boxes.get(e.node);if(e&&n&&l.current){let{k:t}=l.current;l.current={k:t,x:e.x-n.x*t,y:e.y-n.y*t},g()}else(!l.current||!u.current)&&y(!1)},[t,y,g]),(0,Y.useEffect)(()=>{let e=s.current;if(!e)return;let t=new ResizeObserver(()=>u.current?g():y(!1));return t.observe(e),()=>t.disconnect()},[y,g]),(0,Y.useEffect)(()=>()=>{_(),cancelAnimationFrame(f.current)},[]);let C=(0,Y.useCallback)((e,t)=>{let n=l.current;if(!n)return;_();let r=Math.min(ht,Math.max(mt,n.k*t));l.current={k:r,x:e.x-(e.x-n.x)*r/n.k,y:e.y-(e.y-n.y)*r/n.k},u.current=!0,g()},[g]);(0,Y.useEffect)(()=>{let e=s.current;if(!e)return;let t=t=>{t.preventDefault();let n=e.getBoundingClientRect();C({x:t.clientX-n.left,y:t.clientY-n.top},Math.exp(-t.deltaY*.0015))};return e.addEventListener(`wheel`,t,{passive:!1}),()=>e.removeEventListener(`wheel`,t)},[C]);let w=()=>{cancelAnimationFrame(f.current);let e=m.current,t=s.current,n=l.current;if(e?.kind!==`drag`||!t||!n)return;let r=t.getBoundingClientRect(),i=(e,t,n)=>n<e+St?Ct*(e+St-n)/St:n>t-St?-14*(n-t+St)/St:0,a=i(r.left,r.right,e.client.x),c=i(r.top,r.bottom,e.client.y);if(a===0&&c===0)return;l.current={...n,x:n.x+Math.max(-14,Math.min(Ct,a)),y:n.y+Math.max(-14,Math.min(Ct,c))},u.current=!0,g();let d=S(e.client);d&&o.current.onDragMove?.(d),f.current=requestAnimationFrame(w)},T=e=>{let t=s.current.getBoundingClientRect();return{x:e.clientX-t.left,y:e.clientY-t.top}},E=()=>{let[e,t]=[...p.current.values()];return{distance:Math.hypot(e.x-t.x,e.y-t.y),centre:{x:(e.x+t.x)/2,y:(e.y+t.y)/2}}},D=(e,t)=>{cancelAnimationFrame(f.current),o.current.onDragEnd?.(e?S({x:t.clientX,y:t.clientY}):null)},ee=e=>{if(e.pointerType===`mouse`&&e.button!==0)return;_(),e.currentTarget.setPointerCapture(e.pointerId);let t=T(e);p.current.set(e.pointerId,t),p.current.size===2?(m.current?.kind===`drag`&&D(!1,e),m.current={kind:`pinch`,...E()}):p.current.size===1&&(m.current={kind:`press`,start:t,target:e.target})},O=e=>{let t=p.current.get(e.pointerId),n=l.current;if(!t||!n)return;let r=T(e);p.current.set(e.pointerId,r);let i=m.current;i?.kind===`press`&&Math.hypot(r.x-i.start.x,r.y-i.start.y)>yt&&(o.current.onDragStart?.(i.target)?m.current={kind:`drag`,client:{x:e.clientX,y:e.clientY}}:(m.current={kind:`pan`},o.current.onPan()));let a=m.current;if(a?.kind===`drag`){a.client={x:e.clientX,y:e.clientY};let t=S(a.client);t&&o.current.onDragMove?.(t),w()}else if(a?.kind===`pan`)l.current={...n,x:n.x+r.x-t.x,y:n.y+r.y-t.y},u.current=!0,g();else if(a?.kind===`pinch`&&p.current.size===2){let e=E();l.current={...n,x:n.x+e.centre.x-a.centre.x,y:n.y+e.centre.y-a.centre.y},C(e.centre,e.distance/(a.distance||1)),m.current={kind:`pinch`,...e},o.current.onPan()}},k=e=>{if(!p.current.delete(e.pointerId))return;let t=m.current;t?.kind===`press`&&e.type===`pointerup`?o.current.onTap(t.target):t?.kind===`drag`&&D(e.type===`pointerup`,e),p.current.size===1?m.current={kind:`pan`}:p.current.size===0&&(m.current=null)},A=(0,Y.useCallback)(()=>{m.current?.kind===`drag`&&(m.current=null,cancelAnimationFrame(f.current),o.current.onDragEnd?.(null))},[]);return{viewportRef:s,layerRef:c,handlers:{onPointerDown:ee,onPointerMove:O,onPointerUp:k,onPointerCancel:k},fit:y,reveal:b,keepInPlace:x,toLayout:S,cancelDrag:A}}function Et(e){switch(e.kind){case`control`:return/Sequence/.test(e.type)?O:/Fallback/.test(e.type)?u:/Parallel/.test(e.type)?_:/Recovery|Retry/.test(e.type)?l:a;case`decorator`:return/Retry|Repeat|Loop/.test(e.type)?l:I;case`action`:return le;case`condition`:return B;case`subtree`:return V;default:return null}}function Dt({node:e,size:t=14}){let n=Et(e);return n&&(0,X.jsx)(n,{className:`bt-kind`,width:t,height:t})}function Ot(e){return e.kind?e.kind.charAt(0).toUpperCase()+e.kind.slice(1):`Not in the tree file`}var kt=40,At=15,jt=11,Mt=45,Nt=88,Pt=240,Ft=320,It={siblings:18,levels:46},Lt=null;function Rt(e,t){return Lt??=document.createElement(`canvas`).getContext(`2d`),Lt?(Lt.font=t,Lt.measureText(e).width):e.length*7}function zt(e,t){let n=getComputedStyle(document.documentElement),r=getComputedStyle(document.body).fontFamily,i=n.getPropertyValue(`--mono`).trim()||`monospace`;return e.map(e=>{let n=Math.max(Rt(e.type,`650 12px ${r}`),e.name===e.type?0:Rt(e.name,`11px ${r}`)),a=Math.min(Pt,Math.max(Nt,Math.ceil(n+Mt))),o=kt,s=t?Object.entries(e.ports):[];if(s.length>0){let e=Math.max(...s.map(([e,t])=>Rt(`${e} ${t}`,`10.5px ${i}`)));a=Math.max(a,Math.min(Ft,Math.ceil(e+24))),o+=s.length*At+jt}return{width:a,height:o}})}var Bt={running:`240 160 32`,success:`47 191 113`,failure:`240 82 82`,skipped:`139 149 167`,idle:`139 149 167`},Vt=(0,Y.memo)(function({index:e,node:t,box:n,state:r,selected:i,showPorts:a,vertical:o,folded:s,foldedRunning:c}){let l=(0,Y.useRef)(null),u=r?.changes??0,d=(0,Y.useRef)(u),f=ct(r?.status),p=f===`idle`&&r?.result?ct(r.result):null;(0,Y.useEffect)(()=>{if(u!==d.current&&(d.current=u,!wt())){let e=Bt[p??f];l.current?.animate?.([{boxShadow:`0 0 0 0 rgb(${e} / 60%)`},{boxShadow:`0 0 0 8px rgb(${e} / 0%)`}],{duration:500,easing:`ease-out`})}},[u,f,p]);let m=a?Object.entries(t.ports):[],h=`${Ot(t)}: ${t.type}${t.name===t.type?``:` “${t.name}”`}${r?.status?` · ${lt(r.status)}`:``}`;return(0,X.jsxs)(`div`,{ref:l,"data-node":e,className:`bt-node ${f}${p?` was-${p}`:``}${i?` selected`:``}`,style:{left:n.x,top:n.y,width:n.width,height:n.height},title:h,children:[(0,X.jsxs)(`div`,{className:`bt-node-head`,children:[(0,X.jsx)(Dt,{node:t}),(0,X.jsxs)(`div`,{className:`bt-node-labels`,children:[(0,X.jsx)(`span`,{className:`bt-node-type`,children:t.type}),t.name!==t.type&&(0,X.jsx)(`span`,{className:`bt-node-name`,children:t.name})]})]}),m.length>0&&(0,X.jsx)(`dl`,{className:`bt-node-ports`,children:m.map(([e,t])=>(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`dt`,{children:e}),(0,X.jsx)(`dd`,{className:/^\{.*\}$/.test(t)?`entry`:void 0,children:t})]},e))}),s>=0&&(0,X.jsx)(`span`,{"data-fold":e,className:`bt-fold${o?``:` side`}${c?` running`:``}`,title:s===0?`Fold its children away`:`Show its children`,children:s===0?`−`:`+${s}`})]})}),Ht=(0,Y.memo)(function({links:e,running:t,width:n,height:r}){let i=new Set(t?t.split(`,`).map(Number):[]),a=[...e.filter(e=>!i.has(e.child)),...e.filter(e=>i.has(e.child))];return(0,X.jsx)(`svg`,{className:`bt-links`,width:n,height:r,"aria-hidden":`true`,children:a.map(e=>(0,X.jsx)(`path`,{d:e.d,className:i.has(e.child)?`running`:void 0},e.child))})});function Ut({model:e,direction:t,showPorts:n,folded:r,selected:i,follow:a,focus:o,fitRequest:s,covered:c,onSelect:l,onFold:u,onPan:d}){let f=t===`vertical`,{nodes:p,treeSize:m,children:h,states:g}=e,_=(0,Y.useMemo)(()=>p.slice(0,m).flatMap((e,t)=>e.parent<0?[t]:[]),[p,m]),v=(0,Y.useMemo)(()=>zt(p.slice(0,m),n),[p,m,n]),y=(0,Y.useMemo)(()=>rt(_,e=>r.has(e)?[]:h[e],e=>v[e],t,It),[_,h,r,v,t]),b=(0,Y.useMemo)(()=>{let e=Array(m).fill(1);for(let t=m-1;t>0;t--){let n=p[t].parent;n>=0&&(e[n]+=e[t])}return e},[p,m]),x=(0,Y.useCallback)(e=>{let t=e;for(let n=p[e].parent;n>=0;n=p[n].parent)r.has(n)&&(t=n);return t},[p,r]),S=ut(e,x).filter(e=>e<m).join(`,`),C=g.flatMap((e,t)=>e?.status===`RUNNING`&&t<m?[t]:[]).join(`,`),w=(0,Y.useRef)(()=>{}),{viewportRef:T,layerRef:E,handlers:D,fit:ee,reveal:O,keepInPlace:k}=Tt({layout:y,root:_[0],vertical:f,covered:c,version:e.version,onTap:e=>{let t=e.closest(`[data-fold]`),n=e.closest(`[data-node]`);if(t){let e=Number(t.getAttribute(`data-fold`));w.current(e),u(e)}else l(n?Number(n.getAttribute(`data-node`)):null)},onPan:d});return w.current=k,(0,Y.useEffect)(()=>{a&&S&&O(S.split(`,`).map(Number),!1)},[a,S,O]),(0,Y.useEffect)(()=>{o&&O([x(o.node)],!0)},[o]),(0,Y.useEffect)(()=>{i!==null&&c>0&&O([x(i)],!1)},[i,c]),(0,Y.useEffect)(()=>{s>0&&ee(!0)},[s]),(0,X.jsx)(`div`,{ref:T,className:`bt-graph`,...D,children:(0,X.jsxs)(`div`,{ref:E,className:`bt-layer`,style:{width:y.width,height:y.height},children:[(0,X.jsx)(Ht,{links:y.links,running:C,width:y.width,height:y.height}),[...y.boxes].map(([e,t])=>(0,X.jsx)(Vt,{index:e,node:p[e],box:t,state:g[e],selected:i===e,showPorts:n,vertical:f,folded:h[e].length===0?-1:r.has(e)?b[e]-1:0,foldedRunning:r.has(e)&&h[e].some(e=>g[e]?.status===`RUNNING`)},e))]})})}var Wt=/<([A-Za-z_:][-\w:.]*)((?:\s+[A-Za-z_:][-\w:.]*\s*=\s*(?:"[^"]*"|'[^']*'))*)\s*(\/?)>/y,Gt=/<\/([A-Za-z_:][-\w:.]*)\s*>/y,Kt=/([A-Za-z_:][-\w:.]*)\s*=\s*(?:"([^"]*)"|'([^']*)')/g,qt=/&(?:(lt|gt|amp|quot|apos)|#(\d+)|#x([0-9A-Fa-f]+));/g,Jt={lt:`<`,gt:`>`,amp:`&`,quot:`"`,apos:`'`};function Yt(e){return e.replace(qt,(e,t,n,r)=>{if(t)return Jt[t];let i=n?Number(n):parseInt(r,16);return i<=1114111?String.fromCodePoint(i):e})}function Xt(e){let t=[];for(let n=e.indexOf(`
|
|
1
|
+
const __vite__mapDeps=(i,m=__vite__mapDeps,d=(m.f||(m.f=["assets/RobotModelView.js","assets/rolldown-runtime.js","assets/react.js","assets/icons.js","assets/jsx-runtime.js","assets/TerminalView.js","assets/dialogs.js","assets/keys.js","assets/TerminalView.css"])))=>i.map(i=>d[i]);
|
|
2
|
+
import{n as e}from"./rolldown-runtime.js";import{t}from"./react.js";import{t as n}from"./client.js";import{$ as r,A as i,At as a,B as o,C as s,D as c,Dt as l,Et as u,F as d,H as f,I as p,K as m,L as h,Lt as g,M as _,Mt as v,N as y,Nt as b,O as x,Ot as S,P as C,Pt as w,Q as T,R as E,Rt as D,S as ee,T as O,Tt as k,U as A,W as j,X as M,Z as te,_ as N,_t as P,a as F,at as ne,b as I,bt as re,c as ie,ct as L,d as R,dt as ae,et as oe,f as z,ft as se,g as ce,gt as le,h as B,ht as ue,i as V,it as de,j as fe,jt as H,k as pe,kt as me,l as he,lt as U,mt as ge,n as _e,nt as ve,o as ye,p as be,pt as xe,q as Se,r as Ce,rt as we,s as Te,st as Ee,tt as De,u as Oe,ut as ke,v as Ae,vt as je,w as Me,wt as Ne,x as Pe,xt as W,y as Fe,yt as Ie,z as Le}from"./icons.js";import{a as G,c as K,i as Re,l as ze,o as Be,r as Ve,s as He,t as Ue}from"./Joystick.js";import{t as We}from"./jsx-runtime.js";import{n as Ge,r as Ke,t as qe}from"./dialogs.js";import{t as Je}from"./keys.js";(function(){let e=document.createElement(`link`).relList;if(e&&e.supports&&e.supports(`modulepreload`))return;for(let e of document.querySelectorAll(`link[rel="modulepreload"]`))n(e);new MutationObserver(e=>{for(let t of e)if(t.type===`childList`)for(let e of t.addedNodes)e.tagName===`LINK`&&e.rel===`modulepreload`&&n(e)}).observe(document,{childList:!0,subtree:!0});function t(e){let t={};return e.integrity&&(t.integrity=e.integrity),e.referrerPolicy&&(t.referrerPolicy=e.referrerPolicy),t.credentials=e.crossOrigin===`use-credentials`?`include`:e.crossOrigin===`anonymous`?`omit`:`same-origin`,t}function n(e){if(e.ep)return;e.ep=!0;let n=t(e);fetch(e.href,n)}})();var Ye=e(n(),1),q=e(t(),1),J=e(We(),1),Xe={start:`Starting…`,stop:`Stopping…`,restart:`Restarting…`};function Ze(e){let t=Math.max(0,Math.round(e/1e3));return t<60?`${t} s`:t<3600?`${Math.floor(t/60)} min`:t<86400?`${Math.floor(t/3600)} h ${Math.floor(t%3600/60)} min`:`${Math.floor(t/86400)} d`}function Qe(e,t){let n=e.since?` · ${Ze(t-e.since)}`:``;if(e.load===`not-found`)return{text:`Not installed`,tone:`off`};switch(e.active){case`active`:return e.sub===`running`?{text:`Running${n}`,tone:`on`}:{text:`Active (${e.sub})${n}`,tone:`on`};case`activating`:return{text:`Starting…`,tone:`busy`};case`deactivating`:return{text:`Stopping…`,tone:`busy`};case`reloading`:return{text:`Reloading…`,tone:`busy`};case`failed`:return{text:`Failed (${e.result})${n}`,tone:`failed`};default:return{text:`Stopped`,tone:`off`}}}function $e(e,t){let n=e.replace(/\.service$/,``),r=t.trim().replace(/[*?[].*$/,``).replace(/\.service$/,``);return(r&&n.startsWith(r)?n.slice(r.length).replace(/^[-_.]+/,``):``)||n}function et({service:e}){let[t,n]=(0,q.useState)(``),r=(0,q.useRef)(null),{unit:i,scope:a}=e;return(0,q.useEffect)(()=>(n(``),H.subscribeLogs({unit:i,scope:a},({text:e,reset:t})=>n(n=>(t?e:n+e).slice(-16e3)))),[i,a]),(0,q.useEffect)(()=>{let e=r.current;e&&(e.scrollTop=e.scrollHeight)},[t]),(0,J.jsx)(`pre`,{ref:r,className:`command-output service-output`,children:t||`No output yet`})}function tt({config:e}){let t=Ke(),[n,r]=(0,q.useState)(null),[i,a]=(0,q.useState)(new Set),[o,s]=(0,q.useState)({}),[,c]=(0,q.useState)(0),l=e.services.trim();(0,q.useEffect)(()=>{if(r(null),l)return H.subscribeServices({pattern:l},r)},[l]),(0,q.useEffect)(()=>{let e=setInterval(()=>c(e=>e+1),1e3);return()=>clearInterval(e)},[]);let u=e=>`${e.scope} ${e.unit}`,d=async(n,r)=>{let i=$e(n.unit,l);if(r!==`start`&&e.confirmStop&&!await t.confirm({title:`${r===`stop`?`Stop`:`Restart`} ${i}?`,message:n.self?`This is the dashboard itself: the page loses its server until it is running again.`:`${n.unit}: ${n.description}`,confirmLabel:r===`stop`?`Stop`:`Restart`,danger:!0}))return;s(e=>({...e,[u(n)]:r}));let a=await H.serviceAction(n.unit,n.scope,r);s(({[u(n)]:e,...t})=>t),a&&G(`Could not ${r} ${i}: ${a}`,`error`)};if(!l)return(0,J.jsx)(`div`,{className:`widget-message`,children:`No services: set their name in edit mode`});if(!n)return(0,J.jsx)(`div`,{className:`widget-message`,children:`Listing the services…`});if(n.services.length===0)return(0,J.jsx)(`div`,{className:`widget-message${n.error?` error`:``}`,children:n.error??`No service matches “${l}”`});let f=new Set(n.services.map(e=>e.scope)),p=H.serverNow();return(0,J.jsx)(`ul`,{className:`services`,children:n.services.map(e=>{let t=u(e),n=o[t],r=n?{text:Xe[n],tone:`busy`}:Qe(e,p),s=[`active`,`activating`,`reloading`].includes(e.active),c=i.has(t);return(0,J.jsxs)(`li`,{className:`service`,children:[(0,J.jsxs)(`div`,{className:`service-row`,children:[(0,J.jsx)(`span`,{className:`service-dot ${r.tone}`,"aria-hidden":`true`}),(0,J.jsxs)(`div`,{className:`service-text`,title:`${e.unit}: ${e.description}`,children:[(0,J.jsxs)(`span`,{className:`service-name`,children:[$e(e.unit,l),e.self&&(0,J.jsx)(`span`,{className:`service-tag`,children:`this dashboard`}),e.enabled===`enabled`&&(0,J.jsx)(`span`,{className:`service-tag`,children:`at boot`}),f.size>1&&(0,J.jsx)(`span`,{className:`service-tag`,children:e.scope})]}),(0,J.jsx)(`span`,{className:`service-state ${r.tone}`,children:r.text})]}),(0,J.jsxs)(`div`,{className:`service-actions`,children:[s?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`button`,{type:`button`,className:`service-button`,title:`Restart`,"aria-label":`Restart ${e.unit}`,disabled:!!n,onClick:()=>d(e,`restart`),children:(0,J.jsx)(ae,{width:16,height:16})}),(0,J.jsx)(`button`,{type:`button`,className:`service-button stop`,title:`Stop`,"aria-label":`Stop ${e.unit}`,disabled:!!n,onClick:()=>d(e,`stop`),children:(0,J.jsx)(je,{width:16,height:16})})]}):(0,J.jsx)(`button`,{type:`button`,className:`service-button start`,title:`Start`,"aria-label":`Start ${e.unit}`,disabled:!!n||e.load===`not-found`,onClick:()=>d(e,`start`),children:(0,J.jsx)(de,{width:16,height:16})}),(0,J.jsx)(`button`,{type:`button`,className:`service-button`,title:c?`Hide the output`:`Show the output`,"aria-label":`Output of ${e.unit}`,"aria-pressed":c,onClick:()=>a(e=>{let n=new Set(e);return n.delete(t)||n.add(t),n}),children:(0,J.jsx)(W,{width:16,height:16})})]})]}),c&&(0,J.jsx)(et,{service:e})]},t)})})}var Y=Ve({type:`applications`,name:`Application Manager`,description:`The robot’s systemd services: their state, start and stop them, see their output.`,icon:_e,defaultSize:{w:6,h:6},minSize:{w:4,h:2},component:tt,properties:[{key:`services`,label:`Services`,kind:`string`,default:``,placeholder:`myrobot`,help:`The start of their names (myrobot: myrobot*.service), or a glob (myrobot-nav*)`},{key:`confirmStop`,label:`Ask before stopping`,kind:`boolean`,default:!0,help:`And before restarting`}]}),nt={x:0,y:0,z:0},rt=.06;function it(e){return`${(e*180/Math.PI).toFixed(1).replace(/^-(0\.0)$/,`$1`)}°`}function at(e){return e.split(/[\s,]+/).filter(Boolean)}function ot({disabled:e,onChange:t}){let n=(0,q.useRef)(null),r=(0,q.useRef)(null),[i,a]=(0,q.useState)(0),[o,s]=(0,q.useState)(!1),c=(0,q.useRef)(t);c.current=t;let l=e=>{a(e);let t=Math.max(0,(Math.abs(e)-rt)/.94);c.current(Math.sign(e)*t*t)},u=e=>{let t=n.current.getBoundingClientRect(),r=t.width/2;l(Math.max(-1,Math.min(1,(e.clientX-(t.left+r))/r)))},d=e=>{r.current===null||e&&e.pointerId!==r.current||(r.current=null,s(!1),l(0))},f=(0,q.useRef)(d);return f.current=d,(0,q.useEffect)(()=>{let e=()=>document.hidden&&f.current();return document.addEventListener(`visibilitychange`,e),()=>document.removeEventListener(`visibilitychange`,e)},[]),(0,q.useEffect)(()=>{e&&f.current()},[e]),(0,J.jsxs)(`div`,{ref:n,className:`jog-slider${o?` active`:``}${e?` disabled`:``}`,onPointerDown:t=>{e||r.current!==null||t.button!==0||(r.current=t.pointerId,s(!0),t.currentTarget.setPointerCapture(t.pointerId),u(t))},onPointerMove:e=>e.pointerId===r.current&&u(e),onPointerUp:d,onPointerCancel:d,onLostPointerCapture:d,children:[(0,J.jsx)(`div`,{className:`jog-slider-track`}),(0,J.jsx)(`div`,{className:`jog-slider-knob`,style:{left:`${50+i*46}%`}})]})}function st({joint:e}){let{position:t,lower:n,upper:r}=e;if(t===null||n===null||r===null||r<=n)return(0,J.jsx)(`div`,{className:`arm-range empty`});let i=e=>`${Math.max(0,Math.min(100,(e-n)/(r-n)*100))}%`;return(0,J.jsxs)(`div`,{className:`arm-range`,title:`${it(n)} … ${it(r)}`,children:[n<0&&r>0&&(0,J.jsx)(`div`,{className:`arm-range-zero`,style:{left:i(0)}}),(0,J.jsx)(`div`,{className:`arm-range-position`,style:{left:i(t)}})]})}function ct({joint:e,disabled:t,onChange:n}){let r=e.drivable?``:e.located?`Not driven by the hardware`:`Not located: calibrate it`;return(0,J.jsxs)(`div`,{className:`arm-joint${e.drivable?``:` undriven`}`,title:r,children:[(0,J.jsx)(`span`,{className:`arm-joint-name`,children:e.name}),(0,J.jsx)(ot,{disabled:t||!e.drivable,onChange:n}),(0,J.jsxs)(`div`,{className:`arm-joint-readout`,children:[(0,J.jsx)(`span`,{className:e.located?``:`relative`,children:e.position===null?`–`:it(e.position)}),(0,J.jsx)(st,{joint:e})]})]})}function lt({config:e,editing:t}){let n=b()===`open`,[r,i]=(0,q.useState)(null),a=(0,q.useRef)(null),o=(0,q.useRef)(e);o.current=e;let s=(0,q.useRef)({}),c=(0,q.useRef)(nt),l=(0,q.useRef)(!1),{controllers:u,jointStatesTopic:d,descriptionTopic:f,calibrationTopic:p}=e;(0,q.useEffect)(()=>{i(null);let{id:e,unsubscribe:t}=H.subscribeArm({controllers:at(u),jointStatesTopic:d,descriptionTopic:f,calibrationTopic:p},i);return a.current=e,()=>{a.current=null,t()}},[u,d,f,p]);let m=(0,q.useCallback)(()=>{let{jointSpeed:e,cartesianSpeed:t,group:n,link:r,frameId:i}=o.current;if(a.current===null)return;let l={};for(let[t,n]of Object.entries(s.current))l[t]=n*e;let u=c.current;H.send({type:`arm.jog`,id:a.current,joints:l,cartesian:{x:u.x*t,y:u.y*t,z:u.z*t},ik:{group:n,link:r,frameId:i}})},[]),h=(0,q.useCallback)(()=>{let e=Object.values(s.current).some(e=>e!==0)||Object.values(c.current).some(e=>e!==0);e!==l.current&&(l.current=e,m())},[m]);(0,q.useEffect)(()=>{let t=setInterval(()=>l.current&&m(),1e3/Math.min(50,Math.max(1,e.rate)));return()=>clearInterval(t)},[e.rate,m]);let g=(0,q.useCallback)(()=>{s.current={},c.current=nt,l.current&&(l.current=!1,m())},[m]);(0,q.useEffect)(()=>g,[e.cartesian,g]);let _=(e,t)=>{s.current={...s.current,[e]:t},h()},v=e=>{c.current={...c.current,...e},h()},y=t||!n,x=r?.joints??[],S=at(e.controllers)[0],C=e.cartesian?x.filter(e=>e.controller!==S):x,w=x.some(e=>e.drivable),T;return T=n?r?r.jog.state===`blocked`?{text:r.jog.message,className:`error`}:r.problems.length>0?{text:r.problems.join(` · `),className:`error`}:r.jog.state===`moving`?{text:`Moving…`,className:`active`}:{text:e.cartesian?`Pads: x forward, y left, z up (${e.frameId}). Release to stop`:`Hold a slider off centre to move its joint, release to stop`,className:``}:{text:`Connecting…`,className:``}:{text:`Disconnected`,className:`error`},(0,J.jsxs)(`div`,{className:`arm-teleop`,children:[r?.calibrating&&(0,J.jsx)(`div`,{className:`arm-banner`,children:`Calibrating: the joints' limits are lifted`}),e.cartesian&&(0,J.jsxs)(`div`,{className:`teleop-pads two arm-pads`,children:[(0,J.jsx)(Ue,{axes:`xy`,label:`x · y`,disabled:y||!w,onMove:(e,t)=>v({x:t,y:-e})}),(0,J.jsx)(Ue,{axes:`y`,label:`z`,disabled:y||!w,onMove:(e,t)=>v({z:t})})]}),C.length>0&&(0,J.jsx)(`div`,{className:`arm-joints${e.cartesian?` compact`:``}`,children:C.map(e=>(0,J.jsx)(ct,{joint:e,disabled:y,onChange:t=>_(e.name,t)},e.name))}),r&&x.length===0&&r.problems.length===0&&(0,J.jsxs)(`div`,{className:`widget-message`,children:[`No joints in `,e.controllers]}),(0,J.jsx)(`div`,{className:`arm-status ${T.className}`,title:T.text,children:T.text})]})}var ut=Ve({type:`arm-teleop`,name:`Arm Teleop`,description:`Jog the arm: a slider per joint, or the end effector along x, y and z.`,icon:V,defaultSize:{w:5,h:5},minSize:{w:3,h:3},component:lt,properties:[{key:`cartesian`,label:`Cartesian mode`,kind:`boolean`,default:!1,help:`Pads moving the end effector along x, y and z, through MoveIt. Otherwise a slider per joint`},{key:`controllers`,label:`Trajectory controllers`,kind:`string`,default:`arm_controller`,help:`Their joints get a slider each. In Cartesian mode the pads move the first one, the others keep their sliders`},{key:`jointSpeed`,label:`Joint speed (rad/s)`,kind:`number`,default:.3,min:.01,max:2,step:.05,help:`With a slider at its end; slower nearer the centre`},{key:`cartesianSpeed`,label:`Cartesian speed (m/s)`,kind:`number`,default:.03,min:.005,max:.3,step:.005,visible:e=>e.cartesian},{key:`group`,label:`Planning group`,kind:`string`,default:`arm`,visible:e=>e.cartesian},{key:`link`,label:`End effector link`,kind:`string`,default:`tool0`,help:`The IK tip of the planning group, whose position the pads move (keeping its orientation free)`,visible:e=>e.cartesian},{key:`frameId`,label:`Frame of the pads`,kind:`string`,default:`base_link`,visible:e=>e.cartesian},{key:`rate`,label:`Rate (Hz)`,kind:`number`,default:20,min:5,max:50,step:1,help:`How often the jog is sent while held`},{key:`jointStatesTopic`,label:`Joint states topic`,kind:`topic`,default:`/joint_states`,topicTypes:[`sensor_msgs/msg/JointState`]},{key:`descriptionTopic`,label:`Robot description topic`,kind:`topic`,default:`/robot_description`,topicTypes:[`std_msgs/msg/String`],help:`The joints' limits, unless the calibration state gives them`},{key:`calibrationTopic`,label:`Calibration state topic`,kind:`topic`,default:``,placeholder:`none`,topicTypes:[`std_msgs/msg/String`],help:`Optional: a hardware interface's calibration state (JSON, see the README), whose limits replace the URDF's`}]}),dt={Action:`action`,Condition:`condition`,Control:`control`,Decorator:`decorator`,SubTree:`subtree`,SubTreePlus:`subtree`},ft={Action:`action`,Condition:`condition`,Control:`control`,Decorator:`decorator`,SubTree:`subtree`},pt={input_port:`input`,output_port:`output`,inout_port:`inout`};function mt(e){let t=[];for(let n of e.children.filter(e=>e.name===`TreeNodesModel`))for(let e of n.children){let n=ft[e.name];if(!n||!e.attributes.ID)continue;let r=[];for(let t of e.children){let e=pt[t.name];e&&t.attributes.name&&r.push({name:t.attributes.name,direction:e,type:t.attributes.type??``,default:t.attributes.default??null,description:(t.attributes.description??t.text).trim()})}t.push({id:e.attributes.ID,kind:n,ports:r,description:(e.attributes.description??``).trim()})}return t}var X=(e,t,n,r=null,i=`input`)=>({name:e,direction:i,type:t,default:r,description:n}),Z=(e,t,n,r=[],i)=>({id:e,kind:t,ports:r,description:n,format:i}),ht=e=>[X(`variable`,`std::string`,`The value compared to the cases`),...Array.from({length:e},(e,t)=>X(`case_${t+1}`,`std::string`,`Ticks child ${t+1} if equal`))],gt=(e,t)=>Z(`Loop${e}`,`decorator`,`Ticks its child once for each value of a queue, popped from it`,[X(`queue`,`std::shared_ptr<std::deque<${t}>>`,`The queue of values`),X(`if_empty`,`NodeStatus`,`What it returns when the queue is empty`,`SUCCESS`),X(`value`,t,`The value popped`,null,`output`)],4),_t=[Z(`Sequence`,`control`,`Ticks its children in order while they succeed; restarts from the first after a failure`),Z(`ReactiveSequence`,`control`,`As Sequence, but ticks again from the first child each time: conditions are checked while an action runs`),Z(`SequenceWithMemory`,`control`,`As Sequence, but resumes from the child that failed`,[],4),Z(`SequenceStar`,`control`,`As Sequence, but resumes from the child that failed`,[],3),Z(`Fallback`,`control`,`Ticks its children in order until one succeeds`),Z(`ReactiveFallback`,`control`,`As Fallback, but ticks again from the first child each time`),Z(`Parallel`,`control`,`Ticks all its children at once, until enough succeed or fail`,[X(`success_count`,`int`,`Successes needed to succeed; -1: all`,`-1`),X(`failure_count`,`int`,`Failures needed to fail; -1: all`,`1`)],4),Z(`Parallel`,`control`,`Ticks all its children at once, until enough succeed or fail`,[X(`success_threshold`,`int`,`Successes needed to succeed; -1: all`),X(`failure_threshold`,`int`,`Failures needed to fail; -1: all`,`1`)],3),Z(`ParallelAll`,`control`,`Ticks all its children at once until they are all done`,[X(`max_failures`,`int`,`Failures that make it fail; -1: all`,`1`)],4),Z(`IfThenElse`,`control`,`Ticks its second child if its first succeeds, else its third`),Z(`WhileDoElse`,`control`,`Reactive: ticks its second child while its first succeeds, else its third`),...[2,3,4,5,6].map(e=>Z(`Switch${e}`,`control`,`Ticks the child of the case equal to the variable, else the last (default) of its ${e+1}`,ht(e))),Z(`Inverter`,`decorator`,`Succeeds when its child fails, and fails when it succeeds`),Z(`ForceSuccess`,`decorator`,`Succeeds when its child is done, however it ends`),Z(`ForceFailure`,`decorator`,`Fails when its child is done, however it ends`),Z(`Repeat`,`decorator`,`Ticks its child again each time it succeeds, num_cycles times`,[X(`num_cycles`,`int`,`Times to repeat; -1: forever`)]),Z(`RetryUntilSuccessful`,`decorator`,`Ticks its child again each time it fails, up to num_attempts times`,[X(`num_attempts`,`int`,`Attempts; -1: forever`)]),Z(`KeepRunningUntilFailure`,`decorator`,`Ticks its child again each time it succeeds, until it fails`),Z(`Delay`,`decorator`,`Ticks its child after a delay`,[X(`delay_msec`,`unsigned int`,`The delay, ms`)]),Z(`Timeout`,`decorator`,`Halts its child, and fails, if it runs longer than msec`,[X(`msec`,`unsigned int`,`The time allowed, ms`)]),Z(`RunOnce`,`decorator`,`Ticks its child once only; then returns what it returned, or skips`,[X(`then_skip`,`bool`,`Skips once done, else returns its result again`,`true`)],4),Z(`Precondition`,`decorator`,`Ticks its child if the script is true, else returns else`,[X(`if`,`std::string`,`The condition, a script`),X(`else`,`NodeStatus`,`What it returns if the condition is false`,`FAILURE`)],4),Z(`SkipUnlessUpdated`,`decorator`,`Skips its child unless the blackboard entry changed since its last tick`,[X(`entry`,`std::string`,`The blackboard entry`)],4),Z(`WaitValueUpdate`,`decorator`,`Runs until the blackboard entry changes, then ticks its child`,[X(`entry`,`std::string`,`The blackboard entry`)],4),gt(`Int`,`int`),gt(`Double`,`double`),gt(`String`,`std::string`),gt(`Bool`,`bool`),...[`Int`,`Double`,`String`].map(e=>Z(`BlackboardCheck${e}`,`decorator`,`Ticks its child if the two values are equal, else returns return_on_mismatch`,[X(`value_A`,`std::string`,`A value, or a blackboard entry`),X(`value_B`,`std::string`,`A value, or a blackboard entry`),X(`return_on_mismatch`,`NodeStatus`,`What it returns if they differ`,`FAILURE`)],3)),Z(`AlwaysSuccess`,`action`,`Succeeds`),Z(`AlwaysFailure`,`action`,`Fails`),Z(`Script`,`action`,`Runs a script on the blackboard`,[X(`code`,`std::string`,`The script, e.g. counter += 1`)],4),Z(`SetBlackboard`,`action`,`Writes a value into a blackboard entry`,[X(`value`,`std::string`,`The value, or another entry`),X(`output_key`,`std::string`,`The entry written`,null,`inout`)]),Z(`UnsetBlackboard`,`action`,`Removes a blackboard entry`,[X(`key`,`std::string`,`The entry`)],4),Z(`Sleep`,`action`,`Runs for a while, then succeeds`,[X(`msec`,`unsigned int`,`How long, ms`)],4),Z(`ScriptCondition`,`condition`,`Succeeds if the script is true`,[X(`code`,`std::string`,`The condition, a script`)],4),Z(`WasEntryUpdated`,`condition`,`Succeeds if the blackboard entry changed since its last tick`,[X(`entry`,`std::string`,`The blackboard entry`)],4)];function vt(e){return _t.filter(t=>!t.format||t.format===e).map(({format:e,...t})=>t)}var yt=new Map([..._t.map(e=>[e.id,e.kind]),...[`Sequence`,`SequenceStar`,`SequenceWithMemory`,`ReactiveSequence`,`Fallback`,`ReactiveFallback`,`Parallel`,`ParallelAll`,`IfThenElse`,`WhileDoElse`,`ManualSelector`,`TryCatch`,`AsyncSequence`,`AsyncFallback`,`PipelineSequence`,`RecoveryNode`,`RoundRobin`,`NonblockingSequence`,`PersistentSequence`,`PauseResumeController`].map(e=>[e,`control`]),...[`RetryUntilSuccesful`,`RateController`,`DistanceController`,`SpeedController`,`GoalUpdater`,`PathLongerOnApproach`,`SingleTrigger`,`GoalUpdatedController`].map(e=>[e,`decorator`]),...[`GoalReached`,`GoalUpdated`,`GloballyUpdatedGoal`,`InitialPoseReceived`,`IsStuck`,`TransformAvailable`,`DistanceTraveled`,`TimeExpired`,`IsBatteryLow`,`IsBatteryCharging`,`IsPathValid`,`PathExpiringTimer`,`AreErrorCodesPresent`,`WouldAControllerRecoveryHelp`,`WouldAPlannerRecoveryHelp`,`WouldASmootherRecoveryHelp`].map(e=>[e,`condition`])]),bt=/^(Is|Are|Has|Was|Would|Can|Check)[A-Z]|Condition/;function xt(e,t){return yt.get(e)||(t>1?`control`:t===1?`decorator`:bt.test(e)?`condition`:`action`)}var St={image:{title:`Choose an image of the robot`,none:`No folder nor image here`,icon:`🖼`},"behavior-tree":{title:`Choose a behavior tree of the robot`,none:`No folder nor XML file here`,icon:`🌳`},bag:{title:`Choose a rosbag of the robot`,none:`No folder nor rosbag here`,icon:`🎞`},folder:{title:`Choose a folder of the robot`,none:`No folder here`,icon:`📁`}},Ct={image:{placeholder:`~/pictures/map.png`,accept:`image/*`},"behavior-tree":{placeholder:`package://my_robot/behavior_trees/main.xml`,accept:`.xml,text/xml,application/xml`}};function wt({kind:e,children:t,...n}){let[r,i]=(0,q.useState)(!1),[a,o]=(0,q.useState)(!1),s=(0,q.useRef)(null),c=e===`image`?ze(n.value):null,l=async e=>{if(e){o(!0);try{n.onCommit(await He.uploadFile(e))}catch(t){G(`Could not upload ${e.name}: ${t instanceof Error?t.message:t}`,`error`)}finally{o(!1)}}};return(0,J.jsxs)(`div`,{className:`file-input`,children:[t({...n,placeholder:n.placeholder??Ct[e].placeholder}),(0,J.jsxs)(`div`,{className:`file-input-actions`,children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>i(!0),children:`Browse the robot…`}),(0,J.jsx)(`button`,{type:`button`,className:`button`,disabled:a,onClick:()=>s.current?.click(),children:a?`Uploading…`:`Upload…`}),(0,J.jsx)(`input`,{ref:s,type:`file`,accept:Ct[e].accept,hidden:!0,onChange:e=>{l(e.target.files?.[0]),e.target.value=``}})]}),c&&(0,J.jsx)(`img`,{className:`file-input-preview`,src:c,alt:``,onError:e=>e.currentTarget.hidden=!0},c),r&&(0,J.jsx)(Tt,{kind:e,start:n.value,onChoose:e=>{i(!1),n.onCommit(e)},onClose:()=>i(!1)})]})}function Tt({kind:e,start:t,onChoose:n,onClose:r}){let[i,a]=(0,q.useState)(()=>!t.startsWith(`/`)&&!t.startsWith(`~/`)?`~`:e!==`folder`&&/\.[A-Za-z0-9]+$/.test(t)?t.replace(/\/[^/]*$/,``)||`/`:t),[o,s]=(0,q.useState)(null),[c,l]=(0,q.useState)(null),[u,d]=(0,q.useState)(null),f=(0,q.useRef)(!1),{title:p,none:m,icon:h}=St[e],g=e===`image`,_=e===`folder`;(0,q.useEffect)(()=>{let t=!0;return l(null),d(null),He.listFiles(i,e).then(e=>{t&&(f.current=!0,s(e))},e=>{t&&(l(e instanceof Error?e.message:String(e)),!f.current&&i!==`~`&&a(_&&i.lastIndexOf(`/`)>0?i.replace(/\/[^/]*$/,``):`~`))}),()=>{t=!1}},[i,e,_]);let v=e=>`${o.dir.replace(/\/$/,``)}/${e}`,y=_?o?.dir??null:u;return(0,J.jsx)(Ge,{title:p,onClose:r,wide:!0,resizable:!0,children:(0,J.jsxs)(`div`,{className:`modal-body file-browser`,children:[(0,J.jsxs)(`div`,{className:`file-browser-path`,children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,disabled:!o?.parent,onClick:()=>o?.parent&&a(o.parent),children:`Up`}),(0,J.jsx)(`code`,{children:o?.dir??i})]}),c&&(0,J.jsx)(`p`,{className:`field-help error`,children:c}),(0,J.jsxs)(`div`,{className:`file-browser-body${g?``:` single`}`,children:[(0,J.jsxs)(`ul`,{className:`file-browser-list`,children:[o?.entries.length===0&&(0,J.jsx)(`li`,{className:`file-browser-empty`,children:m}),o?.entries.map(e=>(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,title:e.name,className:`file-browser-entry${u===v(e.name)?` selected`:``}`,onClick:()=>e.kind===`dir`?a(v(e.name)):d(v(e.name)),onDoubleClick:()=>e.kind!==`dir`&&n(v(e.name)),children:[(0,J.jsx)(`span`,{"aria-hidden":`true`,children:e.kind===`dir`?`📁`:h}),e.name]})},e.name))]}),g&&(0,J.jsx)(`div`,{className:`file-browser-preview`,children:u?(0,J.jsx)(`img`,{src:ze(u)??``,alt:u}):(0,J.jsx)(`span`,{children:`Select an image to preview it`})})]}),(0,J.jsx)(`p`,{className:`file-browser-chosen`,children:y??`Nothing selected`}),(0,J.jsxs)(`div`,{className:`modal-actions`,children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:r,children:`Cancel`}),(0,J.jsx)(`button`,{type:`button`,className:`button primary`,disabled:!y,onClick:()=>y&&n(y),children:_?`Choose this folder`:`Choose`})]})]})})}function Et(e,t){let n=[0],r={left:[...e[0].left],right:[...e[0].right]};for(let i=1;i<e.length;i++){let{left:a,right:o}=e[i],s=-1/0;for(let e=0;e<Math.min(r.right.length,a.length);e++)s=Math.max(s,r.right[e]-a[e]+t);n.push(s);for(let e=0;e<a.length;e++)e<r.left.length?(r.left[e]=Math.min(r.left[e],a[e]+s),r.right[e]=Math.max(r.right[e],o[e]+s)):(r.left.push(a[e]+s),r.right.push(o[e]+s))}return{offsets:n,outline:r}}var Dt=e=>Math.round(e*10)/10;function Ot(e,t,n,r,i,a){let o=(e,t)=>a?`${Dt(t)},${Dt(e)}`:`${Dt(e)},${Dt(t)}`;if(Math.abs(n-e)<.5)return`M${o(t,e)}L${o(r,n)}`;let s=Math.min(6,Math.abs(n-e)/2,i-t,r-i),c=Math.sign(n-e);return`M${o(t,e)}L${o(i-s,e)}Q${o(i,e)} ${o(i,e+c*s)}L${o(i,n-c*s)}Q${o(i,n)} ${o(i+s,n)}L${o(r,n)}`}function kt(e,t,n,r,i){let a=r===`vertical`,o=e=>a?n(e).width:n(e).height,s=e=>a?n(e).height:n(e).width,c=new Map,l=new Map,u=[],d=(e,n)=>{l.set(e,n),u[n]=Math.max(u[n]??0,s(e));let r=o(e)/2,a=t(e);if(a.length===0)return{left:[-r],right:[r]};let f=Et(a.map(e=>d(e,n+1)),i.siblings),p=(f.offsets[0]+f.offsets[f.offsets.length-1])/2;return a.forEach((e,t)=>c.set(e,f.offsets[t]-p)),{left:[-r,...f.outline.left.map(e=>e-p)],right:[r,...f.outline.right.map(e=>e-p)]}};if(e.length===0)return{boxes:new Map,links:[],width:0,height:0};let f=Et(e.map(e=>d(e,0)),i.siblings*2);e.forEach((e,t)=>c.set(e,f.offsets[t]));let p=Math.min(...f.outline.left),m=Math.max(...f.outline.right)-p,h=[],g=0;for(let e of u)h.push(g),g+=e+i.levels;g-=i.levels;let _=new Map,v=[],y=(e,r)=>{let o=r+c.get(e),s=l.get(e),{width:u,height:d}=n(e),f=o-p,m=a?{x:f-u/2,y:h[s],width:u,height:d}:{x:h[s],y:f-d/2,width:u,height:d};_.set(e,m);let g=t(e);if(g.length===0)return;let b=h[s+1]-i.levels/2;for(let t of g){y(t,o);let n=_.get(t);v.push({parent:e,child:t,d:a?Ot(f,m.y+d,n.x+n.width/2,n.y,b,!0):Ot(f,m.x+u,n.y+n.height/2,n.x,b,!1)})}};return e.forEach(e=>y(e,0)),{boxes:_,links:v,width:a?m:g,height:a?g:m}}var At={received:!1,version:0,treeId:``,nodes:[],treeSize:0,children:[],depths:[],states:[],transitions:[],nextId:0,error:null,warnings:[],mismatch:null};function jt(e,t){return e.received&&e.treeId===t.treeId&&e.treeSize===t.nodes.length&&t.nodes.every((t,n)=>{let r=e.nodes[n];return r.name===t.name&&r.type===t.type&&r.parent===t.parent&&JSON.stringify(r.ports)===JSON.stringify(t.ports)})}function Mt(e,t){let n=t.map(()=>[]),r=[];return t.forEach((e,t)=>{r.push(e.parent<0?0:r[e.parent]+1),e.parent>=0&&n[e.parent].push(t)}),{...e,nodes:t,children:n,depths:r}}function Nt(e,t){switch(t.type){case`reset`:return{...At,version:e.version+1};case`tree`:{let{treeId:n,nodes:r,error:i,warnings:a}=t.tree;return jt(e,t.tree)?{...e,error:i,warnings:a}:Mt({...At,received:!0,version:e.version+1,treeId:n,treeSize:r.length,error:i,warnings:a},r)}case`update`:{let{reset:n,added:r,states:i,transitions:a,mismatch:o}=t.update,s=e;(n||r.length>0)&&(s=Mt(e,[...e.nodes.slice(0,n?e.treeSize:void 0),...r]));let c=n?[]:[...e.states];for(let e of i)c[e.node]=e;let l=a.map((t,n)=>({...t,id:e.nextId+n}));return{...s,states:c,transitions:(n?l:[...e.transitions,...l]).slice(-500),nextId:e.nextId+a.length,mismatch:o}}}}function Pt(e){switch(e){case`RUNNING`:return`running`;case`SUCCESS`:return`success`;case`FAILURE`:return`failure`;case`SKIPPED`:return`skipped`;default:return`idle`}}function Ft(e){return e.charAt(0)+e.slice(1).toLowerCase()}function It(e,t=e=>e){let n=new Set;return e.states.forEach((r,i)=>{r?.status===`RUNNING`&&!e.children[i].some(t=>e.states[t]?.status===`RUNNING`)&&n.add(t(i))}),[...n]}function Lt(e){return e.name===e.type?e.type:`${e.type} · ${e.name}`}function Rt(e){let t=Math.max(0,Math.round(e/1e3));return t<60?`${t} s`:t<3600?`${Math.floor(t/60)} min ${t%60} s`:`${Math.floor(t/3600)} h ${Math.floor(t%3600/60)} min`}function zt(e){let t=new Date(e),n=(e,t=2)=>String(e).padStart(t,`0`);return`${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}.${n(t.getMilliseconds(),3)}`}var Bt=.1,Vt=2.5,Ht=.55,Ut=16,Wt=54,Gt=5,Kt=24,qt=280,Jt=36,Yt=14,Xt=()=>window.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches??!1;function Zt(e){let{layout:t,root:n,vertical:r,covered:i,version:a}=e,o=(0,q.useRef)(e);o.current=e;let s=(0,q.useRef)(null),c=(0,q.useRef)(null),l=(0,q.useRef)(null),u=(0,q.useRef)(!1),d=(0,q.useRef)(0),f=(0,q.useRef)(0),p=(0,q.useRef)(new Map),m=(0,q.useRef)(null),h=(0,q.useRef)(null),g=(0,q.useCallback)(()=>{let e=l.current,t=c.current,n=s.current;if(!e||!t||!n)return;t.style.transform=`translate(${e.x}px, ${e.y}px) scale(${e.k})`;let r=Kt*e.k;for(;r<12;)r*=2;n.style.backgroundSize=`${r}px ${r}px`,n.style.backgroundPosition=`${e.x}px ${e.y}px`},[]),_=()=>{cancelAnimationFrame(d.current),d.current=0},v=(0,q.useCallback)(e=>{_();let t=l.current;if(!t||Xt()){l.current=e,g();return}let n=performance.now(),r=i=>{let a=Math.min(1,(i-n)/qt),o=1-(1-a)**3;l.current={x:t.x+(e.x-t.x)*o,y:t.y+(e.y-t.y)*o,k:t.k+(e.k-t.k)*o},g(),d.current=a<1?requestAnimationFrame(r):0};d.current=requestAnimationFrame(r)},[g]),y=(0,q.useCallback)(e=>{let i=s.current;if(!i||t.width===0)return;let[a,o]=[i.clientWidth,i.clientHeight],c=Math.min(1,Math.max(Bt,Math.min((a-32)/t.width,(o-Wt-Ut)/t.height)));u.current=!1,_();let d=n===void 0?void 0:t.boxes.get(n);if(e||c>=Ht||!d)l.current={k:c,x:(a-t.width*c)/2,y:Wt+Math.max(0,(o-Wt-Ut-t.height*c)/2)};else{let e=Ht;l.current=r?{k:e,x:a/2-(d.x+d.width/2)*e,y:Wt}:{k:e,x:Ut,y:(Wt+o)/2-(d.y+d.height/2)*e}}g()},[t,n,r,g]),b=(0,q.useCallback)((e,n)=>{let r=s.current,a=l.current,o=e.flatMap(e=>t.boxes.get(e)??[]);if(!r||!a||o.length===0)return;u.current=!0;let c=Math.min(...o.map(e=>e.x)),d=Math.min(...o.map(e=>e.y)),f=Math.max(...o.map(e=>e.x+e.width)),p=Math.max(...o.map(e=>e.y+e.height)),m=r.clientWidth-i,h=r.clientHeight,{x:g,y:_,k:y}=a;c*y+g>=Ut&&f*y+g<=m-Ut&&d*y+_>=Wt&&p*y+_<=h-Ut&&!n||v({k:y,x:m/2-(c+f)/2*y,y:(Wt+h-Ut)/2-(d+p)/2*y})},[t,i,v]),x=(0,q.useCallback)(e=>{let n=t.boxes.get(e),r=l.current;n&&r&&(h.current={node:e,x:n.x*r.k+r.x,y:n.y*r.k+r.y})},[t]),S=(0,q.useCallback)(e=>{let t=s.current,n=l.current;if(!t||!n)return null;let r=t.getBoundingClientRect();return e.x<r.left||e.x>r.right||e.y<r.top||e.y>r.bottom?null:{x:(e.x-r.left-n.x)/n.k,y:(e.y-r.top-n.y)/n.k}},[]);(0,q.useLayoutEffect)(()=>{u.current=!1},[a]),(0,q.useLayoutEffect)(()=>{let e=h.current;h.current=null;let n=e&&t.boxes.get(e.node);if(e&&n&&l.current){let{k:t}=l.current;l.current={k:t,x:e.x-n.x*t,y:e.y-n.y*t},g()}else(!l.current||!u.current)&&y(!1)},[t,y,g]),(0,q.useEffect)(()=>{let e=s.current;if(!e)return;let t=new ResizeObserver(()=>u.current?g():y(!1));return t.observe(e),()=>t.disconnect()},[y,g]),(0,q.useEffect)(()=>()=>{_(),cancelAnimationFrame(f.current)},[]);let C=(0,q.useCallback)((e,t)=>{let n=l.current;if(!n)return;_();let r=Math.min(Vt,Math.max(Bt,n.k*t));l.current={k:r,x:e.x-(e.x-n.x)*r/n.k,y:e.y-(e.y-n.y)*r/n.k},u.current=!0,g()},[g]);(0,q.useEffect)(()=>{let e=s.current;if(!e)return;let t=t=>{t.preventDefault();let n=e.getBoundingClientRect();C({x:t.clientX-n.left,y:t.clientY-n.top},Math.exp(-t.deltaY*.0015))};return e.addEventListener(`wheel`,t,{passive:!1}),()=>e.removeEventListener(`wheel`,t)},[C]);let w=()=>{cancelAnimationFrame(f.current);let e=m.current,t=s.current,n=l.current;if(e?.kind!==`drag`||!t||!n)return;let r=t.getBoundingClientRect(),i=(e,t,n)=>n<e+Jt?Yt*(e+Jt-n)/Jt:n>t-Jt?-14*(n-t+Jt)/Jt:0,a=i(r.left,r.right,e.client.x),c=i(r.top,r.bottom,e.client.y);if(a===0&&c===0)return;l.current={...n,x:n.x+Math.max(-14,Math.min(Yt,a)),y:n.y+Math.max(-14,Math.min(Yt,c))},u.current=!0,g();let d=S(e.client);d&&o.current.onDragMove?.(d),f.current=requestAnimationFrame(w)},T=e=>{let t=s.current.getBoundingClientRect();return{x:e.clientX-t.left,y:e.clientY-t.top}},E=()=>{let[e,t]=[...p.current.values()];return{distance:Math.hypot(e.x-t.x,e.y-t.y),centre:{x:(e.x+t.x)/2,y:(e.y+t.y)/2}}},D=(e,t)=>{cancelAnimationFrame(f.current),o.current.onDragEnd?.(e?S({x:t.clientX,y:t.clientY}):null)},ee=e=>{if(e.pointerType===`mouse`&&e.button!==0)return;_(),e.currentTarget.setPointerCapture(e.pointerId);let t=T(e);p.current.set(e.pointerId,t),p.current.size===2?(m.current?.kind===`drag`&&D(!1,e),m.current={kind:`pinch`,...E()}):p.current.size===1&&(m.current={kind:`press`,start:t,target:e.target})},O=e=>{let t=p.current.get(e.pointerId),n=l.current;if(!t||!n)return;let r=T(e);p.current.set(e.pointerId,r);let i=m.current;i?.kind===`press`&&Math.hypot(r.x-i.start.x,r.y-i.start.y)>Gt&&(o.current.onDragStart?.(i.target)?m.current={kind:`drag`,client:{x:e.clientX,y:e.clientY}}:(m.current={kind:`pan`},o.current.onPan()));let a=m.current;if(a?.kind===`drag`){a.client={x:e.clientX,y:e.clientY};let t=S(a.client);t&&o.current.onDragMove?.(t),w()}else if(a?.kind===`pan`)l.current={...n,x:n.x+r.x-t.x,y:n.y+r.y-t.y},u.current=!0,g();else if(a?.kind===`pinch`&&p.current.size===2){let e=E();l.current={...n,x:n.x+e.centre.x-a.centre.x,y:n.y+e.centre.y-a.centre.y},C(e.centre,e.distance/(a.distance||1)),m.current={kind:`pinch`,...e},o.current.onPan()}},k=e=>{if(!p.current.delete(e.pointerId))return;let t=m.current;t?.kind===`press`&&e.type===`pointerup`?o.current.onTap(t.target):t?.kind===`drag`&&D(e.type===`pointerup`,e),p.current.size===1?m.current={kind:`pan`}:p.current.size===0&&(m.current=null)},A=(0,q.useCallback)(()=>{m.current?.kind===`drag`&&(m.current=null,cancelAnimationFrame(f.current),o.current.onDragEnd?.(null))},[]);return{viewportRef:s,layerRef:c,handlers:{onPointerDown:ee,onPointerMove:O,onPointerUp:k,onPointerCancel:k},fit:y,reveal:b,keepInPlace:x,toLayout:S,cancelDrag:A}}function Qt(e){switch(e.kind){case`control`:return/Sequence/.test(e.type)?Te:/Fallback/.test(e.type)?L:/Parallel/.test(e.type)?r:/Recovery|Retry/.test(e.type)?ae:C;case`decorator`:return/Retry|Repeat|Loop/.test(e.type)?ae:Pe;case`action`:return Oe;case`condition`:return be;case`subtree`:return u;default:return null}}function $t({node:e,size:t=14}){let n=Qt(e);return n&&(0,J.jsx)(n,{className:`bt-kind`,width:t,height:t})}function Q(e){return e.kind?e.kind.charAt(0).toUpperCase()+e.kind.slice(1):`Not in the tree file`}var en=40,tn=15,nn=11,rn=45,an=88,on=240,sn=320,cn={siblings:18,levels:46},ln=null;function un(e,t){return ln??=document.createElement(`canvas`).getContext(`2d`),ln?(ln.font=t,ln.measureText(e).width):e.length*7}function dn(e,t){let n=getComputedStyle(document.documentElement),r=getComputedStyle(document.body).fontFamily,i=n.getPropertyValue(`--mono`).trim()||`monospace`;return e.map(e=>{let n=Math.max(un(e.type,`650 12px ${r}`),e.name===e.type?0:un(e.name,`11px ${r}`)),a=Math.min(on,Math.max(an,Math.ceil(n+rn))),o=en,s=t?Object.entries(e.ports):[];if(s.length>0){let e=Math.max(...s.map(([e,t])=>un(`${e} ${t}`,`10.5px ${i}`)));a=Math.max(a,Math.min(sn,Math.ceil(e+24))),o+=s.length*tn+nn}return{width:a,height:o}})}var fn={running:`240 160 32`,success:`47 191 113`,failure:`240 82 82`,skipped:`139 149 167`,idle:`139 149 167`},pn=(0,q.memo)(function({index:e,node:t,box:n,state:r,selected:i,showPorts:a,vertical:o,folded:s,foldedRunning:c}){let l=(0,q.useRef)(null),u=r?.changes??0,d=(0,q.useRef)(u),f=Pt(r?.status),p=f===`idle`&&r?.result?Pt(r.result):null;(0,q.useEffect)(()=>{if(u!==d.current&&(d.current=u,!Xt())){let e=fn[p??f];l.current?.animate?.([{boxShadow:`0 0 0 0 rgb(${e} / 60%)`},{boxShadow:`0 0 0 8px rgb(${e} / 0%)`}],{duration:500,easing:`ease-out`})}},[u,f,p]);let m=a?Object.entries(t.ports):[],h=`${Q(t)}: ${t.type}${t.name===t.type?``:` “${t.name}”`}${r?.status?` · ${Ft(r.status)}`:``}`;return(0,J.jsxs)(`div`,{ref:l,"data-node":e,className:`bt-node ${f}${p?` was-${p}`:``}${i?` selected`:``}`,style:{left:n.x,top:n.y,width:n.width,height:n.height},title:h,children:[(0,J.jsxs)(`div`,{className:`bt-node-head`,children:[(0,J.jsx)($t,{node:t}),(0,J.jsxs)(`div`,{className:`bt-node-labels`,children:[(0,J.jsx)(`span`,{className:`bt-node-type`,children:t.type}),t.name!==t.type&&(0,J.jsx)(`span`,{className:`bt-node-name`,children:t.name})]})]}),m.length>0&&(0,J.jsx)(`dl`,{className:`bt-node-ports`,children:m.map(([e,t])=>(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:e}),(0,J.jsx)(`dd`,{className:/^\{.*\}$/.test(t)?`entry`:void 0,children:t})]},e))}),s>=0&&(0,J.jsx)(`span`,{"data-fold":e,className:`bt-fold${o?``:` side`}${c?` running`:``}`,title:s===0?`Fold its children away`:`Show its children`,children:s===0?`−`:`+${s}`})]})}),mn=(0,q.memo)(function({links:e,running:t,width:n,height:r}){let i=new Set(t?t.split(`,`).map(Number):[]),a=[...e.filter(e=>!i.has(e.child)),...e.filter(e=>i.has(e.child))];return(0,J.jsx)(`svg`,{className:`bt-links`,width:n,height:r,"aria-hidden":`true`,children:a.map(e=>(0,J.jsx)(`path`,{d:e.d,className:i.has(e.child)?`running`:void 0},e.child))})});function hn({model:e,direction:t,showPorts:n,folded:r,selected:i,follow:a,focus:o,fitRequest:s,covered:c,onSelect:l,onFold:u,onPan:d}){let f=t===`vertical`,{nodes:p,treeSize:m,children:h,states:g}=e,_=(0,q.useMemo)(()=>p.slice(0,m).flatMap((e,t)=>e.parent<0?[t]:[]),[p,m]),v=(0,q.useMemo)(()=>dn(p.slice(0,m),n),[p,m,n]),y=(0,q.useMemo)(()=>kt(_,e=>r.has(e)?[]:h[e],e=>v[e],t,cn),[_,h,r,v,t]),b=(0,q.useMemo)(()=>{let e=Array(m).fill(1);for(let t=m-1;t>0;t--){let n=p[t].parent;n>=0&&(e[n]+=e[t])}return e},[p,m]),x=(0,q.useCallback)(e=>{let t=e;for(let n=p[e].parent;n>=0;n=p[n].parent)r.has(n)&&(t=n);return t},[p,r]),S=It(e,x).filter(e=>e<m).join(`,`),C=g.flatMap((e,t)=>e?.status===`RUNNING`&&t<m?[t]:[]).join(`,`),w=(0,q.useRef)(()=>{}),{viewportRef:T,layerRef:E,handlers:D,fit:ee,reveal:O,keepInPlace:k}=Zt({layout:y,root:_[0],vertical:f,covered:c,version:e.version,onTap:e=>{let t=e.closest(`[data-fold]`),n=e.closest(`[data-node]`);if(t){let e=Number(t.getAttribute(`data-fold`));w.current(e),u(e)}else l(n?Number(n.getAttribute(`data-node`)):null)},onPan:d});return w.current=k,(0,q.useEffect)(()=>{a&&S&&O(S.split(`,`).map(Number),!1)},[a,S,O]),(0,q.useEffect)(()=>{o&&O([x(o.node)],!0)},[o]),(0,q.useEffect)(()=>{i!==null&&c>0&&O([x(i)],!1)},[i,c]),(0,q.useEffect)(()=>{s>0&&ee(!0)},[s]),(0,J.jsx)(`div`,{ref:T,className:`bt-graph`,...D,children:(0,J.jsxs)(`div`,{ref:E,className:`bt-layer`,style:{width:y.width,height:y.height},children:[(0,J.jsx)(mn,{links:y.links,running:C,width:y.width,height:y.height}),[...y.boxes].map(([e,t])=>(0,J.jsx)(pn,{index:e,node:p[e],box:t,state:g[e],selected:i===e,showPorts:n,vertical:f,folded:h[e].length===0?-1:r.has(e)?b[e]-1:0,foldedRunning:r.has(e)&&h[e].some(e=>g[e]?.status===`RUNNING`)},e))]})})}var gn=/<([A-Za-z_:][-\w:.]*)((?:\s+[A-Za-z_:][-\w:.]*\s*=\s*(?:"[^"]*"|'[^']*'))*)\s*(\/?)>/y,_n=/<\/([A-Za-z_:][-\w:.]*)\s*>/y,vn=/([A-Za-z_:][-\w:.]*)\s*=\s*(?:"([^"]*)"|'([^']*)')/g,yn=/&(?:(lt|gt|amp|quot|apos)|#(\d+)|#x([0-9A-Fa-f]+));/g,bn={lt:`<`,gt:`>`,amp:`&`,quot:`"`,apos:`'`};function xn(e){return e.replace(yn,(e,t,n,r)=>{if(t)return bn[t];let i=n?Number(n):parseInt(r,16);return i<=1114111?String.fromCodePoint(i):e})}function Sn(e){let t=[];for(let n=e.indexOf(`
|
|
3
3
|
`);n!==-1;n=e.indexOf(`
|
|
4
|
-
`,n+1))t.push(n);let n=e=>{let[n,r]=[0,t.length];for(;n<r;){let i=n+r>>1;t[i]<e?n=i+1:r=i}return n+1},r=(e,t)=>{throw Error(`Line ${n(e)}: ${t}`)},i=(t,n,i)=>{let a=e.indexOf(n,t);return a===-1?r(t,`${i} not closed`):a+n.length},a=null,o=[],s=(e,t,n)=>o.at(-1)?.children.push({type:e,start:t,end:n}),c=0;for(;c<e.length;){let t=e.indexOf(`<`,c),l=t===-1?e.length:t,u=e.slice(c,l).search(/\S/);if(u!==-1&&s(`text`,c+u,c+e.slice(c,l).trimEnd().length),t===-1)break;if(c=t,e.startsWith(`<!--`,c))c=i(c+4,`-->`,`Comment`),s(`comment`,t,c);else if(e.startsWith(`<![CDATA[`,c))c=i(c+9,`]]>`,`CDATA section`),s(`text`,t,c);else if(e.startsWith(`<?`,c))c=i(c+2,`?>`,`Processing instruction`),s(`comment`,t,c);else if(e.startsWith(`<!`,c)){let n=0,i=c+2;for(;i<e.length&&(e[i]!==`>`||n>0);i++)n+=e[i]===`[`?1:e[i]===`]`?-1:0;c=i<e.length?i+1:r(c,`Doctype not closed`),s(`comment`,t,c)}else if(e[c+1]===`/`){
|
|
5
|
-
`,t-1)+1,t);return/^[ \t]*$/.test(n)?n:null},r=new Map,i=(t,a)=>{let o=[],s=t.openEnd,c=null;for(let r of t.children){let t=/\n[ \t]*\r?\n/.test(e.slice(s,r.start));c??=n(r.start),o.push(r.type===`element`?i(r,t):{key:
|
|
4
|
+
`,n+1))t.push(n);let n=e=>{let[n,r]=[0,t.length];for(;n<r;){let i=n+r>>1;t[i]<e?n=i+1:r=i}return n+1},r=(e,t)=>{throw Error(`Line ${n(e)}: ${t}`)},i=(t,n,i)=>{let a=e.indexOf(n,t);return a===-1?r(t,`${i} not closed`):a+n.length},a=null,o=[],s=(e,t,n)=>o.at(-1)?.children.push({type:e,start:t,end:n}),c=0;for(;c<e.length;){let t=e.indexOf(`<`,c),l=t===-1?e.length:t,u=e.slice(c,l).search(/\S/);if(u!==-1&&s(`text`,c+u,c+e.slice(c,l).trimEnd().length),t===-1)break;if(c=t,e.startsWith(`<!--`,c))c=i(c+4,`-->`,`Comment`),s(`comment`,t,c);else if(e.startsWith(`<![CDATA[`,c))c=i(c+9,`]]>`,`CDATA section`),s(`text`,t,c);else if(e.startsWith(`<?`,c))c=i(c+2,`?>`,`Processing instruction`),s(`comment`,t,c);else if(e.startsWith(`<!`,c)){let n=0,i=c+2;for(;i<e.length&&(e[i]!==`>`||n>0);i++)n+=e[i]===`[`?1:e[i]===`]`?-1:0;c=i<e.length?i+1:r(c,`Doctype not closed`),s(`comment`,t,c)}else if(e[c+1]===`/`){_n.lastIndex=c;let t=_n.exec(e)??r(c,`Malformed end tag`),n=o.pop();n?.name!==t[1]&&r(c,n?`</${t[1]}> closes <${n.name}> of line ${n.line}`:`</${t[1]}> closes nothing`),c=_n.lastIndex,n.end=c}else{gn.lastIndex=c;let t=gn.exec(e)??r(c,`Malformed tag`),i={};for(let e of t[2].matchAll(vn))i[e[1]]=xn(e[2]??e[3]);let s=t[3]===`/`,l={type:`element`,name:t[1],attributes:i,children:[],line:n(c),start:c,openEnd:gn.lastIndex-(s?2:1),end:gn.lastIndex},u=o.at(-1);u?u.children.push(l):a?r(c,`<${l.name}> after the root element`):a=l,s||o.push(l),c=gn.lastIndex}}if(o.length>0){let e=o.at(-1);throw Error(`Line ${e.line}: <${e.name}> not closed`)}if(!a)throw Error(`No XML element`);return a}var Cn=1;function wn(e){return`name`in e}function Tn(e,t={},n=[]){return{key:Cn++,name:e,attributes:t,children:n,blank:!1,source:null}}function En(e){return{...e,key:Cn++,blank:!1,source:null,children:e.children.map(e=>wn(e)?En(e):{...e,key:Cn++})}}function Dn(e){let t=Sn(e),n=t=>{let n=e.slice(e.lastIndexOf(`
|
|
5
|
+
`,t-1)+1,t);return/^[ \t]*$/.test(n)?n:null},r=new Map,i=(t,a)=>{let o=[],s=t.openEnd,c=null;for(let r of t.children){let t=/\n[ \t]*\r?\n/.test(e.slice(s,r.start));c??=n(r.start),o.push(r.type===`element`?i(r,t):{key:Cn++,kind:r.type,raw:e.slice(r.start,r.end),blank:t}),s=r.end}let l=n(t.start);if(l!==null&&c!==null&&c.length>l.length&&c.startsWith(l)){let e=c.slice(l.length);r.set(e,(r.get(e)??0)+1)}let u={name:t.name,attributes:t.attributes,children:o,text:e.slice(t.start,t.end),open:e.slice(t.start,t.openEnd).trimEnd(),indent:l,childIndent:c};return{key:Cn++,name:t.name,attributes:t.attributes,children:o,blank:a,source:u}},a=i(t,!1),o=[...r].sort((e,t)=>t[1]-e[1])[0]?.[0]??` `;return{prolog:e.slice(0,t.start),root:a,epilog:e.slice(t.end),indent:o,newline:e.includes(`\r
|
|
6
6
|
`)?`\r
|
|
7
7
|
`:`
|
|
8
|
-
`}}var
|
|
9
|
-
`)))return a.text;let s=o?a.open:
|
|
10
|
-
`);return(0,
|
|
8
|
+
`}}var On={"&":`&`,"<":`<`,'"':`"`,"\n":` `,"\r":` `," ":`	`};function kn(e){return e.replace(/[&<"\n\r\t]/g,e=>On[e])}function An(e){return`<${e.name}${Object.entries(e.attributes).map(([e,t])=>` ${e}="${kn(t)}"`).join(``)}`}function jn(e){let{indent:t,newline:n}=e,r=(e,i)=>{let{source:a}=e,o=a!==null&&e.name===a.name&&e.attributes===a.attributes;if(o&&e.children===a.children&&(i===a.indent||!a.text.includes(`
|
|
9
|
+
`)))return a.text;let s=o?a.open:An(e);if(e.children.length===0)return`${s}/>`;if(e.children.every(e=>!wn(e)&&e.kind===`text`))return`${s}>${e.children.map(e=>e.raw).join(` `)}</${e.name}>`;let c=a&&i===a.indent&&a.childIndent!==null?a.childIndent:i+t,l=`${s}>`;for(let t of e.children)l+=`${t.blank?n:``}${n}${c}${wn(t)?r(t,c):t.raw}`;return`${l}${n}${i}</${e.name}>`};return e.prolog+r(e.root,e.root.source?.indent??``)+e.epilog}function Mn(e,t){let n=[],r=e=>{if(e.key===t)return e;n.push(e);for(let t of e.children){let e=wn(t)?r(t):null;if(e)return e}return n.pop(),null},i=r(e.root);return i&&{node:i,ancestors:n}}function Nn(e,t,n){let r=e=>{if(e.key===t)return n(e);let i=!1,a=e.children.map(e=>{let t=wn(e)?r(e):e;return i||=t!==e,t});return i?{...e,children:a}:e},i=r(e.root);return i===e.root?e:{...e,root:i}}function Pn(e,t){let n=e=>{let r=!1,i=e.children.map(e=>{let t=wn(e)?n(e):e;return r||=t!==e,t});return t(r?{...e,children:i}:e)},r=n(e.root);return r===e.root?e:{...e,root:r}}function Fn(e,t,n,r){return Nn(e,t,e=>{if((e.attributes[n]??null)===r)return e;if(r===null){let{[n]:t,...r}=e.attributes;return{...e,attributes:r}}let t=n===`name`&&!(`name`in e.attributes)?{name:r,...e.attributes}:{...e.attributes,[n]:r};return{...e,attributes:t}})}function In(e,t,n,r){return Nn(e,t,e=>{if(n===r||!(n in e.attributes))return e;let t={};for(let[i,a]of Object.entries(e.attributes))i!==r&&(t[i===n?r:i]=a);return{...e,attributes:t}})}function Ln(e,t,n){return Nn(e,t,e=>({...n,key:e.key,blank:e.blank}))}function Rn(e,t,n){return Nn(e,t,e=>({...e,children:n(e.children)}))}function zn(e,t){let n=t;for(;n>0&&!e[n].blank;){let t=e[n-1];if(wn(t)||t.kind!==`comment`)break;n--}return n}function Bn(e,t){let n=0;for(let r=0;r<e.length;r++)if(wn(e[r])&&n++===t)return zn(e,r);return e.length}function Vn(e,t){let n=e.findIndex(e=>e.key===t);if(n===-1)return null;let r=zn(e,n);return{rest:[...e.slice(0,r),...e.slice(n+1)],taken:e.slice(r,n+1)}}function Hn(e,t){let n=Mn(e,t)?.ancestors.at(-1);return n?Rn(e,n.key,e=>Vn(e,t)?.rest??[...e]):e}function Un(e,t,n,r){return Rn(e,t,e=>{let t=Bn(e,n);return[...e.slice(0,t),r,...e.slice(t)]})}function Wn(e,t,n,r){let i=Mn(e,t),a=Mn(e,n),o=i?.ancestors.at(-1);if(!i||!a||!o||n===t||a.ancestors.some(e=>e.key===t))return null;let s=r;o.key===n&&o.children.filter(wn).findIndex(e=>e.key===t)<r&&s--;let c=[];return Rn(Rn(e,o.key,e=>{let n=Vn(e,t);return c=n.taken,n.rest}),n,e=>{let t=Bn(e,s);return[...e.slice(0,t),...c,...e.slice(t)]})}function Gn(e,t,n){let r=Mn(e,t)?.ancestors.at(-1);return r?Rn(e,r.key,e=>e.map(e=>e.key===t?{...n,blank:e.blank,children:[{...e,blank:!1}]}:e)):e}function Kn(e,t){let n=Mn(e,t),r=n?.ancestors.at(-1);if(!n||!r)return e;let{node:i}=n,a=i.children.map((e,t)=>t===0&&i.blank?{...e,blank:!0}:e);return Rn(e,r.key,e=>e.flatMap(e=>e.key===t?a:[e]))}function qn(e){return e.root.children.flatMap(e=>wn(e)&&e.name===`BehaviorTree`?[{key:e.key,id:e.attributes.ID??``,node:e}]:[])}function Jn(e){return e.root.attributes.BTCPP_format?.trim()===`4`?4:3}function Yn(e,t){dt[e.name]===`subtree`&&e.attributes.ID&&t.add(e.attributes.ID);for(let n of e.children)wn(n)&&Yn(n,t);return t}function Xn(e){let t=qn(e),n=e.root.attributes.main_tree_to_execute,r=n?t.find(e=>e.id===n):void 0;if(r)return r;let i=Yn(e.root,new Set);return t.find(e=>!i.has(e.id))??t[0]}function Zn(e){let t=dt[e.name];return t===`subtree`?`SubTree`:t&&e.attributes.ID?e.attributes.ID:e.name}function Qn(e){let t={...e.attributes};delete t.name;let n=dt[e.name];return n&&n!==`subtree`&&delete t.ID,t}function $n(e){let t=e=>({name:e.name,attributes:e.attributes,children:e.children.filter(wn).map(t),text:e.children.flatMap(e=>!wn(e)&&e.kind===`text`?[e.raw]:[]).join(` `)});return mt(t(e.root))}function er(e,t,n){let r=new Map;for(let t of vt(Jn(e)))r.set(t.id,{model:t,library:`BT.CPP`});for(let e of t)for(let t of e.models)r.set(t.id,{model:t,library:e.name});for(let t of $n(e))r.set(t.id,{model:t,library:`This file`});let i=qn(e).flatMap(e=>e.id?[e.id]:[]),a=new Map(n.filter(e=>!i.includes(e.id)).map(e=>[e.id,e.file]));return{byId:r,trees:[...i,...a.keys()],treeFiles:a}}var tr={action:`An action`,condition:`A condition`,control:`A control node`,decorator:`A decorator`,subtree:`A subtree`};function nr(e,t){let n=[],r=[],i=0,a=(e,o)=>{let s=n.length,c=e.children.filter(wn),l={key:e.key,type:`BehaviorTree`,name:e.attributes.ID??``,kind:null,parent:o,ports:{},model:null,capacity:1,problems:[]};if(o>=0){let n=Zn(e),r=t.byId.get(n)??null,i=dt[e.name],a=i===`subtree`?`subtree`:r?.model.kind??i??xt(n,c.length);if(Object.assign(l,{type:n,name:e.attributes.name??(a===`subtree`?e.attributes.ID??n:n),kind:a,ports:Qn(e),model:r,capacity:!r&&!i&&c.length>0||a===`control`?1/0:+(a===`decorator`)}),a===`subtree`){let n=e.attributes.ID;n?t.trees.includes(n)||l.problems.push(`No tree ${n}, in the file nor its includes`):l.problems.push(`No subtree: set its ID`)}}l.capacity===0&&c.length>0?l.problems.push(`${tr[l.kind]} has no children: it has ${c.length}`):l.kind===null&&c.length!==1?l.problems.push(c.length===0?`Empty: a tree runs one node, at its root`:`A tree has one node at its root, not ${c.length}`):l.kind===`decorator`&&c.length!==1?l.problems.push(`A decorator has one child, not ${c.length}`):l.kind===`control`&&c.length===0&&l.model&&l.problems.push(`A control node needs children`),i+=+(l.problems.length>0),n.push(l),r.push([]);for(let e of c)r[s].push(n.length),a(e,s)};return a(e,-1),{nodes:n,children:r,problems:i}}function rr(e,t){return e.kind===`subtree`?Tn(`SubTree`,{ID:e.id,...t===4?{_autoremap:`true`}:{__shared_blackboard:`true`}}):Tn(e.id)}function ir(e,t,n){let r=e.children[t].length-(n!==null&&e.children[t].includes(n)?1:0);return e.nodes[t].capacity>r}function ar(e,t,n){for(let r=t;r>=0;r=e.nodes[r].parent)if(r===n)return!0;return!1}function or(e,t,n,r,i,a=8){let o=-1,s;for(let[e,r]of t)if(n.x>=r.x-a&&n.x<=r.x+r.width+a&&n.y>=r.y-a&&n.y<=r.y+r.height+a){[o,s]=[e,r];break}if(!s||r!==null&&ar(e,o,r))return null;let c=i?(n.x-s.x)/s.width:(n.y-s.y)/s.height,l=e.nodes[o].parent,u=ir(e,o,r),d=l>=0&&ir(e,l,r),f;if(u&&(!d||c>=.3&&c<=.7))f=`into`;else if(d)f=c<.5?`before`:`after`;else return null;if(f===`into`)return{parent:o,index:e.children[o].length,mode:f,node:o};let p=e.children[l].indexOf(o)+ +(f===`after`);if(r!==null&&e.nodes[r].parent===l){let t=e.children[l].indexOf(r);if(p===t||p===t+1)return null}return{parent:l,index:p,mode:f,node:o}}function sr(e,t){let n=t??0;if(ir(e,n,null))return{parent:n,index:e.children[n].length};let r=e.nodes[n].parent;return r>=0&&ir(e,r,null)?{parent:r,index:e.children[r].indexOf(n)+1}:null}function cr(e,t){let n=e.nodes[t].parent;return n<0||e.children[t].length===0?!1:e.nodes[n].capacity>=e.children[n].length-1+e.children[t].length}function lr(e,t){let n=new Set(qn(e).map(e=>e.id)),r=t;for(let e=2;n.has(r);e++)r=`${t}${e}`;return r}function ur(e,t){let n=Tn(`BehaviorTree`,{ID:t}),r=e.root.children.filter(wn).findLastIndex(e=>e.name===`BehaviorTree`)+1;return{document:Un(e,e.root.key,r,n),key:n.key}}function dr(e,t,n){let r=qn(e).find(e=>e.key===t)?.id;if(r===void 0||r===n)return e;let i=Fn(e,t,`ID`,n);return r&&(i=Pn(i,e=>dt[e.name]===`subtree`&&e.attributes.ID===r?{...e,attributes:{...e.attributes,ID:n}}:e),i.root.attributes.main_tree_to_execute===r&&(i=Fn(i,i.root.key,`main_tree_to_execute`,n))),i}function fr(e,t){return Fn(e,e.root.key,`main_tree_to_execute`,t)}function pr(e,t){let n=qn(e).find(e=>e.key===t)?.id,r=Hn(e,t);return n&&r.root.attributes.main_tree_to_execute===n?Fn(r,r.root.key,`main_tree_to_execute`,null):r}function mr(e,t,n){let r=rr(t,n),i={...e.attributes};return dt[e.name]&&delete i.ID,{...e,name:r.name,attributes:{...i,...r.attributes}}}var hr=-1,gr={width:150,height:40},_r=400,vr=22,yr=(0,q.memo)(function({index:e,node:t,box:n,selected:r,showPorts:i,vertical:a,folded:o,dropInto:s,dragged:c}){let l=t.kind===null,d=i?Object.entries(t.ports):[],f=l?`BehaviorTree`:t.type,p=l?t.name||`Unnamed`:t.name===t.type?``:t.name,m=[l?`The tree ${t.name}`:`${Q(t)}: ${t.type}${p?` “${p}”`:``}`,!l&&!t.model&&`Not in the node libraries`,...t.problems].filter(Boolean).join(`
|
|
10
|
+
`);return(0,J.jsxs)(`div`,{"data-node":e,className:`bt-node bte-node${l?` tree`:``}${r?` selected`:``}${t.problems.length>0?` problem`:``}${!l&&!t.model?` unknown`:``}${s?` drop-into`:``}${c?` dragged`:``}`,style:{left:n.x,top:n.y,width:n.width,height:n.height},title:m,children:[(0,J.jsxs)(`div`,{className:`bt-node-head`,children:[l?(0,J.jsx)(u,{className:`bt-kind`,width:14,height:14}):(0,J.jsx)($t,{node:t}),(0,J.jsxs)(`div`,{className:`bt-node-labels`,children:[(0,J.jsx)(`span`,{className:`bt-node-type`,children:f}),p&&(0,J.jsx)(`span`,{className:`bt-node-name`,children:p})]}),t.problems.length>0&&(0,J.jsx)(`span`,{className:`bte-problem`,"aria-label":t.problems.join(`. `),children:`!`})]}),d.length>0&&(0,J.jsx)(`dl`,{className:`bt-node-ports`,children:d.map(([e,t])=>(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:e}),(0,J.jsx)(`dd`,{className:/^\{.*\}$/.test(t)?`entry`:void 0,children:t||`—`})]},e))}),o>=0&&(0,J.jsx)(`span`,{"data-fold":e,className:`bt-fold${a?``:` side`}`,title:o===0?`Fold its children away`:`Show its children`,children:o===0?`−`:`+${o}`})]})});function br({graph:e,version:t,direction:n,showPorts:r,folded:i,selected:a,readOnly:o,focus:s,fitRequest:c,covered:l,onSelect:u,onOpen:d,onFold:f,onMove:p,ref:m}){let h=n===`vertical`,{nodes:g,children:_}=e,v=_[0].length===0,y=(0,q.useMemo)(()=>dn(g,r).map((e,t)=>g[t].problems.length>0?{...e,width:e.width+vr}:e),[g,r]),b=(0,q.useMemo)(()=>kt([0],e=>e===0&&v?[hr]:e>=0&&i.has(g[e].key)?[]:_[e]??[],e=>e===hr?gr:y[e],n,cn),[g,_,v,i,y,n]),x=(0,q.useMemo)(()=>new Map([...b.boxes].filter(([e])=>e!==hr)),[b]),S=(0,q.useMemo)(()=>new Map(g.map((e,t)=>[e.key,t])),[g]),C=(0,q.useMemo)(()=>{let e=Array(g.length).fill(1);for(let t=g.length-1;t>0;t--)e[g[t].parent]+=e[t];return e},[g]),[w,T]=(0,q.useState)(null),E=(0,q.useRef)(null),D=a===null?null:S.get(a)??null,ee=(t,n)=>{let r=b.boxes.get(hr);return r&&t.x>=r.x&&t.x<=r.x+r.width&&t.y>=r.y&&t.y<=r.y+r.height?{parent:0,index:0,mode:`into`,node:0}:or(e,x,t,n,h)},O=(0,q.useRef)(()=>{}),k=Zt({layout:b,root:0,vertical:h,covered:l,version:t,onTap:e=>{let t=e.closest(`[data-fold]`),n=e.closest(`[data-node]`);if(t){let e=Number(t.getAttribute(`data-fold`));O.current(e),f(g[e].key);return}if(!n){E.current=null,u(null);return}let r=Number(n.getAttribute(`data-node`)),i=performance.now();E.current?.node===r&&i-E.current.time<_r?(E.current=null,d(g[r].key)):(E.current={node:r,time:i},u(g[r].key))},onPan:()=>{},onDragStart:e=>{let t=e.closest(`[data-node]`),n=t?Number(t.getAttribute(`data-node`)):0;return o||n<=0?!1:(T({node:n,target:null,at:null}),!0)},onDragMove:e=>T(t=>t&&{...t,target:ee(e,t.node),at:e}),onDragEnd:e=>{let t=w?.node;T(null);let n=e&&t!==void 0?ee(e,t):null;t!==void 0&&n&&p(g[t].key,n)}});O.current=k.keepInPlace,(0,q.useImperativeHandle)(m,()=>({dragNew:e=>{let t=e&&k.toLayout(e),n=t?ee(t,null):null;return T(e?{node:-1,target:n,at:null}:null),n}}),[k.toLayout,e,x,b,h]),(0,q.useEffect)(()=>{if(!w)return;let e=e=>e.key===`Escape`&&(k.cancelDrag(),T(null));return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[w!==null,k.cancelDrag]),(0,q.useEffect)(()=>{let e=s&&S.get(s.key);e!=null&&k.reveal([A(e)],!1)},[s]),(0,q.useEffect)(()=>{D!==null&&l>0&&k.reveal([A(D)],!1)},[D,l]),(0,q.useEffect)(()=>{c>0&&k.fit(!0)},[c]);function A(e){let t=e;for(let n=g[e].parent;n>=0;n=g[n].parent)i.has(g[n].key)&&(t=n);return t}let j=w?.target??null,M=null;if(j&&j.mode!==`into`){let e=b.boxes.get(j.node),t=cn.siblings/2;M=h?{x:j.mode===`before`?e.x-t-2:e.x+e.width+t-2,y:e.y,width:4,height:e.height}:{x:e.x,y:j.mode===`before`?e.y-t-2:e.y+e.height+t-2,width:e.width,height:4}}let te=b.boxes.get(hr),N=w&&w.node>0&&w.at?b.boxes.get(w.node):void 0;return(0,J.jsx)(`div`,{ref:k.viewportRef,className:`bt-graph bte-graph${w?` dragging`:``}`,...k.handlers,children:(0,J.jsxs)(`div`,{ref:k.layerRef,className:`bt-layer`,style:{width:b.width,height:b.height},children:[(0,J.jsx)(mn,{links:b.links.filter(e=>e.child!==hr),running:``,width:b.width,height:b.height}),te&&(0,J.jsx)(`div`,{className:`bte-slot${j?.node===0?` drop-into`:``}`,style:{left:te.x,top:te.y,width:te.width,height:te.height},children:o?`Empty`:`Add a node from the palette`}),[...x].map(([e,t])=>(0,J.jsx)(yr,{index:e,node:g[e],box:t,selected:D===e,showPorts:r,vertical:h,folded:_[e].length===0||e===0?-1:i.has(g[e].key)?C[e]-1:0,dropInto:j?.mode===`into`&&j.node===e&&e!==0,dragged:w?.node===e},g[e].key)),M&&(0,J.jsx)(`div`,{className:`bte-drop-bar`,style:{left:M.x,top:M.y,width:M.width,height:M.height}}),N&&w?.at&&(0,J.jsx)(`div`,{className:`bt-node bte-ghost${j?``:` nowhere`}`,style:{left:w.at.x-N.width/2,top:w.at.y-N.height/2,width:N.width,height:N.height},children:(0,J.jsxs)(`div`,{className:`bt-node-head`,children:[(0,J.jsx)($t,{node:g[w.node]}),(0,J.jsx)(`div`,{className:`bt-node-labels`,children:(0,J.jsx)(`span`,{className:`bt-node-type`,children:g[w.node].type})})]})})]})})}var xr=[.1,.25,.5,1,2,4,8,16],Sr=120;function Cr(e){return e.playing?Math.min(e.end,e.time+(Date.now()-e.at)*e.speed):e.time}function wr(e){let t=Math.max(0,Math.floor(e/1e3)),n=e=>String(e).padStart(2,`0`),r=Math.floor(t/3600),i=Math.floor(t%3600/60);return r?`${r}:${n(i)}:${n(t%60)}`:`${i}:${n(t%60)}`}function Tr(e){return e.replace(/\/+$/,``).replace(/^.*\//,``)||e}function Er(e){let t=new Date,n=e=>String(e).padStart(2,`0`),r=`${t.getFullYear()}-${n(t.getMonth()+1)}-${n(t.getDate())}`,i=`${n(t.getHours())}-${n(t.getMinutes())}-${n(t.getSeconds())}`;return`${e.trim().replace(/\/+$/,``)||`~`}/behavior_tree_${r}_${i}`}function Dr({topic:e,folder:t,onRecording:n,onClose:r}){let i=(0,q.useId)(),[a,o]=(0,q.useState)(()=>Er(t)),[s,c]=(0,q.useState)(!1),[l,u]=(0,q.useState)(!1),[d,f]=(0,q.useState)(null),p=async()=>{u(!0),f(null);try{let t=await H.recordBehaviorTree(e,a.trim());G(`Recording ${e} into ${t}`),n(t??a),r()}catch(e){f(e instanceof Error?e.message:String(e)),u(!1)}};return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(Ge,{title:`Record the tree’s log`,onClose:r,wide:!0,children:(0,J.jsxs)(`form`,{className:`modal-body`,onSubmit:e=>{e.preventDefault(),p()},children:[(0,J.jsxs)(`p`,{className:`dialog-message`,children:[`A rosbag of `,(0,J.jsx)(`code`,{children:e}),`, recorded on the robot (ros2 bag record) until you stop it: to play back here, or with the ROS tools.`]}),(0,J.jsxs)(`div`,{className:`field`,children:[(0,J.jsx)(`label`,{className:`field-label`,htmlFor:i,children:`Into`}),(0,J.jsxs)(`div`,{className:`bt-record-path`,children:[(0,J.jsx)(`input`,{id:i,value:a,spellCheck:!1,onChange:e=>o(e.target.value),autoFocus:!0}),(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>c(!0),children:`Browse…`})]}),(0,J.jsx)(`p`,{className:`field-help`,children:`A new folder, which the recording makes: /…, ~/…`}),d&&(0,J.jsx)(`p`,{className:`field-help error`,children:d})]}),(0,J.jsxs)(`div`,{className:`modal-actions`,children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:r,children:`Cancel`}),(0,J.jsx)(`button`,{type:`submit`,className:`button primary`,disabled:l||!a.trim(),children:l?`Starting…`:`Record`})]})]})}),s&&(0,J.jsx)(Tt,{kind:`folder`,start:a.replace(/\/[^/]*$/,``)||`~`,onChoose:e=>{c(!1),o(`${e.replace(/\/+$/,``)}/${Tr(a)}`)},onClose:()=>c(!1)})]})}function Or({playback:e,onControl:t,onClose:n}){let[r,i]=(0,q.useState)(null),a=(0,q.useRef)(null),o=(0,q.useRef)(0),s=(0,q.useRef)(null);(0,q.useEffect)(()=>()=>{s.current&&clearTimeout(s.current)},[]);let c=()=>{s.current&&=(clearTimeout(s.current),null),a.current!==null&&(o.current=Date.now(),t({time:a.current}),a.current=null)},l=e=>{i(e),a.current=e;let t=o.current+Sr-Date.now();t<=0?c():s.current??=setTimeout(c,t)},u=()=>{c(),i(null)},{start:d,end:f,playing:p,speed:m,error:h}=e,g=r??Cr(e),_=xr.includes(m)?xr:[...xr,m].sort((e,t)=>e-t);return(0,J.jsxs)(`div`,{className:`bt-playback`,children:[(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,title:p?`Pause`:`Play`,"aria-label":p?`Pause`:`Play`,disabled:f===0,onClick:()=>t({playing:!p}),children:p?(0,J.jsx)(oe,{width:16,height:16}):(0,J.jsx)(de,{width:16,height:16})}),h?(0,J.jsx)(`span`,{className:`bt-playback-error`,title:h,children:h}):(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`input`,{type:`range`,"aria-label":`Where the playback is`,min:d,max:Math.max(f,d+1),step:`any`,value:g,disabled:f===0,onChange:e=>l(Number(e.target.value)),onPointerUp:u,onKeyUp:u,onBlur:()=>r!==null&&u()}),(0,J.jsxs)(`span`,{className:`bt-playback-time`,children:[wr(g-d),` / `,wr(f-d)]}),(0,J.jsx)(`select`,{"aria-label":`Speed`,title:`Speed`,value:m,onChange:e=>t({speed:Number(e.target.value)}),children:_.map(e=>(0,J.jsxs)(`option`,{value:e,children:[e,`×`]},e))})]}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,title:`Back to the live log`,"aria-label":`Back to the live log`,onClick:n,children:(0,J.jsx)(B,{width:16,height:16})})]})}function kr(e){return`<?xml version="1.0" encoding="UTF-8"?>
|
|
11
11
|
<root ${e===4?`BTCPP_format="4" `:``}main_tree_to_execute="MainTree">
|
|
12
12
|
<BehaviorTree ID="MainTree">
|
|
13
13
|
<Sequence/>
|
|
14
14
|
</BehaviorTree>
|
|
15
15
|
</root>
|
|
16
|
-
`}function
|
|
17
|
-
`)}function
|
|
18
|
-
`),children:[n[0],n.length>1?` (and ${n.length-1} more)`:``]}),t.map(({path:e,removable:t})=>(0,
|
|
19
|
-
`)?(0,
|
|
20
|
-
`).length+1),onChange:e=>r(e.target.value)}):(0,
|
|
21
|
-
`).map(e=>e.trim()).filter(Boolean)}function
|
|
22
|
-
`);(0,
|
|
23
|
-
`):[]},{file:e=>s({type:`file`,file:e}),models:d})},[o.path,o.opened,de]),(0,Y.useEffect)(()=>{let e=ae.current;if(!e)return;let t=new ResizeObserver(([e])=>D(e.contentRect.width));return t.observe(e),()=>t.disconnect()},[]);let{document:U}=o,fe=U?Cn(U):4,pe=(0,Y.useMemo)(()=>U?Sn(U):[],[U]),me=(0,Y.useMemo)(()=>U?Tn(U):void 0,[U]),W=pe.find(e=>e.key===o.tree)??me,K=(0,Y.useMemo)(()=>U?kn(U,u?.libraries??[],u?.trees??[]):null,[U,u]),q=(0,Y.useMemo)(()=>W&&K?jn(W.node,K):null,[W,K]),ve=(0,Y.useMemo)(()=>new Map(q?.nodes.map((e,t)=>[e.key,t])??[]),[q]),J=f===null?null:ve.get(f)??null,ye=dr(o),be=T>0&&T<Ar,xe=!S&&U!==null&&(ee??!be),Se=T-(xe&&!be?240:0),Ce=!S&&q!==null&&J!==null,we=Ce&&Se-jr>=Mr?jr:0;(0,Y.useEffect)(()=>{h(new Set),ne(e=>e.filter(e=>pe.some(t=>t.key===e)))},[W?.key]);let Te=(0,Y.useMemo)(()=>{if(!K||!U)return[];let e=[...K.byId.values()].map(({model:e,library:t})=>({model:e,library:t})),t=K.trees.filter(e=>e!==W?.id).map(e=>({model:{id:e,kind:`subtree`,ports:[],description:K.treeFiles.has(e)?`In ${K.treeFiles.get(e)}`:`A tree of this file`},library:K.treeFiles.has(e)?er(K.treeFiles.get(e)):`This file`})),n=new Map,r=(e,t)=>{let i=En(e);if(t>1&&i!==`SubTree`&&!K.byId.has(i)&&!n.has(i)){let t=e.children.filter(Qt).length;n.set(i,{model:{id:i,kind:Ye(i,t),ports:[],description:`Used in this file, in no library`},library:`Used here`})}e.children.forEach(e=>Qt(e)&&r(e,t+1))};return pe.forEach(e=>r(e.node,1)),[...e,...t,...n.values()]},[K,U,W?.id,pe]),Ee=e=>{p(e),_(t=>({key:e,seq:(t?.seq??0)+1}))},De=(0,Y.useCallback)((e,t={})=>{s({type:`edit`,document:e,tag:t.tag,tree:t.tree}),t.select!==void 0&&(p(t.select),t.select!==null&&_(e=>({key:t.select,seq:(e?.seq??0)+1})))},[]),Oe=async()=>{if(!U||N||!ye)return;if(o.readOnly){G(`${o.readOnly}: Save as…`,`error`);return}let e=ur(U);P(!0);try{let t=await R.saveBehaviorTreeFile(o.path,e,o.base);t.conflict?(s({type:`conflict`,version:t.version}),G(`Not saved: the file changed on the robot since it was read`,`error`)):(s({type:`saved`,text:e,version:t.version}),G(`Saved ${er(o.path)}`))}catch(e){G(`Could not save ${o.path}: ${e instanceof Error?e.message:e}`,`error`)}finally{P(!1)}},ke=async e=>{(!ye||await le.confirm({title:`Discard the changes?`,message:`${er(o.path)} has changes not saved.`,confirmLabel:`Discard them`,danger:!0}))&&(p(null),ne([]),s({type:`open`,path:e}))},Ae=(e,t)=>{if(!U||!q)return;let n=t??In(q,J);if(!n){G(`Select where it goes: a control node, or a node in one`,`error`);return}let r=Mn(e.model,fe);De(vn(U,q.nodes[n.parent].key,n.index,r),{select:r.key}),be&&k(!1)},je=(e,t)=>{if(!U||!q)return;let n=yn(U,e,q.nodes[t.parent].key,t.index);n&&De(n,{select:e})},Z=q&&J!==null&&J>0?q.nodes[J]:null,Me=Z&&U?sn(U,Z.key)?.node??null:null,Ne=Z&&q?Z.parent:-1,Pe=q&&Ne>=0?q.children[Ne]:[],Fe=Z?Pe.indexOf(J):-1,Ie=q&&Ne>=0?q.nodes[Ne].capacity>Pe.length:!1,Le=()=>{U&&Z&&q&&De(_n(U,Z.key),{select:q.nodes[Ne].key})},Re=()=>{U&&Me&&(Pr=Me,navigator.clipboard?.writeText(Br(U,Me)).catch(()=>{}))},ze=()=>{if(!U||!q||!Pr)return;let e=In(q,J);if(!e){G(`Select where it goes: a control node, or a node in one`,`error`);return}let t=en(Pr);De(vn(U,q.nodes[e.parent].key,e.index,t),{select:t.key})},Be={moveEarlier:Z&&Fe>0?()=>je(Z.key,{parent:Ne,index:Fe-1,mode:`before`,node:Ne}):null,moveLater:Z&&Fe>=0&&Fe<Pe.length-1?()=>je(Z.key,{parent:Ne,index:Fe+2,mode:`after`,node:Ne}):null,duplicate:U&&Me&&Ie&&q?()=>{let e=en(Me);De(vn(U,q.nodes[Ne].key,Fe+1,e),{select:e.key})}:null,wrap:Z?()=>z(`wrap`):null,replace:Z&&Z.kind!==`subtree`?()=>z(`replace`):null,unwrap:U&&Z&&q&&Ln(q,J)?()=>De(xn(U,Z.key),{select:q.nodes[q.children[J][0]].key}):null,remove:Le},Ve=async e=>{let t=pe.find(t=>t.id===e);if(t&&W){ne(e=>[...e,W.key]),p(null),s({type:`tree`,key:t.key});return}let n=K?.treeFiles.get(e);n?await ke(n):G(`No tree ${e}, in the file nor its includes`,`error`)},He=async()=>{if(!U)return;let e=await le.prompt({title:`New tree`,label:`Its ID`,initial:Rn(U,`Subtree`),confirmLabel:`Add`});if(!e)return;if(pe.some(t=>t.id===e)){G(`There is a tree ${e} already`,`error`);return}let t=zn(U,e);p(null),De(t.document,{tree:t.key})},Q=t=>{let n=t.target,r=t.ctrlKey||t.metaKey,i=t.key.toLowerCase();if(r&&i===`s`){t.preventDefault(),Oe();return}if(n.closest(`input, textarea, select, [role="dialog"]`)||!U)return;let a=e=>{t.preventDefault(),e?.()};if(r&&i===`z`)a(()=>s({type:t.shiftKey?`redo`:`undo`}));else if(r&&i===`y`)a(()=>s({type:`redo`}));else if(r&&i===`c`)a(Re);else if(r&&i===`x`)a(Z&&(()=>(Re(),Le())));else if(r&&i===`v`)a(ze);else if(r&&i===`d`)a(Be.duplicate);else if((i===`delete`||i===`backspace`)&&Z)a(Le);else if(i===`escape`)p(null);else if((i===`f2`||i===`enter`)&&Z)a(()=>ae.current?.querySelector(`.bte-properties input`)?.focus());else if(i.startsWith(`arrow`)&&q){let[n,r,o,s]=e.direction===`vertical`?[`arrowup`,`arrowdown`,`arrowleft`,`arrowright`]:[`arrowleft`,`arrowright`,`arrowup`,`arrowdown`],c=J??0;if(t.altKey){a(i===o?Be.moveEarlier:i===s?Be.moveLater:null);return}let l;if(i===n)l=q.nodes[c].parent>=0?q.nodes[c].parent:void 0;else if(i===r)l=m.has(q.nodes[c].key)?void 0:q.children[c][0];else if(c>0){let e=q.children[q.nodes[c].parent];l=e[e.indexOf(c)+(i===o?-1:+(i===s))]}l!==void 0&&a(()=>Ee(q.nodes[l].key))}},$=q?q.nodes.flatMap((e,t)=>e.problems.length>0?[t]:[]):[],Ue=()=>{if(q&&$.length>0){let e=$.find(e=>e>(J??-1))??$[0];Ee(q.nodes[e].key)}},We;We=o.path?S||!U&&o.savedText!==null?(0,X.jsx)(sr,{text:U?ur(U):o.savedText??``,readOnly:!1,onDocument:e=>De(e,{tag:`xml`}),onDone:()=>s({type:`seal`})}):U?q?(0,X.jsx)(Yn,{ref:oe,graph:q,version:`${o.path}#${W?.key}`,direction:e.direction,showPorts:b,folded:m,selected:f,readOnly:!1,focus:g,fitRequest:v,covered:we,onSelect:p,onOpen:e=>{let t=ve.get(e),n=t===void 0?void 0:q.nodes[t];n?.kind===`subtree`&&n.ports.ID?Ve(n.ports.ID):n&&t>0&&ae.current?.querySelector(`.bte-properties input`)?.focus()},onFold:e=>h(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n}),onMove:je}):(0,X.jsxs)(`div`,{className:`widget-message bte-empty`,children:[(0,X.jsx)(`p`,{children:`No BehaviorTree in this file.`}),(0,X.jsx)(`button`,{type:`button`,className:`button primary`,onClick:()=>void He(),children:`Add a tree`})]}):(0,X.jsx)(`div`,{className:`widget-message`,children:o.error??`Reading the tree…`}):(0,X.jsxs)(`div`,{className:`widget-message bte-empty`,children:[(0,X.jsx)(`p`,{children:`No tree file: open one of the robot, or make a new one. Its file can be set in edit mode too.`}),(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>I(`open`),children:`Open…`}),` `,(0,X.jsx)(`button`,{type:`button`,className:`button primary`,onClick:()=>I(`new`),children:`New…`})]})]});let Ge=null;Ce&&U&&q&&K&&J!==null&&(J===0&&W?Ge=(0,X.jsx)(Or,{id:W.id,isMain:me?.key===W.key,trees:pe.filter(e=>e.key!==W.key).map(e=>e.id),problems:q.nodes[0].problems,onRename:e=>De(Bn(U,W.key,e)),onMain:()=>De(Vn(U,W.id)),onRemove:pe.length>1?()=>{p(null),De(Hn(U,W.key),{tree:pe.find(e=>e.key!==W.key).key})}:null,onClose:()=>p(null)}):Z&&Me&&(Ge=(0,X.jsx)(Dr,{node:Z,element:Me,catalog:K,format:fe,actions:Be,onAttribute:(e,t,n)=>De(un(U,Z.key,e,t),n?{tag:`${Z.key}:${e}`}:{}),onRenameAttribute:(e,t)=>De(dn(U,Z.key,e,t)),onSeal:()=>s({type:`seal`}),onOpenTree:e=>void Ve(e),onClose:()=>p(null)},Z.key)));let Ke=[];o.error&&(U||o.savedText!==null)&&Ke.push({text:o.error,tone:`error`}),o.external&&Ke.push({text:o.external.text===null?`Not saved: the file changed on the robot since it was read`:`The file changed on the robot, and this one has changes`,tone:`warning`,actions:[{label:`Load it`,run:()=>s({type:`reload`}),disabled:o.external.text===null},{label:`Keep mine`,run:()=>s({type:`keep`})}]});let qe=o.path?N?{text:`Saving ${er(o.path)}…`,tone:`running`}:ye?{text:`${er(o.path)} · changed`,tone:`changed`}:o.readOnly&&U?{text:`${er(o.path)} · read-only: ${o.readOnly}`,tone:`idle`}:{text:U?`${er(o.path)} · saved`:er(o.path),tone:U?`success`:`idle`}:{text:`No file`,tone:`idle`};return(0,X.jsxs)(`div`,{ref:ae,className:`bt bte`,tabIndex:-1,onKeyDown:Q,children:[Ke.map(e=>(0,X.jsxs)(`div`,{className:`bt-banner ${e.tone} bte-banner`,title:e.text,children:[(0,X.jsx)(`span`,{children:e.text}),e.actions?.map(e=>(0,X.jsx)(`button`,{type:`button`,className:`link-button`,disabled:e.disabled,onClick:()=>{e.run(),ae.current?.focus({preventScroll:!0})},children:e.label},e.label))]},e.text)),(0,X.jsxs)(`div`,{className:`bte-toolbar`,role:`toolbar`,"aria-label":`Editor`,children:[(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":xe,title:`The nodes to add`,"aria-label":`The nodes to add`,disabled:!U||S,onClick:()=>k(!xe),children:(0,X.jsx)(re,{width:17,height:17})}),B.length>0&&(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Back to the tree it was opened from`,"aria-label":`Back`,onClick:()=>{p(null),s({type:`tree`,key:B.at(-1)}),ne(e=>e.slice(0,-1))},children:(0,X.jsx)(O,{width:17,height:17,style:{transform:`scaleX(-1)`}})}),(0,X.jsx)(`select`,{className:`bte-tree-select`,"aria-label":`The tree shown`,value:W?.key??``,disabled:pe.length===0||S,onChange:e=>{p(null),ne([]),s({type:`tree`,key:Number(e.target.value)})},children:pe.map(e=>(0,X.jsxs)(`option`,{value:e.key,children:[e.id||`Unnamed tree`,e.key===me?.key?` (main)`:``]},e.key))}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`New tree`,"aria-label":`New tree`,disabled:!U||S,onClick:()=>void He(),children:(0,X.jsx)(ge,{width:17,height:17})}),(0,X.jsx)(`span`,{className:`overlay-separator`}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Undo (Ctrl+Z)`,"aria-label":`Undo`,disabled:o.past.length===0,onClick:()=>s({type:`undo`}),children:(0,X.jsx)(ce,{width:17,height:17})}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Redo (Ctrl+Shift+Z)`,"aria-label":`Redo`,disabled:o.future.length===0,onClick:()=>s({type:`redo`}),children:(0,X.jsx)(w,{width:17,height:17})}),(0,X.jsx)(`span`,{className:`overlay-separator bte-wide`}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,title:`Fit the tree`,"aria-label":`Fit the tree`,disabled:!q||S,onClick:()=>y(e=>e+1),children:(0,X.jsx)(he,{width:17,height:17})}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,"aria-pressed":b,title:`The ports on the nodes`,"aria-label":`The ports on the nodes`,disabled:!q||S,onClick:()=>x(e=>!e),children:(0,X.jsx)(E,{width:17,height:17})}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,"aria-pressed":S,title:`The XML`,"aria-label":`The XML`,disabled:!o.path||!U&&o.savedText===null,onClick:()=>C(e=>!e),children:(0,X.jsx)(M,{width:17,height:17})}),(0,X.jsx)(`span`,{className:`bte-toolbar-end`}),(0,X.jsxs)(`button`,{type:`button`,className:`button bte-save${ye?` primary`:``}`,disabled:!ye||N||o.readOnly!==null,title:o.readOnly??`Save (Ctrl+S)`,onClick:()=>void Oe(),children:[(0,X.jsx)(se,{width:16,height:16}),(0,X.jsx)(`span`,{className:`bte-save-label`,children:`Save`})]}),(0,X.jsxs)(`div`,{className:`menu`,children:[(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-label":`File`,title:`File`,"aria-expanded":A,onClick:()=>j(e=>!e),children:(0,X.jsx)(te,{width:17,height:17})}),A&&(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(`div`,{className:`menu-backdrop`,onPointerDown:()=>j(!1)}),(0,X.jsxs)(`div`,{className:`menu-list`,role:`menu`,onClick:()=>j(!1),children:[(0,X.jsx)(`button`,{type:`button`,role:`menuitem`,className:`bte-narrow`,disabled:!q||S,onClick:()=>y(e=>e+1),children:`Fit the tree`}),(0,X.jsx)(`button`,{type:`button`,role:`menuitem`,className:`bte-narrow`,disabled:!q||S,onClick:()=>x(e=>!e),children:b?`Hide the ports`:`Show the ports`}),(0,X.jsx)(`button`,{type:`button`,role:`menuitem`,className:`bte-narrow`,disabled:!o.path||!U&&o.savedText===null,onClick:()=>C(e=>!e),children:S?`Back to the graph`:`The XML`}),(0,X.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:()=>I(`open`),children:`Open…`}),(0,X.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:()=>I(`new`),children:`New file…`}),(0,X.jsx)(`button`,{type:`button`,role:`menuitem`,disabled:!U,onClick:()=>I(`save-as`),children:`Save as…`}),(0,X.jsx)(`button`,{type:`button`,role:`menuitem`,disabled:!U,onClick:()=>U&&Vr(er(o.path)||`tree.xml`,ur(U)),children:`Download`}),(0,X.jsx)(`button`,{type:`button`,role:`menuitem`,disabled:!ye,onClick:async()=>{await le.confirm({title:`Discard the changes?`,message:`The file is read again from the robot.`,confirmLabel:`Discard them`,danger:!0})&&(p(null),s({type:`open`,path:o.path}))},children:`Discard the changes`})]})]})]})]}),(0,X.jsxs)(`div`,{className:`bte-body${be?` narrow`:``}`,children:[xe&&(0,X.jsx)(br,{items:Te,libraries:ue.map(t=>({path:t,removable:c.includes(t)&&!Lr(e.libraries).includes(t)})),warnings:u?.warnings??[],onAdd:e=>Ae(e),onDrag:(e,t)=>{ie({item:e,at:t}),oe.current?.dragNew(t)},onDrop:(e,t)=>{let n=t?oe.current?.dragNew(t)??null:null;oe.current?.dragNew(null),ie(null),n&&Ae(e,n)},onLoadLibrary:()=>I(`library`),onRemoveLibrary:e=>{let t=c.filter(t=>t!==e);l(t),zr(r,t)},onClose:()=>k(!1)}),(0,X.jsxs)(`div`,{className:`bt-main bte-canvas`,children:[We,Ge]})]}),(0,X.jsxs)(`div`,{className:`bt-status ${qe.tone}`,title:o.path||void 0,children:[(0,X.jsx)(`span`,{className:`bt-dot`,"aria-hidden":`true`}),(0,X.jsx)(`span`,{className:`bt-status-text`,children:qe.text}),$.length>0&&!S&&(0,X.jsxs)(`button`,{type:`button`,className:`bte-problems-chip`,onClick:Ue,title:`Show the next`,children:[$.length,` `,$.length===1?`problem`:`problems`]})]}),V&&(0,X.jsx)(`div`,{className:`bt-node bte-palette-ghost`,style:{left:V.at.x+12,top:V.at.y+8},children:(0,X.jsxs)(`div`,{className:`bt-node-head`,children:[(0,X.jsx)(Dt,{node:{kind:V.item.model.kind,type:V.item.model.id}}),(0,X.jsx)(`span`,{className:`bt-node-type`,children:V.item.model.id})]})}),L&&U&&Z&&Me&&K&&(0,X.jsx)(kr,{title:L===`wrap`?`Wrap ${Z.type} in`:`Replace ${Z.type} with`,models:[...K.byId.values()],kinds:L===`wrap`?[`decorator`,`control`]:Z.kind===`control`||Z.kind===`decorator`?[Z.kind]:[`action`,`condition`],onPick:e=>{if(z(null),L===`wrap`){let t=Mn(e,fe);De(bn(U,Z.key,t),{select:t.key})}else De(fn(U,Me.key,Un(Me,e,fe)),{select:Me.key})},onClose:()=>z(null)}),(F===`open`||F===`library`)&&(0,X.jsx)($e,{kind:`behavior-tree`,start:o.path.startsWith(`/`)||o.path.startsWith(`~/`)?o.path:`~`,onChoose:e=>{if(I(null),F===`open`)ke(e);else if(!ue.includes(e)){let t=[...c,e];l(t),zr(r,t)}},onClose:()=>I(null)}),(F===`new`||F===`save-as`)&&(0,X.jsx)(or,{mode:F,initial:F===`new`?`${o.path.startsWith(`/`)||o.path.startsWith(`~/`)?o.path.replace(/\/[^/]*$/,``):`~`}/behavior_tree.xml`:o.path.startsWith(`/`)||o.path.startsWith(`~/`)?o.path.replace(/(\.xml)?$/i,`_copy.xml`):`~/${er(o.path)}`,text:U?ur(U):ir(4),onSaved:(e,t,n)=>{I(null),F===`save-as`?(s({type:`saved`,text:t,version:n,path:e}),G(`Saved as ${e}`)):ke(e)},onClose:()=>I(null)})]})}var Ur=J({type:`behavior-tree-editor`,name:`Behavior Tree Editor`,description:`Edits a behavior tree’s XML file of the robot as a graph: nodes from palettes, ports, subtrees.`,icon:de,defaultSize:{w:10,h:7},minSize:{w:4,h:4},component:Hr,properties:[{key:`tree`,label:`Tree file`,kind:`behavior-tree`,default:``,placeholder:`~/behavior_trees/main.xml`,help:`The XML file it opens (/…, ~/…, package://…): its toolbar opens others, and makes new ones. Uploads are saved as robot files`},{key:`libraries`,label:`Node libraries`,kind:`text`,default:``,placeholder:`~/my_robot/behavior_trees/my_nodes.xml
|
|
24
|
-
package://my_robot_bt/nodes.xml`,help:`XML files of TreeNodesModel (as Groot exports them), one a line: their nodes join the palette, besides BT.CPP’s, Nav2’s and the file’s`},{key:`direction`,label:`Graph direction`,kind:`select`,default:`vertical`,options:[{value:`vertical`,label:`Top to bottom`},{value:`horizontal`,label:`Left to right`}]},{key:`showPorts`,label:`Show the ports in the graph`,kind:`boolean`,default:!1,help:`The toolbar switches them; the side panel edits them`}]}),Wr=(0,Y.memo)(function({index:e,node:t,depth:n,state:r,selected:i,folded:a,now:o,onSelect:s,onFold:c}){let l=ct(r?.status),u=l===`idle`&&r?.result?ct(r.result):null,d=``;return r?.status&&(d=lt(r.status),l===`running`&&r.since&&o?d+=` · ${ft(o-r.since)}`:u&&(d+=` · was ${r.result.toLowerCase()}`)),(0,X.jsxs)(`li`,{className:`bt-row ${l}${u?` was-${u}`:``}${i?` selected`:``}`,"data-row":e,children:[(0,X.jsx)(`span`,{className:`bt-row-indent`,style:{width:n*14}}),a>=0?(0,X.jsx)(`button`,{type:`button`,className:`bt-row-fold`,"aria-expanded":a===0,"aria-label":a===0?`Fold ${t.name}`:`Unfold ${t.name}`,title:a===0?void 0:`${a} nodes folded away`,onClick:()=>c(e),children:(0,X.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`12`,height:`12`,"aria-hidden":`true`,children:(0,X.jsx)(`path`,{d:`m9 6 6 6-6 6`,fill:`none`,stroke:`currentColor`,strokeWidth:`2.5`,strokeLinecap:`round`})})}):(0,X.jsx)(`span`,{className:`bt-row-fold`}),(0,X.jsxs)(`button`,{type:`button`,className:`bt-row-main`,title:`${Ot(t)}: ${t.type}`,onClick:()=>s(e),children:[(0,X.jsx)(`span`,{className:`bt-dot`,"aria-hidden":`true`}),(0,X.jsx)(Dt,{node:t}),(0,X.jsxs)(`span`,{className:`bt-row-labels`,children:[(0,X.jsx)(`span`,{className:`bt-row-type`,children:t.type}),t.name!==t.type&&(0,X.jsx)(`span`,{className:`bt-row-name`,children:t.name})]}),(0,X.jsxs)(`span`,{className:`bt-row-status`,children:[d,r&&r.successes+r.failures>0&&(0,X.jsxs)(`span`,{className:`bt-row-counts`,children:[(0,X.jsxs)(`span`,{className:`success`,children:[`✓`,r.successes]}),` `,(0,X.jsxs)(`span`,{className:`failure`,children:[`✗`,r.failures]})]})]})]})]})});function Gr({model:e,folded:t,selected:n,follow:r,now:i,onSelect:a,onFold:o}){let s=(0,Y.useRef)(null),{nodes:c,treeSize:l,children:u,depths:d,states:f}=e,p=(0,Y.useMemo)(()=>{let e=Array(c.length).fill(1);for(let t=l-1;t>0;t--){let n=c[t].parent;n>=0&&(e[n]+=e[t])}let n=[];for(let r=0;r<c.length;){let i=t.has(r)?e[r]-1:0;n.push({index:r,folded:u[r].length===0?-1:i}),r+=i+1}return n},[c,l,u,t]),m=ut(e,e=>{let n=e;for(let r=c[e].parent;r>=0;r=c[r].parent)t.has(r)&&(n=r);return n}).join(`,`);(0,Y.useEffect)(()=>{let e=s.current,t=e?.querySelector(`[data-row="${m.split(`,`)[0]}"]`);r&&e&&t&&(t.offsetTop<e.scrollTop?e.scrollTop=t.offsetTop:t.offsetTop+t.offsetHeight>e.scrollTop+e.clientHeight&&(e.scrollTop=t.offsetTop+t.offsetHeight-e.clientHeight))},[r,m]);let h=({index:e,folded:t})=>(0,X.jsx)(Wr,{index:e,node:c[e],depth:d[e],state:f[e],selected:n===e,folded:t,now:f[e]?.status===`RUNNING`?i:0,onSelect:a,onFold:o},e),g=p.filter(e=>e.index<l),_=p.filter(e=>e.index>=l);return(0,X.jsxs)(`div`,{ref:s,className:`bt-list`,children:[g.length>0&&(0,X.jsx)(`ul`,{children:g.map(h)}),_.length>0&&(0,X.jsxs)(X.Fragment,{children:[l>0&&(0,X.jsx)(`h3`,{className:`bt-list-heading`,children:`Not in the tree file`}),(0,X.jsx)(`ul`,{children:_.map(h)})]})]})}var Kr=420,qr=316,Jr=240;function Yr(e){let[t,n]=(0,Y.useState)(()=>R.serverNow());return(0,Y.useEffect)(()=>{let t=setInterval(()=>n(R.serverNow()),e);return()=>clearInterval(t)},[e]),t}function Xr(e,t,n){if(t.state===`error`)return{text:t.message,tone:`error`};let r=t=>+![`action`,`condition`].includes(e.nodes[t].kind??``),i=ut(e).sort((e,t)=>r(e)-r(t));if(i.length>0){let t=i.slice(0,2).map(t=>e.nodes[t].name),r=e.states[i[0]]?.since;return{text:`Running ${t.join(`, `)}${i.length>2?` and ${i.length-2} more`:``}${r?` · ${ft(n-r)}`:``}`,tone:`running`}}let a=e.treeSize>0?e.states[0]:void 0;return a?.status===`SUCCESS`||a?.status===`FAILURE`?{text:a.status===`SUCCESS`?`Succeeded`:`Failed`,tone:ct(a.status)}:a?.result?{text:`Idle · its last run ${a.result===`SUCCESS`?`succeeded`:`failed`}${a.since?`, ${ft(n-a.since)} ago`:``}`,tone:`idle`}:t.state===`waiting`?{text:t.message,tone:`idle`}:{text:`Idle`,tone:`idle`}}function Zr({model:e,index:t,now:n,onSelect:r,onClose:i}){let a=e.nodes[t],o=e.states[t],s=[];for(let t=a.parent;t>=0;t=e.nodes[t].parent)s.unshift(t);let c=Object.entries(a.ports),l=e.transitions.filter(e=>e.node===t).slice(-8).reverse(),u=`not seen changing`;return o?.since?u=`for ${ft(n-o.since)}`:o?.status&&(u=`since before this page`),(0,X.jsxs)(`aside`,{className:`bt-details`,"aria-label":`${a.name}: details`,children:[(0,X.jsxs)(`header`,{className:`bt-details-header`,children:[(0,X.jsx)(Dt,{node:a,size:18}),(0,X.jsxs)(`div`,{className:`bt-details-title`,children:[(0,X.jsx)(`strong`,{children:a.type}),(0,X.jsxs)(`span`,{children:[a.name===a.type?``:`${a.name} · `,Ot(a)]})]}),(0,X.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Close`,onClick:i,children:(0,X.jsx)(U,{width:16,height:16})})]}),(0,X.jsxs)(`div`,{className:`bt-details-body`,children:[s.length>0&&(0,X.jsx)(`nav`,{className:`bt-path`,"aria-label":`Its parents`,children:s.map(t=>(0,X.jsx)(`button`,{type:`button`,onClick:()=>r(t),children:e.nodes[t].name},t))}),(0,X.jsxs)(`dl`,{className:`bt-facts`,children:[(0,X.jsx)(`dt`,{children:`Status`}),(0,X.jsxs)(`dd`,{children:[o?.status?(0,X.jsx)(`span`,{className:`bt-pill ${ct(o.status)}`,children:lt(o.status)}):`Unknown`,` `,(0,X.jsx)(`span`,{className:`bt-muted`,children:u})]}),o?.result&&(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(`dt`,{children:`Last result`}),(0,X.jsx)(`dd`,{children:(0,X.jsx)(`span`,{className:`bt-pill ${ct(o.result)}`,children:lt(o.result)})})]}),(0,X.jsx)(`dt`,{children:`Seen`}),(0,X.jsxs)(`dd`,{children:[o?.changes??0,` transitions · `,(0,X.jsxs)(`span`,{className:`success`,children:[o?.successes??0,` successes`]}),` ·`,` `,(0,X.jsxs)(`span`,{className:`failure`,children:[o?.failures??0,` failures`]})]})]}),c.length>0&&(0,X.jsxs)(`section`,{children:[(0,X.jsx)(`h3`,{children:`Ports`}),(0,X.jsx)(`dl`,{className:`bt-ports`,children:c.map(([e,t])=>(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`dt`,{children:e}),(0,X.jsx)(`dd`,{className:/^\{.*\}$/.test(t)?`entry`:void 0,children:t})]},e))})]}),(0,X.jsxs)(`section`,{children:[(0,X.jsx)(`h3`,{children:`Latest transitions`}),l.length>0?(0,X.jsx)(`ol`,{className:`bt-node-log`,children:l.map(e=>(0,X.jsxs)(`li`,{children:[(0,X.jsx)(`time`,{children:pt(e.time)}),(0,X.jsx)(`span`,{className:`bt-pill ${ct(e.from)}`,children:lt(e.from)}),`→`,(0,X.jsx)(`span`,{className:`bt-pill ${ct(e.to)}`,children:lt(e.to)})]},e.id))}):(0,X.jsx)(`p`,{className:`bt-muted`,children:`None seen`})]})]})]})}function Qr({model:e,onSelect:t}){let n=(0,Y.useRef)(null),r=(0,Y.useRef)(!0);return(0,Y.useLayoutEffect)(()=>{let e=n.current;e&&r.current&&(e.scrollTop=e.scrollHeight)},[e.transitions]),(0,X.jsx)(`section`,{className:`bt-log`,"aria-label":`Latest transitions`,children:e.transitions.length===0?(0,X.jsx)(`p`,{className:`bt-muted bt-log-empty`,children:`No transition yet`}):(0,X.jsx)(`ol`,{ref:n,onScroll:e=>{let t=e.currentTarget;r.current=t.scrollHeight-t.scrollTop-t.clientHeight<8},children:e.transitions.map(n=>(0,X.jsx)(`li`,{children:(0,X.jsxs)(`button`,{type:`button`,onClick:()=>t(n.node),children:[(0,X.jsx)(`time`,{children:pt(n.time)}),(0,X.jsx)(`span`,{className:`bt-log-node`,children:dt(e.nodes[n.node])}),(0,X.jsx)(`span`,{className:`bt-pill ${ct(n.from)}`,children:lt(n.from)}),`→`,(0,X.jsx)(`span`,{className:`bt-pill ${ct(n.to)}`,children:lt(n.to)})]})},n.id))})})}function $r({config:e,editing:t}){let[n,r]=(0,Y.useReducer)(st,it),[i,a]=(0,Y.useState)({state:`waiting`,message:`Connecting…`}),[s,c]=(0,Y.useState)(null),[l,u]=(0,Y.useState)(!0),[d,f]=(0,Y.useState)(!1),[p,h]=(0,Y.useState)(null),[g,_]=(0,Y.useState)(new Set),[v,y]=(0,Y.useState)(null),[b,C]=(0,Y.useState)(0),[w,T]=(0,Y.useState)(0),E=(0,Y.useRef)(null),[D,ee]=(0,Y.useState)(null),[O,k]=(0,Y.useState)(null),A=(0,Y.useRef)(null),[j,M]=(0,Y.useState)(null),[N,P]=(0,Y.useState)(!1),[F,I]=(0,Y.useState)(!1),L=(0,Y.useRef)(null),te=Yr(O?.playing?250:1e3),z=e.topic.trim(),B=e.tree.trim();(0,Y.useEffect)(()=>{if(r({type:`reset`}),M(null),k(null),A.current=null,!z&&!D){a({state:`error`,message:`No log topic: set one in edit mode`});return}a({state:`waiting`,message:`Connecting…`});let e={status:(e,t)=>a({state:e,message:t}),tree:e=>r({type:`tree`,tree:e}),update:e=>r({type:`update`,update:e}),recording:M,playback:e=>k({...e,at:Date.now()})};if(D){let{id:t,unsubscribe:n}=R.subscribeBehaviorTreePlayback({bag:D,topic:z,tree:B},e);return A.current=t,n}return R.subscribeBehaviorTree({topic:z,tree:B},e)},[z,B,D]);let ne=(0,Y.useCallback)(e=>{A.current!==null&&(k(t=>t&&{...t,time:e.time??Qn(t),playing:e.playing??t.playing,speed:e.speed??t.speed,at:Date.now()}),R.controlBehaviorTreePlayback(A.current,e))},[]),re=async()=>{try{let e=await R.recordBehaviorTree(z,null);e&&(L.current=e,G(`Recorded ${z} into ${e}`))}catch(e){G(`Could not stop recording ${z}: ${e instanceof Error?e.message:e}`,`error`)}};(0,Y.useEffect)(()=>{h(null),_(new Set)},[n.version]),(0,Y.useEffect)(()=>{let e=E.current;if(!e)return;let t=new ResizeObserver(([e])=>T(e.contentRect.width));return t.observe(e),()=>t.disconnect()},[]),(0,Y.useEffect)(()=>{if(p===null)return;let e=e=>e.key===`Escape`&&h(null);return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[p]);let ie=(0,Y.useCallback)(e=>{_(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n})},[]),ae=(0,Y.useCallback)(e=>{h(e),y(t=>({node:e,seq:(t?.seq??0)+1}))},[]),oe=n.treeSize>0,se=oe?s??(e.view===`auto`?w<Kr?`list`:`graph`:e.view):`list`,H=p!==null&&n.nodes[p]!==void 0,ce=H&&w-qr>=Jr?qr:0,le=O?Qn(O):te,ue=Xr(n,i,le);D&&O&&!O.error&&(ue.text=`${er(D)}: ${ue.text}`);let de=[];n.error&&de.push({text:`${n.error}. The nodes are the log’s`,tone:`error`}),n.mismatch&&de.push({text:n.mismatch,tone:`warning`}),n.warnings.length>0&&de.push({text:n.warnings[0]+(n.warnings.length>1?` (and ${n.warnings.length-1} more)`:``),title:n.warnings.join(`
|
|
25
|
-
`),tone:`warning`});let U;return U=n.received?n.nodes.length===0?(0,X.jsx)(`div`,{className:`widget-message`,children:B?`The nodes will show as they change`:`No tree file: the nodes will show as they change. Set the tree’s file in edit mode to see it whole`}):se===`graph`?(0,X.jsx)(Ut,{model:n,direction:e.direction,showPorts:e.showPorts,folded:g,selected:p,follow:l,focus:v,fitRequest:b,covered:ce,onSelect:h,onFold:ie,onPan:()=>u(!1)}):(0,X.jsx)(Gr,{model:n,folded:g,selected:p,follow:l,now:le,onSelect:h,onFold:ie}):(0,X.jsx)(`div`,{className:`widget-message`,children:i.state===`error`?i.message:`Reading the tree…`}),(0,X.jsxs)(`div`,{ref:E,className:`bt`,children:[de.map(e=>(0,X.jsx)(`div`,{className:`bt-banner ${e.tone}`,title:e.title??e.text,children:e.text},e.text)),(0,X.jsxs)(`div`,{className:`bt-main ${se}`,children:[U,(0,X.jsxs)(`div`,{className:`overlay-toolbar`,children:[se===`graph`&&(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Fit the tree`,"aria-label":`Fit the tree`,onClick:()=>{u(!1),C(e=>e+1)},children:(0,X.jsx)(he,{width:17,height:17})}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":l,title:`Follow the running nodes`,"aria-label":`Follow the running nodes`,onClick:()=>u(e=>!e),children:(0,X.jsx)(m,{width:17,height:17})}),(0,X.jsx)(`span`,{className:`overlay-separator`}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":se===`graph`,title:oe?`As a graph`:`As a graph: needs the tree’s file`,"aria-label":`As a graph`,disabled:!oe,onClick:()=>c(`graph`),children:(0,X.jsx)(V,{width:17,height:17})}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":se===`list`,title:`As a list`,"aria-label":`As a list`,onClick:()=>c(`list`),children:(0,X.jsx)(o,{width:17,height:17})}),(0,X.jsx)(`span`,{className:`overlay-separator`}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":d,title:`The latest transitions`,"aria-label":`The latest transitions`,onClick:()=>f(e=>!e),children:(0,X.jsx)(x,{width:17,height:17})}),(0,X.jsx)(`span`,{className:`overlay-separator`}),!D&&(0,X.jsx)(`button`,{type:`button`,className:`overlay-button${j?` recording`:``}`,"aria-pressed":j!==null,title:j?`Stop recording into ${j.path}`:`Record the log into a rosbag`,"aria-label":j?`Stop recording`:`Record the log`,disabled:!z||t,onClick:()=>j?void re():P(!0),children:(0,X.jsx)(S,{width:17,height:17})}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":D!==null,title:D?`Back to the live log, from ${D}`:`Play a rosbag back`,"aria-label":D?`Back to the live log`:`Play a rosbag back`,disabled:t,onClick:()=>D?ee(null):I(!0),children:(0,X.jsx)(W,{width:17,height:17})})]}),H&&(0,X.jsx)(Zr,{model:n,index:p,now:le,onSelect:ae,onClose:()=>h(null)})]}),d&&(0,X.jsx)(Qr,{model:n,onSelect:ae}),D&&O&&(0,X.jsx)(rr,{playback:O,onControl:ne,onClose:()=>ee(null)}),(0,X.jsxs)(`div`,{className:`bt-status ${ue.tone}`,title:ue.text,children:[(0,X.jsx)(`span`,{className:`bt-dot`,"aria-hidden":`true`}),(0,X.jsx)(`span`,{className:`bt-status-text`,children:ue.text}),j&&!D&&(0,X.jsxs)(`span`,{className:`bt-rec`,title:`Recording into ${j.path}`,children:[`REC `,ft(te-j.since)]})]}),N&&(0,X.jsx)(nr,{topic:z,folder:e.recordFolder,onRecording:e=>L.current=e,onClose:()=>P(!1)}),F&&(0,X.jsx)($e,{kind:`bag`,start:L.current?.replace(/\/+[^/]+\/*$/,``)||e.recordFolder,onChoose:e=>{I(!1),L.current=e,ee(e)},onClose:()=>I(!1)})]})}var ei=J({type:`behavior-tree`,name:`Behavior Tree Inspector`,description:`What a behavior tree is doing: its running branch, its nodes’ status, and their transitions.`,icon:V,defaultSize:{w:8,h:6},minSize:{w:3,h:3},component:$r,properties:[{key:`topic`,label:`Log topic`,kind:`topic`,default:`/behavior_tree_log`,topicTypes:[`nav2_msgs/msg/BehaviorTreeLog`],help:`nav2_msgs/BehaviorTreeLog: Nav2’s bt_navigator logs its tree on /behavior_tree_log`},{key:`tree`,label:`Tree file`,kind:`behavior-tree`,default:``,placeholder:`package://nav2_bt_navigator/behavior_trees/navigate_to_pose_w_replanning_and_recovery.xml`,help:`The XML of the tree the robot runs (/…, ~/…, package://…), or upload it. Without it, the nodes are listed as they change`},{key:`view`,label:`View`,kind:`select`,default:`auto`,options:[{value:`auto`,label:`Automatic: the graph, the list when narrow`},{value:`graph`,label:`Graph`},{value:`list`,label:`List`}],help:`Its toolbar switches between them`},{key:`direction`,label:`Graph direction`,kind:`select`,default:`vertical`,options:[{value:`vertical`,label:`Top to bottom`},{value:`horizontal`,label:`Left to right`}],visible:e=>e.view!==`list`},{key:`showPorts`,label:`Show the ports in the graph`,kind:`boolean`,default:!1,help:`The nodes’ parameters and blackboard entries ({goal}); their details show them anyway`,visible:e=>e.view!==`list`},{key:`recordFolder`,label:`Recordings folder`,kind:`string`,default:`~/bags`,help:`Where the record button puts its rosbags, and the playback button looks for them first`}]}),ti=5e3;function ni(e){let t=/^#([0-9a-f]{6})$/i.exec(e)?.[1];if(!t)return`#fff`;let[n,r,i]=[0,2,4].map(e=>parseInt(t.slice(e,e+2),16)/255);return .2126*n+.7152*r+.0722*i>.6?`#111`:`#fff`}function ri(e){let t=Math.max(0,Math.floor(e/1e3));return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}function ii(e){return e.error?{text:e.error,ok:!1}:e.signal?{text:`Stopped (${e.signal})`,ok:!1}:e.exitCode===0?{text:`Done`,ok:!0}:{text:`Exit code ${e.exitCode}`,ok:!1}}function ai({config:e,instance:t,panelId:n,editing:r}){let i=k(n,t.id),a=_e(),[o,s]=(0,Y.useState)(null),[,c]=(0,Y.useState)(0),l=(0,Y.useRef)(null),u=i?.running??!1,d=u||o!==null,f=e.label||`Run`;(0,Y.useEffect)(()=>{o&&i!==o.from&&s(null)},[i,o]),(0,Y.useEffect)(()=>{if(!d)return;let e=setInterval(()=>{c(e=>e+1),s(e=>e&&Date.now()-e.at>ti?null:e)},1e3);return()=>clearInterval(e)},[d]),(0,Y.useEffect)(()=>{let e=l.current;e&&(e.scrollTop=e.scrollHeight)},[i?.output]);let p=async()=>{if(r)return;let o={panelId:n,widgetId:t.id};u?e.allowStop&&await a.confirm({title:`Stop "${f}"?`,message:`The command gets SIGINT, then SIGTERM and SIGKILL if it does not stop.`,confirmLabel:`Stop`,danger:!0})&&R.send({type:`command.stop`,...o}):d||(e.command.trim()?(!e.confirm||await a.confirm({title:`Run "${f}"?`,message:(0,X.jsx)(`pre`,{className:`dialog-command`,children:e.command}),confirmLabel:`Run`}))&&(R.send({type:`command.run`,...o})?s({from:i,at:Date.now()}):G(`Not connected to the robot`,`error`)):G(`"${f}" has no command: set one in edit mode`,`error`))},m=null;if(d)m={text:`Running ${u&&i?ri(R.serverNow()-i.startedAt):``}${u&&e.allowStop?` · press to stop`:``}`,className:``};else if(i){let{text:e,ok:t}=ii(i);m={text:`${t?`✓`:`✗`} ${e}`,className:t?`ok`:`failed`}}let h=d?e.runningColor:e.color;return(0,X.jsxs)(`div`,{className:`command-button${e.showOutput?` with-output`:``}`,children:[(0,X.jsxs)(`button`,{type:`button`,className:`command-button-face${d?` busy`:``}`,style:{backgroundColor:h,color:ni(h)},onClick:p,title:e.command,tabIndex:r?-1:0,children:[(0,X.jsx)(`span`,{className:`command-button-label`,children:f}),m&&(0,X.jsx)(`span`,{className:`command-button-status ${m.className}`,children:m.text})]}),e.showOutput&&(0,X.jsx)(`pre`,{ref:l,className:`command-output`,children:i?.output||(d?``:`No output yet`)})]})}var oi=J({type:`button`,name:`Button`,description:`Run a bash command on the robot, e.g. start a service or a launch file.`,icon:r,defaultSize:{w:3,h:1},minSize:{w:1,h:1},component:ai,properties:[{key:`label`,label:`Label`,kind:`string`,default:`Run`},{key:`command`,label:`Bash command`,kind:`text`,default:``,placeholder:`ros2 launch my_robot navigation.launch.py`,help:`Runs with bash -c, as the server's user, in the workspace's environment`},{key:`confirm`,label:`Ask before running`,kind:`boolean`,default:!1},{key:`allowStop`,label:`Press again to stop`,kind:`boolean`,default:!0,help:`While the command runs, pressing the button stops it`},{key:`showOutput`,label:`Show output`,kind:`boolean`,default:!1,help:`The last lines the command printed, below the button`},{key:`color`,label:`Colour`,kind:`color`,default:`#2f6fed`},{key:`runningColor`,label:`Colour while running`,kind:`color`,default:`#e8890c`}]}),si=3e3,ci=2e3;function li(e,t,n){let r=window.devicePixelRatio||1,i=Math.round(e.clientWidth*r),a=Math.round(e.clientHeight*r);if(i===0||a===0)return;(e.width!==i||e.height!==a)&&(e.width=i,e.height=a);let o=e.getContext(`2d`);if(!o)return;let s=i,c=a;if(n!==`fill`){let e=(n===`contain`?Math.min:Math.max)(i/t.width,a/t.height);s=t.width*e,c=t.height*e}o.clearRect(0,0,i,a),o.drawImage(t,(i-s)/2,(a-c)/2,s,c)}function ui({config:e}){let t=(0,Y.useRef)(null),n=(0,Y.useRef)(null),r=(0,Y.useRef)(e.fit);r.current=e.fit;let[i,a]=(0,Y.useState)({state:`waiting`,message:`Connecting…`}),[o,s]=(0,Y.useState)(null),[c,l]=(0,Y.useState)(!1),u=(0,Y.useRef)(0),d=e.topic.trim(),{transport:f,maxFps:p,quality:m,maxWidth:h}=e;(0,Y.useEffect)(()=>{if(s(null),!d){a({state:`error`,message:`No image topic: set one in edit mode`});return}a({state:`waiting`,message:`Connecting…`});let e=[],i=!0,o=R.subscribeImage({topic:d,transport:f,maxFps:p,quality:m,maxWidth:h},{status:(e,t)=>a({state:e,message:t}),frame:async(a,{width:o,height:c})=>{let d=await createImageBitmap(a);if(!i){d.close();return}let f=t.current;f&&li(f,d,r.current),n.current?.close(),n.current=d;let p=performance.now();for(u.current=p,e.push(p);e.length>2&&p-e[0]>ci;)e.shift();l(!1),s({width:o||d.width,height:c||d.height,fps:e.length>1?(e.length-1)*1e3/(p-e[0]):0})}});return()=>{i=!1,o(),n.current?.close(),n.current=null;let e=t.current;e?.getContext(`2d`)?.clearRect(0,0,e.width,e.height)}},[d,f,p,m,h]),(0,Y.useEffect)(()=>{let e=t.current;if(!e)return;let i=()=>n.current&&li(e,n.current,r.current);i();let a=new ResizeObserver(i);return a.observe(e),()=>a.disconnect()},[e.fit]),(0,Y.useEffect)(()=>{let e=setInterval(()=>{l(u.current>0&&performance.now()-u.current>si)},1e3);return()=>clearInterval(e)},[]);let g=null;return i.state===`streaming`?c&&(g=`No image for ${Math.round((performance.now()-u.current)/1e3)} s`):g=i.message,(0,X.jsxs)(`div`,{className:`camera`,children:[(0,X.jsx)(`canvas`,{ref:t,className:g&&o?`dimmed`:void 0}),g&&(0,X.jsxs)(`div`,{className:`camera-overlay ${i.state}`,children:[(0,X.jsx)(j,{width:28,height:28}),(0,X.jsx)(`span`,{children:g})]}),e.showInfo&&o&&!g&&(0,X.jsxs)(`div`,{className:`camera-info`,children:[o.width,`×`,o.height,` · `,o.fps.toFixed(1),` fps`]})]})}var di=J({type:`camera`,name:`Camera`,description:`Show an image topic, raw or compressed.`,icon:j,defaultSize:{w:6,h:4},minSize:{w:2,h:2},component:ui,properties:[{key:`topic`,label:`Topic`,kind:`topic`,default:``,topicTypes:[`sensor_msgs/msg/Image`,`sensor_msgs/msg/CompressedImage`],placeholder:`/arm_camera/image_raw`},{key:`transport`,label:`Transport`,kind:`select`,default:`auto`,options:[{value:`auto`,label:`Auto: the type the topic is published with`},{value:`raw`,label:`Raw: sensor_msgs/Image`},{value:`compressed`,label:`Compressed: <topic>/compressed`}],help:`Compressed images take far less bandwidth from the camera driver to the server`},{key:`maxFps`,label:`Max frame rate`,kind:`number`,default:10,min:.1,max:60,step:1},{key:`maxWidth`,label:`Max width (raw images, px)`,kind:`number`,default:640,min:0,max:8192,step:1,help:`Wider raw images are scaled down before being sent. 0: full size`},{key:`quality`,label:`JPEG quality (raw images)`,kind:`number`,default:75,min:1,max:100,step:1},{key:`fit`,label:`Fit`,kind:`select`,default:`contain`,options:[{value:`contain`,label:`Whole image`},{value:`cover`,label:`Fill the widget, cropped`},{value:`fill`,label:`Stretch`}]},{key:`showInfo`,label:`Show size and frame rate`,kind:`boolean`,default:!0}]});function fi({config:e}){let t=xe(e.image),[n,r]=(0,Y.useState)(0),[i,a]=(0,Y.useState)(!1);if((0,Y.useEffect)(()=>a(!1),[t]),(0,Y.useEffect)(()=>{if(!t||e.refreshSeconds<=0)return;let n=setInterval(()=>r(e=>e+1),e.refreshSeconds*1e3);return()=>clearInterval(n)},[t,e.refreshSeconds]),!e.image.trim())return(0,X.jsx)(`div`,{className:`widget-message`,children:`No image: choose one in edit mode`});if(!t)return(0,X.jsxs)(`div`,{className:`widget-message error`,children:[`“`,e.image,`” is not a path (/…, ~/…, package://…)`]});let o=n?`${t}${t.includes(`?`)?`&`:`?`}v=${n}`:t;return(0,X.jsxs)(`div`,{className:`image-viewer`,children:[(0,X.jsx)(`img`,{src:o,alt:e.image,style:{objectFit:e.fit},className:i?`failed`:void 0,onLoad:()=>a(!1),onError:()=>a(!0)}),i&&(0,X.jsxs)(`div`,{className:`widget-message error image-viewer-error`,children:[`Cannot load `,e.image]})]})}var pi=J({type:`image`,name:`Image Viewer`,description:`A static image: a file of the robot, or one uploaded from here.`,icon:s,defaultSize:{w:5,h:4},minSize:{w:1,h:1},component:fi,properties:[{key:`image`,label:`Image`,kind:`image`,default:``,help:`A file of the robot (/…, ~/…, package://…), or upload one from this device`},{key:`fit`,label:`Fit`,kind:`select`,default:`contain`,options:[{value:`contain`,label:`Whole image`},{value:`cover`,label:`Fill the widget, cropped`},{value:`fill`,label:`Stretch`}]},{key:`refreshSeconds`,label:`Reload every (s)`,kind:`number`,default:0,min:0,step:1,help:`For an image the robot updates. 0: never`}]}),mi=[{level:`debug`,tag:`DEBUG`,label:`Debug`,letter:`D`},{level:`info`,tag:`INFO`,label:`Info`,letter:`I`},{level:`warn`,tag:`WARN`,label:`Warn`,letter:`W`},{level:`error`,tag:`ERROR`,label:`Error`,letter:`E`},{level:`fatal`,tag:`FATAL`,label:`Fatal`,letter:`F`}];function hi(e){return Math.min(mi.length-1,Math.max(0,Math.floor(e/10)-1))}function gi(e){let t=mi.findIndex(t=>t.level===e);return new Set(mi.slice(Math.max(0,t)).map(e=>e.level))}var _i={received:!1,started:0,entries:[],pending:[],paused:!1,skipped:0,running:new Map,cleared:null,version:0};function vi(e){return e.replace(/^\/+/,``).replaceAll(`/`,`.`)}function yi(e,t){for(let n=e;n;n=n.slice(0,Math.max(0,n.lastIndexOf(`.`)))){let e=t.get(n);if(e)return e}return null}function bi(e){return e.length>1e4?e.slice(-fe):e}function xi(e){return e.entries.at(-1)?.seq??e.cleared?.seq??0}function Si(e,t){switch(t.type){case`reset`:return{..._i,version:e.version+1};case`update`:{let{reset:n,started:r,entries:i,skipped:a,nodes:o}=t.update,s=o?new Map(o.map(e=>[vi(e),e])):e.running;if(!n)return e.paused?{...e,running:s,pending:bi([...e.pending,...i]),skipped:e.skipped+a}:{...e,running:s,entries:bi([...e.entries,...i]),skipped:e.skipped+a};let c=e.received&&r===e.started,l=c?e.cleared:null,u=l?i.filter(e=>e.seq>l.seq):i,d=e.paused&&c?xi(e):1/0;return{...e,received:!0,started:r,running:s,cleared:l,entries:bi(u.filter(e=>e.seq<=d)),pending:bi(u.filter(e=>e.seq>d)),skipped:0,version:c?e.version:e.version+1}}case`pause`:return e.paused?e:{...e,paused:!0};case`resume`:return{...e,paused:!1,entries:bi([...e.entries,...e.pending]),pending:[]};case`clear`:{let t=(e.pending.at(-1)??e.entries.at(-1))?.seq??e.cleared?.seq??0;return{...e,entries:[],pending:[],skipped:0,cleared:{started:e.started,seq:t}}}}}function Ci(e,t){let n=0,r=e.length;for(;n<r;){let i=n+r>>1;e[i].seq<t?n=i+1:r=i}return n}function wi(e,t){if(t){if(!e.trim())return{test:null,error:null};try{let t=new RegExp(e,`i`);return{test:e=>t.test(e),error:null}}catch(e){return{test:null,error:e instanceof Error?e.message:String(e)}}}let n=e.split(`;`).map(e=>e.trim().toLowerCase()).filter(Boolean);return n.length===0?{test:null,error:null}:{test:e=>{let t=e.toLowerCase();return n.some(e=>t.includes(e))},error:null}}function Ti(e){let t=e.split(/[;,\s]+/).filter(Boolean).map(e=>{let t=vi(e).split(`*`).map(e=>e.replace(/[.+?^${}()|[\]\\]/g,`\\$&`)).join(`.*`);return RegExp(`^${t}(\\..+)?$`)});return t.length>0?e=>t.some(t=>t.test(e)):null}function Ei(e,t,n){let r=new Map,i=e=>{let t=r.get(e);return t===void 0&&(t=!n.scope||n.scope(e),r.set(e,t)),t},a=new Map,o=e=>{let n=a.get(e);return n||(n={name:e,node:yi(e,t),counts:mi.map(()=>0),total:0},a.set(e,n)),n},s=mi.map(()=>0),c=[],l=0;for(let t of e){if(!i(t.name))continue;l++;let e=hi(t.level),r=o(t.name);r.counts[e]++,r.total++,!(n.nodes.size>0&&!n.nodes.has(t.name)||n.include&&!n.include(t.msg)||n.exclude?.(t.msg))&&(s[e]++,n.levels.has(mi[e].level)&&c.push(t))}for(let e of[...t.keys(),...n.nodes])i(e)&&o(e);return{shown:c,levels:s,total:l,nodes:[...a.values()].sort((e,t)=>e.name.localeCompare(t.name))}}var Di=Date.UTC(2001,0,1);function Oi(e){return(e/1e3).toFixed(6)}function ki(e){if(e<Di)return(e/1e3).toFixed(3);let t=new Date(e),n=(e,t=2)=>String(e).padStart(t,`0`);return`${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}.${n(t.getMilliseconds(),3)}`}function Ai(e){return`[${mi[hi(e.level)].tag}] [${Oi(e.stamp)}] [${e.name}]: ${e.msg}`}function ji(e){return e<1e3?String(e):e<1e4?`${(e/1e3).toFixed(1).replace(/\.0$/,``)}k`:`${Math.round(e/1e3)}k`}var Mi=22,Ni=38,Pi=8,Fi=(0,Y.memo)(function({entry:e,top:t,selected:n,time:r,showNode:i,onSelect:a}){let{level:o,tag:s}=mi[hi(e.level)],c=e.msg.indexOf(`
|
|
16
|
+
`}function Ar(e){return e.replace(/\/[^/]*$/,``)||`~`}function jr({mode:e,initial:t,text:n,onSaved:r,onClose:i}){let a=(0,q.useId)(),[o,s]=(0,q.useState)(t),[c,l]=(0,q.useState)(4),[u,d]=(0,q.useState)(!1),[f,p]=(0,q.useState)(!1),[m,h]=(0,q.useState)(null),g=/^(\/|~\/).+\.xml$/i.test(o.trim()),_=async t=>{let i=o.trim(),a=e===`new`?kr(c):n;p(!0),h(null);try{r(i,a,(await H.saveBehaviorTreeFile(i,a,null,!t)).version)}catch(e){let t=e instanceof Error?e.message:String(e);h({message:t,exists:/exists already/.test(t)}),p(!1)}};return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(Ge,{title:e===`new`?`New behavior tree`:`Save the tree as`,onClose:i,wide:!0,children:(0,J.jsxs)(`form`,{className:`modal-body`,onSubmit:e=>{e.preventDefault(),_(!1)},children:[(0,J.jsxs)(`div`,{className:`field`,children:[(0,J.jsx)(`label`,{className:`field-label`,htmlFor:a,children:`File on the robot`}),(0,J.jsxs)(`div`,{className:`bt-record-path`,children:[(0,J.jsx)(`input`,{id:a,value:o,spellCheck:!1,autoFocus:!0,onChange:e=>{s(e.target.value),h(null)}}),(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>d(!0),children:`Browse…`})]}),(0,J.jsx)(`p`,{className:`field-help`,children:`An XML file: /…, ~/…`}),m&&(0,J.jsx)(`p`,{className:`field-help error`,children:m.message})]}),e===`new`&&(0,J.jsxs)(`div`,{className:`field`,children:[(0,J.jsx)(`label`,{className:`field-label`,htmlFor:`${a}-format`,children:`Format`}),(0,J.jsxs)(`select`,{id:`${a}-format`,value:c,onChange:e=>l(Number(e.target.value)),children:[(0,J.jsx)(`option`,{value:4,children:`BT.CPP 4: ROS 2 Jazzy and later`}),(0,J.jsx)(`option`,{value:3,children:`BT.CPP 3: ROS 2 Humble`})]})]}),(0,J.jsxs)(`div`,{className:`modal-actions`,children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:i,children:`Cancel`}),m?.exists&&(0,J.jsx)(`button`,{type:`button`,className:`button danger`,disabled:f,onClick:()=>void _(!0),children:`Replace it`}),(0,J.jsx)(`button`,{type:`submit`,className:`button primary`,disabled:f||!g,children:f?`Saving…`:e===`new`?`Create`:`Save`})]})]})}),u&&(0,J.jsx)(Tt,{kind:`folder`,start:Ar(o.trim()),onChoose:e=>{d(!1),s(`${e.replace(/\/+$/,``)}/${Tr(o.trim())||`tree.xml`}`)},onClose:()=>d(!1)})]})}function Mr({text:e,readOnly:t,onDocument:n,onDone:r}){let[i,a]=(0,q.useState)(e),[o,s]=(0,q.useState)(null),c=(0,q.useRef)(!1),l=(0,q.useRef)(null);(0,q.useEffect)(()=>{c.current||(a(e),s(null))},[e]),(0,q.useEffect)(()=>()=>void(l.current&&clearTimeout(l.current)),[]);let u=e=>{l.current=null;try{n(Dn(e)),s(null),c.current=!1}catch(e){s(e instanceof Error?e.message:String(e))}};return(0,J.jsxs)(`div`,{className:`bte-xml`,children:[(0,J.jsx)(`textarea`,{value:i,spellCheck:!1,readOnly:t,"aria-label":`The file’s XML`,onChange:e=>{let t=e.target.value;c.current=!0,a(t),l.current&&clearTimeout(l.current),l.current=setTimeout(()=>u(t),400)},onBlur:()=>{l.current&&(clearTimeout(l.current),u(i)),r()}}),o&&(0,J.jsx)(`p`,{className:`bte-xml-error`,children:o})]})}function Nr(e,t=0){return{opened:t,path:e,document:null,error:null,savedText:null,base:null,readOnly:null,external:null,past:[],future:[],tag:null,tree:null}}var Pr=new WeakMap;function Fr(e){let t=Pr.get(e);return t===void 0&&(t=jn(e),Pr.set(e,t)),t}function Ir(e){return e.document!==null&&Fr(e.document)!==e.savedText}function Lr(e,t,n){let r=t&&n!==null?qn(t).find(e=>e.key===n)?.id:void 0;return((r===void 0?void 0:qn(e).find(e=>e.id===r))??Xn(e))?.key??null}function Rr(e,t,n){let r={...e,savedText:t,base:n,external:null,past:[],future:[],tag:null};try{let n=Dn(t);return{...r,document:n,error:null,tree:Lr(n,e.document,e.tree)}}catch(e){return{...r,document:null,error:`Not XML: ${e instanceof Error?e.message:e}`,tree:null}}}function zr(e,t){switch(t.type){case`open`:return Nr(t.path,e.opened+1);case`file`:{let{text:n,version:r,readOnly:i,error:a}=t.file;if(n===null||r===null)return{...e,readOnly:i,error:e.document?e.error:a,external:null};let o=i===e.readOnly?e:{...e,readOnly:i};return e.document===null&&e.past.length===0&&e.savedText!==n?Rr(o,n,r):r===e.base?o:(e.document?Fr(e.document):e.savedText)===n?{...o,savedText:n,base:r,external:null}:!Ir(e)&&e.document!==null?Rr(o,n,r):{...o,external:{text:n,version:r}}}case`edit`:{if(t.document===e.document)return e;if(!e.document)return{...e,document:t.document,error:null,tag:t.tag??null,tree:Lr(t.document,null,null)};let n=t.tag!==void 0&&t.tag===e.tag;return{...e,document:t.document,error:null,past:n?e.past:[...e.past,e.document].slice(-200),future:[],tag:t.tag??null,tree:t.tree??e.tree}}case`seal`:return e.tag===null?e:{...e,tag:null};case`undo`:{let t=e.past.at(-1);return!t||!e.document?e:{...e,document:t,past:e.past.slice(0,-1),future:[e.document,...e.future],tag:null,tree:Lr(t,e.document,e.tree)}}case`redo`:{let[t,...n]=e.future;return!t||!e.document?e:{...e,document:t,past:[...e.past,e.document],future:n,tag:null,tree:Lr(t,e.document,e.tree)}}case`tree`:return{...e,tree:t.key};case`saved`:return{...e,path:t.path??e.path,savedText:t.text,base:t.version,readOnly:t.path?null:e.readOnly,external:null};case`conflict`:return{...e,external:e.external?.version===t.version?e.external:{text:null,version:t.version}};case`reload`:return e.external?.text==null?e:Rr(e,e.external.text,e.external.version);case`keep`:return e.external?{...e,base:e.external.version,savedText:e.external.text??e.savedText,external:null}:e}}var Br=new Map;function Vr(){return[...Br.values()].some(e=>Ir(e.state))}var Hr=[{kind:`control`,title:`Controls`},{kind:`decorator`,title:`Decorators`},{kind:`action`,title:`Actions`},{kind:`condition`,title:`Conditions`},{kind:`subtree`,title:`Subtrees`}],Ur=5;function Wr(e){let{model:t}=e,n=t.ports.map(e=>`${e.direction===`output`?`→ `:``}${e.name}${e.default===null?``:` = ${e.default}`}`);return[`${t.id} · ${e.library}`,t.description,n.length>0&&`Ports: ${n.join(`, `)}`].filter(Boolean).join(`
|
|
17
|
+
`)}function Gr({items:e,libraries:t,warnings:n,onAdd:r,onDrag:i,onDrop:a,onLoadLibrary:o,onRemoveLibrary:s,onClose:c}){let[l,u]=(0,q.useState)(``),[d,f]=(0,q.useState)(new Set),p=(0,q.useRef)(null),m=(0,q.useRef)(!1),h=(0,q.useMemo)(()=>{let t=l.toLowerCase().split(/\s+/).filter(Boolean),n=e=>{let n=`${e.model.id} ${e.library} ${e.model.description}`.toLowerCase();return t.every(e=>n.includes(e))},r=e=>t.length>0&&e.model.id.toLowerCase().startsWith(t[0])?0:1;return Hr.map(t=>({...t,items:e.filter(e=>e.model.kind===t.kind&&n(e)).sort((e,t)=>r(e)-r(t)||e.model.id.localeCompare(t.model.id))})).filter(e=>e.items.length>0)},[e,l]),g=(e,t)=>{t.pointerType!==`touch`&&t.button===0&&(t.currentTarget.setPointerCapture(t.pointerId),p.current={item:e,start:{x:t.clientX,y:t.clientY},dragging:!1})},_=e=>{let t=p.current;if(!t)return;let n={x:e.clientX,y:e.clientY};t.dragging||=Math.hypot(n.x-t.start.x,n.y-t.start.y)>Ur,t.dragging&&i(t.item,n)},v=e=>{let t=p.current;p.current=null,t?.dragging&&(m.current=!0,a(t.item,e.type===`pointerup`?{x:e.clientX,y:e.clientY}:null))};return(0,J.jsxs)(`aside`,{className:`bte-palette`,"aria-label":`Nodes to add`,children:[(0,J.jsxs)(`header`,{className:`bte-palette-header`,children:[(0,J.jsx)(`input`,{type:`search`,placeholder:`Search the nodes`,"aria-label":`Search the nodes`,value:l,onChange:e=>u(e.target.value)}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Close the nodes`,title:`Close`,onClick:c,children:(0,J.jsx)(B,{width:16,height:16})})]}),(0,J.jsxs)(`div`,{className:`bte-palette-body`,children:[h.length===0&&(0,J.jsxs)(`p`,{className:`bt-muted bte-palette-empty`,children:[`No node `,l?`matches`:`known`]}),h.map(e=>{let t=l!==``||!d.has(e.kind);return(0,J.jsxs)(`section`,{children:[(0,J.jsxs)(`button`,{type:`button`,className:`bte-palette-group`,"aria-expanded":t,onClick:()=>f(t=>{let n=new Set(t);return n.delete(e.kind)||n.add(e.kind),n}),children:[e.title,(0,J.jsx)(`span`,{className:`bt-muted`,children:e.items.length})]}),t&&(0,J.jsx)(`ul`,{children:e.items.map(e=>(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,className:`bte-palette-item`,title:Wr(e),onPointerDown:t=>g(e,t),onPointerMove:_,onPointerUp:v,onPointerCancel:v,onClick:()=>{m.current?m.current=!1:r(e)},children:[(0,J.jsx)($t,{node:{kind:e.model.kind,type:e.model.id}}),(0,J.jsx)(`span`,{className:`bte-palette-name`,children:e.model.id}),(0,J.jsx)(`span`,{className:`bte-palette-library`,children:e.library})]})},`${e.library}/${e.model.id}`))})]},e.kind)})]}),(0,J.jsxs)(`footer`,{className:`bte-palette-footer`,children:[n.length>0&&(0,J.jsxs)(`p`,{className:`field-help error`,title:n.join(`
|
|
18
|
+
`),children:[n[0],n.length>1?` (and ${n.length-1} more)`:``]}),t.map(({path:e,removable:t})=>(0,J.jsxs)(`div`,{className:`bte-library`,title:t?e:`${e}: the widget’s, in its properties`,children:[(0,J.jsx)(`span`,{children:e.replace(/^.*\//,``)}),t&&(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Remove the library ${e}`,onClick:()=>s(e),children:(0,J.jsx)(B,{width:14,height:14})})]},e)),(0,J.jsxs)(`button`,{type:`button`,className:`button`,onClick:o,children:[(0,J.jsx)(ne,{width:16,height:16}),` Load a library…`]})]})]})}var Kr=[`_skipIf`,`_successIf`,`_failureIf`,`_while`,`_onSuccess`,`_onFailure`,`_onHalted`,`_post`],qr={input:`in`,output:`out`,inout:`in/out`};function Jr({id:e,value:t,placeholder:n,onChange:r,onDone:i,label:a}){let o={id:e,value:t,placeholder:n,spellCheck:!1,"aria-label":a,onBlur:i};return t.includes(`
|
|
19
|
+
`)?(0,J.jsx)(`textarea`,{...o,rows:Math.min(8,t.split(`
|
|
20
|
+
`).length+1),onChange:e=>r(e.target.value)}):(0,J.jsx)(`input`,{...o,onChange:e=>r(e.target.value),onKeyDown:e=>e.key===`Enter`&&e.currentTarget.blur()})}function Yr({value:e,label:t,validate:n,onCommit:r}){let[i,a]=(0,q.useState)(e);(0,q.useEffect)(()=>a(e),[e]);let o=i.trim()===e?null:n(i.trim());return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`input`,{value:i,"aria-label":t,"aria-invalid":o!==null,spellCheck:!1,onChange:e=>a(e.target.value),onBlur:()=>{!o&&i.trim()!==e?r(i.trim()):a(e)},onKeyDown:t=>{t.key===`Enter`?t.currentTarget.blur():t.key===`Escape`&&a(e)}}),o&&(0,J.jsx)(`p`,{className:`field-help error`,children:o})]})}var Xr=/^[A-Za-z_:][-\w:.]*$/;function Zr({title:e,children:t}){return(0,J.jsxs)(`section`,{children:[(0,J.jsx)(`h3`,{children:e}),t]})}function Qr({node:e,element:t,catalog:n,format:r,actions:i,onAttribute:a,onRenameAttribute:o,onSeal:s,onOpenTree:c,onClose:l}){let u=(0,q.useId)(),[d,f]=(0,q.useState)({name:``,value:``}),p=e.model?.model??null,m=e.kind===`subtree`,h=r===4?`_autoremap`:`__shared_blackboard`,g=new Set([`name`,...m?[`ID`,h]:[]]),_=p?.ports??[],v=Object.keys(e.ports).filter(e=>!g.has(e)&&!_.some(t=>t.name===e)),y=[..._.map(e=>e.name).filter(t=>!(t in e.ports)),...r===4?Kr.filter(t=>!(t in e.ports)):[]],b=d.name&&!Xr.test(d.name)?`Not an attribute name`:d.name in t.attributes||g.has(d.name)?`It has it already`:null,x=()=>{d.name&&!b&&(a(d.name,d.value),f({name:``,value:``}))};return(0,J.jsxs)(`aside`,{className:`bt-details bte-properties`,"aria-label":`${e.type}: properties`,children:[(0,J.jsxs)(`header`,{className:`bt-details-header`,children:[(0,J.jsx)($t,{node:e,size:18}),(0,J.jsxs)(`div`,{className:`bt-details-title`,children:[(0,J.jsx)(`strong`,{children:e.type}),(0,J.jsxs)(`span`,{children:[Q(e),` · `,e.model?.library??`not in the libraries`]})]}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Close`,onClick:l,children:(0,J.jsx)(B,{width:16,height:16})})]}),(0,J.jsxs)(`div`,{className:`bte-actions`,role:`toolbar`,"aria-label":`What to do with it`,children:[(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,title:`Move earlier (Alt+←)`,"aria-label":`Move earlier`,disabled:!i.moveEarlier,onClick:()=>i.moveEarlier?.(),children:(0,J.jsx)(Te,{width:16,height:16,style:{transform:`scaleX(-1)`}})}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,title:`Move later (Alt+→)`,"aria-label":`Move later`,disabled:!i.moveLater,onClick:()=>i.moveLater?.(),children:(0,J.jsx)(Te,{width:16,height:16})}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,title:`Duplicate (Ctrl+D)`,"aria-label":`Duplicate`,disabled:!i.duplicate,onClick:()=>i.duplicate?.(),children:(0,J.jsx)(N,{width:16,height:16})}),(0,J.jsxs)(`span`,{className:`bte-actions-text`,children:[(0,J.jsx)(`button`,{type:`button`,className:`link-button`,disabled:!i.replace,onClick:()=>i.replace?.(),title:`Another node of its kind in its place: its name, ports and children kept`,children:`Change`}),(0,J.jsx)(`button`,{type:`button`,className:`link-button`,disabled:!i.wrap,onClick:()=>i.wrap?.(),title:`Put it under a new control node or decorator`,children:`Wrap`}),(0,J.jsx)(`button`,{type:`button`,className:`link-button`,disabled:!i.unwrap,onClick:()=>i.unwrap?.(),title:`Delete it, its children in its place`,children:`Unwrap`})]}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button danger`,title:`Delete, with its children (Delete)`,"aria-label":`Delete`,onClick:i.remove,children:(0,J.jsx)(Ne,{width:16,height:16})})]}),(0,J.jsxs)(`div`,{className:`bt-details-body`,children:[e.problems.length>0&&(0,J.jsx)(`ul`,{className:`bte-problems`,children:e.problems.map(e=>(0,J.jsx)(`li`,{children:e},e))}),p?.description&&(0,J.jsx)(`p`,{className:`bt-muted bte-description`,children:p.description}),(0,J.jsxs)(`div`,{className:`field`,children:[(0,J.jsx)(`label`,{className:`field-label`,htmlFor:`${u}-name`,children:`Name`}),(0,J.jsx)(Jr,{id:`${u}-name`,value:t.attributes.name??``,placeholder:m?t.attributes.ID??``:e.type,onChange:e=>a(`name`,e||null,!0),onDone:s})]}),m&&(0,J.jsxs)(`div`,{className:`field`,children:[(0,J.jsx)(`label`,{className:`field-label`,htmlFor:`${u}-tree`,children:`Tree`}),(0,J.jsxs)(`div`,{className:`bte-row`,children:[(0,J.jsxs)(`select`,{id:`${u}-tree`,value:t.attributes.ID??``,onChange:e=>a(`ID`,e.target.value),children:[!n.trees.includes(t.attributes.ID??``)&&(0,J.jsx)(`option`,{value:t.attributes.ID??``,children:t.attributes.ID||`—`}),n.trees.map(e=>(0,J.jsx)(`option`,{value:e,children:e},e))]}),(0,J.jsx)(`button`,{type:`button`,className:`button`,disabled:!t.attributes.ID,onClick:()=>c(t.attributes.ID??``),children:`Open`})]}),(0,J.jsxs)(`label`,{className:`bte-check`,children:[(0,J.jsx)(`input`,{type:`checkbox`,checked:t.attributes[h]===`true`,onChange:e=>a(h,e.target.checked?`true`:null)}),r===4?`Its ports those of this tree’s blackboard of the same names (_autoremap)`:`Shares this tree’s blackboard (__shared_blackboard)`]})]}),_.length>0&&(0,J.jsx)(Zr,{title:`Ports`,children:_.map(e=>(0,J.jsxs)(`div`,{className:`field bte-port`,children:[(0,J.jsxs)(`label`,{className:`field-label`,htmlFor:`${u}-port-${e.name}`,children:[(0,J.jsx)(`span`,{className:`bte-port-name`,children:e.name}),(0,J.jsx)(`span`,{className:`bte-direction ${e.direction}`,children:qr[e.direction]}),e.type&&(0,J.jsx)(`span`,{className:`bt-muted bte-port-type`,children:e.type})]}),(0,J.jsx)(Jr,{id:`${u}-port-${e.name}`,value:t.attributes[e.name]??``,placeholder:e.default===null?e.direction===`input`?``:`{${e.name}}`:`${e.default} (default)`,onChange:t=>a(e.name,t===``?null:t,!0),onDone:s}),e.description&&(0,J.jsx)(`p`,{className:`field-help`,children:e.description})]},e.name))}),v.length>0&&(0,J.jsx)(Zr,{title:p?`Other attributes`:`Attributes`,children:v.map(e=>(0,J.jsxs)(`div`,{className:`bte-attribute`,children:[(0,J.jsx)(Yr,{value:e,label:`Its name`,validate:e=>Xr.test(e)?e in t.attributes?`It has it already`:null:`Not an attribute name`,onCommit:t=>o(e,t)}),(0,J.jsx)(Jr,{value:t.attributes[e],label:`${e}: its value`,onChange:t=>a(e,t,!0),onDone:s}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Remove ${e}`,title:`Remove`,onClick:()=>a(e,null),children:(0,J.jsx)(B,{width:14,height:14})})]},e))}),(0,J.jsxs)(Zr,{title:`Add an attribute`,children:[(0,J.jsxs)(`form`,{className:`bte-attribute`,onSubmit:e=>{e.preventDefault(),x()},children:[(0,J.jsx)(`input`,{list:`${u}-suggestions`,placeholder:`name`,"aria-label":`The new attribute’s name`,spellCheck:!1,value:d.name,onChange:e=>f(t=>({...t,name:e.target.value.trim()}))}),(0,J.jsx)(`datalist`,{id:`${u}-suggestions`,children:y.map(e=>(0,J.jsx)(`option`,{value:e},e))}),(0,J.jsx)(`input`,{placeholder:`value`,"aria-label":`The new attribute’s value`,spellCheck:!1,value:d.value,onChange:e=>f(t=>({...t,value:e.target.value}))}),(0,J.jsx)(`button`,{type:`submit`,className:`icon-button`,"aria-label":`Add`,title:`Add`,disabled:!d.name||b!==null,children:(0,J.jsx)(ne,{width:16,height:16})})]}),b&&(0,J.jsx)(`p`,{className:`field-help error`,children:b})]})]})]})}function $r({id:e,isMain:t,trees:n,problems:r,onRename:i,onMain:a,onRemove:o,onClose:s}){return(0,J.jsxs)(`aside`,{className:`bt-details bte-properties`,"aria-label":`The tree ${e}: properties`,children:[(0,J.jsxs)(`header`,{className:`bt-details-header`,children:[(0,J.jsx)(u,{className:`bt-kind`,width:18,height:18}),(0,J.jsxs)(`div`,{className:`bt-details-title`,children:[(0,J.jsx)(`strong`,{children:e||`Unnamed tree`}),(0,J.jsxs)(`span`,{children:[`BehaviorTree`,t?` · the main one`:``]})]}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Close`,onClick:s,children:(0,J.jsx)(B,{width:16,height:16})})]}),(0,J.jsxs)(`div`,{className:`bt-details-body`,children:[r.length>0&&(0,J.jsx)(`ul`,{className:`bte-problems`,children:r.map(e=>(0,J.jsx)(`li`,{children:e},e))}),(0,J.jsxs)(`div`,{className:`field`,children:[(0,J.jsx)(`span`,{className:`field-label`,children:`ID`}),(0,J.jsx)(Yr,{value:e,label:`The tree’s ID`,validate:e=>e?n.includes(e)?`Another tree has it`:null:`A tree needs an ID`,onCommit:i}),(0,J.jsx)(`p`,{className:`field-help`,children:`Its subtrees and main_tree_to_execute follow`})]}),(0,J.jsxs)(`label`,{className:`bte-check`,children:[(0,J.jsx)(`input`,{type:`checkbox`,checked:t,disabled:t||!e,onChange:a}),`The main tree: the one BT.CPP runs (main_tree_to_execute)`]}),o&&(0,J.jsxs)(`button`,{type:`button`,className:`button danger`,onClick:o,children:[(0,J.jsx)(Ne,{width:16,height:16}),` Delete the tree`]})]})]})}function ei({title:e,models:t,kinds:n,onPick:r,onClose:i}){let[a,o]=(0,q.useState)(``),s=(0,q.useMemo)(()=>{let e=a.toLowerCase().split(/\s+/).filter(Boolean);return t.filter(({model:t,library:r})=>n.includes(t.kind)&&e.every(e=>`${t.id} ${r}`.toLowerCase().includes(e))).sort((e,t)=>n.indexOf(e.model.kind)-n.indexOf(t.model.kind)||e.model.id.localeCompare(t.model.id))},[t,n,a]);return(0,J.jsx)(Ge,{title:e,onClose:i,children:(0,J.jsxs)(`form`,{className:`modal-body bte-picker`,onSubmit:e=>{e.preventDefault(),s[0]&&r(s[0].model)},children:[(0,J.jsx)(`input`,{type:`search`,placeholder:`Search`,"aria-label":`Search`,value:a,autoFocus:!0,onChange:e=>o(e.target.value)}),(0,J.jsxs)(`ul`,{children:[s.map(({model:e,library:t})=>(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,className:`bte-palette-item`,title:e.description,onClick:()=>r(e),children:[(0,J.jsx)($t,{node:{kind:e.kind,type:e.id}}),(0,J.jsx)(`span`,{className:`bte-palette-name`,children:e.id}),(0,J.jsx)(`span`,{className:`bte-palette-library`,children:t})]})},`${t}/${e.id}`)),s.length===0&&(0,J.jsx)(`li`,{className:`bt-muted`,children:`None`})]})]})})}var ti=620,ni=316,ri=240,ii=`tassello.behaviorTreeEditor.libraries`,ai=null,oi=!1;function si(){oi||(oi=!0,window.addEventListener(`beforeunload`,e=>{Vr()&&e.preventDefault()}))}function ci(e){return e.split(`
|
|
21
|
+
`).map(e=>e.trim()).filter(Boolean)}function li(e){try{let t=JSON.parse(localStorage.getItem(ii)??`{}`);return Array.isArray(t[e])?t[e]:[]}catch{return[]}}function ui(e,t){try{let n=JSON.parse(localStorage.getItem(ii)??`{}`);t.length>0?n[e]=t:delete n[e],localStorage.setItem(ii,JSON.stringify(n))}catch{}}function di(e,t){return jn({...e,prolog:``,epilog:``,root:{...t,source:null}})}function fi(e,t){let n=URL.createObjectURL(new Blob([t],{type:`application/xml`})),r=document.createElement(`a`);r.href=n,r.download=e,r.click(),setTimeout(()=>URL.revokeObjectURL(n),1e3)}function pi({config:e,instance:t,panelId:n}){let r=`${n}/${t.id}`,a=e.tree.trim(),[o]=(0,q.useState)(()=>{let e=Br.get(r);return e?.config===a?e:{config:a,state:Nr(a),libraries:li(r)}}),[s,c]=(0,q.useReducer)(zr,o.state),[u,d]=(0,q.useState)(o.libraries),[f,p]=(0,q.useState)(null),[m,h]=(0,q.useState)(null),[g,_]=(0,q.useState)(new Set),[v,y]=(0,q.useState)(null),[b,x]=(0,q.useState)(0),[S,C]=(0,q.useState)(e.showPorts),[w,T]=(0,q.useState)(!1),[E,D]=(0,q.useState)(0),[ee,O]=(0,q.useState)(null),[k,A]=(0,q.useState)(!1),[j,te]=(0,q.useState)(!1),[N,F]=(0,q.useState)(null),[I,re]=(0,q.useState)(null),[ie,L]=(0,q.useState)([]),[R,ae]=(0,q.useState)(null),oe=(0,q.useRef)(null),z=(0,q.useRef)(null),se=(0,q.useRef)(o.config),le=Ke();(0,q.useEffect)(si,[]),(0,q.useEffect)(()=>{a!==se.current&&(se.current=a,c({type:`open`,path:a}))},[a]),(0,q.useEffect)(()=>{Br.set(r,{config:se.current,state:s,libraries:u})},[r,s,u]);let B=(0,q.useMemo)(()=>[...new Set([...ci(e.libraries),...u])],[e.libraries,u]),ue=B.join(`
|
|
22
|
+
`);(0,q.useEffect)(()=>{if(s.path)return H.subscribeBehaviorTreeFile({path:s.path,libraries:ue?ue.split(`
|
|
23
|
+
`):[]},{file:e=>c({type:`file`,file:e}),models:p})},[s.path,s.opened,ue]),(0,q.useEffect)(()=>{let e=oe.current;if(!e)return;let t=new ResizeObserver(([e])=>D(e.contentRect.width));return t.observe(e),()=>t.disconnect()},[]);let{document:V}=s,de=V?Jn(V):4,fe=(0,q.useMemo)(()=>V?qn(V):[],[V]),pe=(0,q.useMemo)(()=>V?Xn(V):void 0,[V]),me=fe.find(e=>e.key===s.tree)??pe,he=(0,q.useMemo)(()=>V?er(V,f?.libraries??[],f?.trees??[]):null,[V,f]),U=(0,q.useMemo)(()=>me&&he?nr(me.node,he):null,[me,he]),ge=(0,q.useMemo)(()=>new Map(U?.nodes.map((e,t)=>[e.key,t])??[]),[U]),ve=m===null?null:ge.get(m)??null,ye=Ir(s),be=E>0&&E<ti,Se=!w&&V!==null&&(ee??!be),Ce=E-(Se&&!be?240:0),we=!w&&U!==null&&ve!==null,Ee=we&&Ce-ni>=ri?ni:0;(0,q.useEffect)(()=>{_(new Set),L(e=>e.filter(e=>fe.some(t=>t.key===e)))},[me?.key]);let De=(0,q.useMemo)(()=>{if(!he||!V)return[];let e=[...he.byId.values()].map(({model:e,library:t})=>({model:e,library:t})),t=he.trees.filter(e=>e!==me?.id).map(e=>({model:{id:e,kind:`subtree`,ports:[],description:he.treeFiles.has(e)?`In ${he.treeFiles.get(e)}`:`A tree of this file`},library:he.treeFiles.has(e)?Tr(he.treeFiles.get(e)):`This file`})),n=new Map,r=(e,t)=>{let i=Zn(e);if(t>1&&i!==`SubTree`&&!he.byId.has(i)&&!n.has(i)){let t=e.children.filter(wn).length;n.set(i,{model:{id:i,kind:xt(i,t),ports:[],description:`Used in this file, in no library`},library:`Used here`})}e.children.forEach(e=>wn(e)&&r(e,t+1))};return fe.forEach(e=>r(e.node,1)),[...e,...t,...n.values()]},[he,V,me?.id,fe]),Oe=e=>{h(e),y(t=>({key:e,seq:(t?.seq??0)+1}))},Ae=(0,q.useCallback)((e,t={})=>{c({type:`edit`,document:e,tag:t.tag,tree:t.tree}),t.select!==void 0&&(h(t.select),t.select!==null&&y(e=>({key:t.select,seq:(e?.seq??0)+1})))},[]),je=async()=>{if(!V||j||!ye)return;if(s.readOnly){G(`${s.readOnly}: Save as…`,`error`);return}let e=Fr(V);te(!0);try{let t=await H.saveBehaviorTreeFile(s.path,e,s.base);t.conflict?(c({type:`conflict`,version:t.version}),G(`Not saved: the file changed on the robot since it was read`,`error`)):(c({type:`saved`,text:e,version:t.version}),G(`Saved ${Tr(s.path)}`))}catch(e){G(`Could not save ${s.path}: ${e instanceof Error?e.message:e}`,`error`)}finally{te(!1)}},Me=async e=>{(!ye||await le.confirm({title:`Discard the changes?`,message:`${Tr(s.path)} has changes not saved.`,confirmLabel:`Discard them`,danger:!0}))&&(h(null),L([]),c({type:`open`,path:e}))},Ne=(e,t)=>{if(!V||!U)return;let n=t??sr(U,ve);if(!n){G(`Select where it goes: a control node, or a node in one`,`error`);return}let r=rr(e.model,de);Ae(Un(V,U.nodes[n.parent].key,n.index,r),{select:r.key}),be&&O(!1)},Pe=(e,t)=>{if(!V||!U)return;let n=Wn(V,e,U.nodes[t.parent].key,t.index);n&&Ae(n,{select:e})},W=U&&ve!==null&&ve>0?U.nodes[ve]:null,Fe=W&&V?Mn(V,W.key)?.node??null:null,Ie=W&&U?W.parent:-1,Le=U&&Ie>=0?U.children[Ie]:[],K=W?Le.indexOf(ve):-1,Re=U&&Ie>=0?U.nodes[Ie].capacity>Le.length:!1,ze=()=>{V&&W&&U&&Ae(Hn(V,W.key),{select:U.nodes[Ie].key})},Be=()=>{V&&Fe&&(ai=Fe,navigator.clipboard?.writeText(di(V,Fe)).catch(()=>{}))},Ve=()=>{if(!V||!U||!ai)return;let e=sr(U,ve);if(!e){G(`Select where it goes: a control node, or a node in one`,`error`);return}let t=En(ai);Ae(Un(V,U.nodes[e.parent].key,e.index,t),{select:t.key})},He={moveEarlier:W&&K>0?()=>Pe(W.key,{parent:Ie,index:K-1,mode:`before`,node:Ie}):null,moveLater:W&&K>=0&&K<Le.length-1?()=>Pe(W.key,{parent:Ie,index:K+2,mode:`after`,node:Ie}):null,duplicate:V&&Fe&&Re&&U?()=>{let e=En(Fe);Ae(Un(V,U.nodes[Ie].key,K+1,e),{select:e.key})}:null,wrap:W?()=>re(`wrap`):null,replace:W&&W.kind!==`subtree`?()=>re(`replace`):null,unwrap:V&&W&&U&&cr(U,ve)?()=>Ae(Kn(V,W.key),{select:U.nodes[U.children[ve][0]].key}):null,remove:ze},Ue=async e=>{let t=fe.find(t=>t.id===e);if(t&&me){L(e=>[...e,me.key]),h(null),c({type:`tree`,key:t.key});return}let n=he?.treeFiles.get(e);n?await Me(n):G(`No tree ${e}, in the file nor its includes`,`error`)},We=async()=>{if(!V)return;let e=await le.prompt({title:`New tree`,label:`Its ID`,initial:lr(V,`Subtree`),confirmLabel:`Add`});if(!e)return;if(fe.some(t=>t.id===e)){G(`There is a tree ${e} already`,`error`);return}let t=ur(V,e);h(null),Ae(t.document,{tree:t.key})},Ge=t=>{let n=t.target,r=t.ctrlKey||t.metaKey,i=t.key.toLowerCase();if(r&&i===`s`){t.preventDefault(),je();return}if(n.closest(`input, textarea, select, [role="dialog"]`)||!V)return;let a=e=>{t.preventDefault(),e?.()};if(r&&i===`z`)a(()=>c({type:t.shiftKey?`redo`:`undo`}));else if(r&&i===`y`)a(()=>c({type:`redo`}));else if(r&&i===`c`)a(Be);else if(r&&i===`x`)a(W&&(()=>(Be(),ze())));else if(r&&i===`v`)a(Ve);else if(r&&i===`d`)a(He.duplicate);else if((i===`delete`||i===`backspace`)&&W)a(ze);else if(i===`escape`)h(null);else if((i===`f2`||i===`enter`)&&W)a(()=>oe.current?.querySelector(`.bte-properties input`)?.focus());else if(i.startsWith(`arrow`)&&U){let[n,r,o,s]=e.direction===`vertical`?[`arrowup`,`arrowdown`,`arrowleft`,`arrowright`]:[`arrowleft`,`arrowright`,`arrowup`,`arrowdown`],c=ve??0;if(t.altKey){a(i===o?He.moveEarlier:i===s?He.moveLater:null);return}let l;if(i===n)l=U.nodes[c].parent>=0?U.nodes[c].parent:void 0;else if(i===r)l=g.has(U.nodes[c].key)?void 0:U.children[c][0];else if(c>0){let e=U.children[U.nodes[c].parent];l=e[e.indexOf(c)+(i===o?-1:+(i===s))]}l!==void 0&&a(()=>Oe(U.nodes[l].key))}},qe=U?U.nodes.flatMap((e,t)=>e.problems.length>0?[t]:[]):[],Je=()=>{if(U&&qe.length>0){let e=qe.find(e=>e>(ve??-1))??qe[0];Oe(U.nodes[e].key)}},Ye;Ye=s.path?w||!V&&s.savedText!==null?(0,J.jsx)(Mr,{text:V?Fr(V):s.savedText??``,readOnly:!1,onDocument:e=>Ae(e,{tag:`xml`}),onDone:()=>c({type:`seal`})}):V?U?(0,J.jsx)(br,{ref:z,graph:U,version:`${s.path}#${me?.key}`,direction:e.direction,showPorts:S,folded:g,selected:m,readOnly:!1,focus:v,fitRequest:b,covered:Ee,onSelect:h,onOpen:e=>{let t=ge.get(e),n=t===void 0?void 0:U.nodes[t];n?.kind===`subtree`&&n.ports.ID?Ue(n.ports.ID):n&&t>0&&oe.current?.querySelector(`.bte-properties input`)?.focus()},onFold:e=>_(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n}),onMove:Pe}):(0,J.jsxs)(`div`,{className:`widget-message bte-empty`,children:[(0,J.jsx)(`p`,{children:`No BehaviorTree in this file.`}),(0,J.jsx)(`button`,{type:`button`,className:`button primary`,onClick:()=>void We(),children:`Add a tree`})]}):(0,J.jsx)(`div`,{className:`widget-message`,children:s.error??`Reading the tree…`}):(0,J.jsxs)(`div`,{className:`widget-message bte-empty`,children:[(0,J.jsx)(`p`,{children:`No tree file: open one of the robot, or make a new one. Its file can be set in edit mode too.`}),(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>F(`open`),children:`Open…`}),` `,(0,J.jsx)(`button`,{type:`button`,className:`button primary`,onClick:()=>F(`new`),children:`New…`})]})]});let Xe=null;we&&V&&U&&he&&ve!==null&&(ve===0&&me?Xe=(0,J.jsx)($r,{id:me.id,isMain:pe?.key===me.key,trees:fe.filter(e=>e.key!==me.key).map(e=>e.id),problems:U.nodes[0].problems,onRename:e=>Ae(dr(V,me.key,e)),onMain:()=>Ae(fr(V,me.id)),onRemove:fe.length>1?()=>{h(null),Ae(pr(V,me.key),{tree:fe.find(e=>e.key!==me.key).key})}:null,onClose:()=>h(null)}):W&&Fe&&(Xe=(0,J.jsx)(Qr,{node:W,element:Fe,catalog:he,format:de,actions:He,onAttribute:(e,t,n)=>Ae(Fn(V,W.key,e,t),n?{tag:`${W.key}:${e}`}:{}),onRenameAttribute:(e,t)=>Ae(In(V,W.key,e,t)),onSeal:()=>c({type:`seal`}),onOpenTree:e=>void Ue(e),onClose:()=>h(null)},W.key)));let Ze=[];s.error&&(V||s.savedText!==null)&&Ze.push({text:s.error,tone:`error`}),s.external&&Ze.push({text:s.external.text===null?`Not saved: the file changed on the robot since it was read`:`The file changed on the robot, and this one has changes`,tone:`warning`,actions:[{label:`Load it`,run:()=>c({type:`reload`}),disabled:s.external.text===null},{label:`Keep mine`,run:()=>c({type:`keep`})}]});let Qe=s.path?j?{text:`Saving ${Tr(s.path)}…`,tone:`running`}:ye?{text:`${Tr(s.path)} · changed`,tone:`changed`}:s.readOnly&&V?{text:`${Tr(s.path)} · read-only: ${s.readOnly}`,tone:`idle`}:{text:V?`${Tr(s.path)} · saved`:Tr(s.path),tone:V?`success`:`idle`}:{text:`No file`,tone:`idle`};return(0,J.jsxs)(`div`,{ref:oe,className:`bt bte`,tabIndex:-1,onKeyDown:Ge,children:[Ze.map(e=>(0,J.jsxs)(`div`,{className:`bt-banner ${e.tone} bte-banner`,title:e.text,children:[(0,J.jsx)(`span`,{children:e.text}),e.actions?.map(e=>(0,J.jsx)(`button`,{type:`button`,className:`link-button`,disabled:e.disabled,onClick:()=>{e.run(),oe.current?.focus({preventScroll:!0})},children:e.label},e.label))]},e.text)),(0,J.jsxs)(`div`,{className:`bte-toolbar`,role:`toolbar`,"aria-label":`Editor`,children:[(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":Se,title:`The nodes to add`,"aria-label":`The nodes to add`,disabled:!V||w,onClick:()=>O(!Se),children:(0,J.jsx)(_e,{width:17,height:17})}),ie.length>0&&(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Back to the tree it was opened from`,"aria-label":`Back`,onClick:()=>{h(null),c({type:`tree`,key:ie.at(-1)}),L(e=>e.slice(0,-1))},children:(0,J.jsx)(Te,{width:17,height:17,style:{transform:`scaleX(-1)`}})}),(0,J.jsx)(`select`,{className:`bte-tree-select`,"aria-label":`The tree shown`,value:me?.key??``,disabled:fe.length===0||w,onChange:e=>{h(null),L([]),c({type:`tree`,key:Number(e.target.value)})},children:fe.map(e=>(0,J.jsxs)(`option`,{value:e.key,children:[e.id||`Unnamed tree`,e.key===pe?.key?` (main)`:``]},e.key))}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`New tree`,"aria-label":`New tree`,disabled:!V||w,onClick:()=>void We(),children:(0,J.jsx)(ne,{width:17,height:17})}),(0,J.jsx)(`span`,{className:`overlay-separator`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Undo (Ctrl+Z)`,"aria-label":`Undo`,disabled:s.past.length===0,onClick:()=>c({type:`undo`}),children:(0,J.jsx)(l,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Redo (Ctrl+Shift+Z)`,"aria-label":`Redo`,disabled:s.future.length===0,onClick:()=>c({type:`redo`}),children:(0,J.jsx)(ke,{width:17,height:17})}),(0,J.jsx)(`span`,{className:`overlay-separator bte-wide`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,title:`Fit the tree`,"aria-label":`Fit the tree`,disabled:!U||w,onClick:()=>x(e=>e+1),children:(0,J.jsx)(i,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,"aria-pressed":S,title:`The ports on the nodes`,"aria-label":`The ports on the nodes`,disabled:!U||w,onClick:()=>C(e=>!e),children:(0,J.jsx)(P,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,"aria-pressed":w,title:`The XML`,"aria-label":`The XML`,disabled:!s.path||!V&&s.savedText===null,onClick:()=>T(e=>!e),children:(0,J.jsx)(ce,{width:17,height:17})}),(0,J.jsx)(`span`,{className:`bte-toolbar-end`}),(0,J.jsxs)(`button`,{type:`button`,className:`button bte-save${ye?` primary`:``}`,disabled:!ye||j||s.readOnly!==null,title:s.readOnly??`Save (Ctrl+S)`,onClick:()=>void je(),children:[(0,J.jsx)(xe,{width:16,height:16}),(0,J.jsx)(`span`,{className:`bte-save-label`,children:`Save`})]}),(0,J.jsxs)(`div`,{className:`menu`,children:[(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-label":`File`,title:`File`,"aria-expanded":k,onClick:()=>A(e=>!e),children:(0,J.jsx)(M,{width:17,height:17})}),k&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`div`,{className:`menu-backdrop`,onPointerDown:()=>A(!1)}),(0,J.jsxs)(`div`,{className:`menu-list`,role:`menu`,onClick:()=>A(!1),children:[(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,className:`bte-narrow`,disabled:!U||w,onClick:()=>x(e=>e+1),children:`Fit the tree`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,className:`bte-narrow`,disabled:!U||w,onClick:()=>C(e=>!e),children:S?`Hide the ports`:`Show the ports`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,className:`bte-narrow`,disabled:!s.path||!V&&s.savedText===null,onClick:()=>T(e=>!e),children:w?`Back to the graph`:`The XML`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:()=>F(`open`),children:`Open…`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:()=>F(`new`),children:`New file…`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,disabled:!V,onClick:()=>F(`save-as`),children:`Save as…`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,disabled:!V,onClick:()=>V&&fi(Tr(s.path)||`tree.xml`,Fr(V)),children:`Download`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,disabled:!ye,onClick:async()=>{await le.confirm({title:`Discard the changes?`,message:`The file is read again from the robot.`,confirmLabel:`Discard them`,danger:!0})&&(h(null),c({type:`open`,path:s.path}))},children:`Discard the changes`})]})]})]})]}),(0,J.jsxs)(`div`,{className:`bte-body${be?` narrow`:``}`,children:[Se&&(0,J.jsx)(Gr,{items:De,libraries:B.map(t=>({path:t,removable:u.includes(t)&&!ci(e.libraries).includes(t)})),warnings:f?.warnings??[],onAdd:e=>Ne(e),onDrag:(e,t)=>{ae({item:e,at:t}),z.current?.dragNew(t)},onDrop:(e,t)=>{let n=t?z.current?.dragNew(t)??null:null;z.current?.dragNew(null),ae(null),n&&Ne(e,n)},onLoadLibrary:()=>F(`library`),onRemoveLibrary:e=>{let t=u.filter(t=>t!==e);d(t),ui(r,t)},onClose:()=>O(!1)}),(0,J.jsxs)(`div`,{className:`bt-main bte-canvas`,children:[Ye,Xe]})]}),(0,J.jsxs)(`div`,{className:`bt-status ${Qe.tone}`,title:s.path||void 0,children:[(0,J.jsx)(`span`,{className:`bt-dot`,"aria-hidden":`true`}),(0,J.jsx)(`span`,{className:`bt-status-text`,children:Qe.text}),qe.length>0&&!w&&(0,J.jsxs)(`button`,{type:`button`,className:`bte-problems-chip`,onClick:Je,title:`Show the next`,children:[qe.length,` `,qe.length===1?`problem`:`problems`]})]}),R&&(0,J.jsx)(`div`,{className:`bt-node bte-palette-ghost`,style:{left:R.at.x+12,top:R.at.y+8},children:(0,J.jsxs)(`div`,{className:`bt-node-head`,children:[(0,J.jsx)($t,{node:{kind:R.item.model.kind,type:R.item.model.id}}),(0,J.jsx)(`span`,{className:`bt-node-type`,children:R.item.model.id})]})}),I&&V&&W&&Fe&&he&&(0,J.jsx)(ei,{title:I===`wrap`?`Wrap ${W.type} in`:`Replace ${W.type} with`,models:[...he.byId.values()],kinds:I===`wrap`?[`decorator`,`control`]:W.kind===`control`||W.kind===`decorator`?[W.kind]:[`action`,`condition`],onPick:e=>{if(re(null),I===`wrap`){let t=rr(e,de);Ae(Gn(V,W.key,t),{select:t.key})}else Ae(Ln(V,Fe.key,mr(Fe,e,de)),{select:Fe.key})},onClose:()=>re(null)}),(N===`open`||N===`library`)&&(0,J.jsx)(Tt,{kind:`behavior-tree`,start:s.path.startsWith(`/`)||s.path.startsWith(`~/`)?s.path:`~`,onChoose:e=>{if(F(null),N===`open`)Me(e);else if(!B.includes(e)){let t=[...u,e];d(t),ui(r,t)}},onClose:()=>F(null)}),(N===`new`||N===`save-as`)&&(0,J.jsx)(jr,{mode:N,initial:N===`new`?`${s.path.startsWith(`/`)||s.path.startsWith(`~/`)?s.path.replace(/\/[^/]*$/,``):`~`}/behavior_tree.xml`:s.path.startsWith(`/`)||s.path.startsWith(`~/`)?s.path.replace(/(\.xml)?$/i,`_copy.xml`):`~/${Tr(s.path)}`,text:V?Fr(V):kr(4),onSaved:(e,t,n)=>{F(null),N===`save-as`?(c({type:`saved`,text:t,version:n,path:e}),G(`Saved as ${e}`)):Me(e)},onClose:()=>F(null)})]})}var mi=Ve({type:`behavior-tree-editor`,name:`Behavior Tree Editor`,description:`Edits a behavior tree’s XML file of the robot as a graph: nodes from palettes, ports, subtrees.`,icon:k,defaultSize:{w:10,h:7},minSize:{w:4,h:4},component:pi,properties:[{key:`tree`,label:`Tree file`,kind:`behavior-tree`,default:``,placeholder:`~/behavior_trees/main.xml`,help:`The XML file it opens (/…, ~/…, package://…): its toolbar opens others, and makes new ones. Uploads are saved as robot files`},{key:`libraries`,label:`Node libraries`,kind:`text`,default:``,placeholder:`~/my_robot/behavior_trees/my_nodes.xml
|
|
24
|
+
package://my_robot_bt/nodes.xml`,help:`XML files of TreeNodesModel (as Groot exports them), one a line: their nodes join the palette, besides BT.CPP’s, Nav2’s and the file’s`},{key:`direction`,label:`Graph direction`,kind:`select`,default:`vertical`,options:[{value:`vertical`,label:`Top to bottom`},{value:`horizontal`,label:`Left to right`}]},{key:`showPorts`,label:`Show the ports in the graph`,kind:`boolean`,default:!1,help:`The toolbar switches them; the side panel edits them`}]}),hi=(0,q.memo)(function({index:e,node:t,depth:n,state:r,selected:i,folded:a,now:o,onSelect:s,onFold:c}){let l=Pt(r?.status),u=l===`idle`&&r?.result?Pt(r.result):null,d=``;return r?.status&&(d=Ft(r.status),l===`running`&&r.since&&o?d+=` · ${Rt(o-r.since)}`:u&&(d+=` · was ${r.result.toLowerCase()}`)),(0,J.jsxs)(`li`,{className:`bt-row ${l}${u?` was-${u}`:``}${i?` selected`:``}`,"data-row":e,children:[(0,J.jsx)(`span`,{className:`bt-row-indent`,style:{width:n*14}}),a>=0?(0,J.jsx)(`button`,{type:`button`,className:`bt-row-fold`,"aria-expanded":a===0,"aria-label":a===0?`Fold ${t.name}`:`Unfold ${t.name}`,title:a===0?void 0:`${a} nodes folded away`,onClick:()=>c(e),children:(0,J.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`12`,height:`12`,"aria-hidden":`true`,children:(0,J.jsx)(`path`,{d:`m9 6 6 6-6 6`,fill:`none`,stroke:`currentColor`,strokeWidth:`2.5`,strokeLinecap:`round`})})}):(0,J.jsx)(`span`,{className:`bt-row-fold`}),(0,J.jsxs)(`button`,{type:`button`,className:`bt-row-main`,title:`${Q(t)}: ${t.type}`,onClick:()=>s(e),children:[(0,J.jsx)(`span`,{className:`bt-dot`,"aria-hidden":`true`}),(0,J.jsx)($t,{node:t}),(0,J.jsxs)(`span`,{className:`bt-row-labels`,children:[(0,J.jsx)(`span`,{className:`bt-row-type`,children:t.type}),t.name!==t.type&&(0,J.jsx)(`span`,{className:`bt-row-name`,children:t.name})]}),(0,J.jsxs)(`span`,{className:`bt-row-status`,children:[d,r&&r.successes+r.failures>0&&(0,J.jsxs)(`span`,{className:`bt-row-counts`,children:[(0,J.jsxs)(`span`,{className:`success`,children:[`✓`,r.successes]}),` `,(0,J.jsxs)(`span`,{className:`failure`,children:[`✗`,r.failures]})]})]})]})]})});function gi({model:e,folded:t,selected:n,follow:r,now:i,onSelect:a,onFold:o}){let s=(0,q.useRef)(null),{nodes:c,treeSize:l,children:u,depths:d,states:f}=e,p=(0,q.useMemo)(()=>{let e=Array(c.length).fill(1);for(let t=l-1;t>0;t--){let n=c[t].parent;n>=0&&(e[n]+=e[t])}let n=[];for(let r=0;r<c.length;){let i=t.has(r)?e[r]-1:0;n.push({index:r,folded:u[r].length===0?-1:i}),r+=i+1}return n},[c,l,u,t]),m=It(e,e=>{let n=e;for(let r=c[e].parent;r>=0;r=c[r].parent)t.has(r)&&(n=r);return n}).join(`,`);(0,q.useEffect)(()=>{let e=s.current,t=e?.querySelector(`[data-row="${m.split(`,`)[0]}"]`);r&&e&&t&&(t.offsetTop<e.scrollTop?e.scrollTop=t.offsetTop:t.offsetTop+t.offsetHeight>e.scrollTop+e.clientHeight&&(e.scrollTop=t.offsetTop+t.offsetHeight-e.clientHeight))},[r,m]);let h=({index:e,folded:t})=>(0,J.jsx)(hi,{index:e,node:c[e],depth:d[e],state:f[e],selected:n===e,folded:t,now:f[e]?.status===`RUNNING`?i:0,onSelect:a,onFold:o},e),g=p.filter(e=>e.index<l),_=p.filter(e=>e.index>=l);return(0,J.jsxs)(`div`,{ref:s,className:`bt-list`,children:[g.length>0&&(0,J.jsx)(`ul`,{children:g.map(h)}),_.length>0&&(0,J.jsxs)(J.Fragment,{children:[l>0&&(0,J.jsx)(`h3`,{className:`bt-list-heading`,children:`Not in the tree file`}),(0,J.jsx)(`ul`,{children:_.map(h)})]})]})}var _i=420,vi=316,yi=240;function bi(e){let[t,n]=(0,q.useState)(()=>H.serverNow());return(0,q.useEffect)(()=>{let t=setInterval(()=>n(H.serverNow()),e);return()=>clearInterval(t)},[e]),t}function xi(e,t,n){if(t.state===`error`)return{text:t.message,tone:`error`};let r=t=>+![`action`,`condition`].includes(e.nodes[t].kind??``),i=It(e).sort((e,t)=>r(e)-r(t));if(i.length>0){let t=i.slice(0,2).map(t=>e.nodes[t].name),r=e.states[i[0]]?.since;return{text:`Running ${t.join(`, `)}${i.length>2?` and ${i.length-2} more`:``}${r?` · ${Rt(n-r)}`:``}`,tone:`running`}}let a=e.treeSize>0?e.states[0]:void 0;return a?.status===`SUCCESS`||a?.status===`FAILURE`?{text:a.status===`SUCCESS`?`Succeeded`:`Failed`,tone:Pt(a.status)}:a?.result?{text:`Idle · its last run ${a.result===`SUCCESS`?`succeeded`:`failed`}${a.since?`, ${Rt(n-a.since)} ago`:``}`,tone:`idle`}:t.state===`waiting`?{text:t.message,tone:`idle`}:{text:`Idle`,tone:`idle`}}function Si({model:e,index:t,now:n,onSelect:r,onClose:i}){let a=e.nodes[t],o=e.states[t],s=[];for(let t=a.parent;t>=0;t=e.nodes[t].parent)s.unshift(t);let c=Object.entries(a.ports),l=e.transitions.filter(e=>e.node===t).slice(-8).reverse(),u=`not seen changing`;return o?.since?u=`for ${Rt(n-o.since)}`:o?.status&&(u=`since before this page`),(0,J.jsxs)(`aside`,{className:`bt-details`,"aria-label":`${a.name}: details`,children:[(0,J.jsxs)(`header`,{className:`bt-details-header`,children:[(0,J.jsx)($t,{node:a,size:18}),(0,J.jsxs)(`div`,{className:`bt-details-title`,children:[(0,J.jsx)(`strong`,{children:a.type}),(0,J.jsxs)(`span`,{children:[a.name===a.type?``:`${a.name} · `,Q(a)]})]}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Close`,onClick:i,children:(0,J.jsx)(B,{width:16,height:16})})]}),(0,J.jsxs)(`div`,{className:`bt-details-body`,children:[s.length>0&&(0,J.jsx)(`nav`,{className:`bt-path`,"aria-label":`Its parents`,children:s.map(t=>(0,J.jsx)(`button`,{type:`button`,onClick:()=>r(t),children:e.nodes[t].name},t))}),(0,J.jsxs)(`dl`,{className:`bt-facts`,children:[(0,J.jsx)(`dt`,{children:`Status`}),(0,J.jsxs)(`dd`,{children:[o?.status?(0,J.jsx)(`span`,{className:`bt-pill ${Pt(o.status)}`,children:Ft(o.status)}):`Unknown`,` `,(0,J.jsx)(`span`,{className:`bt-muted`,children:u})]}),o?.result&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`dt`,{children:`Last result`}),(0,J.jsx)(`dd`,{children:(0,J.jsx)(`span`,{className:`bt-pill ${Pt(o.result)}`,children:Ft(o.result)})})]}),(0,J.jsx)(`dt`,{children:`Seen`}),(0,J.jsxs)(`dd`,{children:[o?.changes??0,` transitions · `,(0,J.jsxs)(`span`,{className:`success`,children:[o?.successes??0,` successes`]}),` ·`,` `,(0,J.jsxs)(`span`,{className:`failure`,children:[o?.failures??0,` failures`]})]})]}),c.length>0&&(0,J.jsxs)(`section`,{children:[(0,J.jsx)(`h3`,{children:`Ports`}),(0,J.jsx)(`dl`,{className:`bt-ports`,children:c.map(([e,t])=>(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:e}),(0,J.jsx)(`dd`,{className:/^\{.*\}$/.test(t)?`entry`:void 0,children:t})]},e))})]}),(0,J.jsxs)(`section`,{children:[(0,J.jsx)(`h3`,{children:`Latest transitions`}),l.length>0?(0,J.jsx)(`ol`,{className:`bt-node-log`,children:l.map(e=>(0,J.jsxs)(`li`,{children:[(0,J.jsx)(`time`,{children:zt(e.time)}),(0,J.jsx)(`span`,{className:`bt-pill ${Pt(e.from)}`,children:Ft(e.from)}),`→`,(0,J.jsx)(`span`,{className:`bt-pill ${Pt(e.to)}`,children:Ft(e.to)})]},e.id))}):(0,J.jsx)(`p`,{className:`bt-muted`,children:`None seen`})]})]})]})}function Ci({model:e,onSelect:t}){let n=(0,q.useRef)(null),r=(0,q.useRef)(!0);return(0,q.useLayoutEffect)(()=>{let e=n.current;e&&r.current&&(e.scrollTop=e.scrollHeight)},[e.transitions]),(0,J.jsx)(`section`,{className:`bt-log`,"aria-label":`Latest transitions`,children:e.transitions.length===0?(0,J.jsx)(`p`,{className:`bt-muted bt-log-empty`,children:`No transition yet`}):(0,J.jsx)(`ol`,{ref:n,onScroll:e=>{let t=e.currentTarget;r.current=t.scrollHeight-t.scrollTop-t.clientHeight<8},children:e.transitions.map(n=>(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,onClick:()=>t(n.node),children:[(0,J.jsx)(`time`,{children:zt(n.time)}),(0,J.jsx)(`span`,{className:`bt-log-node`,children:Lt(e.nodes[n.node])}),(0,J.jsx)(`span`,{className:`bt-pill ${Pt(n.from)}`,children:Ft(n.from)}),`→`,(0,J.jsx)(`span`,{className:`bt-pill ${Pt(n.to)}`,children:Ft(n.to)})]})},n.id))})})}function wi({config:e,editing:t}){let[n,r]=(0,q.useReducer)(Nt,At),[a,o]=(0,q.useState)({state:`waiting`,message:`Connecting…`}),[s,c]=(0,q.useState)(null),[l,d]=(0,q.useState)(!0),[f,p]=(0,q.useState)(!1),[m,g]=(0,q.useState)(null),[_,v]=(0,q.useState)(new Set),[y,b]=(0,q.useState)(null),[S,C]=(0,q.useState)(0),[w,T]=(0,q.useState)(0),E=(0,q.useRef)(null),[D,ee]=(0,q.useState)(null),[O,k]=(0,q.useState)(null),j=(0,q.useRef)(null),[M,N]=(0,q.useState)(null),[P,F]=(0,q.useState)(!1),[ne,I]=(0,q.useState)(!1),re=(0,q.useRef)(null),ie=bi(O?.playing?250:1e3),L=e.topic.trim(),R=e.tree.trim();(0,q.useEffect)(()=>{if(r({type:`reset`}),N(null),k(null),j.current=null,!L&&!D){o({state:`error`,message:`No log topic: set one in edit mode`});return}o({state:`waiting`,message:`Connecting…`});let e={status:(e,t)=>o({state:e,message:t}),tree:e=>r({type:`tree`,tree:e}),update:e=>r({type:`update`,update:e}),recording:N,playback:e=>k({...e,at:Date.now()})};if(D){let{id:t,unsubscribe:n}=H.subscribeBehaviorTreePlayback({bag:D,topic:L,tree:R},e);return j.current=t,n}return H.subscribeBehaviorTree({topic:L,tree:R},e)},[L,R,D]);let ae=(0,q.useCallback)(e=>{j.current!==null&&(k(t=>t&&{...t,time:e.time??Cr(t),playing:e.playing??t.playing,speed:e.speed??t.speed,at:Date.now()}),H.controlBehaviorTreePlayback(j.current,e))},[]),oe=async()=>{try{let e=await H.recordBehaviorTree(L,null);e&&(re.current=e,G(`Recorded ${L} into ${e}`))}catch(e){G(`Could not stop recording ${L}: ${e instanceof Error?e.message:e}`,`error`)}};(0,q.useEffect)(()=>{g(null),v(new Set)},[n.version]),(0,q.useEffect)(()=>{let e=E.current;if(!e)return;let t=new ResizeObserver(([e])=>T(e.contentRect.width));return t.observe(e),()=>t.disconnect()},[]),(0,q.useEffect)(()=>{if(m===null)return;let e=e=>e.key===`Escape`&&g(null);return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[m]);let z=(0,q.useCallback)(e=>{v(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n})},[]),se=(0,q.useCallback)(e=>{g(e),b(t=>({node:e,seq:(t?.seq??0)+1}))},[]),ce=n.treeSize>0,le=ce?s??(e.view===`auto`?w<_i?`list`:`graph`:e.view):`list`,B=m!==null&&n.nodes[m]!==void 0,ue=B&&w-vi>=yi?vi:0,V=O?Cr(O):ie,de=xi(n,a,V);D&&O&&!O.error&&(de.text=`${Tr(D)}: ${de.text}`);let fe=[];n.error&&fe.push({text:`${n.error}. The nodes are the log’s`,tone:`error`}),n.mismatch&&fe.push({text:n.mismatch,tone:`warning`}),n.warnings.length>0&&fe.push({text:n.warnings[0]+(n.warnings.length>1?` (and ${n.warnings.length-1} more)`:``),title:n.warnings.join(`
|
|
25
|
+
`),tone:`warning`});let pe;return pe=n.received?n.nodes.length===0?(0,J.jsx)(`div`,{className:`widget-message`,children:R?`The nodes will show as they change`:`No tree file: the nodes will show as they change. Set the tree’s file in edit mode to see it whole`}):le===`graph`?(0,J.jsx)(hn,{model:n,direction:e.direction,showPorts:e.showPorts,folded:_,selected:m,follow:l,focus:y,fitRequest:S,covered:ue,onSelect:g,onFold:z,onPan:()=>d(!1)}):(0,J.jsx)(gi,{model:n,folded:_,selected:m,follow:l,now:V,onSelect:g,onFold:z}):(0,J.jsx)(`div`,{className:`widget-message`,children:a.state===`error`?a.message:`Reading the tree…`}),(0,J.jsxs)(`div`,{ref:E,className:`bt`,children:[fe.map(e=>(0,J.jsx)(`div`,{className:`bt-banner ${e.tone}`,title:e.title??e.text,children:e.text},e.text)),(0,J.jsxs)(`div`,{className:`bt-main ${le}`,children:[pe,(0,J.jsxs)(`div`,{className:`overlay-toolbar`,children:[le===`graph`&&(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Fit the tree`,"aria-label":`Fit the tree`,onClick:()=>{d(!1),C(e=>e+1)},children:(0,J.jsx)(i,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":l,title:`Follow the running nodes`,"aria-label":`Follow the running nodes`,onClick:()=>d(e=>!e),children:(0,J.jsx)(te,{width:17,height:17})}),(0,J.jsx)(`span`,{className:`overlay-separator`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":le===`graph`,title:ce?`As a graph`:`As a graph: needs the tree’s file`,"aria-label":`As a graph`,disabled:!ce,onClick:()=>c(`graph`),children:(0,J.jsx)(u,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":le===`list`,title:`As a list`,"aria-label":`As a list`,onClick:()=>c(`list`),children:(0,J.jsx)(A,{width:17,height:17})}),(0,J.jsx)(`span`,{className:`overlay-separator`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":f,title:`The latest transitions`,"aria-label":`The latest transitions`,onClick:()=>p(e=>!e),children:(0,J.jsx)(h,{width:17,height:17})}),(0,J.jsx)(`span`,{className:`overlay-separator`}),!D&&(0,J.jsx)(`button`,{type:`button`,className:`overlay-button${M?` recording`:``}`,"aria-pressed":M!==null,title:M?`Stop recording into ${M.path}`:`Record the log into a rosbag`,"aria-label":M?`Stop recording`:`Record the log`,disabled:!L||t,onClick:()=>M?void oe():F(!0),children:(0,J.jsx)(U,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":D!==null,title:D?`Back to the live log, from ${D}`:`Play a rosbag back`,"aria-label":D?`Back to the live log`:`Play a rosbag back`,disabled:t,onClick:()=>D?ee(null):I(!0),children:(0,J.jsx)(x,{width:17,height:17})})]}),B&&(0,J.jsx)(Si,{model:n,index:m,now:V,onSelect:se,onClose:()=>g(null)})]}),f&&(0,J.jsx)(Ci,{model:n,onSelect:se}),D&&O&&(0,J.jsx)(Or,{playback:O,onControl:ae,onClose:()=>ee(null)}),(0,J.jsxs)(`div`,{className:`bt-status ${de.tone}`,title:de.text,children:[(0,J.jsx)(`span`,{className:`bt-dot`,"aria-hidden":`true`}),(0,J.jsx)(`span`,{className:`bt-status-text`,children:de.text}),M&&!D&&(0,J.jsxs)(`span`,{className:`bt-rec`,title:`Recording into ${M.path}`,children:[`REC `,Rt(ie-M.since)]})]}),P&&(0,J.jsx)(Dr,{topic:L,folder:e.recordFolder,onRecording:e=>re.current=e,onClose:()=>F(!1)}),ne&&(0,J.jsx)(Tt,{kind:`bag`,start:re.current?.replace(/\/+[^/]+\/*$/,``)||e.recordFolder,onChoose:e=>{I(!1),re.current=e,ee(e)},onClose:()=>I(!1)})]})}var Ti=Ve({type:`behavior-tree`,name:`Behavior Tree Inspector`,description:`What a behavior tree is doing: its running branch, its nodes’ status, and their transitions.`,icon:u,defaultSize:{w:8,h:6},minSize:{w:3,h:3},component:wi,properties:[{key:`topic`,label:`Log topic`,kind:`topic`,default:`/behavior_tree_log`,topicTypes:[`nav2_msgs/msg/BehaviorTreeLog`],help:`nav2_msgs/BehaviorTreeLog: Nav2’s bt_navigator logs its tree on /behavior_tree_log`},{key:`tree`,label:`Tree file`,kind:`behavior-tree`,default:``,placeholder:`package://nav2_bt_navigator/behavior_trees/navigate_to_pose_w_replanning_and_recovery.xml`,help:`The XML of the tree the robot runs (/…, ~/…, package://…), or upload it. Without it, the nodes are listed as they change`},{key:`view`,label:`View`,kind:`select`,default:`auto`,options:[{value:`auto`,label:`Automatic: the graph, the list when narrow`},{value:`graph`,label:`Graph`},{value:`list`,label:`List`}],help:`Its toolbar switches between them`},{key:`direction`,label:`Graph direction`,kind:`select`,default:`vertical`,options:[{value:`vertical`,label:`Top to bottom`},{value:`horizontal`,label:`Left to right`}],visible:e=>e.view!==`list`},{key:`showPorts`,label:`Show the ports in the graph`,kind:`boolean`,default:!1,help:`The nodes’ parameters and blackboard entries ({goal}); their details show them anyway`,visible:e=>e.view!==`list`},{key:`recordFolder`,label:`Recordings folder`,kind:`string`,default:`~/bags`,help:`Where the record button puts its rosbags, and the playback button looks for them first`}]}),Ei=5e3;function Di(e){let t=/^#([0-9a-f]{6})$/i.exec(e)?.[1];if(!t)return`#fff`;let[n,r,i]=[0,2,4].map(e=>parseInt(t.slice(e,e+2),16)/255);return .2126*n+.7152*r+.0722*i>.6?`#111`:`#fff`}function Oi(e){let t=Math.max(0,Math.floor(e/1e3));return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}function ki(e){return e.error?{text:e.error,ok:!1}:e.signal?{text:`Stopped (${e.signal})`,ok:!1}:e.exitCode===0?{text:`Done`,ok:!0}:{text:`Exit code ${e.exitCode}`,ok:!1}}function Ai({config:e,instance:t,panelId:n,editing:r}){let i=v(n,t.id),a=Ke(),[o,s]=(0,q.useState)(null),[,c]=(0,q.useState)(0),l=(0,q.useRef)(null),u=i?.running??!1,d=u||o!==null,f=e.label||`Run`;(0,q.useEffect)(()=>{o&&i!==o.from&&s(null)},[i,o]),(0,q.useEffect)(()=>{if(!d)return;let e=setInterval(()=>{c(e=>e+1),s(e=>e&&Date.now()-e.at>Ei?null:e)},1e3);return()=>clearInterval(e)},[d]),(0,q.useEffect)(()=>{let e=l.current;e&&(e.scrollTop=e.scrollHeight)},[i?.output]);let p=async()=>{if(r)return;let o={panelId:n,widgetId:t.id};u?e.allowStop&&await a.confirm({title:`Stop "${f}"?`,message:`The command gets SIGINT, then SIGTERM and SIGKILL if it does not stop.`,confirmLabel:`Stop`,danger:!0})&&H.send({type:`command.stop`,...o}):d||(e.command.trim()?(!e.confirm||await a.confirm({title:`Run "${f}"?`,message:(0,J.jsx)(`pre`,{className:`dialog-command`,children:e.command}),confirmLabel:`Run`}))&&(H.send({type:`command.run`,...o})?s({from:i,at:Date.now()}):G(`Not connected to the robot`,`error`)):G(`"${f}" has no command: set one in edit mode`,`error`))},m=null;if(d)m={text:`Running ${u&&i?Oi(H.serverNow()-i.startedAt):``}${u&&e.allowStop?` · press to stop`:``}`,className:``};else if(i){let{text:e,ok:t}=ki(i);m={text:`${t?`✓`:`✗`} ${e}`,className:t?`ok`:`failed`}}let h=d?e.runningColor:e.color;return(0,J.jsxs)(`div`,{className:`command-button${e.showOutput?` with-output`:``}`,children:[(0,J.jsxs)(`button`,{type:`button`,className:`command-button-face${d?` busy`:``}`,style:{backgroundColor:h,color:Di(h)},onClick:p,title:e.command,tabIndex:r?-1:0,children:[(0,J.jsx)(`span`,{className:`command-button-label`,children:f}),m&&(0,J.jsx)(`span`,{className:`command-button-status ${m.className}`,children:m.text})]}),e.showOutput&&(0,J.jsx)(`pre`,{ref:l,className:`command-output`,children:i?.output||(d?``:`No output yet`)})]})}var ji=Ve({type:`button`,name:`Button`,description:`Run a bash command on the robot, e.g. start a service or a launch file.`,icon:W,defaultSize:{w:3,h:1},minSize:{w:1,h:1},component:Ai,properties:[{key:`label`,label:`Label`,kind:`string`,default:`Run`},{key:`command`,label:`Bash command`,kind:`text`,default:``,placeholder:`ros2 launch my_robot navigation.launch.py`,help:`Runs with bash -c, as the server's user, in the workspace's environment`},{key:`confirm`,label:`Ask before running`,kind:`boolean`,default:!1},{key:`allowStop`,label:`Press again to stop`,kind:`boolean`,default:!0,help:`While the command runs, pressing the button stops it`},{key:`showOutput`,label:`Show output`,kind:`boolean`,default:!1,help:`The last lines the command printed, below the button`},{key:`color`,label:`Colour`,kind:`color`,default:`#2f6fed`},{key:`runningColor`,label:`Colour while running`,kind:`color`,default:`#e8890c`}]}),Mi=3e3,Ni=2e3;function Pi(e,t,n){let r=window.devicePixelRatio||1,i=Math.round(e.clientWidth*r),a=Math.round(e.clientHeight*r);if(i===0||a===0)return;(e.width!==i||e.height!==a)&&(e.width=i,e.height=a);let o=e.getContext(`2d`);if(!o)return;let s=i,c=a;if(n!==`fill`){let e=(n===`contain`?Math.min:Math.max)(i/t.width,a/t.height);s=t.width*e,c=t.height*e}o.clearRect(0,0,i,a),o.drawImage(t,(i-s)/2,(a-c)/2,s,c)}function Fi({config:e}){let t=(0,q.useRef)(null),n=(0,q.useRef)(null),r=(0,q.useRef)(e.fit);r.current=e.fit;let[i,a]=(0,q.useState)({state:`waiting`,message:`Connecting…`}),[o,s]=(0,q.useState)(null),[c,l]=(0,q.useState)(!1),u=(0,q.useRef)(0),d=e.topic.trim(),{transport:f,maxFps:p,quality:m,maxWidth:h}=e;(0,q.useEffect)(()=>{if(s(null),!d){a({state:`error`,message:`No image topic: set one in edit mode`});return}a({state:`waiting`,message:`Connecting…`});let e=[],i=!0,o=H.subscribeImage({topic:d,transport:f,maxFps:p,quality:m,maxWidth:h},{status:(e,t)=>a({state:e,message:t}),frame:async(a,{width:o,height:c})=>{let d=await createImageBitmap(a);if(!i){d.close();return}let f=t.current;f&&Pi(f,d,r.current),n.current?.close(),n.current=d;let p=performance.now();for(u.current=p,e.push(p);e.length>2&&p-e[0]>Ni;)e.shift();l(!1),s({width:o||d.width,height:c||d.height,fps:e.length>1?(e.length-1)*1e3/(p-e[0]):0})}});return()=>{i=!1,o(),n.current?.close(),n.current=null;let e=t.current;e?.getContext(`2d`)?.clearRect(0,0,e.width,e.height)}},[d,f,p,m,h]),(0,q.useEffect)(()=>{let e=t.current;if(!e)return;let i=()=>n.current&&Pi(e,n.current,r.current);i();let a=new ResizeObserver(i);return a.observe(e),()=>a.disconnect()},[e.fit]),(0,q.useEffect)(()=>{let e=setInterval(()=>{l(u.current>0&&performance.now()-u.current>Mi)},1e3);return()=>clearInterval(e)},[]);let g=null;return i.state===`streaming`?c&&(g=`No image for ${Math.round((performance.now()-u.current)/1e3)} s`):g=i.message,(0,J.jsxs)(`div`,{className:`camera`,children:[(0,J.jsx)(`canvas`,{ref:t,className:g&&o?`dimmed`:void 0}),g&&(0,J.jsxs)(`div`,{className:`camera-overlay ${i.state}`,children:[(0,J.jsx)(z,{width:28,height:28}),(0,J.jsx)(`span`,{children:g})]}),e.showInfo&&o&&!g&&(0,J.jsxs)(`div`,{className:`camera-info`,children:[o.width,`×`,o.height,` · `,o.fps.toFixed(1),` fps`]})]})}var Ii=Ve({type:`camera`,name:`Camera`,description:`Show an image topic, raw or compressed.`,icon:z,defaultSize:{w:6,h:4},minSize:{w:2,h:2},component:Fi,properties:[{key:`topic`,label:`Topic`,kind:`topic`,default:``,topicTypes:[`sensor_msgs/msg/Image`,`sensor_msgs/msg/CompressedImage`],placeholder:`/arm_camera/image_raw`},{key:`transport`,label:`Transport`,kind:`select`,default:`auto`,options:[{value:`auto`,label:`Auto: the type the topic is published with`},{value:`raw`,label:`Raw: sensor_msgs/Image`},{value:`compressed`,label:`Compressed: <topic>/compressed`}],help:`Compressed images take far less bandwidth from the camera driver to the server`},{key:`maxFps`,label:`Max frame rate`,kind:`number`,default:10,min:.1,max:60,step:1},{key:`maxWidth`,label:`Max width (raw images, px)`,kind:`number`,default:640,min:0,max:8192,step:1,help:`Wider raw images are scaled down before being sent. 0: full size`},{key:`quality`,label:`JPEG quality (raw images)`,kind:`number`,default:75,min:1,max:100,step:1},{key:`fit`,label:`Fit`,kind:`select`,default:`contain`,options:[{value:`contain`,label:`Whole image`},{value:`cover`,label:`Fill the widget, cropped`},{value:`fill`,label:`Stretch`}]},{key:`showInfo`,label:`Show size and frame rate`,kind:`boolean`,default:!0}]}),Li=[{level:`debug`,tag:`DEBUG`,label:`Debug`,letter:`D`},{level:`info`,tag:`INFO`,label:`Info`,letter:`I`},{level:`warn`,tag:`WARN`,label:`Warn`,letter:`W`},{level:`error`,tag:`ERROR`,label:`Error`,letter:`E`},{level:`fatal`,tag:`FATAL`,label:`Fatal`,letter:`F`}];function Ri(e){return Math.min(Li.length-1,Math.max(0,Math.floor(e/10)-1))}function zi(e){let t=Li.findIndex(t=>t.level===e);return new Set(Li.slice(Math.max(0,t)).map(e=>e.level))}var Bi={received:!1,started:0,entries:[],pending:[],paused:!1,skipped:0,running:new Map,cleared:null,version:0};function Vi(e){return e.replace(/^\/+/,``).replaceAll(`/`,`.`)}function Hi(e,t){for(let n=e;n;n=n.slice(0,Math.max(0,n.lastIndexOf(`.`)))){let e=t.get(n);if(e)return e}return null}function Ui(e){return e.length>1e4?e.slice(-D):e}function Wi(e){return e.entries.at(-1)?.seq??e.cleared?.seq??0}function Gi(e,t){switch(t.type){case`reset`:return{...Bi,version:e.version+1};case`update`:{let{reset:n,started:r,entries:i,skipped:a,nodes:o}=t.update,s=o?new Map(o.map(e=>[Vi(e),e])):e.running;if(!n)return e.paused?{...e,running:s,pending:Ui([...e.pending,...i]),skipped:e.skipped+a}:{...e,running:s,entries:Ui([...e.entries,...i]),skipped:e.skipped+a};let c=e.received&&r===e.started,l=c?e.cleared:null,u=l?i.filter(e=>e.seq>l.seq):i,d=e.paused&&c?Wi(e):1/0;return{...e,received:!0,started:r,running:s,cleared:l,entries:Ui(u.filter(e=>e.seq<=d)),pending:Ui(u.filter(e=>e.seq>d)),skipped:0,version:c?e.version:e.version+1}}case`pause`:return e.paused?e:{...e,paused:!0};case`resume`:return{...e,paused:!1,entries:Ui([...e.entries,...e.pending]),pending:[]};case`clear`:{let t=(e.pending.at(-1)??e.entries.at(-1))?.seq??e.cleared?.seq??0;return{...e,entries:[],pending:[],skipped:0,cleared:{started:e.started,seq:t}}}}}function Ki(e,t){let n=0,r=e.length;for(;n<r;){let i=n+r>>1;e[i].seq<t?n=i+1:r=i}return n}function qi(e,t){if(t){if(!e.trim())return{test:null,error:null};try{let t=new RegExp(e,`i`);return{test:e=>t.test(e),error:null}}catch(e){return{test:null,error:e instanceof Error?e.message:String(e)}}}let n=e.split(`;`).map(e=>e.trim().toLowerCase()).filter(Boolean);return n.length===0?{test:null,error:null}:{test:e=>{let t=e.toLowerCase();return n.some(e=>t.includes(e))},error:null}}function Ji(e){let t=e.split(/[;,\s]+/).filter(Boolean).map(e=>{let t=Vi(e).split(`*`).map(e=>e.replace(/[.+?^${}()|[\]\\]/g,`\\$&`)).join(`.*`);return RegExp(`^${t}(\\..+)?$`)});return t.length>0?e=>t.some(t=>t.test(e)):null}function Yi(e,t,n){let r=new Map,i=e=>{let t=r.get(e);return t===void 0&&(t=!n.scope||n.scope(e),r.set(e,t)),t},a=new Map,o=e=>{let n=a.get(e);return n||(n={name:e,node:Hi(e,t),counts:Li.map(()=>0),total:0},a.set(e,n)),n},s=Li.map(()=>0),c=[],l=0;for(let t of e){if(!i(t.name))continue;l++;let e=Ri(t.level),r=o(t.name);r.counts[e]++,r.total++,!(n.nodes.size>0&&!n.nodes.has(t.name)||n.include&&!n.include(t.msg)||n.exclude?.(t.msg))&&(s[e]++,n.levels.has(Li[e].level)&&c.push(t))}for(let e of[...t.keys(),...n.nodes])i(e)&&o(e);return{shown:c,levels:s,total:l,nodes:[...a.values()].sort((e,t)=>e.name.localeCompare(t.name))}}var Xi=Date.UTC(2001,0,1);function Zi(e){return(e/1e3).toFixed(6)}function Qi(e){if(e<Xi)return(e/1e3).toFixed(3);let t=new Date(e),n=(e,t=2)=>String(e).padStart(t,`0`);return`${n(t.getHours())}:${n(t.getMinutes())}:${n(t.getSeconds())}.${n(t.getMilliseconds(),3)}`}function $i(e){return`[${Li[Ri(e.level)].tag}] [${Zi(e.stamp)}] [${e.name}]: ${e.msg}`}function ea(e){return e<1e3?String(e):e<1e4?`${(e/1e3).toFixed(1).replace(/\.0$/,``)}k`:`${Math.round(e/1e3)}k`}var ta=[{level:`ok`,label:`OK`,tag:`OK`},{level:`warn`,label:`Warn`,tag:`WARN`},{level:`error`,label:`Error`,tag:`ERROR`},{level:`stale`,label:`Stale`,tag:`STALE`}],na={ok:0,warn:1,stale:2,error:3};function ra(e){return ta.find(t=>t.level===e)}function ia(e){switch(e){case 0:return`ok`;case 1:return`warn`;case 3:return`stale`;default:return`error`}}function aa(e){return e.stale?`stale`:ia(e.level)}function oa(e){return new Set(ta.filter(({level:t})=>na[t]>=na[e]).map(({level:e})=>e))}function sa(e,t){return e===null||t===null?e??t:na[e]>=na[t]?e:t}var ca={received:!1,started:0,statuses:new Map,changes:[],frozen:null,forgotten:new Map,version:0};function la(e){return e.length>1e3?e.slice(-g):e}function ua(e){return e.frozen??e}function da(e,t){return e.get(t.id)===t.since}function fa(e,t){switch(t.type){case`reset`:return{...ca,version:e.version+1};case`update`:{let{reset:n,started:r,statuses:i,changes:a}=t.update;if(!n){let t=new Map(e.statuses);for(let e of i)t.set(e.id,e);return{...e,statuses:t,changes:la([...e.changes,...a])}}let o=e.received&&r===e.started,s={statuses:new Map(i.map(e=>[e.id,e])),changes:la(a)};return{...e,...s,received:!0,started:r,frozen:e.frozen&&!o?s:e.frozen,forgotten:o?e.forgotten:new Map,version:o?e.version:e.version+1}}case`pause`:return e.frozen?e:{...e,frozen:{statuses:e.statuses,changes:e.changes}};case`resume`:return{...e,frozen:null};case`forget`:{let{statuses:n}=ua(e),r=new Map(e.forgotten);for(let e of t.ids){let t=n.get(e);t?.stale&&r.set(e,t.since)}return{...e,forgotten:r}}}}function pa(e){let t=(e.startsWith(`/`)?e.split(`/`).map(e=>e.replace(/:\s*$/,``).trim()):ma(e)).filter(Boolean);return t.length>0?t:[e.trim()||`(no name)`]}function ma(e){let t=e.indexOf(`: `);return t>0?[e.slice(0,t).trim(),e.slice(t+2).trim()]:[e.trim()]}function ha(e){let t=e.split(/[,;]/).map(e=>e.trim()).filter(Boolean).map(e=>{let t=e.includes(`/`)?e.split(`/`).filter(Boolean):ma(e);return{rooted:e.startsWith(`/`),globs:t.map(e=>{let t=e.split(`*`).map(e=>e.replace(/[.+?^${}()|[\]\\]/g,`\\$&`)).join(`.*`);return RegExp(`^${t}$`,`i`)})}}).filter(({globs:e})=>e.length>0);return t.length===0?null:e=>t.some(({rooted:t,globs:n})=>{let r=t?0:e.length-n.length;for(let t=0;t<=r;t++)if(n.every((n,r)=>t+r<e.length&&n.test(e[t+r])))return!0;return!1})}var ga=new Intl.Collator(void 0,{numeric:!0,sensitivity:`base`});function _a(e){let t=[],n=new Map,r=(e,r,i)=>{let a=n.get(r);return a||(a={key:r,label:i,entry:null,children:[],own:null,worst:`ok`,counted:!1},n.set(r,a),(e?.children??t).push(a)),a};for(let t of e){let e=pa(t.name),n=null,i=``;for(let t of e.slice(0,-1))i+=`\n${t}`,n=r(n,i,t);let a=e[e.length-1],o=r(n,`${i}\n${a}`,a);o.entry&&(o=r(n,`${i}\n${a}#${t.id}`,a)),o.entry=t}let i=e=>{e.children.sort((e,t)=>ga.compare(e.label,t.label));let t=null;for(let n of e.children)i(n),t=sa(t,n.worst);let n=e.entry?aa(e.entry):null;n===`error`&&t===`stale`&&(n=`stale`),e.own=n,e.worst=sa(n,t)??`ok`,e.counted=n!==null&&(t===null||na[n]>na[t])};return t.sort((e,t)=>ga.compare(e.label,t.label)),t.forEach(i),{roots:t,nodes:n}}var va={mode:`auto`,chosen:new Map};function ya(e,t){if(t.mode!==`auto`||e.filtering)return t;let n=e.rows.filter(({node:e,open:n})=>n&&e.worst!==`ok`&&!t.chosen.has(e.key));if(n.length===0)return t;let r=new Map(t.chosen);for(let{node:e}of n)r.set(e.key,!0);return{...t,chosen:r}}function ba(){return{ok:0,warn:0,error:0,stale:0}}function xa(e,t){let{entry:n}=e;return n?t(n.name)||t(n.message)||t(n.hardwareId):t(e.label)}function Sa(e,t,n){let r=[];for(let n of e)(!t.scope||t.scope(pa(n.name)))&&r.push(n);let{roots:i,nodes:a}=_a(r),o=t.text!==null||ta.some(({level:e})=>!t.levels.has(e)),s=new Set,c=new Set,l=new Map,u=ba(),d=(e,n)=>{let r=n||!t.text||xa(e,t.text),i=ba(),a=!1;for(let t of e.children){let e=d(t,r);for(let{level:t}of ta)i[t]+=e[t];a||=c.has(t)}return e.counted&&u[e.own]++,e.counted&&r&&(i[e.own]++,t.levels.has(e.own)&&(s.add(e),a=!0)),a&&c.add(e),l.set(e,i),i},f=ba(),p=null;for(let e of i){let t=d(e,!1);for(let{level:e}of ta)f[e]+=t[e];p=sa(p,e.worst)}let m=(e,t)=>n.chosen.get(e.key)??(o||n.mode===`all`||e.worst!==`ok`||t),h=[],g=(e,t)=>{for(let n of e){if(!c.has(n))continue;let r=n.children.length>0?m(n,e.length===1):null;h.push({node:n,depth:t,open:r,dim:o&&!s.has(n),counts:l.get(n)}),r&&g(n.children,t+1)}};g(i,0);let _=[...s].sort((e,t)=>na[t.own]-na[e.own]||ga.compare(e.entry.name,t.entry.name)),v=new Map;for(let e of a.values())e.entry&&v.set(e.entry.id,e.key);return{rows:h,list:_,counts:f,totals:u,total:ta.reduce((e,{level:t})=>e+u[t],0),matching:s.size,worst:p,nodes:a,keys:v,filtering:o}}function Ca(e,t,n){let r=new Map,i=e=>{let t=r.get(e.id);return t===void 0&&(t=!n.scope||n.scope(pa(e.name)),r.set(e.id,t)),t},a=[];for(let r=e.length-1;r>=0;r--){let o=e[r],s=t.get(o.status);s&&i(s)&&n.levels.has(ia(o.level))&&(!n.text||n.text(s.name)||n.text(o.message))&&a.push(o)}return a}var wa=/^(ok|warn(ing)?|error|stale|all stale)$/i;function Ta(e){let t=e.entry?.message.trim()??``;return e.children.length>0&&wa.test(t)?``:t}function Ea(e,t=!1){let n=new Date(e),r=(e,t=2)=>String(e).padStart(t,`0`),i=`${r(n.getHours())}:${r(n.getMinutes())}:${r(n.getSeconds())}`;return t?`${i}.${r(n.getMilliseconds(),3)}`:i}function Da(e){let t=Math.max(0,Math.round(e/1e3));return t<60?`${t} s`:t<3600?`${Math.floor(t/60)} min ${t%60} s`:`${Math.floor(t/3600)} h ${Math.floor(t%3600/60)} min`}function Oa(e){let t=aa(e),n=ra(t).tag;t===`stale`&&ia(e.level)!==`stale`&&(n+=` (${ra(ia(e.level)).tag})`);let r=[`[${n}] ${e.name}${e.message?`: ${e.message}`:``}`];e.hardwareId&&r.push(` hardware_id: ${e.hardwareId}`);for(let{key:t,value:n}of e.values)r.push(` ${t}: ${n}`);return r.join(`
|
|
26
|
+
`)}function ka(e,t){let n=ra(ia(e.level)).tag,r=e.message?`: ${e.message}`:``;return`[${Ea(e.time,!0)}] [${n}] ${t?.name??`?`}${r}`}function Aa({level:e,size:t=14}){let n={fill:`none`,stroke:`var(--diag-mark)`,strokeWidth:1.8,strokeLinecap:`round`};return(0,J.jsxs)(`svg`,{className:`diag-icon ${e}`,viewBox:`0 0 16 16`,width:t,height:t,"aria-hidden":`true`,children:[e===`ok`&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`circle`,{cx:`8`,cy:`8`,r:`7`,fill:`currentColor`}),(0,J.jsx)(`path`,{d:`m4.8 8.3 2.2 2.1 4.2-4.6`,strokeLinejoin:`round`,...n})]}),e===`warn`&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`path`,{d:`M8 1.2c.5 0 .9.3 1.2.8l6 10.6c.5.9-.1 2-1.2 2H2c-1.1 0-1.7-1.1-1.2-2l6-10.6c.3-.5.7-.8 1.2-.8Z`,fill:`currentColor`}),(0,J.jsx)(`path`,{d:`M8 5.6v3.6M8 11.9v.1`,...n})]}),e===`error`&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`circle`,{cx:`8`,cy:`8`,r:`7`,fill:`currentColor`}),(0,J.jsx)(`path`,{d:`m5.5 5.5 5 5M10.5 5.5l-5 5`,...n})]}),e===`stale`&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`circle`,{cx:`8`,cy:`8`,r:`6.2`,fill:`none`,stroke:`currentColor`,strokeWidth:`1.7`,strokeDasharray:`2.4 2`}),(0,J.jsx)(`circle`,{cx:`8`,cy:`8`,r:`1.6`,fill:`currentColor`})]})]})}var ja=16,Ma=26,Na=(0,q.memo)(function({index:e,rowKey:t,depth:n,label:r,level:i,message:a,open:o,dim:s,status:c,errors:l,stale:u,warnings:d,selected:f,role:p,onSelect:m,onFold:h}){let g=[{level:`error`,count:l,name:`in error`},{level:`stale`,count:u,name:`stale`},{level:`warn`,count:d,name:`warning`}].filter(({count:e})=>e>0);return(0,J.jsxs)(`div`,{role:p,"aria-level":p===`treeitem`?n+1:void 0,"aria-expanded":o??void 0,"aria-selected":f,"data-row":e,className:`diag-row ${i}${f?` selected`:``}${s?` dim`:``}`,style:{paddingLeft:4+n*ja},title:a?`${r}: ${a}`:r,onClick:()=>{c?m(f?null:t):(m(t),o!==null&&h(t,o))},children:[o===null?p===`treeitem`&&(0,J.jsx)(`span`,{className:`diag-fold`}):(0,J.jsx)(`span`,{className:`diag-fold`,"aria-hidden":`true`,onClick:e=>{e.stopPropagation(),h(t,o)},children:(0,J.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`12`,height:`12`,children:(0,J.jsx)(`path`,{d:`m9 6 6 6-6 6`,fill:`none`,stroke:`currentColor`,strokeWidth:`2.5`,strokeLinecap:`round`})})}),(0,J.jsx)(Aa,{level:i}),(0,J.jsx)(`span`,{className:`diag-label`,children:r}),(0,J.jsx)(`span`,{className:`diag-msg`,children:a}),g.map(({level:e,count:t,name:n})=>(0,J.jsx)(`span`,{className:`diag-badge ${e}`,title:`${t} ${n} under it`,children:ea(t)},e))]})});function Pa({kind:e,rows:t,selected:n,empty:r,onSelect:i,onFold:a}){let o=(0,q.useRef)(null),s=e=>{let t=o.current,n=t?.querySelector(`[data-row="${e}"]`);t&&n&&(n.offsetTop<t.scrollTop?t.scrollTop=n.offsetTop:n.offsetTop+n.offsetHeight>t.scrollTop+t.clientHeight&&(t.scrollTop=n.offsetTop+n.offsetHeight-t.clientHeight))};return(0,J.jsx)(`div`,{ref:o,className:`diag-rows ${e}`,role:e===`tree`?`tree`:`listbox`,"aria-label":`Statuses`,tabIndex:0,onKeyDown:e=>{if(t.length===0)return;let r=n===null?-1:t.findIndex(e=>e.key===n),c=t[r],l=Math.max(1,Math.floor((o.current?.clientHeight??0)/Ma)-1),u;switch(e.key){case`ArrowDown`:u=r+1;break;case`ArrowUp`:u=r<0?0:r-1;break;case`PageDown`:u=r+l;break;case`PageUp`:u=r-l;break;case`Home`:u=0;break;case`End`:u=t.length-1;break;case`ArrowRight`:if(c?.open===!1){e.preventDefault(),a(c.key,!1);return}if(!c?.open)return;u=r+1;break;case`ArrowLeft`:if(c?.open){e.preventDefault(),a(c.key,!0);return}if(!c||c.depth===0)return;for(u=r-1;u>0&&t[u].depth>=c.depth;)u--;break;case`Enter`:case` `:c&&c.open!==null&&(e.preventDefault(),a(c.key,c.open));return;default:return}e.preventDefault(),u=Math.min(t.length-1,Math.max(0,u)),i(t[u].key),s(u)},children:t.length>0?t.map(({key:t,problems:r,...o},s)=>(0,J.jsx)(Na,{rowKey:t,index:s,...o,errors:r?.error??0,stale:r?.stale??0,warnings:r?.warn??0,selected:t===n,role:e===`tree`?`treeitem`:`option`,onSelect:i,onFold:a},t)):(0,J.jsx)(`p`,{className:`diag-empty`,children:r})})}var Fa=640,Ia=300,La=[{level:`error`,one:`error`,many:`errors`},{level:`stale`,one:`stale`,many:`stale`},{level:`warn`,one:`warning`,many:`warnings`}];function Ra(e){return`${e.toLocaleString()} status${e===1?``:`es`}`}async function za(e){if(navigator.clipboard&&window.isSecureContext)return navigator.clipboard.writeText(e);let t=document.createElement(`textarea`);t.value=e,t.setAttribute(`readonly`,``),t.style.position=`fixed`,t.style.opacity=`0`,document.body.append(t),t.select();let n=document.execCommand(`copy`);if(t.remove(),!n)throw Error(`the browser does not allow it`)}function Ba(e,t){let n=URL.createObjectURL(new Blob([t],{type:`text/plain`})),r=document.createElement(`a`);r.href=n,r.download=e,r.click(),setTimeout(()=>URL.revokeObjectURL(n),1e3)}function Va(e){let t=new Date,n=e=>String(e).padStart(2,`0`),r=`${t.getFullYear()}${n(t.getMonth()+1)}${n(t.getDate())}`,i=`${n(t.getHours())}${n(t.getMinutes())}${n(t.getSeconds())}`;return`${e}_${H.hostname||`robot`}_${r}_${i}.txt`}function Ha(e){let[t,n]=(0,q.useState)(()=>H.serverNow());return(0,q.useEffect)(()=>{let t=setInterval(()=>n(H.serverNow()),e);return()=>clearInterval(t)},[e]),t}function Ua({entry:e,label:t,changes:n,onClose:r}){let i=Ha(1e3),a=aa(e),o=ia(e.level),s=(0,q.useMemo)(()=>n.filter(t=>t.status===e.id).slice(-10).reverse(),[n,e.id]),c=()=>za(Oa(e)).then(()=>G(`Copied the status`),e=>G(`Could not copy the status: ${e instanceof Error?e.message:e}`,`error`));return(0,J.jsxs)(`section`,{className:`diag-details ${a}`,"aria-label":`${t}: details`,children:[(0,J.jsxs)(`header`,{className:`diag-details-header`,children:[(0,J.jsx)(Aa,{level:a,size:16}),(0,J.jsx)(`span`,{className:`diag-pill`,children:ra(a).tag}),(0,J.jsx)(`strong`,{className:`diag-details-name`,title:e.name,children:t}),(0,J.jsx)(`span`,{className:`diag-spacer`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Copy`,"aria-label":`Copy`,onClick:()=>void c(),children:(0,J.jsx)(N,{width:16,height:16})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Close (Esc)`,"aria-label":`Close`,onClick:r,children:(0,J.jsx)(B,{width:16,height:16})})]}),(0,J.jsxs)(`div`,{className:`diag-details-body`,children:[e.message&&(0,J.jsx)(`pre`,{className:`diag-details-msg`,children:e.message}),(0,J.jsxs)(`dl`,{className:`diag-facts`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:`Name`}),(0,J.jsx)(`dd`,{children:e.name})]}),(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:`Since`}),(0,J.jsxs)(`dd`,{children:[Ea(e.since),` · `,Da(i-e.since)]})]}),e.stale&&(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:`Last received`}),(0,J.jsxs)(`dd`,{children:[Ea(e.updated),` · `,Da(i-e.updated),` ago`,o!==`stale`&&`, at ${ra(o).tag}`]})]}),e.hardwareId&&(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:`Hardware ID`}),(0,J.jsx)(`dd`,{children:e.hardwareId})]})]}),(0,J.jsx)(`h3`,{children:`Values`}),e.values.length>0?(0,J.jsx)(`dl`,{className:`diag-values`,children:e.values.map(({key:e,value:t},n)=>(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:e}),(0,J.jsx)(`dd`,{children:t})]},n))}):(0,J.jsx)(`p`,{className:`diag-muted`,children:`None`}),(0,J.jsx)(`h3`,{children:`Latest changes`}),s.length>0?(0,J.jsx)(`ol`,{className:`diag-status-changes`,children:s.map(e=>{let t=ia(e.level);return(0,J.jsxs)(`li`,{className:t,children:[(0,J.jsx)(`time`,{title:new Date(e.time).toLocaleString(),children:Ea(e.time)}),(0,J.jsx)(`span`,{className:`diag-pill`,children:ra(t).tag}),(0,J.jsx)(`span`,{className:`diag-msg`,children:e.message})]},e.seq)})}):(0,J.jsx)(`p`,{className:`diag-muted`,children:`None seen`})]})]})}function Wa({changes:e,entries:t,selected:n,empty:r,onSelect:i}){return e.length===0?(0,J.jsx)(`p`,{className:`diag-empty`,children:r}):(0,J.jsx)(`ol`,{className:`diag-changes`,"aria-label":`Latest changes`,children:e.map(e=>{let r=ia(e.level),a=t.get(e.status)?.name??``,o=e.message?`${a}: ${e.message}`:a;return(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,className:`diag-change ${r}${e.status===n?` selected`:``}`,title:`${new Date(e.time).toLocaleString()} · ${o}`,onClick:()=>i(e.status),children:[(0,J.jsx)(`time`,{children:Ea(e.time)}),(0,J.jsx)(Aa,{level:r}),(0,J.jsx)(`span`,{className:`diag-change-name`,children:a}),(0,J.jsx)(`span`,{className:`diag-msg`,children:e.message})]})},e.seq)})})}function Ga({config:e}){let[t,n]=(0,q.useReducer)(fa,ca),[r,i]=(0,q.useState)({state:`waiting`,message:`Connecting…`}),[a,o]=(0,q.useState)(()=>oa(e.level)),[s,c]=(0,q.useState)(e.filter),[l,d]=(0,q.useState)(e.regex),[f,p]=(0,q.useState)(e.view),[m,g]=(0,q.useState)(va),[_,v]=(0,q.useState)(null),[y,b]=(0,q.useState)({width:0,height:0}),x=(0,q.useRef)(null);(0,q.useEffect)(()=>o(oa(e.level)),[e.level]),(0,q.useEffect)(()=>c(e.filter),[e.filter]),(0,q.useEffect)(()=>d(e.regex),[e.regex]),(0,q.useEffect)(()=>p(e.view),[e.view]);let C=e.topic.trim();(0,q.useEffect)(()=>{if(n({type:`reset`}),!C)i({state:`error`,message:`No diagnostics topic: set one in edit mode`});else return i({state:`waiting`,message:`Connecting…`}),H.subscribeDiagnostics({topic:C},{status:(e,t)=>i({state:e,message:t}),update:e=>n({type:`update`,update:e})})},[C]),(0,q.useEffect)(()=>{v(null),g(va)},[t.version]),(0,q.useEffect)(()=>{let e=x.current;if(!e)return;let t=new ResizeObserver(([e])=>b({width:e.contentRect.width,height:e.contentRect.height}));return t.observe(e),()=>t.disconnect()},[]);let w=(0,q.useDeferredValue)(s),T=(0,q.useMemo)(()=>ha(e.statuses),[e.statuses]),E=(0,q.useMemo)(()=>qi(w,l),[w,l]),D=(0,q.useMemo)(()=>({scope:T,levels:a,text:E.test}),[T,a,E]),{statuses:O,changes:k}=ua(t),j=(0,q.useMemo)(()=>[...O.values()].filter(e=>!da(t.forgotten,e)),[O,t.forgotten]),M=(0,q.useMemo)(()=>Sa(j,D,m),[j,D,m]);(0,q.useEffect)(()=>g(e=>ya(M,e)),[M]);let te=(0,q.useMemo)(()=>f===`changes`?Ca(k,O,D):[],[f,k,O,D]),N=(0,q.useMemo)(()=>f===`list`?M.list.map(e=>({key:e.key,depth:0,label:e.entry.name,level:e.own,message:e.entry.message,open:null,dim:!1,status:!0,problems:null})):M.rows.map(({node:e,depth:t,open:n,dim:r,counts:i})=>({key:e.key,depth:t,label:e.label,level:e.worst,message:Ta(e),open:n,dim:r,status:e.entry!==null,problems:n===!1?i:null})),[f,M]),P=(0,q.useCallback)((e,t)=>g(n=>({...n,chosen:new Map(n.chosen).set(e,!t)})),[]),F=(e,t)=>o(n=>{if(t)return new Set([e]);let r=new Set(n);return r.delete(e)||r.add(e),r}),ne=_===null?void 0:M.nodes.get(_),I=ne?.entry?{entry:ne.entry,label:ne.label}:null,re=[...M.nodes.values()].flatMap(e=>e.entry?.stale?[e.entry.id]:[]),{width:ie,height:L}=y,R=ie>=Fa,ae=f===`changes`?`No change matches the filters`:`No status matches the filters`;t.received?M.nodes.size===0?ae=j.length<O.size?`The statuses no longer published are forgotten: they show again once published`:T?`No status of ${e.statuses.trim()} yet`:`No status yet`:f===`changes`&&k.length===0&&(ae=`No change of level yet`):ae=r.state===`error`?r.message:`Reading the diagnostics…`;let z;if(r.state===`error`)z={text:r.message,tone:`failed`};else if(!t.received)z={text:r.message,tone:`idle`};else{let e=[];if(r.state===`waiting`&&e.push(r.message),M.total>0){let t=La.filter(({level:e})=>M.totals[e]>0).map(({level:e,one:t,many:n})=>`${M.totals[e].toLocaleString()} ${M.totals[e]===1?t:n}`);e.push(t.length>0?t.join(`, `):`All OK`),e.push(M.filtering&&f!==`changes`?`${M.matching.toLocaleString()} of ${Ra(M.total)} shown`:Ra(M.total))}t.frozen&&e.push(`paused`),z={text:e.join(` · `)||`No status yet`,tone:t.frozen?`paused`:M.worst??`idle`}}let se;return se=f===`changes`?(0,J.jsx)(Wa,{changes:te,entries:O,selected:I?.entry.id??null,empty:ae,onSelect:e=>v(M.keys.get(e)??null)}):(0,J.jsx)(Pa,{kind:f,rows:N,selected:_,empty:ae,onSelect:v,onFold:P}),(0,J.jsxs)(`div`,{ref:x,className:`diag${I&&!R&&L>0&&L<Ia?` cramped`:``}`,onKeyDown:e=>{e.key===`Escape`&&_!==null&&v(null)},children:[(0,J.jsxs)(`div`,{className:`diag-toolbar`,role:`toolbar`,"aria-label":`Diagnostics`,children:[(0,J.jsx)(`div`,{className:`diag-levels`,role:`group`,"aria-label":`Levels`,children:ta.map(({level:e,label:t})=>(0,J.jsxs)(`button`,{type:`button`,className:`diag-level ${e}`,"aria-pressed":a.has(e),"aria-label":`${t}: ${M.counts[e]}`,title:`${t}: ${Ra(M.counts[e])}. Shift+click: this level only`,onClick:t=>F(e,t.shiftKey),children:[(0,J.jsx)(Aa,{level:e,size:13}),(0,J.jsx)(`span`,{className:`diag-level-name`,children:t}),(0,J.jsx)(`span`,{className:`diag-level-count`,children:ea(M.counts[e])})]},e))}),(0,J.jsxs)(`div`,{className:`diag-filter`,children:[(0,J.jsxs)(`label`,{className:`diag-search${E.error?` invalid`:``}`,title:E.error??`Only the statuses whose name, message or hardware ID contain any of these, separated by ;`,children:[(0,J.jsx)(ge,{width:14,height:14}),(0,J.jsx)(`input`,{type:`search`,value:s,placeholder:`Filter…`,"aria-label":`Only the statuses containing`,spellCheck:!1,onChange:e=>c(e.target.value)})]}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button diag-regex`,"aria-pressed":l,title:`As a regular expression`,"aria-label":`As a regular expression`,onClick:()=>d(e=>!e),children:`.*`})]}),(0,J.jsxs)(`div`,{className:`diag-tools`,children:[(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":f===`tree`,title:`As a tree`,"aria-label":`As a tree`,onClick:()=>p(`tree`),children:(0,J.jsx)(u,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":f===`list`,title:`As a list, the worst first`,"aria-label":`As a list`,onClick:()=>p(`list`),children:(0,J.jsx)(A,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":f===`changes`,title:`The latest changes of level`,"aria-label":`The latest changes`,onClick:()=>p(`changes`),children:(0,J.jsx)(h,{width:17,height:17})}),(0,J.jsx)(`span`,{className:`overlay-separator`}),f===`tree`&&(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":m.mode===`all`,title:m.mode===`all`?`Unfold only the groups with problems`:`Unfold all the groups`,"aria-label":`Unfold all the groups`,onClick:()=>g({mode:m.mode===`all`?`auto`:`all`,chosen:new Map}),children:(0,J.jsx)(S,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":t.frozen!==null,title:t.frozen?`Resume`:`Pause: the statuses stay as they are`,"aria-label":t.frozen?`Resume`:`Pause`,onClick:()=>n({type:t.frozen?`resume`:`pause`}),children:(0,J.jsx)(oe,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:f===`changes`?`Download the changes shown`:`Download the statuses shown`,"aria-label":f===`changes`?`Download the changes shown`:`Download the statuses shown`,disabled:f===`changes`?te.length===0:M.list.length===0,onClick:()=>{if(f===`changes`){let e=te.map(e=>ka(e,O.get(e.status))).reverse();Ba(Va(`diagnostics_changes`),e.join(`
|
|
27
|
+
`)+`
|
|
28
|
+
`)}else Ba(Va(`diagnostics`),M.list.map(e=>Oa(e.entry)).join(`
|
|
29
|
+
|
|
30
|
+
`)+`
|
|
31
|
+
`)},children:(0,J.jsx)(ee,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Forget the statuses no longer published${re.length>0?` (${re.length})`:``}`,"aria-label":`Forget the statuses no longer published`,disabled:re.length===0,onClick:()=>n({type:`forget`,ids:re}),children:(0,J.jsx)(Ne,{width:17,height:17})})]})]}),(0,J.jsxs)(`div`,{className:`diag-body${R?` beside`:``}`,children:[(0,J.jsx)(`div`,{className:`diag-main`,children:se}),I&&(0,J.jsx)(Ua,{entry:I.entry,label:I.label,changes:k,onClose:()=>v(null)})]}),(0,J.jsxs)(`div`,{className:`diag-status ${z.tone}`,title:z.text,children:[z.tone===`ok`||z.tone===`warn`||z.tone===`error`||z.tone===`stale`?(0,J.jsx)(Aa,{level:z.tone,size:12}):(0,J.jsx)(`span`,{className:`diag-dot`,"aria-hidden":`true`}),(0,J.jsx)(`span`,{className:`diag-status-text`,children:z.text})]})]})}var Ka=Ve({type:`diagnostics`,name:`Diagnostics`,description:`The robot’s diagnostics (/diagnostics, /diagnostics_agg): each status’s level, message and values, filtered by level and text.`,icon:I,defaultSize:{w:8,h:6},minSize:{w:3,h:3},component:Ga,properties:[{key:`topic`,label:`Diagnostics topic`,kind:`topic`,default:`/diagnostics`,topicTypes:[`diagnostic_msgs/msg/DiagnosticArray`],help:`diagnostic_msgs/DiagnosticArray: /diagnostics has every node’s statuses, /diagnostics_agg the aggregator’s tree of them`},{key:`statuses`,label:`Statuses`,kind:`string`,default:``,placeholder:`Sensors, motor_*`,help:`Only these, with those under them: names, paths or globs (*), separated by commas. From the root if they start with /, else at any depth. All if empty`},{key:`level`,label:`Levels shown`,kind:`select`,default:`ok`,options:[{value:`ok`,label:`All`},{value:`warn`,label:`Problems: warnings, errors, stale`},{value:`stale`,label:`Errors and stale`},{value:`error`,label:`Errors only`}],help:`When the panel opens: its toolbar shows and hides each level`},{key:`filter`,label:`Filter`,kind:`string`,default:``,placeholder:`lidar; battery`,help:`Only the statuses whose name, message or hardware ID contain any of these, separated by ;. The toolbar changes it`},{key:`regex`,label:`Filter as a regular expression`,kind:`boolean`,default:!1},{key:`view`,label:`View`,kind:`select`,default:`tree`,options:[{value:`tree`,label:`Tree`},{value:`list`,label:`List, the worst first`},{value:`changes`,label:`Latest changes of level`}],help:`When the panel opens: its toolbar changes it`}]});function qa(e,t){return e===`/`?`/${t}`:`${e}/${t}`}function Ja(e){if(e===`/`)return null;let t=e.lastIndexOf(`/`);return t<=0?`/`:e.slice(0,t)}function $(e){return e===`/`?`/`:e.slice(e.lastIndexOf(`/`)+1)}function Ya(e,t){return e===t||e.startsWith(t===`/`?`/`:`${t}/`)}function Xa(e,t){return t&&t!==`/`&&Ya(e,t)?`~${e.slice(t.length)}`:e}function Za(e,t,n=`/`){let r=n,i=n===`/`?`/`:$(n);if(n===`/`&&t&&t!==`/`&&Ya(e,t)&&(r=t,i=`~`),!Ya(e,r))return[{name:e,path:e}];let a=[{name:i,path:r}],o=r;for(let t of e.slice(r.length).split(`/`).filter(Boolean))o=qa(o,t),a.push({name:t,path:o});return a}function Qa(e,t,n){let r=e.trim();if(r.startsWith(`package://`))return r;let i=r===`~`||r.startsWith(`~/`)?n+r.slice(1):r.startsWith(`/`)?r:`${t}/${r}`,a=[];for(let e of i.split(`/`))e===`..`?a.pop():e&&e!==`.`&&a.push(e);return i=`/${a.join(`/`)}`,i}function $a(e){if(e<1e3)return`${e} ${e===1?`byte`:`bytes`}`;let t=[`kB`,`MB`,`GB`,`TB`,`PB`],n=e/1e3,r=0;for(;n>=999.5&&r<t.length-1;)n/=1e3,r++;return`${n<99.95?n.toFixed(1):Math.round(n)} ${t[r]}`}var eo=new Intl.DateTimeFormat(void 0,{hour:`2-digit`,minute:`2-digit`}),to=new Intl.DateTimeFormat(void 0,{day:`numeric`,month:`short`}),no=new Intl.DateTimeFormat(void 0,{day:`numeric`,month:`short`,year:`numeric`}),ro=new Intl.DateTimeFormat(void 0,{dateStyle:`medium`,timeStyle:`medium`});function io(e,t){let n=new Date(e),r=new Date(t);return n.toDateString()===r.toDateString()?eo.format(n):(n.getFullYear()===r.getFullYear()?to:no).format(n)}function ao(e){return ro.format(new Date(e))}function oo(e,t){let n=Math.max(0,Math.round((t-e)/1e3)),r=[[60,`second`],[60,`minute`],[24,`hour`],[30,`day`],[12,`month`],[1/0,`year`]],i=n;for(let[e,t]of r){if(i<e)return i<1&&t===`second`?`just now`:`${i} ${t}${i===1?``:`s`} ago`;i=Math.floor(i/e)}return``}function so(e,t,n=!1){let r=[`r`,`w`,`x`],i=n?`l`:t===`dir`?`d`:t===`file`?`-`:`?`;for(let t=6;t>=0;t-=3)for(let n=0;n<3;n++){let a=e>>t+2-n&1?r[n]:`-`;if(n===2&&e>>9+t/3&1){let e=t===0?`t`:`s`;a=a===`x`?e:e.toUpperCase()}i+=a}return i}function co(e){return(e&4095).toString(8).padStart(3,`0`)}function lo(e){return e.startsWith(`.`)}var uo=new Intl.Collator(void 0,{numeric:!0,sensitivity:`base`});function fo(e,t){return uo.compare(e,t)||(e<t?-1:+(e>t))}function po(e,{key:t,descending:n}){let r=n?-1:1;return[...e].sort((e,n)=>{let i=Number(n.kind===`dir`)-Number(e.kind===`dir`);if(i!==0)return i;let a=0;return t===`size`&&e.kind!==`dir`?a=e.size-n.size:t===`modified`&&(a=e.modified-n.modified),r*(a||fo(e.name,n.name))})}function mo(e,{hidden:t,text:n}){let r=n.toLowerCase().split(/\s+/).filter(Boolean);return e.filter(e=>(t||!lo(e.name))&&r.every(t=>e.name.toLowerCase().includes(t)))}function ho(e,t,n,r,i,a){let o=[],s=(e,c,l)=>{let u=t.get(e);if(!u){let t=n.get(e);o.push({type:`note`,path:`${e}/…`,depth:c,text:t??`Reading…`,error:t!==void 0});return}let d=po(mo(u.entries,c===0?a:{...a,text:``}),i);d.length===0&&c>0&&o.push({type:`note`,path:`${e}/…`,depth:c,text:`Empty`,error:!1});for(let t of d){let n=qa(e,t.name),i=t.kind===`dir`?r.has(n)&&!l.has(n):null;o.push({type:`entry`,path:n,entry:t,depth:c,open:i}),i&&s(n,c+1,new Set(l).add(n))}};return s(e,0,new Set([e])),o}function go(e,t,n){let r=e.flatMap(e=>e.type===`entry`?[e.path]:[]),i=r.indexOf(t),a=r.indexOf(n);return i<0||a<0?a<0?[]:[n]:r.slice(Math.min(i,a),Math.max(i,a)+1)}function _o(e,t){let n=new Set(e.map(e=>e.name));if(!n.has(t))return t;let r=t.lastIndexOf(`.`),i=r>0?r:t.length;for(let e=2;;e++){let r=`${t.slice(0,i)} (${e})${t.slice(i)}`;if(!n.has(r))return r}}var vo=new Set(`txt md markdown rst log csv tsv yaml yml json jsonc xml urdf xacro sdf srdf launch world rviz repos rosinstall py pyi pyx cpp cc cxx c h hpp hh hxx ipp tpp ino cu js mjs cjs ts tsx jsx html htm css scss sh bash zsh fish env ini cfg conf config toml properties service timer socket mount target path desktop rules msg srv action idl cmake mk make patch diff lua rs go java kt rb pl sql proto gitignore dockerignore editorconfig gitmodules gitattributes dae xsd xsl tex bib in am ac m4 pc lock`.split(` `)),yo=new Set([`makefile`,`dockerfile`,`license`,`readme`,`authors`,`changelog`,`colcon_ignore`,`ament_ignore`,`catkin_ignore`,`vagrantfile`,`gemfile`,`rakefile`,`procfile`,`cmakelists.txt`]),bo=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`bmp`,`svg`,`ico`,`pgm`,`ppm`,`pnm`]),xo=new Set([`zip`,`tar`,`gz`,`tgz`,`bz2`,`xz`,`zst`,`7z`,`rar`,`deb`,`whl`]),So=new Set([`mp4`,`webm`,`mkv`,`avi`,`mov`,`mp3`,`wav`,`ogg`,`flac`,`pdf`]),Co=new Set([`mcap`,`db3`,`bag`]);function wo(e){let t=e.lastIndexOf(`.`);return t>0?e.slice(t+1).toLowerCase():``}function To(e){if(e.kind===`dir`)return e.bag?`bag`:`folder`;let t=wo(e.name);return bo.has(t)?`image`:Co.has(t)?`bag`:xo.has(t)?`archive`:So.has(t)?`media`:vo.has(t)||yo.has(e.name.toLowerCase())?`text`:e.kind===`file`&&(!t||t===`so`)?e.mode&73||t===`so`?`program`:`text`:`other`}function Eo(e){return bo.has(wo(e))}function Do(e){if(e.kind===`other`)return e.link===null?`Special file`:`Broken link`;let t={folder:`Folder`,bag:e.kind===`dir`?`Rosbag`:`Rosbag file`,text:`Text`,image:`Image`,archive:`Archive`,media:`Media`,program:`Program`,other:`File`}[To(e)],n=wo(e.name);return`${t}${e.kind===`file`&&n?` (${n.toUpperCase()})`:``}${e.link===null?``:`, a link`}`}function Oo(e,t){let n=new Set((e??[]).map(e=>e.name));return t.filter(e=>n.has(e))}function ko(e,t=3){return e.length<=t?e.length<=1?e[0]??``:`${e.slice(0,-1).join(`, `)} and ${e.at(-1)}`:`${e.slice(0,t).join(`, `)} and ${e.length-t} more`}function Ao(e,t,n=`${t}s`){return`${e.toLocaleString()} ${e===1?t:n}`}function jo(e){return Ao(e,`item`)}function Mo(e,t){let n=t>0?e/t:0;return n>=.95?`full`:n>=.85?`warn`:`ok`}var No=16,Po=10,Fo={folder:_,bag:x,text:c,image:Le,archive:Ce,media:x,program:W,other:O};function Io({entry:e,size:t=16}){let n=e.kind===`other`?`other`:To(e),r=n===`text`&&/\.(py|cpp|hpp|h|c|cc|js|ts|sh)$/i.test(e.name)?ce:Fo[n];return(0,J.jsx)(r,{className:`fm-icon ${n}`,width:t,height:t})}function Lo({name:e,onDone:t}){let n=(0,q.useRef)(null),r=(0,q.useRef)(!1);(0,q.useLayoutEffect)(()=>{let t=n.current;if(t){t.focus();let n=e.lastIndexOf(`.`);t.setSelectionRange(0,n>0?n:e.length)}},[e]);let i=e=>{r.current||(r.current=!0,t(e))};return(0,J.jsx)(`input`,{ref:n,className:`fm-rename`,defaultValue:e,spellCheck:!1,"aria-label":`New name of ${e}`,onClick:e=>e.stopPropagation(),onDoubleClick:e=>e.stopPropagation(),onKeyDown:e=>{e.stopPropagation(),e.key===`Enter`?i(e.currentTarget.value):e.key===`Escape`&&i(null)},onBlur:e=>i(e.currentTarget.value)})}var Ro=(0,q.memo)(function({row:e,index:t,top:n,selected:r,focused:i,cut:a,dropping:o,renaming:s,now:c,handlers:l}){if(e.type===`note`)return(0,J.jsx)(`div`,{className:`fm-note${e.error?` error`:``}`,style:{top:n,paddingLeft:8+e.depth*No+20},children:e.text});let{entry:u,path:d,depth:p,open:m}=e,h=u.kind===`dir`;return(0,J.jsxs)(`div`,{role:`treeitem`,"aria-level":p+1,"aria-expanded":m??void 0,"aria-selected":r,"data-row":t,className:`bt-row fm-row${r?` selected`:``}${i?` focused`:``}${a?` cut`:``}${o?` drop-into`:``}${u.kind===`other`?` special`:``}`,style:{top:n},title:`${u.name}\n${Do(u)}${u.link===null?``:` → ${u.link}`}`,draggable:!s,onPointerDown:e=>l.onPointer(e.pointerType),onClick:e=>l.onClick(d,e),onDoubleClick:()=>l.onOpen(d),onContextMenu:e=>{e.preventDefault(),l.onMenu(d,e.clientX,e.clientY)},onDragStart:e=>l.onDragStart(d,e),onDragEnd:l.onDragEnd,onDragOver:h?e=>l.onDragOver(d,e):void 0,onDrop:h?e=>l.onDrop(d,e):void 0,children:[(0,J.jsx)(`span`,{className:`bt-row-indent`,style:{width:p*No}}),m===null?(0,J.jsx)(`span`,{className:`bt-row-fold`}):(0,J.jsx)(`button`,{type:`button`,className:`bt-row-fold`,tabIndex:-1,"aria-label":m?`Fold ${u.name}`:`Unfold ${u.name}`,"aria-expanded":m,onClick:e=>{e.stopPropagation(),l.onFold(d,!m)},onDoubleClick:e=>e.stopPropagation(),children:(0,J.jsx)(`svg`,{viewBox:`0 0 24 24`,width:`12`,height:`12`,"aria-hidden":`true`,children:(0,J.jsx)(`path`,{d:`m9 6 6 6-6 6`,fill:`none`,stroke:`currentColor`,strokeWidth:`2.5`,strokeLinecap:`round`})})}),(0,J.jsxs)(`span`,{className:`fm-row-name`,children:[(0,J.jsx)(Io,{entry:u}),s?(0,J.jsx)(Lo,{name:u.name,onDone:e=>l.onRename(d,e)}):(0,J.jsx)(`span`,{className:`fm-name`,children:u.name}),u.link!==null&&(0,J.jsx)(f,{className:`fm-link`,width:12,height:12,"aria-label":`A link`})]}),(0,J.jsx)(`span`,{className:`fm-size`,children:h?``:$a(u.size)}),(0,J.jsx)(`span`,{className:`fm-date`,children:io(u.modified,c)}),(0,J.jsx)(`button`,{type:`button`,className:`fm-row-more`,tabIndex:-1,"aria-label":`What to do with ${u.name}`,onClick:e=>{e.stopPropagation();let t=e.currentTarget.getBoundingClientRect();l.onMenu(d,t.right,t.bottom)},onDoubleClick:e=>e.stopPropagation(),children:(0,J.jsx)(M,{width:15,height:15})})]})}),zo=[{key:`name`,label:`Name`,className:`fm-head-name`},{key:`size`,label:`Size`,className:`fm-size`},{key:`modified`,label:`Modified`,className:`fm-date`}];function Bo({rows:e,version:t,selected:n,focus:r,cut:i,dropTarget:a,droppingHere:o,renaming:s,sort:c,now:l,empty:u,reveal:d,handlers:f,onSort:p}){let m=(0,q.useRef)(null),[h,g]=(0,q.useState)({top:0,height:0});(0,q.useLayoutEffect)(()=>{let e=m.current;if(!e)return;let t=new ResizeObserver(()=>g({top:e.scrollTop,height:e.clientHeight}));return t.observe(e),()=>t.disconnect()},[]),(0,q.useLayoutEffect)(()=>{let e=m.current;e&&(e.scrollTop=0,g({top:0,height:e.clientHeight}))},[t]);let _=(0,q.useRef)(-1);(0,q.useEffect)(()=>{let t=m.current,n=d&&d.seq!==_.current?e.findIndex(e=>e.path===d.path):-1;if(!t||n<0)return;_.current=d.seq;let r=n*28;r<t.scrollTop?t.scrollTop=r:r+28>t.scrollTop+t.clientHeight&&(t.scrollTop=r+28-t.clientHeight)},[d,e]);let v=Math.max(0,Math.floor(h.top/28)-Po),y=Math.min(e.length,Math.ceil((h.top+h.height)/28)+Po),b=[];for(let t=v;t<y;t++){let o=e[t];b.push((0,J.jsx)(Ro,{row:o,index:t,top:t*28,selected:n.has(o.path),focused:r===o.path,cut:i.has(o.path),dropping:a===o.path,renaming:s===o.path,now:l,handlers:f},o.path))}return(0,J.jsxs)(`div`,{className:`fm-list-box`,children:[(0,J.jsxs)(`div`,{className:`fm-head`,role:`row`,children:[zo.map(({key:e,label:t,className:n})=>(0,J.jsxs)(`button`,{type:`button`,className:n,"aria-sort":c.key===e?c.descending?`descending`:`ascending`:void 0,title:`By ${t.toLowerCase()}`,onClick:()=>p(e),children:[t,c.key===e&&(0,J.jsx)(`span`,{"aria-hidden":`true`,children:c.descending?` ↓`:` ↑`})]},e)),(0,J.jsx)(`span`,{className:`fm-row-more`})]}),(0,J.jsx)(`div`,{ref:m,className:`fm-list${o?` drop-into`:``}`,role:`tree`,"aria-label":`Files`,"aria-multiselectable":`true`,tabIndex:0,onScroll:e=>g({top:e.currentTarget.scrollTop,height:e.currentTarget.clientHeight}),onKeyDown:e=>f.onKeyDown(e,Math.max(1,Math.floor(h.height/28)-1)),onClick:e=>e.target===e.currentTarget&&f.onClick(``,e),onContextMenu:e=>{(e.target===e.currentTarget||e.target.classList.contains(`fm-rows`))&&(e.preventDefault(),f.onMenu(null,e.clientX,e.clientY))},onDragOver:e=>f.onDragOver(null,e),onDrop:e=>f.onDrop(null,e),children:e.length>0?(0,J.jsx)(`div`,{className:`fm-rows`,style:{height:e.length*28},onClick:e=>e.target===e.currentTarget&&f.onClick(``,e),children:b}):(0,J.jsx)(`div`,{className:`widget-message fm-empty`,children:u})})]})}var Vo=[{who:`Owner`,shift:6},{who:`Group`,shift:3},{who:`Others`,shift:0}];function Ho({details:e,disabled:t,onChange:n}){let r=[{label:`Read`,bit:4},{label:`Write`,bit:2},{label:e.kind===`dir`?`Enter`:`Run`,bit:1}];return(0,J.jsxs)(`table`,{className:`fm-perms`,children:[(0,J.jsx)(`thead`,{children:(0,J.jsxs)(`tr`,{children:[(0,J.jsx)(`th`,{}),r.map(({label:e})=>(0,J.jsx)(`th`,{scope:`col`,children:e},e))]})}),(0,J.jsx)(`tbody`,{children:Vo.map(({who:i,shift:a})=>(0,J.jsxs)(`tr`,{children:[(0,J.jsx)(`th`,{scope:`row`,children:i}),r.map(({label:r,bit:o})=>{let s=o<<a;return(0,J.jsx)(`td`,{children:(0,J.jsx)(`input`,{type:`checkbox`,"aria-label":`${i}: ${r}`,checked:(e.mode&s)!==0,disabled:t,onChange:()=>n(e.mode^s)})},r)})]},i))})]})}function Uo({term:e,children:t}){return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`dt`,{children:e}),(0,J.jsx)(`dd`,{children:t})]})}function Wo({path:e}){let[t,n]=(0,q.useState)({busy:!1,result:null,error:null});(0,q.useEffect)(()=>n({busy:!1,result:null,error:null}),[e]);let r=()=>{n({busy:!0,result:null,error:null}),K.analyze(e).then(e=>n({busy:!1,result:e,error:null}),e=>n({busy:!1,result:null,error:e instanceof Error?e.message:String(e)}))},{busy:i,result:a,error:o}=t;return a?(0,J.jsxs)(`span`,{title:a.partial??void 0,children:[a.partial?`At least `:``,$a(a.size),` in `,Ao(a.files,`file`),`, `,Ao(a.folders,`folder`)]}):(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`button`,{type:`button`,className:`link-button fm-inline-button`,disabled:i,onClick:r,children:i?`Computing…`:`Compute its size`}),o&&(0,J.jsxs)(`span`,{className:`fm-error`,children:[` `,o]})]})}function Go({paths:e,folder:t,entries:n,version:r,home:i,readOnly:a,now:o,actions:s,onClose:c}){let l=e.length<=1?e[0]??t:null,[u,d]=(0,q.useState)(null),[f,p]=(0,q.useState)(null),[m,h]=(0,q.useState)(!1),[g,_]=(0,q.useState)(0);(0,q.useEffect)(()=>{if(!l)return;let e=!0;return K.details(l).then(t=>{e&&(d(t),p(null))},t=>{e&&(d(null),p(t instanceof Error?t.message:String(t)))}),()=>{e=!1}},[l,r,g]),(0,q.useEffect)(()=>{d(null),p(null)},[l]);let v,y;if(l){let e=u&&u.path===l?u:null,r=e??n.get(l)??null,c=l===t,d=$(l);v=(0,J.jsxs)(J.Fragment,{children:[r&&(0,J.jsx)(Io,{entry:r,size:18}),(0,J.jsxs)(`div`,{className:`bt-details-title`,children:[(0,J.jsx)(`strong`,{title:l,children:d}),(0,J.jsxs)(`span`,{children:[r?Do(r):`Reading…`,c?`, shown`:``]})]})]});let p=async e=>{h(!0),await s.onChmod(l,e),h(!1),_(e=>e+1)},g=r?To(r):`other`;y=(0,J.jsxs)(J.Fragment,{children:[f&&(0,J.jsx)(`p`,{className:`fm-error`,children:f}),r&&Eo(d)&&r.kind===`file`&&(0,J.jsx)(`button`,{type:`button`,className:`fm-preview`,title:`Open it`,onClick:()=>s.onOpen(l),children:(0,J.jsx)(`img`,{src:K.viewUrl(l,`${r.size}-${r.modified}`),alt:``,onError:e=>e.currentTarget.hidden=!0})}),e&&(0,J.jsxs)(`dl`,{className:`bt-facts`,children:[(0,J.jsx)(Uo,{term:`Where`,children:Ja(l)?(0,J.jsx)(`button`,{type:`button`,className:`link-button fm-inline-button`,onClick:()=>s.onGo(Ja(l)),children:Xa(Ja(l),i)}):`The root`}),e.kind===`dir`?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(Uo,{term:`Holds`,children:[e.items===null?`Cannot be read`:jo(e.items),e.hidden?(0,J.jsxs)(`span`,{className:`bt-muted`,children:[` (`,e.hidden,` hidden)`]}):null]}),(0,J.jsx)(Uo,{term:`Size`,children:(0,J.jsx)(Wo,{path:l})})]}):(0,J.jsxs)(Uo,{term:`Size`,children:[$a(e.size),e.size>=1e3&&(0,J.jsxs)(`span`,{className:`bt-muted`,children:[` (`,e.size.toLocaleString(),` bytes)`]})]}),(0,J.jsx)(Uo,{term:`Modified`,children:(0,J.jsx)(`span`,{title:ao(e.modified),children:oo(e.modified,o)})}),e.created!==null&&(0,J.jsx)(Uo,{term:`Created`,children:(0,J.jsx)(`span`,{title:ao(e.created),children:oo(e.created,o)})}),(0,J.jsxs)(Uo,{term:`Owner`,children:[e.owner,(0,J.jsxs)(`span`,{className:`bt-muted`,children:[`, group `,e.group]})]}),(0,J.jsxs)(Uo,{term:`Mode`,children:[(0,J.jsx)(`code`,{children:so(e.mode,e.kind,e.link!==null)}),` `,(0,J.jsx)(`span`,{className:`bt-muted`,children:co(e.mode)})]}),e.link!==null&&(0,J.jsx)(Uo,{term:`Links to`,children:e.link||`?`}),e.realPath&&(0,J.jsx)(Uo,{term:`Is at`,children:Xa(e.realPath,i)}),e.space&&(0,J.jsxs)(Uo,{term:`Disk`,children:[$a(e.space.free),` free of `,$a(e.space.total),(0,J.jsxs)(`span`,{className:`bt-muted`,children:[` on `,e.space.mount]})]}),!e.writable&&(0,J.jsx)(Uo,{term:`Access`,children:e.readable?`Read only, for the server’s user`:`Not readable by the server’s user`})]}),e&&e.kind!==`other`&&(0,J.jsxs)(`section`,{children:[(0,J.jsx)(`h3`,{children:`Permissions`}),(0,J.jsx)(Ho,{details:e,disabled:a||m,onChange:e=>void p(e)})]}),r&&(0,J.jsxs)(`div`,{className:`fm-details-actions`,children:[!c&&(0,J.jsx)(`button`,{type:`button`,className:`button primary`,onClick:()=>s.onOpen(l),children:r.kind===`dir`?`Open`:g===`text`?`Edit`:g===`image`?`View`:`Open as text`}),r.kind!==`other`&&(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>s.onDownload([l]),title:r.kind===`dir`?`As a .tar.gz`:void 0,children:`Download`}),!a&&!c&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>s.onRename(l),children:`Rename`}),(0,J.jsx)(`button`,{type:`button`,className:`button danger`,onClick:()=>s.onDelete([l]),children:`Delete`})]})]})]})}else{let t=e.map(e=>n.get(e)).filter(e=>e!==void 0),r=t.filter(e=>e.kind===`file`),o=t.filter(e=>e.kind===`dir`).length,c=e.every(t=>Ja(t)===Ja(e[0]));v=(0,J.jsxs)(`div`,{className:`bt-details-title`,children:[(0,J.jsxs)(`strong`,{children:[jo(e.length),` selected`]}),(0,J.jsx)(`span`,{children:c?`In ${Xa(Ja(e[0])??`/`,i)}`:`In several folders`})]}),y=(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`dl`,{className:`bt-facts`,children:[(0,J.jsx)(Uo,{term:`Files`,children:r.length.toLocaleString()}),(0,J.jsx)(Uo,{term:`Folders`,children:o.toLocaleString()}),(0,J.jsxs)(Uo,{term:`Size`,children:[$a(r.reduce((e,t)=>e+t.size,0)),o>0&&(0,J.jsx)(`span`,{className:`bt-muted`,children:` of the files`})]})]}),(0,J.jsxs)(`div`,{className:`fm-details-actions`,children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,disabled:!c,onClick:()=>s.onDownload(e),title:c?`As a .tar.gz`:`Entries of one folder at a time`,children:`Download`}),!a&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>s.onMove(e,!1),children:`Move to…`}),(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>s.onMove(e,!0),children:`Copy to…`}),(0,J.jsx)(`button`,{type:`button`,className:`button danger`,onClick:()=>s.onDelete(e),children:`Delete`})]})]})]})}return(0,J.jsxs)(`section`,{className:`bt-details fm-details`,"aria-label":`Details`,children:[(0,J.jsxs)(`header`,{className:`bt-details-header`,children:[v,(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Close the details`,title:`Close (Esc)`,onClick:c,children:(0,J.jsx)(B,{width:16,height:16})})]}),(0,J.jsx)(`div`,{className:`bt-details-body`,children:y})]})}var Ko=3e3;async function qo(e){if(navigator.clipboard&&window.isSecureContext)return navigator.clipboard.writeText(e);let t=document.createElement(`textarea`);t.value=e,t.setAttribute(`readonly`,``),t.style.position=`fixed`,t.style.opacity=`0`,document.body.append(t),t.select();let n=document.execCommand(`copy`);if(t.remove(),!n)throw Error(`the browser does not allow it`)}function Jo(e){let t=document.createElement(`a`);t.href=e,t.download=``,t.click()}function Yo(e){return e instanceof Error?e.message:String(e)}function Xo(e){let t=[...e.items].filter(e=>e.kind===`file`).map(e=>e.webkitGetAsEntry?.()??null),n=[...e.files].map(e=>({file:e,name:e.name}));if(t.length===0||t.some(e=>e===null))return Promise.resolve(n);let r=[],i=async(e,t)=>{if(e.isFile){let n=await new Promise((t,n)=>e.file(t,n));r.push({file:n,name:t+e.name})}else if(e.isDirectory){let n=e.createReader();for(;;){let r=await new Promise((e,t)=>n.readEntries(e,t));if(r.length===0)break;for(let n of r)await i(n,`${t}${e.name}/`)}}};return(async()=>{for(let e of t)await i(e,``);return r})()}function Zo(e){let[t,n]=(0,q.useState)(new Map),[r,i]=(0,q.useState)(new Map),[a,o]=(0,q.useState)(!1),[s,c]=(0,q.useState)(0),l=(0,q.useRef)(new Map),u=e.join(`\0`);return(0,q.useEffect)(()=>{let e=u?u.split(`\0`):[],t=!1,r,a=(e,t)=>{if(!e.has(t))return e;let n=new Map(e);return n.delete(t),n},s=async e=>{try{let r=await K.list(e,l.current.get(e));if(t)return;o(!1),r&&(l.current.set(e,r.version),n(t=>new Map(t).set(e,r))),i(t=>a(t,e))}catch(r){if(t)return;r instanceof Be?(l.current.delete(e),n(t=>a(t,e)),i(t=>new Map(t).set(e,r.message))):o(!0)}},c=async()=>{document.visibilityState===`visible`&&await Promise.all(e.map(s)),t||(r=setTimeout(()=>void c(),Ko))};return c(),()=>{t=!0,clearTimeout(r)}},[u,s]),{listings:t,errors:r,offline:a,refresh:(0,q.useCallback)(()=>c(e=>e+1),[])}}function Qo({x:e,y:t,items:n,onClose:r}){let i=(0,q.useRef)(null),[a,o]=(0,q.useState)({left:e,top:t});return(0,q.useLayoutEffect)(()=>{let n=i.current;if(!n)return;let{width:r,height:a}=n.getBoundingClientRect();o({left:Math.max(4,Math.min(e,window.innerWidth-r-4)),top:Math.max(4,t+a>window.innerHeight-4?t-a:t)}),n.querySelector(`button:not(:disabled)`)?.focus({preventScroll:!0})},[e,t]),(0,q.useEffect)(()=>{let e=e=>{e.key===`Escape`&&(e.stopPropagation(),r())};return window.addEventListener(`keydown`,e,!0),()=>window.removeEventListener(`keydown`,e,!0)},[r]),(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`div`,{className:`menu-backdrop`,onPointerDown:r,onContextMenu:e=>{e.preventDefault(),r()}}),(0,J.jsx)(`div`,{ref:i,className:`menu-list fm-menu`,role:`menu`,style:a,onKeyDown:e=>{if(e.key!==`ArrowDown`&&e.key!==`ArrowUp`)return;e.preventDefault();let t=[...i.current?.querySelectorAll(`button:not(:disabled)`)??[]];t[(t.indexOf(document.activeElement)+(e.key===`ArrowDown`?1:-1)+t.length)%t.length]?.focus()},children:n.map(e=>(0,J.jsxs)(`button`,{type:`button`,role:`menuitem`,className:`${e.danger?`danger`:``}${e.separated?` separated`:``}${e.narrow?` bte-narrow`:``}`,disabled:e.disabled,onClick:()=>{r(),e.run()},children:[(0,J.jsx)(`span`,{children:e.label}),e.keys&&(0,J.jsx)(`kbd`,{children:e.keys})]},e.label))})]})}function $o({question:e,onDone:t}){let{names:n,folder:r,verb:i,resolve:a}=e,o=e=>{a(e),t()},s=n.length===1;return(0,J.jsx)(Ge,{title:s?`${n[0]} exists already`:`${n.length} names are taken`,onClose:()=>o(null),children:(0,J.jsxs)(`div`,{className:`modal-body`,children:[(0,J.jsxs)(`div`,{className:`dialog-message`,children:[s?`There is`:`There are`,` `,(0,J.jsx)(`strong`,{children:ko(n)}),` in `,(0,J.jsx)(`code`,{children:$(r)}),` already, where`,` `,s?`it is`:`they are`,` `,i,`.`,(0,J.jsxs)(`ul`,{className:`fm-choices`,children:[(0,J.jsxs)(`li`,{children:[(0,J.jsx)(`strong`,{children:`Replace`}),`: what is there is deleted`,s?``:`, folders with all they hold`]}),(0,J.jsxs)(`li`,{children:[(0,J.jsx)(`strong`,{children:`Keep both`}),`: the new `,s?`one gets`:`ones get`,` a number after the name, “name (2).ext”`]}),(0,J.jsxs)(`li`,{children:[(0,J.jsx)(`strong`,{children:`Skip`}),`: `,s?`it is`:`they are`,` not `,i]})]})]}),(0,J.jsxs)(`div`,{className:`modal-actions`,children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>o(null),children:`Cancel`}),(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>o(`skip`),children:`Skip`}),(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>o(`keep-both`),autoFocus:!0,children:`Keep both`}),(0,J.jsx)(`button`,{type:`button`,className:`button danger`,onClick:()=>o(`replace`),children:`Replace`})]})]})})}function es({initial:e,text:t,onSaved:n,onClose:r}){let i=(0,q.useId)(),[a,o]=(0,q.useState)(e),[s,c]=(0,q.useState)(!1),[l,u]=(0,q.useState)(!1),[d,f]=(0,q.useState)(null),p=/^(\/|~\/).*[^/]$/.test(a.trim()),m=async e=>{let r=a.trim();u(!0),f(null);try{let i=await K.saveText(r,t,null,!e);n(r,i.version,i.stamp)}catch(e){f({message:e instanceof Error?e.message:String(e),exists:e instanceof Be&&e.status===409}),u(!1)}};return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(Ge,{title:`Save as`,onClose:r,wide:!0,children:(0,J.jsxs)(`form`,{className:`modal-body`,onSubmit:e=>{e.preventDefault(),m(!1)},children:[(0,J.jsxs)(`div`,{className:`field`,children:[(0,J.jsx)(`label`,{className:`field-label`,htmlFor:i,children:`File on the robot`}),(0,J.jsxs)(`div`,{className:`bt-record-path`,children:[(0,J.jsx)(`input`,{id:i,value:a,spellCheck:!1,autoFocus:!0,onChange:e=>{o(e.target.value),f(null)}}),(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>c(!0),children:`Browse…`})]}),(0,J.jsx)(`p`,{className:`field-help`,children:`/…, ~/…: its folder must exist`}),d&&(0,J.jsx)(`p`,{className:`field-help error`,children:d.message})]}),(0,J.jsxs)(`div`,{className:`modal-actions`,children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:r,children:`Cancel`}),d?.exists&&(0,J.jsx)(`button`,{type:`button`,className:`button danger`,disabled:l,onClick:()=>void m(!0),children:`Replace it`}),(0,J.jsx)(`button`,{type:`submit`,className:`button primary`,disabled:l||!p,children:l?`Saving…`:`Save`})]})]})}),s&&(0,J.jsx)(Tt,{kind:`folder`,start:Ja(a.trim())??`~`,onChoose:e=>{c(!1),o(`${e.replace(/\/+$/,``)}/${$(a.trim())||`untitled.txt`}`)},onClose:()=>c(!1)})]})}function ts({used:e,total:t}){let n=t>0?Math.min(1,e/t):0;return(0,J.jsx)(`span`,{className:`fm-usage ${Mo(e,t)}`,role:`meter`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":Math.round(n*100),title:`${$a(e)} used of ${$a(t)}`,children:(0,J.jsx)(`span`,{style:{width:`${n*100}%`}})})}var ns=new Map;function rs(e,t){return t>0?`${Math.round(e/t*100)}%`:``}function is({rows:e,onPick:t}){let n=Math.max(1,...e.map(e=>e.size));return(0,J.jsx)(`ul`,{className:`fm-bars`,children:e.map(e=>(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,className:`fm-bar-row`,disabled:!t,onClick:()=>t?.(e.key),title:e.label,children:[(0,J.jsx)(`span`,{className:`fm-bar-label`,children:e.label}),(0,J.jsx)(`span`,{className:`fm-bar-size`,children:$a(e.size)}),(0,J.jsx)(`span`,{className:`fm-bar-note`,children:e.note}),(0,J.jsx)(`span`,{className:`fm-bar`,children:(0,J.jsx)(`span`,{style:{width:`${e.size/n*100}%`}})})]})},e.key))})}function as({folder:e,home:t,disks:n,now:r,onGo:i,onReveal:a,onRefreshDisks:o}){let[s,c]=(0,q.useState)(()=>ns.get(e)??null),[l,u]=(0,q.useState)(!1),[d,f]=(0,q.useState)(null),[m,h]=(0,q.useState)(e);m!==e&&(h(e),c(ns.get(e)??null),f(null));let g=()=>{u(!0),f(null),K.analyze(e).then(t=>{let n={result:t,at:Date.now()};ns.set(t.path,n),t.path===e&&c(n),u(!1)},e=>{f(e instanceof Error?e.message:String(e)),u(!1)})},_=s?.result;return(0,J.jsxs)(`div`,{className:`fm-overview`,children:[n&&(0,J.jsxs)(`section`,{children:[(0,J.jsxs)(`h3`,{children:[`Disks`,(0,J.jsx)(`button`,{type:`button`,className:`icon-button fm-heading-button`,"aria-label":`Read the disks again`,title:`Read again`,onClick:o,children:(0,J.jsx)(ae,{width:14,height:14})})]}),(0,J.jsx)(`ul`,{className:`fm-disks`,children:n.map(e=>{let t=e.used+e.free,n=e.inodes&&e.inodes.total>0?e.inodes:null,r=n?n.total-n.free:0;return(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,className:`fm-disk-card ${Mo(e.used,t)}`,onClick:()=>i(e.mount),title:`Go to ${e.mount}`,children:[(0,J.jsxs)(`span`,{className:`fm-disk-head`,children:[(0,J.jsx)(p,{width:16,height:16}),(0,J.jsx)(`strong`,{children:e.mount}),(0,J.jsxs)(`span`,{className:`bt-muted`,children:[e.device,` · `,e.type,e.readOnly?` · read-only`:``]})]}),(0,J.jsx)(ts,{used:e.used,total:t}),(0,J.jsxs)(`span`,{className:`fm-disk-numbers`,children:[(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`strong`,{children:$a(e.free)}),` free of `,$a(e.total)]}),(0,J.jsxs)(`span`,{children:[$a(e.used),` used, `,rs(e.used,t)]})]}),n&&Mo(r,n.total)!==`ok`&&(0,J.jsxs)(`span`,{className:`fm-error`,children:[rs(r,n.total),` of its inodes used: `,Ao(n.free,`file`),` more at most`]})]})},e.mount)})})]}),(0,J.jsxs)(`section`,{children:[(0,J.jsx)(`h3`,{children:`This folder`}),(0,J.jsx)(`p`,{className:`fm-overview-path`,children:Xa(e,t)}),!_&&(0,J.jsx)(`p`,{className:`bt-muted fm-overview-hint`,children:`What takes its space: its largest entries, its files by type, the largest and the latest files under it.`}),(0,J.jsxs)(`div`,{className:`fm-analyze`,children:[(0,J.jsxs)(`button`,{type:`button`,className:`button${_?``:` primary`}`,disabled:l,onClick:g,children:[(0,J.jsx)(we,{width:16,height:16}),l?`Analyzing…`:_?`Analyze again`:`Analyze this folder`]}),s&&!l&&(0,J.jsxs)(`span`,{className:`bt-muted`,children:[`Analyzed `,oo(s.at,r)]})]}),d&&(0,J.jsx)(`p`,{className:`fm-error`,children:d}),_&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`p`,{className:`fm-summary`,children:[(0,J.jsx)(`strong`,{children:$a(_.size)}),` in `,Ao(_.files,`file`),` and `,Ao(_.folders,`folder`),(0,J.jsxs)(`span`,{className:`bt-muted`,children:[` `,`(`,$a(_.disk),` on the disk`,_.links>0?`, ${Ao(_.links,`link`)} not followed`:``,`)`]})]}),(_.partial||_.unreadable>0||_.mounts>0)&&(0,J.jsx)(`p`,{className:`fm-error`,children:[_.partial&&`${_.partial}: at least as much`,_.unreadable>0&&`${Ao(_.unreadable,`folder`)} not readable`,_.mounts>0&&`${Ao(_.mounts,`other disk`)} left out`].filter(Boolean).join(`; `)}),_.children.length>0&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`h4`,{children:`Largest inside`}),(0,J.jsx)(is,{rows:_.children.filter(e=>e.size>0).slice(0,12).map(e=>({key:e.name,label:`${e.name}${e.kind===`dir`?`/`:``}`,size:e.size,note:`${rs(e.size,_.size)}${e.kind===`dir`?` · ${Ao(e.files,`file`)}`:``}`})),onPick:e=>{let t=_.children.find(t=>t.name===e),n=qa(_.path,e);t?.kind===`dir`?i(n):a(n)}})]}),_.types.length>0&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`h4`,{children:`By type`}),(0,J.jsx)(is,{rows:_.types.map(e=>({key:e.type,label:e.type?e.type.slice(1):`No extension`,size:e.size,note:`${rs(e.size,_.size)} · ${Ao(e.files,`file`)}`}))})]}),_.largest.length>0&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`h4`,{children:`Largest files`}),(0,J.jsx)(`ul`,{className:`fm-file-list`,children:_.largest.map(e=>(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,className:`fm-file-row`,title:e.path,onClick:()=>a(qa(_.path,e.path)),children:[(0,J.jsx)(`span`,{className:`fm-bar-label`,children:$(e.path)}),(0,J.jsx)(`span`,{className:`bt-muted fm-file-where`,children:e.path.includes(`/`)?Ja(e.path):``}),(0,J.jsx)(`span`,{className:`fm-bar-size`,children:$a(e.size)})]})},e.path))})]}),_.recent.length>0&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`h4`,{children:`Latest changes`}),(0,J.jsx)(`ul`,{className:`fm-file-list`,children:_.recent.map(e=>(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,className:`fm-file-row`,title:e.path,onClick:()=>a(qa(_.path,e.path)),children:[(0,J.jsx)(`span`,{className:`fm-bar-label`,children:$(e.path)}),(0,J.jsx)(`span`,{className:`bt-muted fm-file-where`,children:e.path.includes(`/`)?Ja(e.path):``}),(0,J.jsx)(`span`,{className:`fm-bar-size`,children:oo(e.modified,r)})]})},e.path))})]})]})]})]})}var os={re:/\s+/y,keepStart:!0},ss=/"(?:[^"\\]|\\.)*"?/y,cs=/'(?:[^'\\]|\\.)*'?/y,ls=/(?:0[xX][\da-fA-F_]+|0[bB][01_]+|0[oO][0-7_]+|(?:\d[\d_]*(?:\.[\d_]*)?|\.\d[\d_]*)(?:[eE][+-]?\d+)?)[a-zA-Z]*/y;function us(e){return new Set(e.split(` `))}function ds(e,t,n,r=/[A-Za-z_$][\w$]*/y){return{re:r,token:r=>e.has(r)?`keyword`:t.has(r)?`type`:n.has(r)?`atom`:``}}function fs(e,t,n=0){return{fill:t,rules:[{re:e,token:t,next:n}]}}var ps=us(`and as assert async await break class continue def del elif else except finally for from global if import in is lambda match case nonlocal not or pass raise return try while with yield`),ms=us(`bool bytes dict float int list object set str tuple type self cls super print len range open isinstance`),hs=us(`True False None NotImplemented Ellipsis __name__ __file__`),gs=us(`alignas alignof asm break case catch class concept const consteval constexpr constinit const_cast continue co_await co_return co_yield decltype default delete do dynamic_cast else enum explicit export extern final for friend goto if inline mutable namespace new noexcept operator override private protected public register reinterpret_cast requires return sizeof static static_assert static_cast struct switch template this thread_local throw try typedef typeid typename union using virtual volatile while`),_s=us(`auto bool char char8_t char16_t char32_t double float int long short signed unsigned void wchar_t size_t ssize_t std string vector map unordered_map set array optional shared_ptr unique_ptr weak_ptr function`),vs=us(`true false nullptr NULL`),ys=us(`as async await break case catch class const continue debugger default delete do else enum export extends finally for from function get if implements import in instanceof interface let new of private protected public readonly return set static super switch this throw try type typeof var void while with yield`),bs=us(`any boolean never number object string symbol unknown bigint Array Map Set Promise Record`),xs=us(`true false null undefined NaN Infinity`),Ss=us(`if then else elif fi for in do done while until case esac function return select time export local readonly declare source alias unset shift exit break continue trap set`),Cs=us(`echo printf cd ls cat grep sed awk test read eval exec ros2 colcon sudo apt source`),ws=new Set,Ts={python:{label:`Python`,comment:`#`,states:[{rules:[os,{re:/#.*/y,token:`comment`},{re:/[rRbBuUfF]{0,2}"""/y,token:`string`,next:1},{re:/[rRbBuUfF]{0,2}'''/y,token:`string`,next:2},{re:/[rRbBuUfF]{0,2}"(?:[^"\\]|\\.)*"?/y,token:`string`},{re:/[rRbBuUfF]{0,2}'(?:[^'\\]|\\.)*'?/y,token:`string`},{re:/@[\w.]+/y,token:`meta`,start:!0},{re:/(def|class)(\s+)([A-Za-z_]\w*)/y,groups:[`keyword`,``,`function`]},{re:ls,token:`number`},ds(ps,ms,hs)]},fs(/(?:[^"\\]|\\.|"(?!""))*"""/y,`string`),fs(/(?:[^'\\]|\\.|'(?!''))*'''/y,`string`)]},cpp:{label:`C, C++`,comment:`//`,states:[{rules:[os,{re:/\/\/.*/y,token:`comment`},{re:/\/\*/y,token:`comment`,next:1},{re:/(#\s*include)(\s*)(<[^>]*>?)/y,groups:[`meta`,``,`string`],start:!0},{re:/#\s*\w+/y,token:`meta`,start:!0},{re:/(?:u8|[uUL])?"(?:[^"\\]|\\.)*"?/y,token:`string`},{re:/(?:u8|[uUL])?'(?:[^'\\]|\\.)*'?/y,token:`string`},{re:ls,token:`number`},{re:/[A-Za-z_]\w*_t\b/y,token:`type`},ds(gs,_s,vs,/[A-Za-z_]\w*/y)]},fs(/.*?\*\//y,`comment`)]},javascript:{label:`JavaScript, TypeScript`,comment:`//`,states:[{rules:[os,{re:/\/\/.*/y,token:`comment`},{re:/\/\*/y,token:`comment`,next:1},{re:ss,token:`string`},{re:cs,token:`string`},{re:/`(?:[^`\\]|\\.)*`?/y,token:`string`},{re:ls,token:`number`},{re:/(function)(\s+)([A-Za-z_$][\w$]*)/y,groups:[`keyword`,``,`function`]},ds(ys,bs,xs)]},fs(/.*?\*\//y,`comment`)]},json:{label:`JSON`,comment:null,states:[{rules:[os,{re:/"(?:[^"\\]|\\.)*"(?=\s*:)/y,token:`key`},{re:ss,token:`string`},{re:/-?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/y,token:`number`},{re:/(?:true|false|null)\b/y,token:`atom`},{re:/[{}[\],:]/y,token:`punctuation`},{re:/\/\/.*/y,token:`comment`}]}]},yaml:{label:`YAML`,comment:`#`,states:[{rules:[os,{re:/#.*/y,token:`comment`},{re:/(?:---|\.\.\.)(?=\s|$)/y,token:`meta`,start:!0},{re:/-(?=\s|$)/y,token:`punctuation`,keepStart:!0},{re:/(?:"(?:[^"\\]|\\.)*"|'(?:[^']|'')*'|[^\s#'"{}[\],&*!|>%@`][^#]*?)\s*:(?=\s|$)/y,token:`key`,start:!0},{re:/[&*][^\s,[\]{}]+/y,token:`meta`},{re:/![^\s]*/y,token:`meta`},{re:ss,token:`string`},{re:/'(?:[^']|'')*'?/y,token:`string`},{re:/[|>][-+]?\d*(?=\s*(?:#|$))/y,token:`meta`},{re:/(?:true|false|yes|no|on|off|null|True|False|TRUE|FALSE|Yes|No|Null|NULL|~)(?=\s*(?:#|$|,|\]|\}))/y,token:`atom`},{re:/[-+]?(?:0x[\da-fA-F]+|0o[0-7]+|\d[\d_]*(?:\.\d*)?(?:[eE][-+]?\d+)?|\.\d+(?:[eE][-+]?\d+)?|\.inf|\.nan)(?=\s*(?:#|$|,|\]|\}))/y,token:`number`},{re:/[{}[\],:]/y,token:`punctuation`},{re:/[^\s#,[\]{}]+/y}]}]},xml:{label:`XML: URDF, launch`,comment:null,states:[{rules:[os,{re:/<!--/y,token:`comment`,next:1},{re:/<!\[CDATA\[/y,token:`meta`,next:2},{re:/<[?!][\w:-]*/y,token:`meta`,next:3},{re:/(<\/?)([\w:.-]+)/y,groups:[`punctuation`,`tag`],next:3},{re:/&(?:#\d+|#x[\da-fA-F]+|\w+);/y,token:`atom`},{re:/\$[({][^)}]*[)}]?/y,token:`variable`},{re:/[^<&$\s]+/y}]},fs(/.*?-->/y,`comment`),{fill:``,rules:[{re:/(.*?)(\]\]>)/y,groups:[``,`meta`],next:0}]},{rules:[os,{re:/\/?>|\?>/y,token:`punctuation`,next:0},{re:/[\w:.-]+/y,token:`attribute`},{re:/=/y,token:`punctuation`},{re:/"[^"]*"/y,token:`string`},{re:/'[^']*'/y,token:`string`},{re:/"[^"]*/y,token:`string`,next:4},{re:/'[^']*/y,token:`string`,next:5}]},fs(/[^"]*"/y,`string`,3),fs(/[^']*'/y,`string`,3)]},shell:{label:`Shell`,comment:`#`,states:[{rules:[os,{re:/#!.*/y,token:`meta`,start:!0},{re:/#.*/y,token:`comment`},{re:ss,token:`string`},{re:/'[^']*'?/y,token:`string`},{re:/\$\{[^}]*\}?|\$\(|\$[\w@#?$!*-]+/y,token:`variable`},{re:/([A-Za-z_]\w*)(\+?=)/y,groups:[`variable`,`punctuation`]},{re:/\d+(?=\s|$|[;&|)])/y,token:`number`},ds(Ss,Cs,ws,/[A-Za-z_][\w.-]*/y),{re:/[^\s"'$#\w]+/y}]}]},cmake:{label:`CMake`,comment:`#`,states:[{rules:[os,{re:/#\[\[/y,token:`comment`,next:1},{re:/#.*/y,token:`comment`},{re:ss,token:`string`},{re:/\$(?:ENV)?\{[^}]*\}?/y,token:`variable`},{re:/([A-Za-z_]\w*)(\s*)(?=\()/y,groups:[`function`,``]},{re:/[A-Z][A-Z0-9_]+\b/y,token:`atom`},{re:/[\w.-]+/y}]},fs(/.*?\]\]/y,`comment`)]},ini:{label:`INI, TOML, systemd`,comment:`#`,states:[{rules:[os,{re:/[#;].*/y,token:`comment`,start:!0},{re:/#.*/y,token:`comment`},{re:/\[[^\]]*\]?/y,token:`tag`,start:!0},{re:/[^=\s[#;][^=]*?(?=\s*=)/y,token:`key`,start:!0},{re:/=/y,token:`punctuation`},{re:ss,token:`string`},{re:cs,token:`string`},{re:/(?:true|false|yes|no|on|off)\b/iy,token:`atom`},{re:/[-+]?\d[\d_.]*\b/y,token:`number`},{re:/[^\s"'=#;]+/y}]}]},markdown:{label:`Markdown`,comment:null,states:[{rules:[{re:/#{1,6}(?:\s.*|$)/y,token:`heading`,start:!0},{re:/```.*/y,token:`meta`,start:!0,next:1},{re:/>.*/y,token:`comment`,start:!0},{re:/(?:[-*+]|\d+[.)])(?=\s)/y,token:`punctuation`,start:!0,keepStart:!0},os,{re:/`[^`]*`?/y,token:`string`},{re:/\*\*[^*]+\*\*|__[^_]+__/y,token:`emphasis`},{re:/!?\[[^\]]*\]\([^)]*\)/y,token:`link`},{re:/<https?:[^>]*>|https?:\/\/[^\s)>]+/y,token:`link`},{re:/[^\s`*_[!<h]+/y}]},{fill:`string`,rules:[{re:/```\s*$/y,token:`meta`,start:!0,next:0}]}]},ros:{label:`ROS interface`,comment:`#`,states:[{rules:[os,{re:/#.*/y,token:`comment`},{re:/---\s*$/y,token:`meta`,start:!0},{re:/[A-Za-z_][\w/]*(?:<=\d+)?(?:\[[^\]]*\])?/y,token:`type`,start:!0},{re:/[A-Z][A-Z0-9_]*(?=\s*=)/y,token:`atom`},{re:/=/y,token:`punctuation`},{re:ss,token:`string`},{re:cs,token:`string`},{re:/-?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/y,token:`number`},{re:/[A-Za-z_]\w*/y}]}]}},Es=[{id:`plain`,label:`Plain text`},...Object.entries(Ts).map(([e,t])=>({id:e,label:t.label})).sort((e,t)=>e.label.localeCompare(t.label))],Ds={yaml:`yaml`,yml:`yaml`,rviz:`yaml`,repos:`yaml`,rosinstall:`yaml`,json:`json`,jsonc:`json`,xml:`xml`,urdf:`xml`,xacro:`xml`,sdf:`xml`,srdf:`xml`,launch:`xml`,world:`xml`,dae:`xml`,xsd:`xml`,xsl:`xml`,svg:`xml`,html:`xml`,htm:`xml`,py:`python`,pyi:`python`,pyx:`python`,c:`cpp`,cc:`cpp`,cpp:`cpp`,cxx:`cpp`,h:`cpp`,hh:`cpp`,hpp:`cpp`,hxx:`cpp`,ipp:`cpp`,tpp:`cpp`,ino:`cpp`,cu:`cpp`,proto:`cpp`,idl:`cpp`,js:`javascript`,mjs:`javascript`,cjs:`javascript`,jsx:`javascript`,ts:`javascript`,tsx:`javascript`,cmake:`cmake`,sh:`shell`,bash:`shell`,zsh:`shell`,env:`shell`,ini:`ini`,cfg:`ini`,conf:`ini`,toml:`ini`,properties:`ini`,service:`ini`,timer:`ini`,socket:`ini`,mount:`ini`,target:`ini`,path:`ini`,desktop:`ini`,rules:`ini`,md:`markdown`,markdown:`markdown`,msg:`ros`,srv:`ros`,action:`ros`},Os={"cmakelists.txt":`cmake`,dockerfile:`shell`,makefile:`shell`,".bashrc":`shell`,".bash_profile":`shell`,".bash_aliases":`shell`,".bash_logout":`shell`,".profile":`shell`,".zshrc":`shell`,".gitconfig":`ini`,".editorconfig":`ini`,".gitmodules":`ini`,"colcon.meta":`json`};function ks(e,t=``){let n=e.toLowerCase();if(Os[n])return Os[n];let r=n.lastIndexOf(`.`);return(r>0?Ds[n.slice(r+1)]:void 0)||(/^#!.*\b(?:ba|z|da)?sh\b/.test(t)?`shell`:/^#!.*\bpython/.test(t)?`python`:/^<\?xml\b/.test(t)?`xml`:`plain`)}function As(e){return e===`plain`?null:Ts[e].comment}var js=4e3;function Ms(e,t,n){if(e===`plain`||t.length===0)return{spans:t.length>0?[[t.length,``]]:[],state:n};let{states:r}=Ts[e],i=[],a=(e,t)=>{if(e<=0)return;let n=i[i.length-1];n&&n[1]===t?n[0]+=e:i.push([e,t])},o=Math.min(t.length,js),s=0,c=!0;for(;s<o;){let e=r[n]??r[0],i=!1;for(let r of e.rules){if(r.start&&!c)continue;r.re.lastIndex=s;let e=r.re.exec(t);if(e&&e[0].length!==0){r.groups?r.groups.forEach((t,n)=>a(e[n+1]?.length??0,t)):a(e[0].length,typeof r.token==`function`?r.token(e[0]):r.token??``),s+=e[0].length,r.next!==void 0&&(n=r.next),c&&=r.keepStart===!0,i=!0;break}}i||(e.fill===void 0?(a(1,``),c&&=/\s/.test(t[s]),s++):(a(o-s,e.fill),s=o))}return a(t.length-o,``),{spans:i,state:n}}var Ns={past:[],future:[],last:null},Ps=1e3,Fs=2e7,Is=1500;function Ls(e,t,n=0){if(e===t)return null;let r=0;n>0&&n<=Math.min(e.length,t.length)&&e.slice(0,n)===t.slice(0,n)&&(r=n);let i=Math.min(e.length,t.length);for(;r<i&&e.charCodeAt(r)===t.charCodeAt(r);)r++;let a=0;for(;a<i-r&&e.charCodeAt(e.length-1-a)===t.charCodeAt(t.length-1-a);)a++;return{from:r,removed:e.slice(r,e.length-a),inserted:t.slice(r,t.length-a)}}function Rs(e,{from:t,removed:n,inserted:r}){return e.slice(0,t)+r+e.slice(t+n.length)}function zs({from:e,removed:t,inserted:n}){return{from:e,removed:n,inserted:t}}function Bs(e){return/^\s+$/.test(e)}function Vs(e,t,n){let r=e.change,i=t.change;if(n===`type`&&i.removed===``&&!i.inserted.includes(`
|
|
32
|
+
`)&&i.from===r.from+r.inserted.length)return Bs(i.inserted)&&r.inserted&&!Bs(r.inserted.slice(-1))?null:{change:{from:r.from,removed:r.removed,inserted:r.inserted+i.inserted},before:e.before,after:t.after};if(n===`delete`&&r.inserted===``&&i.inserted===``&&!i.removed.includes(`
|
|
33
|
+
`)){if(i.from+i.removed.length===r.from)return{change:{from:i.from,removed:i.removed+r.removed,inserted:``},before:e.before,after:t.after};if(i.from===r.from)return{change:{from:r.from,removed:r.removed+i.removed,inserted:``},before:e.before,after:t.after}}return null}function Hs(e,t,n,r){let i=e.past[e.past.length-1],a=i&&e.last&&e.last.kind===n&&n!==`other`&&r-e.last.time<Is?Vs(i,t,n):null,o=a?[...e.past.slice(0,-1),a]:[...e.past,t],s=0,c=o.length;for(;c>0&&o.length-c<Ps;){let{change:e}=o[c-1];if(s+=e.removed.length+e.inserted.length,s>Fs)break;c--}return{past:o.slice(c),future:[],last:{kind:n,time:r}}}function Us(e,t){let n=t.past[t.past.length-1];return n?{text:Rs(e,zs(n.change)),history:{past:t.past.slice(0,-1),future:[...t.future,n],last:null},selection:n.before}:null}function Ws(e,t){let n=t.future[t.future.length-1];return n?{text:Rs(e,n.change),history:{past:[...t.past,n],future:t.future.slice(0,-1),last:null},selection:n.after}:null}function Gs(e){let t=[0];for(let n=e.indexOf(`
|
|
34
|
+
`);n>=0;n=e.indexOf(`
|
|
35
|
+
`,n+1))t.push(n+1);return t}function Ks(e,t){let n=0,r=e.length-1;for(;n<r;){let i=n+r+1>>1;e[i]<=t?n=i:r=i-1}return n}function qs(e){let t=(e.match(/\n/g)??[]).length,n=(e.match(/\r\n/g)??[]).length;return n>0&&n*2>=t?`\r
|
|
36
|
+
`:`
|
|
37
|
+
`}function Js(e){return e===`tab`?` `:` `.repeat(e)}function Ys(e,t=2){let n=0,r=0,i=new Map,a=0;for(let t of e.split(`
|
|
38
|
+
`,1e4)){if(!t.trim())continue;if(t.startsWith(` `)){n++;continue}let e=t.length-t.trimStart().length;e>0&&r++;let o=Math.abs(e-a);o>0&&o<=8&&i.set(o,(i.get(o)??0)+1),a=e}if(n>r)return`tab`;let o=t,s=0;for(let e of[2,4,8,3])(i.get(e)??0)>s&&(o=e,s=i.get(e));return r>0?o:t}function Xs(e,{start:t,end:n}){let r=e.lastIndexOf(`
|
|
39
|
+
`,t-1)+1,i=n>t&&e[n-1]===`
|
|
40
|
+
`?n-1:n,a=e.indexOf(`
|
|
41
|
+
`,i);return{from:r,to:a<0?e.length:a}}function Zs(e,t,n,r){let{from:i,to:a}=Xs(e,t),o=Js(n),s=o===` `?1:o.length,c=e.slice(i,a).split(`
|
|
42
|
+
`),l=0,u=0,d=c.map((e,t)=>{let n,i;if(r){let t=/^(\t| {1,8})/.exec(e)?.[0]??``,r=t===` `?1:Math.min(t.length,s);i=e.slice(r),n=-r}else e.length===0&&c.length>1?(i=e,n=0):(i=o+e,n=o.length);return t===0&&(l=n),u+=n,i}),f=e.slice(0,i)+d.join(`
|
|
43
|
+
`)+e.slice(a),p=Math.max(i,t.start+l);return{text:f,selection:{start:p,end:Math.max(p,t.end+u)}}}function Qs(e,t,n){let{from:r,to:i}=Xs(e,t),a=e.slice(r,i).split(`
|
|
44
|
+
`),o=a.filter(e=>e.trim()),s=o.length>0&&o.every(e=>e.trimStart().startsWith(n)),c=Math.min(...o.map(e=>e.length-e.trimStart().length)),l=0,u=0,d=a.map((e,t)=>{let r=e;if(s){let t=e.indexOf(n);if(t>=0){let i=n.length+ +(e[t+n.length]===` `);r=e.slice(0,t)+e.slice(t+i)}}else e.trim()&&(r=`${e.slice(0,c)}${n} ${e.slice(c)}`);return t===0&&(l=r.length-e.length),u+=r.length-e.length,r}),f=e.slice(0,r)+d.join(`
|
|
45
|
+
`)+e.slice(i),p=Math.max(r,t.start+l);return{text:f,selection:{start:p,end:Math.max(p,t.end+u)}}}function $s(e,t){let n=e.lastIndexOf(`
|
|
46
|
+
`,t-1)+1;return`\n${/^[ \t]*/.exec(e.slice(n,t))?.[0]??``}`}function ec(e,t){let n=t.regex?e:e.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`);return t.wholeWord&&(n=`\\b(?:${n})\\b`),new RegExp(n,`g${t.caseSensitive?``:`i`}m`)}function tc(e,t,n){if(!t)return{matches:[],error:null,capped:!1};let r;try{r=ec(t,n)}catch(e){return{matches:[],error:e instanceof Error?e.message:String(e),capped:!1}}let i=[];for(let t=r.exec(e);t;t=r.exec(e))if(t[0].length===0)r.lastIndex++;else if(i.push([t.index,t.index+t[0].length]),i.length>=1e4)return{matches:i,error:null,capped:!0};return{matches:i,error:null,capped:!1}}function nc(e,t){return e.replace(/\$(\$|&|\d{1,2}|<([^>]*)>)/g,(e,n,r)=>{if(n===`$`)return`$`;if(n===`&`)return t[0];if(r!==void 0)return t.groups?.[r]??``;let i=Number(n);if(i>=1&&i<t.length)return t[i]??``;let a=Number(n[0]);return n.length===2&&a>=1&&a<t.length?(t[a]??``)+n[1]:e})}function rc(e,t,n,r,i){let a=ec(n,i);a.lastIndex=t;let o=a.exec(e);return!o||o.index!==t||o[0].length===0?null:i.regex?nc(r,o):r}function ic(e,t,n,r){if(!t)return{text:e,count:0};let i=ec(t,r),a=``,o=0,s=0;for(let t=i.exec(e);t;t=i.exec(e))t[0].length===0?i.lastIndex++:(a+=e.slice(o,t.index)+(r.regex?nc(n,t):n),o=t.index+t[0].length,s++);return{text:a+e.slice(o),count:s}}function ac(e){return{folder:e,back:[],forward:[],expanded:new Set,tabs:[],active:null,nextId:1}}function oc(e){return e.replace(/\r\n/g,`
|
|
47
|
+
`)}function sc(e,t){return{start:Math.min(e.start,t),end:Math.min(e.end,t)}}function cc(e,t,n){let r=oc(t.text);return{...e,text:r,saved:r,base:t.version,stamp:t.stamp,eol:qs(t.text),readOnly:t.readOnly,error:null,missing:!1,external:null,history:Ns,selection:n?sc(e.selection,r.length):{start:0,end:0},scroll:n?e.scroll:{top:0,left:0},language:e.text===null?ks($(e.path),r.split(`
|
|
48
|
+
`,1)[0]):e.language,indent:e.text===null?Ys(r,e.language===`python`?4:2):e.indent}}function lc(e){return e.kind===`text`&&e.text!==null&&(e.text!==e.saved||e.missing)}function uc(e,t,n){return Ya(e,t)?n+e.slice(t.length):e}function dc(e,t,n){return{...e,tabs:e.tabs.map(e=>e.id===t&&e.kind===`text`?n(e):e)}}function fc(e,t){switch(t.type){case`go`:return t.folder===e.folder?{...e,active:null}:{...e,folder:t.folder,back:[...e.back,e.folder].slice(-50),forward:[],active:null};case`resolved`:return e.folder===t.from?{...e,folder:t.folder}:e;case`back`:case`forward`:{let n=t.type===`back`?e.back:e.forward,r=n[n.length-1];return r===void 0?e:{...e,folder:r,back:t.type===`back`?e.back.slice(0,-1):[...e.back,e.folder],forward:t.type===`back`?[...e.forward,e.folder]:e.forward.slice(0,-1),active:null}}case`fold`:{let n=new Set(e.expanded);if(t.open)n.add(t.folder);else for(let e of n)Ya(e,t.folder)&&n.delete(e);return{...e,expanded:n}}case`open`:{let n=e.tabs.find(e=>e.path===t.path&&e.kind===t.kind);if(n)return{...e,active:n.id};let r=e.nextId,i=t.kind===`image`?{kind:`image`,id:r,path:t.path,reads:0}:{kind:`text`,id:r,path:t.path,text:null,saved:null,base:null,stamp:null,eol:`
|
|
49
|
+
`,readOnly:null,error:null,missing:!1,external:null,history:Ns,selection:{start:0,end:0},scroll:{top:0,left:0},language:ks($(t.path)),indent:2,reads:0};return{...e,tabs:[...e.tabs,i],active:r,nextId:r+1}}case`activate`:return{...e,active:t.id};case`close`:{let n=e.tabs.findIndex(e=>e.id===t.id);if(n<0)return e;let r=e.tabs.filter(e=>e.id!==t.id),i=e.active===t.id?r[Math.min(n,r.length-1)]?.id??null:e.active;return{...e,tabs:r,active:i}}case`read`:return dc(e,t.id,e=>cc(e,t.file,e.text!==null));case`changed`:return dc(e,t.id,e=>t.file.version===e.base?{...e,stamp:t.file.stamp}:e.text===null||!lc(e)?cc(e,t.file,!0):{...e,stamp:t.file.stamp,external:{text:oc(t.file.text),version:t.file.version,stamp:t.file.stamp}});case`failed`:return dc(e,t.id,e=>({...e,error:t.error}));case`missing`:return dc(e,t.id,e=>({...e,missing:e.text!==null,error:e.text===null?`No file ${e.path}`:null}));case`edit`:return dc(e,t.id,e=>({...e,text:t.text,history:Hs(e.history,t.step,t.kind,t.time),selection:t.step.after}));case`undo`:case`redo`:return dc(e,t.id,e=>{let n=e.text===null?null:(t.type===`undo`?Us:Ws)(e.text,e.history);return n?{...e,text:n.text,history:n.history,selection:n.selection}:e});case`view`:return dc(e,t.id,e=>({...e,selection:t.selection,scroll:t.scroll??e.scroll}));case`saved`:return dc(e,t.id,e=>({...e,path:t.path??e.path,saved:t.text,base:t.version,stamp:t.stamp,readOnly:t.path&&t.path!==e.path?null:e.readOnly,missing:!1,external:null}));case`conflict`:return dc(e,t.id,e=>({...e,external:{text:null,version:t.version,stamp:t.stamp}}));case`reload`:return dc(e,t.id,e=>e.external?.text==null?{...e,external:null,reads:e.reads+1}:cc(e,{path:e.path,text:e.external.text,version:e.external.version,stamp:e.external.stamp??``,readOnly:e.readOnly},!0));case`keep`:return dc(e,t.id,e=>e.external?{...e,base:e.external.version,stamp:e.external.stamp??e.stamp,external:null}:e);case`settings`:return dc(e,t.id,e=>({...e,language:t.language??e.language,indent:t.indent??e.indent,eol:t.eol??e.eol}));case`moved`:{let n=e=>uc(e,t.from,t.to);return{...e,folder:n(e.folder),back:e.back.map(n),forward:e.forward.map(n),expanded:new Set([...e.expanded].map(n)),tabs:e.tabs.map(e=>Ya(e.path,t.from)?{...e,path:n(e.path)}:e)}}case`deleted`:{let n=e=>t.paths.some(t=>Ya(e,t));return{...e,tabs:e.tabs.filter(e=>e.kind===`text`||!n(e.path)).map(e=>e.kind===`text`&&n(e.path)&&e.text!==null?{...e,missing:!0}:e),active:e.tabs.some(t=>t.id===e.active&&t.kind===`image`&&n(t.path))?null:e.active,expanded:new Set([...e.expanded].filter(e=>!n(e)))}}}}var pc=new Map;function mc(){return[...pc.values()].some(e=>e.state.tabs.some(lc))}var hc={home:E,root:p,folder:_,ros:se,bookmark:R};function gc({places:e,disks:t,folder:n,dropTarget:r,canBookmark:i,onGo:a,onBookmark:o,onRemoveBookmark:s,onDragOver:c,onDrop:l,onClose:u}){let[d,f]=(0,q.useState)(new Set),m=e.reduce((e,t)=>Ya(n,t.path)&&(!e||t.path.length>e.path.length)?t:e,null),h=(e,t,n)=>(0,J.jsxs)(`button`,{type:`button`,className:`bte-palette-group`,"aria-expanded":!d.has(e),onClick:()=>f(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n}),children:[t,(0,J.jsx)(`span`,{className:`bt-muted`,children:n})]}),g=e=>({onDragOver:t=>c(e,t),onDrop:t=>l(e,t)}),_=[{key:`places`,title:`Places`,list:e.filter(e=>e.kind!==`ros`&&e.kind!==`bookmark`)},{key:`ros`,title:`ROS`,list:e.filter(e=>e.kind===`ros`)},{key:`bookmarks`,title:`Bookmarks`,list:e.filter(e=>e.kind===`bookmark`)}];return(0,J.jsxs)(`aside`,{className:`bte-palette fm-sidebar`,"aria-label":`Places`,children:[(0,J.jsxs)(`header`,{className:`bte-palette-header fm-sidebar-header`,children:[(0,J.jsx)(`span`,{className:`fm-sidebar-title`,children:`Places`}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Close the places`,title:`Close`,onClick:u,children:(0,J.jsx)(B,{width:16,height:16})})]}),(0,J.jsxs)(`div`,{className:`bte-palette-body`,children:[_.map(({key:e,title:t,list:n})=>n.length>0&&(0,J.jsxs)(`section`,{children:[e!==`places`&&h(e,t,n.length),!d.has(e)&&(0,J.jsx)(`ul`,{children:n.map(e=>{let t=hc[e.kind];return(0,J.jsxs)(`li`,{className:`fm-place-item`,children:[(0,J.jsxs)(`button`,{type:`button`,className:`bte-palette-item fm-place${m===e?` active`:``}${r===e.path?` drop-into`:``}`,title:e.path,onClick:()=>a(e.path),...g(e.path),children:[(0,J.jsx)(t,{className:`fm-icon folder`,width:15,height:15}),(0,J.jsx)(`span`,{className:`bte-palette-name`,children:e.name})]}),e.removable&&(0,J.jsx)(`button`,{type:`button`,className:`icon-button fm-place-remove`,"aria-label":`Remove the bookmark ${e.name}`,title:`Remove the bookmark`,onClick:()=>s(e.path),children:(0,J.jsx)(B,{width:13,height:13})})]},`${e.kind}:${e.path}`)})})]},e)),t&&t.length>0&&(0,J.jsxs)(`section`,{children:[h(`disks`,`Disks`,t.length),!d.has(`disks`)&&(0,J.jsx)(`ul`,{children:t.map(e=>(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,className:`bte-palette-item fm-disk${r===e.mount?` drop-into`:``}`,title:`${e.mount}: ${e.device} (${e.type}${e.readOnly?`, read-only`:``})`,onClick:()=>a(e.mount),...g(e.mount),children:[(0,J.jsxs)(`span`,{className:`fm-disk-name`,children:[(0,J.jsx)(p,{className:`fm-icon folder`,width:15,height:15}),(0,J.jsx)(`span`,{className:`bte-palette-name`,children:e.mount}),(0,J.jsxs)(`span`,{className:`bte-palette-library`,children:[$a(e.free),` free`]})]}),(0,J.jsx)(ts,{used:e.used,total:e.used+e.free})]})},e.mount))})]})]}),(0,J.jsx)(`footer`,{className:`bte-palette-footer`,children:(0,J.jsxs)(`button`,{type:`button`,className:`button`,disabled:!i,onClick:o,children:[(0,J.jsx)(ne,{width:16,height:16}),` Bookmark this folder`]})})]})}var _c=[{value:2,label:`Spaces: 2`},{value:3,label:`Spaces: 3`},{value:4,label:`Spaces: 4`},{value:8,label:`Spaces: 8`},{value:`tab`,label:`Tabs`}];function vc({tab:e,readOnly:t,onSettings:n}){let r=(0,q.useMemo)(()=>Gs(e.text),[e.text]),i=Ks(r,e.selection.end),a=Math.abs(e.selection.end-e.selection.start);return(0,J.jsxs)(`span`,{className:`fm-status-tools`,children:[(0,J.jsxs)(`span`,{className:`fm-status-caret`,children:[`Ln `,(i+1).toLocaleString(),`, Col `,e.selection.end-r[i]+1,a>0?` (${a.toLocaleString()} selected)`:``]}),(0,J.jsx)(`select`,{className:`fm-status-select`,"aria-label":`Highlighting`,value:e.language,onChange:e=>n({language:e.target.value}),children:Es.map(({id:e,label:t})=>(0,J.jsx)(`option`,{value:e,children:t},e))}),(0,J.jsx)(`select`,{className:`fm-status-select`,"aria-label":`Indentation`,value:String(e.indent),onChange:e=>n({indent:e.target.value===`tab`?`tab`:Number(e.target.value)}),children:_c.map(({value:e,label:t})=>(0,J.jsx)(`option`,{value:String(e),children:t},e))}),(0,J.jsxs)(`select`,{className:`fm-status-select`,"aria-label":`Line ends`,value:e.eol,disabled:t,onChange:e=>n({eol:e.target.value===`\r
|
|
50
|
+
`?`\r
|
|
51
|
+
`:`
|
|
52
|
+
`}),children:[(0,J.jsx)(`option`,{value:`
|
|
53
|
+
`,children:`LF`}),(0,J.jsx)(`option`,{value:`\r
|
|
54
|
+
`,children:`CRLF`})]})]})}function yc({uploads:e,textTab:t,saving:n,image:r,folder:i,readOnly:a,onSettings:o}){let s,c=null;if(e){let t=e.total>0?Math.round(e.sent/e.total*100):100;s={text:`Uploading ${e.name}${e.count>1?` (${e.index+1} of ${e.count})`:``} · ${t}%`,tone:`running`},c=(0,J.jsx)(`button`,{type:`button`,className:`link-button fm-status-action`,onClick:e.abort,children:`Cancel`})}else if(t){let e=$(t.path);s=n?{text:`Saving ${e}…`,tone:`running`}:t.text===null?{text:e,tone:t.error?`error`:`idle`}:lc(t)?{text:`${e} · changed`,tone:`changed`}:t.readOnly?{text:`${e} · read-only: ${t.readOnly}`,tone:`idle`}:{text:`${e} · saved`,tone:`success`},s.title=t.path,t.text!==null&&(c=(0,J.jsx)(vc,{tab:t,readOnly:a,onSettings:o}))}else if(r)s={text:`${$(r.path)}${r.size?` · ${r.size}`:``}`,tone:`idle`,title:r.path};else if(i.error)s={text:i.error,tone:`error`};else if(!i.listing)s={text:i.offline?`Cannot reach the robot`:`Reading…`,tone:`idle`};else{let{listing:e}=i,t=e.entries.filter(e=>lo(e.name)).length,n=[`${jo(i.shown)}${!i.showHidden&&t>0?`, ${t} hidden`:``}`];if(i.selected>0){let e=i.entries.filter(e=>e.kind===`file`),t=e.reduce((e,t)=>e+t.size,0);n.push(`${i.selected.toLocaleString()} selected${e.length>0?`, ${$a(t)}`:``}`)}e.writable||n.push(`read-only`),s={text:n.join(` · `),tone:`idle`,title:i.path};let{space:r}=e;r&&(c=(0,J.jsxs)(`span`,{className:`fm-status-space ${Mo(r.total-r.free,r.total)}`,title:`${$a(r.free)} free of ${$a(r.total)} on ${r.mount}`,children:[$a(r.free),` free`]}))}return(0,J.jsxs)(`div`,{className:`bt-status ${s.tone}`,title:s.title??s.text,children:[(0,J.jsx)(`span`,{className:`bt-dot`,"aria-hidden":`true`}),(0,J.jsx)(`span`,{className:`bt-status-text`,children:s.text}),c]})}function bc({tabs:e,active:t,folder:n,home:r,onActivate:i,onClose:a}){return(0,J.jsxs)(`div`,{className:`fm-tabs`,role:`tablist`,"aria-label":`Open files`,children:[(0,J.jsxs)(`button`,{type:`button`,role:`tab`,"aria-selected":t===null,className:`fm-tab${t===null?` active`:``}`,title:n?Xa(n,r):void 0,onClick:()=>i(null),children:[(0,J.jsx)(_,{className:`fm-icon folder`,width:14,height:14}),(0,J.jsx)(`span`,{className:`fm-tab-name`,children:n?$(Xa(n,r))||`/`:`Files`})]}),e.map(e=>(0,J.jsxs)(`div`,{role:`tab`,"aria-selected":e.id===t,tabIndex:0,className:`fm-tab${e.id===t?` active`:``}`,title:Xa(e.path,r),onClick:()=>i(e.id),onKeyDown:t=>t.key===`Enter`&&i(e.id),onAuxClick:t=>t.button===1&&a(e),children:[(0,J.jsx)(Io,{entry:{name:$(e.path),kind:`file`,bag:!1,mode:420,link:null},size:14}),(0,J.jsx)(`span`,{className:`fm-tab-name`,children:$(e.path)}),lc(e)&&(0,J.jsx)(`span`,{className:`fm-dirty`,"aria-label":`Changed`,title:`Changed`}),(0,J.jsx)(`button`,{type:`button`,className:`fm-tab-close`,"aria-label":`Close ${$(e.path)}`,title:`Close`,onClick:t=>{t.stopPropagation(),a(e)},children:(0,J.jsx)(B,{width:12,height:12})})]},e.id))]})}function xc({path:e,reads:t,onSize:n}){let[r,i]=(0,q.useState)(!0),[a,o]=(0,q.useState)(!1);if((0,q.useEffect)(()=>o(!1),[e,t]),a)return(0,J.jsx)(`div`,{className:`widget-message error`,children:`This image cannot be shown: download it`});let s=/\.(pgm|ppm|pnm)$/i.test(e);return(0,J.jsx)(`div`,{className:`fm-image${r?` fit`:``}${s?` map`:``}`,title:r?`Click: at its size`:`Click: to fit`,onClick:()=>i(e=>!e),children:(0,J.jsx)(`img`,{src:K.viewUrl(e,String(t)),alt:$(e),onLoad:e=>n(`${e.currentTarget.naturalWidth} × ${e.currentTarget.naturalHeight}`),onError:()=>o(!0)})})}var Sc=20,Cc=6,wc=10,Tc=4,Ec=30,Dc=5e4,Oc={open:!1,replace:!1,query:``,replacement:``,options:{caseSensitive:!1,regex:!1,wholeWord:!1}};function kc(e,t,n,r){if(t===`plain`)return e.language=t,[];if(e.language!==t)e.language=t,e.states=[0];else if(e.lines!==n){let t=Math.min(e.lines.length,n.length,e.states.length-1),r=0;for(;r<t&&e.lines[r]===n[r];)r++;e.states.length=r+1}e.lines=n;for(let i=e.states.length-1;i<Math.min(r,n.length);i++)e.states.push(Ms(t,n[i],e.states[i]).state);return e.states}function Ac(e,t){let n=0;for(let r=0;r<t&&r<e.length;r++)n=e[r]===` `?(Math.floor(n/Tc)+1)*Tc:n+1;return n}function jc(e,t,n,r,i,a){let o=[],s=0,c=a;for(let[a,l]of n){let n=s+a;for(;s<n;){for(;c<r.length&&r[c][1]-t<=s;)c++;let a=c<r.length&&r[c][0]-t<=s,u=a?Math.min(n,r[c][1]-t):Math.min(n,c<r.length?Math.max(s+1,r[c][0]-t):n),d=`${l?`fm-t-${l}`:``}${a?` fm-match${c===i?` current`:``}`:``}`,f=e.slice(s,u);o.push(d?(0,J.jsx)(`span`,{className:d,children:f},s):f),s=u}}return o}function Mc({find:e,count:t,current:n,capped:r,error:i,readOnly:a,inputRef:o,onChange:s,onStep:c,onReplace:l,onReplaceAll:u,onClose:d}){let f=(t,n,r)=>(0,J.jsx)(`button`,{type:`button`,className:`overlay-button fm-find-option`,"aria-pressed":e.options[t],title:r,"aria-label":r,onClick:()=>s({...e,options:{...e.options,[t]:!e.options[t]}}),children:n}),p=(e,t)=>{e.key===`Enter`?(e.preventDefault(),t?e.ctrlKey||e.metaKey?u():l():c(e.shiftKey?-1:1)):e.key===`Escape`&&(e.preventDefault(),d())},m=i?`Invalid`:e.query?t===0?`Not found`:`${n>=0?`${(n+1).toLocaleString()} of `:``}${t.toLocaleString()}${r?`+`:``}`:``;return(0,J.jsxs)(`div`,{className:`fm-find`,role:`search`,children:[(0,J.jsxs)(`div`,{className:`fm-find-row`,children:[(0,J.jsxs)(`label`,{className:`fm-search fm-find-input${i?` invalid`:``}`,title:i??void 0,children:[(0,J.jsx)(`input`,{ref:o,type:`text`,value:e.query,placeholder:`Find`,"aria-label":`Find`,spellCheck:!1,onChange:t=>s({...e,query:t.target.value}),onKeyDown:e=>p(e,!1)}),(0,J.jsx)(`span`,{className:`fm-find-count`,children:m})]}),f(`caseSensitive`,`Aa`,`Match case`),f(`wholeWord`,`W`,`Whole words`),f(`regex`,`.*`,`Regular expression`),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Previous (Shift+Enter)`,"aria-label":`Previous`,disabled:t===0,onClick:()=>c(-1),children:(0,J.jsx)(F,{width:16,height:16,style:{transform:`scaleY(-1)`}})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Next (Enter)`,"aria-label":`Next`,disabled:t===0,onClick:()=>c(1),children:(0,J.jsx)(F,{width:16,height:16})}),!a&&(0,J.jsx)(`button`,{type:`button`,className:`overlay-button fm-find-option`,"aria-pressed":e.replace,title:`Replace (Ctrl+H)`,"aria-label":`Replace`,onClick:()=>s({...e,replace:!e.replace}),children:`⇄`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Close (Esc)`,"aria-label":`Close the search`,onClick:d,children:(0,J.jsx)(B,{width:16,height:16})})]}),e.replace&&!a&&(0,J.jsxs)(`div`,{className:`fm-find-row`,children:[(0,J.jsx)(`label`,{className:`fm-search fm-find-input`,children:(0,J.jsx)(`input`,{type:`text`,value:e.replacement,placeholder:e.options.regex?`Replace with ($1: a group)`:`Replace with`,"aria-label":`Replace with`,spellCheck:!1,onChange:t=>s({...e,replacement:t.target.value}),onKeyDown:e=>p(e,!0)})}),(0,J.jsx)(`button`,{type:`button`,className:`button fm-find-button`,disabled:t===0,onClick:l,title:`Replace this one (Enter)`,children:`Replace`}),(0,J.jsx)(`button`,{type:`button`,className:`button fm-find-button`,disabled:t===0,onClick:u,title:`Replace them all (Ctrl+Enter)`,children:`All`})]})]})}var Nc=(0,q.forwardRef)(function({tab:e,wrap:t,readOnly:n,dispatch:r,onSave:i,onGoToLine:a},o){let{id:s,text:c,language:l,indent:u}=e,d=(0,q.useRef)(null),f=(0,q.useRef)(null),p=(0,q.useRef)(null),m=(0,q.useRef)(null),h=(0,q.useRef)(null),g=(0,q.useRef)(e.selection),_=(0,q.useRef)(e.scroll),v=(0,q.useRef)(e.selection),y=(0,q.useRef)(7.8),b=(0,q.useRef)({language:l,lines:[],states:[0]}),x=(0,q.useRef)(0),[S,C]=(0,q.useState)({first:0,last:60}),[w,T]=(0,q.useState)({...Oc,open:!1}),[E,D]=(0,q.useState)(-1),ee=(0,q.useMemo)(()=>c.split(`
|
|
55
|
+
`),[c]),O=(0,q.useMemo)(()=>Gs(c),[c]),k=(0,q.useMemo)(()=>w.open&&w.query?tc(c,w.query,w.options):{matches:[],error:null,capped:!1},[w.open,w.query,w.options,c]),{matches:A}=k;(0,q.useEffect)(()=>{Oc=w},[w]);let j=()=>{let e=d.current;if(!e)return;let{scrollTop:t,scrollLeft:n,clientHeight:r}=e;_.current={top:t,left:n},f.current&&(f.current.style.transform=`translate(${-n}px, ${-t}px)`),p.current&&(p.current.style.transform=`translateY(${-t}px)`);let i=Math.floor((t-Cc)/Sc),a=Math.ceil((t+r)/Sc);C(e=>i>=e.first&&a<=e.last&&e.last-e.first<=a-i+120?e:{first:Math.max(0,i-Ec),last:a+Ec})},M=e=>{let n=d.current;if(n){if(t)n.scrollTop=Math.max(0,e/Math.max(1,c.length)*n.scrollHeight-n.clientHeight/2);else{let t=Ks(O,e),r=Cc+t*Sc;r<n.scrollTop+Cc?n.scrollTop=r-Cc:r+Sc>n.scrollTop+n.clientHeight-Cc&&(n.scrollTop=r+Sc-n.clientHeight+12);let i=wc+Ac(ee[t]??``,e-O[t])*y.current;i<n.scrollLeft+wc?n.scrollLeft=Math.max(0,i-wc-4*y.current):i>n.scrollLeft+n.clientWidth-4*y.current&&(n.scrollLeft=i-n.clientWidth+8*y.current)}j()}},te=(0,q.useRef)(!1);(0,q.useLayoutEffect)(()=>{let t=d.current;if(!t||c===h.current)return;h.current=c,t.value=c;let{start:n,end:r}=e.selection;t.setSelectionRange(n,r),v.current=e.selection,te.current?M(r):(te.current=!0,t.scrollTop=e.scroll.top,t.scrollLeft=e.scroll.left,j())}),(0,q.useLayoutEffect)(()=>{let e=d.current;if(!e)return;let t=document.createElement(`canvas`).getContext(`2d`);t&&(t.font=getComputedStyle(e).font,y.current=t.measureText(`0000000000`).width/10||y.current);let n=new ResizeObserver(j);n.observe(e);let i=t=>{g.current={start:e.selectionStart,end:e.selectionEnd},(t.inputType===`historyUndo`||t.inputType===`historyRedo`)&&(t.preventDefault(),r({type:t.inputType===`historyUndo`?`undo`:`redo`,id:s}))};return e.addEventListener(`beforeinput`,i),()=>{n.disconnect(),e.removeEventListener(`beforeinput`,i),cancelAnimationFrame(x.current),r({type:`view`,id:s,selection:v.current,scroll:_.current})}},[s]),(0,q.useLayoutEffect)(j,[t]),(0,q.useImperativeHandle)(o,()=>({focus:()=>d.current?.focus({preventScroll:!0}),goToLine:e=>{let t=Math.min(ee.length,Math.max(1,e))-1;N({start:O[t],end:O[t]}),d.current?.focus({preventScroll:!0})},find:e=>ne(e)}));let N=e=>{let t=d.current;t&&(t.setSelectionRange(e.start,e.end),v.current=e,r({type:`view`,id:s,selection:e}),M(e.end))},P=(t,i,a=`other`)=>{let o=Ls(c,t);if(!o||n)return;let l=d.current,u=l?{start:l.selectionStart,end:l.selectionEnd}:e.selection;r({type:`edit`,id:s,text:t,step:{change:o,before:u,after:i},kind:a,time:Date.now()})},F=(e,t=`other`)=>{let n=d.current;if(!n)return;let{selectionStart:r,selectionEnd:i}=n,a=r+e.length;P(c.slice(0,r)+e+c.slice(i),{start:a,end:a},t)},ne=e=>{let t=d.current,n=t?c.slice(t.selectionStart,t.selectionEnd):``,r=n&&!n.includes(`
|
|
56
|
+
`)?w.options.regex?n.replace(/[.*+?^${}()|[\]\\]/g,`\\$&`):n:w.query;T({...w,open:!0,replace:e||w.open&&w.replace,query:r}),requestAnimationFrame(()=>{m.current?.focus(),m.current?.select()})},I=()=>{T({...w,open:!1}),D(-1),d.current?.focus({preventScroll:!0})},re=e=>{if(A.length===0)return;let t=e>0?v.current.end:v.current.start,n;E>=0&&A[E][0]===v.current.start&&A[E][1]===v.current.end?n=(E+e+A.length)%A.length:e>0?(n=A.findIndex(([e])=>e>=t),n=n<0?0:n):(n=A.findLastIndex(([,e])=>e<=t),n=n<0?A.length-1:n),D(n),N({start:A[n][0],end:A[n][1]})};(0,q.useEffect)(()=>{if(!w.open||A.length===0){D(-1);return}let e=A.findIndex(([e])=>e>=v.current.start),t=e<0?0:e;D(t),M(A[t][0])},[w.query,w.options,w.open]);let ie=()=>{let e=A[E];if(!e||n){re(1);return}let t=rc(c,e[0],w.query,w.replacement,w.options);if(t===null)return;let r=e[0]+t.length;P(c.slice(0,e[0])+t+c.slice(e[1]),{start:r,end:r})},L=()=>{if(!n)try{let e=ic(c,w.query,w.replacement,w.options);if(e.count>0){let t=Math.min(v.current.start,e.text.length);P(e.text,{start:t,end:t}),G(`Replaced ${e.count.toLocaleString()} ${e.count===1?`match`:`matches`}`)}}catch(e){G(`Not replaced: ${e instanceof Error?e.message:e}`,`error`)}},R=e=>{let t=e.ctrlKey||e.metaKey,o=e.key.toLowerCase(),f=t=>{e.preventDefault(),e.stopPropagation(),t()};if(t&&o===`s`)f(i);else if(t&&o===`z`)f(()=>r({type:e.shiftKey?`redo`:`undo`,id:s}));else if(t&&o===`y`)f(()=>r({type:`redo`,id:s}));else if(t&&o===`f`)f(()=>ne(!1));else if(t&&o===`h`)f(()=>ne(!0));else if(t&&o===`g`||e.key===`F3`)f(()=>w.open&&w.query?re(e.shiftKey?-1:1):ne(!1));else if(t&&o===`i`)f(a);else if(e.key===`Escape`&&w.open)f(I);else if(n)return;else if(t&&(o===`/`||e.code===`Slash`)){let e=As(l);e&&f(()=>{let t=Qs(c,v.current,e);P(t.text,t.selection)})}else e.key===`Tab`&&!t&&!e.altKey?f(()=>{let t=d.current,n={start:t.selectionStart,end:t.selectionEnd};if(e.shiftKey||c.slice(n.start,n.end).includes(`
|
|
57
|
+
`)){let t=Zs(c,n,u,e.shiftKey);P(t.text,t.selection)}else F(Js(u),`type`)}):e.key===`Enter`&&!t&&!e.shiftKey&&!e.altKey&&!e.nativeEvent.isComposing&&f(()=>F($s(c,d.current.selectionStart)))},ae=()=>{let e=d.current;if(!e||n)return;let t=e.value,i=g.current,a=Ls(c,t,Math.min(i.start,e.selectionStart));if(!a)return;h.current=t;let o={start:e.selectionStart,end:e.selectionEnd};v.current=o;let l=a.removed===``&&a.inserted.length<=2&&!a.inserted.includes(`
|
|
58
|
+
`)?`type`:a.inserted===``&&a.removed.length<=2?`delete`:`other`;r({type:`edit`,id:s,text:t,step:{change:a,before:i,after:o},kind:l,time:Date.now()}),g.current=o},oe=()=>{let e=d.current;e&&(v.current={start:e.selectionStart,end:e.selectionEnd},g.current=v.current,cancelAnimationFrame(x.current),x.current=requestAnimationFrame(()=>r({type:`view`,id:s,selection:v.current})))},z=ee.length<=Dc?l:`plain`,se=Ks(O,e.selection.end),ce=Math.min(S.first,ee.length),le=Math.min(S.last,ee.length),B=t?[]:kc(b.current,z,ee,le),ue=[],V=[];if(!t){let e=0,t=A.length;for(;e<t;){let n=e+t>>1;A[n][1]<=O[ce]?e=n+1:t=n}let n=e;for(let e=ce;e<le;e++){let t=ee[e],r=O[e];for(;n<A.length&&A[n][1]<=r;)n++;let{spans:i}=Ms(z,t,B[e]??0);ue.push((0,J.jsx)(`div`,{className:`fm-line`,style:{top:Cc+e*Sc},children:jc(t,r,i,A,E,n)},e)),V.push((0,J.jsx)(`div`,{className:`fm-number${e===se?` current`:``}`,style:{top:Cc+e*Sc},onPointerDown:t=>{t.preventDefault();let n=e+1<O.length?O[e+1]:c.length;N({start:r,end:n}),d.current?.focus({preventScroll:!0})},children:e+1},e))}}return(0,J.jsxs)(`div`,{className:`fm-editor`,children:[w.open&&(0,J.jsx)(Mc,{find:w,count:A.length,current:E,capped:k.capped,error:k.error,readOnly:n,inputRef:m,onChange:T,onStep:re,onReplace:ie,onReplaceAll:L,onClose:I}),(0,J.jsxs)(`div`,{className:`fm-text${t?` wrap`:``}`,style:{"--fm-gutter":`${String(ee.length).length+2}ch`,"--fm-tab":Tc},children:[!t&&(0,J.jsx)(`div`,{className:`fm-gutter`,"aria-hidden":`true`,children:(0,J.jsx)(`div`,{ref:p,className:`fm-gutter-lines`,style:{height:12+ee.length*Sc},children:V})}),(0,J.jsxs)(`div`,{className:`fm-code`,children:[!t&&(0,J.jsx)(`div`,{className:`fm-overlay`,"aria-hidden":`true`,children:(0,J.jsxs)(`div`,{ref:f,className:`fm-overlay-lines`,children:[(0,J.jsx)(`div`,{className:`fm-caret-line`,style:{top:Cc+se*Sc}}),ue]})}),(0,J.jsx)(`textarea`,{ref:d,className:`fm-area`,wrap:t?`soft`:`off`,readOnly:n,spellCheck:!1,autoCapitalize:`off`,autoComplete:`off`,autoCorrect:`off`,"aria-label":`The text of ${e.path}`,onChange:ae,onKeyDown:R,onSelect:oe,onScroll:j})]})]})]})}),Pc=620,Fc=316,Ic=420,Lc=3e4,Rc=12,zc=`tassello.fileManager.bookmarks`,Bc=`application/x-tassello-files`,Vc=800,Hc=5,Uc=520,Wc=null,Gc=new Set;function Kc(e){Wc=e,Gc.forEach(e=>e())}function qc(e){return Gc.add(e),()=>Gc.delete(e)}var Jc=new Set;function Yc(e){Jc.forEach(t=>t(e))}var Xc=!1;function Zc(){Xc||(Xc=!0,window.addEventListener(`beforeunload`,e=>{mc()&&e.preventDefault()}))}function Qc(e){return e.split(`
|
|
59
|
+
`).map(e=>e.trim()).filter(Boolean)}function $c(e){try{let t=JSON.parse(localStorage.getItem(zc)??`{}`);return Array.isArray(t[e])?t[e]:[]}catch{return[]}}function el(e,t){try{let n=JSON.parse(localStorage.getItem(zc)??`{}`);t.length>0?n[e]=t:delete n[e],localStorage.setItem(zc,JSON.stringify(n))}catch{}}function tl(e){let[t,n]=(0,q.useState)(()=>Date.now());return(0,q.useEffect)(()=>{let t=setInterval(()=>n(Date.now()),e);return()=>clearInterval(t)},[e]),t}function nl({config:e,instance:t,panelId:n}){let r=`${n}/${t.id}`,i=e.folder.trim()||`~`,[s]=(0,q.useState)(()=>{let e=pc.get(r);return e?.config===i?e:{config:i,state:ac(i)}}),[c,u]=(0,q.useReducer)(fc,s.state),d=(0,q.useRef)(s.config),f=Ke(),p=e.readOnly,[m,h]=(0,q.useState)(null),[g,_]=(0,q.useState)(null),[v,b]=(0,q.useState)(0),[x,S]=(0,q.useState)(null),[C,w]=(0,q.useState)(null),[T,E]=(0,q.useState)(new Set),[D,O]=(0,q.useState)(null),[k,A]=(0,q.useState)(null),[j,te]=(0,q.useState)({key:`name`,descending:!1}),[N,P]=(0,q.useState)(``),[F,ne]=(0,q.useState)(e.showHidden),[I,re]=(0,q.useState)(e.wrap),[L,R]=(0,q.useState)(`list`),[ae,oe]=(0,q.useState)(!1),[z,se]=(0,q.useState)(null),[ce,B]=(0,q.useState)(null),[ue,V]=(0,q.useState)(null),[de,fe]=(0,q.useState)(null),[H,pe]=(0,q.useState)(null),[he,U]=(0,q.useState)(null),[_e,ve]=(0,q.useState)(null),[be,Se]=(0,q.useState)(null),[Ce,Ee]=(0,q.useState)(!1),[De,Oe]=(0,q.useState)(null),[Ae,je]=(0,q.useState)(null),[Me,Ne]=(0,q.useState)(null),[Pe,W]=(0,q.useState)(``),[Fe,Ie]=(0,q.useState)(0),[Le,Re]=(0,q.useState)(()=>$c(r)),ze=(0,q.useSyncExternalStore)(qc,()=>Wc),Ve=tl(3e4),He=(0,q.useRef)(null),Ue=(0,q.useRef)(null),We=(0,q.useRef)(null),Ge=(0,q.useRef)(null),qe=(0,q.useRef)(null),Je=(0,q.useRef)(null),Ye=(0,q.useRef)(`mouse`),Xe=(0,q.useRef)(null),Ze=(0,q.useRef)({text:``,at:0}),Qe=(0,q.useRef)(null),$e=(0,q.useRef)(c.folder);$e.current=c.folder;let et=(0,q.useRef)(c.tabs);et.current=c.tabs,(0,q.useEffect)(Zc,[]),(0,q.useEffect)(()=>(Jc.add(u),()=>void Jc.delete(u)),[]),(0,q.useEffect)(()=>{pc.set(r,{config:d.current,state:c})},[r,c]),(0,q.useEffect)(()=>{i!==d.current&&(d.current=i,u({type:`go`,folder:i}))},[i]),(0,q.useEffect)(()=>ne(e.showHidden),[e.showHidden]),(0,q.useEffect)(()=>re(e.wrap),[e.wrap]),(0,q.useEffect)(()=>{K.places().then(h,()=>h({home:``,user:``,ros:[]}))},[]),(0,q.useEffect)(()=>{if(c.folder.startsWith(`/`)){w(null);return}let e=!0;return K.list(c.folder).then(t=>e&&t&&u({type:`resolved`,from:c.folder,folder:t.path}),t=>e&&w(Yo(t))),()=>{e=!1}},[c.folder]),(0,q.useEffect)(()=>{e.confine?i.startsWith(`/`)?S(Qa(i,`/`,``)):K.list(i).then(e=>e&&S(e.path),()=>S(null)):S(null)},[e.confine,i]),(0,q.useEffect)(()=>{let e=He.current;if(!e)return;let t=new ResizeObserver(([e])=>Ie(e.contentRect.width));return t.observe(e),()=>t.disconnect()},[]);let tt=m?.home??``,Y=c.folder.startsWith(`/`)?c.folder:``,nt=Fe>0&&Fe<Pc,rt=c.tabs.find(e=>e.id===c.active)??null,it=rt===null,at=z??!nt,ot=e.confine&&x!==null;(0,q.useEffect)(()=>{if(!(at||L===`overview`)||e.confine)return;let t=!0,n=()=>{document.visibilityState===`visible`&&K.disks().then(e=>t&&_(e),()=>{})};n();let r=setInterval(n,Lc);return()=>{t=!1,clearInterval(r)}},[at,L,e.confine,v]);let{listings:st,errors:ct,offline:lt,refresh:ut}=Zo((0,q.useMemo)(()=>Y?[Y,...[...c.expanded].filter(e=>e!==Y&&Ya(e,Y)).slice(0,Rc)]:[],[Y,c.expanded])),dt=st.get(Y)??null,ft=Y?ct.get(Y)??null:C,pt=(0,q.useMemo)(()=>({hidden:F,text:N}),[F,N]),mt=(0,q.useMemo)(()=>dt?ho(Y,st,ct,c.expanded,j,pt):[],[dt,Y,st,ct,c.expanded,j,pt]),X=(0,q.useMemo)(()=>{let e=new Map;for(let t of mt)t.type===`entry`&&e.set(t.path,t.entry);return e},[mt]),Z=(0,q.useMemo)(()=>new Set(ze?.cut?ze.paths:[]),[ze]);(0,q.useEffect)(()=>{B(null),P(``);let e=Qe.current;e&&Ja(e)===Y?(Qe.current=null,E(new Set([e])),O(e),A(e),Oe(t=>({path:e,seq:(t?.seq??0)+1}))):(E(new Set),O(null),A(null))},[Y]),(0,q.useEffect)(()=>{dt&&E(e=>{let t=[...e].filter(e=>X.has(e));return t.length===e.size?e:new Set(t)})},[X,dt]);let ht=()=>requestAnimationFrame(()=>(He.current?.querySelector(`.fm-list, .fm-area`)??He.current)?.focus({preventScroll:!0})),gt=e=>{E(new Set([e])),O(e),A(e),Oe(t=>({path:e,seq:(t?.seq??0)+1}))},_t=e=>{ot&&!Ya(e,x)?G(`This widget stays in ${Xa(x,tt)}`,`error`):u({type:`go`,folder:e})},vt=e=>{let t=Ja(e);t&&(R(`list`),t===Y?(u({type:`activate`,id:null}),gt(e)):(Qe.current=e,_t(t)))},yt=(e,t=X.get(e))=>{if(!t)return;if(t.kind===`dir`){_t(e);return}let n=To(t);n===`image`?u({type:`open`,path:e,kind:`image`}):n===`text`?u({type:`open`,path:e,kind:`text`}):(gt(e),oe(!0))},bt=async e=>{let t=Qa(e,Y||`/`,tt);try{let e=await K.details(t);e.kind===`dir`?_t(e.path):(vt(e.path),yt(e.path,e))}catch(e){G(Yo(e),`error`)}},xt=(e,t,n)=>new Promise(r=>fe({names:e,folder:t,verb:n,resolve:r})),St=async e=>{try{return await K.operate(e)}catch(e){return G(Yo(e),`error`),null}finally{ut()}},Ct=async(e,t,n)=>{let r=t.filter(t=>e===`copy`||Ja(t)!==n);if(p||r.length===0)return;let i=`ask`,a=await St({op:e,paths:r,to:n,conflict:i});if(a&&a.conflicts.length>0){let t=await xt(a.conflicts,n,e===`move`?`moved`:`copied`);if(!t)return;i=t,a=await St({op:e,paths:r,to:n,conflict:i})}if(!a||a.paths.length===0)return;let o=a.paths;if(e===`move`)for(let e of r){let t=qa(n,$(e));o.includes(t)&&Yc({type:`moved`,from:e,to:t})}let s=Ja(r[0]),c=s!==null&&r.every(e=>Ja(e)===s)&&i!==`replace`?{label:`Undo`,run:()=>void(e===`move`?Ct(`move`,o,s):wt(o,!1))}:void 0;G(`${e===`move`?`Moved`:`Copied`} ${ko(o.map($),2)} into ${$(n)}`,`info`,c),n===$e.current&&(E(new Set(o)),Oe(e=>({path:o[0],seq:(e?.seq??0)+1})))},wt=async(e,t=!0)=>{if(p||e.length===0)return;let n=e.filter(e=>X.get(e)?.kind===`dir`).length,r=c.tabs.filter(t=>lc(t)&&e.some(e=>Ya(t.path,e))).length;(!t||await f.confirm({title:e.length===1?`Delete ${$(e[0])}?`:`Delete ${jo(e.length)}?`,message:(0,J.jsxs)(J.Fragment,{children:[e.length>1&&(0,J.jsx)(`p`,{children:(0,J.jsx)(`strong`,{children:ko(e.map($),5)})}),(0,J.jsxs)(`p`,{children:[e.length===1?`It is`:`They are`,` deleted for good: there is no trash`,n>0?`, and ${n===1&&e.length===1?`the folder goes`:`folders go`} with all ${n===1&&e.length===1?`it holds`:`they hold`}`:``,`.`,r>0?` ${Ao(r,`file`)} open here ${r===1?`has`:`have`} changes not saved.`:``]})]}),confirmLabel:`Delete`,danger:!0}))&&await St({op:`delete`,paths:e})&&(Yc({type:`deleted`,paths:e}),E(new Set),G(`Deleted ${ko(e.map($),2)}`))},Et=async(e,t)=>{if(B(null),ht(),t===null||!t||t===$(e)||p)return;if(t.includes(`/`)){G(`A name has no /: move it with Cut and Paste instead`,`error`);return}let n=await St({op:`rename`,path:e,name:t});if(n){let t=n.paths[0];Yc({type:`moved`,from:e,to:t}),gt(t)}},Dt=async e=>{if(p||!Y)return;let t=await f.prompt({title:e===`mkdir`?`New folder`:`New file`,label:`Its name`,initial:_o(dt?.entries??[],e===`mkdir`?`New folder`:`untitled.txt`),confirmLabel:`Make it`});if(!t)return;if(t.includes(`/`)){G(`A name has no /`,`error`);return}let n=qa(Y,t);await St({op:e,path:n})&&(R(`list`),gt(n),e===`create`&&u({type:`open`,path:n,kind:`text`}))},Ot=async(e,t)=>{await St({op:`chmod`,path:e,mode:t})},kt=e=>{e.length!==0&&(e.every(t=>Ja(t)===Ja(e[0]))?Jo(K.downloadUrl(e)):G(`Download entries of one folder at a time`,`error`))},At=async(e,t)=>{if(p||e.length===0)return;if(_e){G(`Uploading already: wait for it, or cancel it`,`error`);return}let n=st.get(t)?.entries??(await K.list(t).catch(()=>void 0))?.entries,r=Oo(n,[...new Set(e.map(({name:e})=>e.split(`/`)[0]))]),i=`ask`,a=new Map;if(r.length>0){let o=await xt(r,t,`uploaded`);if(!o)return;if(i=o,o===`keep-both`)for(let t of r)e.some(({name:e})=>e.startsWith(`${t}/`))&&a.set(t,_o(n??[],t))}let o=e.reduce((e,{file:t})=>e+t.size,0),s=0,c=!1,l=null,u=()=>{c=!0,l?.abort()},d=[],f=0,m=null;for(let n=0;n<e.length&&!c;n++){let{file:r,name:c}=e[n],[p,...h]=c.split(`/`),g=h.length>0&&a.has(p)?[a.get(p),...h].join(`/`):c;ve({name:$(g),index:n,count:e.length,sent:s,total:o,abort:u});let _=s;l=K.upload(t,g,r,i,e=>ve(t=>t&&{...t,sent:_+e}));try{let e=await l.result;d.push(...e.paths),f+=e.conflicts.length}catch(e){if(!(e instanceof DOMException&&e.name===`AbortError`)){m=`${$(g)}: ${Yo(e)}`;break}}s+=r.size}ve(null),ut(),m?G(`Upload stopped at ${m}`,`error`):G(c?`Upload cancelled: ${d.length} of ${Ao(e.length,`file`)} uploaded`:`Uploaded ${Ao(d.length,`file`)} into ${$(t)}${f>0?`, ${f} skipped`:``}`);let h=[...new Set(d.map(e=>(t===`/`?``:t)+`/`+e.slice(t.length).split(`/`).filter(Boolean)[0]))];t===$e.current&&h.length>0&&(E(new Set(h)),Oe(e=>({path:h[0],seq:(e?.seq??0)+1})))},jt=e=>{if(!Wc||p)return;let{paths:t,cut:n}=Wc;n&&Kc(null),Ct(n?`move`:`copy`,t,e)},Mt=(e,t)=>{e.length===0||t&&p||(Kc({paths:e,cut:t}),qo(e.join(`
|
|
60
|
+
`)).catch(()=>{}),G(`${t?`Cut`:`Copied`} ${ko(e.map($),2)}: paste ${e.length===1?`it`:`them`} into a folder`))},Nt=e=>qo(e).then(()=>G(`Copied ${e}`),e=>G(`Could not copy the path: ${Yo(e)}`,`error`)),Pt=(0,q.useMemo)(()=>[...Qc(e.bookmarks).map(e=>({path:e,removable:!1})),...Le.map(e=>({path:e,removable:!0}))].map(({path:e,removable:t})=>({path:Qa(e,`/`,tt),removable:t})),[e.bookmarks,Le,tt]),Ft=(0,q.useMemo)(()=>{let e=[],t=t=>{(!ot||Ya(t.path,x))&&!e.some(e=>e.path===t.path&&e.kind===t.kind)&&e.push({removable:!1,...t})};tt&&t({name:m?.user?`Home (${m.user})`:`Home`,path:tt,kind:`home`}),ot||t({name:`The root`,path:`/`,kind:`root`});let n=x??(i.startsWith(`/`)?i:null);n&&n!==tt&&n!==`/`&&t({name:$(n),path:n,kind:`folder`});for(let e of m?.ros??[])t({name:e.name,path:e.path,kind:`ros`});for(let{path:e,removable:n}of Pt)t({name:$(e),path:e,kind:`bookmark`,removable:n});return e},[tt,m,ot,x,i,Pt]),It=()=>{if(!Y||Pt.some(e=>e.path===Y))return;let e=[...Le,Xa(Y,tt)];Re(e),el(r,e)},Lt=e=>{let t=Le.filter(t=>Qa(t,`/`,tt)!==e);Re(t),el(r,t)},Rt=[...T],zt=Y?Ja(Y):null,Bt=zt!==null&&(!ot||Ya(zt,x)),Vt=e=>{let t=X.get(e),n=T.has(e)?[...T]:[e];T.has(e)||(E(new Set([e])),O(e),A(e));let r=n.length===1,i=t?To(t):`other`,a=[];return r&&t&&(a.push({label:t.kind===`dir`?`Open`:i===`text`?`Edit`:i===`image`?`View`:`Details`,run:()=>yt(e)}),t.kind===`file`&&i!==`text`&&a.push({label:`Open as text`,run:()=>u({type:`open`,path:e,kind:`text`})})),a.push({label:r&&t?.kind===`dir`?`Download as .tar.gz`:`Download`,run:()=>kt(n)}),p||(a.push({label:`Cut`,keys:`Ctrl+X`,run:()=>Mt(n,!0),separated:!0},{label:`Copy`,keys:`Ctrl+C`,run:()=>Mt(n,!1)}),r&&t?.kind===`dir`&&Wc&&a.push({label:`Paste into it`,run:()=>jt(e)}),a.push({label:`Duplicate`,run:()=>void Ct(`copy`,n,Ja(n[0])??`/`)},{label:`Move to…`,run:()=>pe({paths:n,copy:!1})},{label:`Copy to…`,run:()=>pe({paths:n,copy:!0})}),r&&a.push({label:`Rename`,keys:`F2`,run:()=>B(e),separated:!0})),r&&a.push({label:`Copy the path`,run:()=>void Nt(e),separated:p}),a.push({label:`Details`,keys:`Alt+Enter`,run:()=>oe(!0)}),p||a.push({label:`Delete`,keys:`Delete`,danger:!0,separated:!0,run:()=>void wt(n)}),a},Ht=e=>[...p?[]:[{label:`New folder…`,run:()=>void Dt(`mkdir`),narrow:e},{label:`New file…`,run:()=>void Dt(`create`)},{label:`Upload files…`,run:()=>qe.current?.click(),narrow:e},{label:`Upload a folder…`,run:()=>Je.current?.click()},{label:`Paste`,keys:`Ctrl+V`,disabled:!Wc,run:()=>jt(Y)}],{label:`Select all`,keys:`Ctrl+A`,run:()=>E(new Set(mt.flatMap(e=>e.type===`entry`&&e.depth===0?[e.path]:[]))),separated:!p},{label:F?`Hide the hidden files`:`Show the hidden files`,keys:`Ctrl+H`,run:()=>ne(e=>!e)},{label:`Read again`,run:ut},{label:L===`overview`?`Back to the files`:`What takes the space`,run:()=>R(L===`overview`?`list`:`overview`),narrow:e,separated:!0},{label:ae?`Hide the details`:`Details`,run:()=>oe(e=>!e),narrow:e},{label:`Download this folder`,run:()=>kt([Y]),separated:!0},{label:`Copy its path`,run:()=>void Nt(Y)},{label:`Bookmark this folder`,disabled:Pt.some(e=>e.path===Y),run:It}],Ut=(e,t,n)=>V({x:e,y:t,items:n}),Wt=(0,q.useRef)(null),Gt=(0,q.useMemo)(()=>{let e=e=>((...t)=>Wt.current[e](...t));return{onPointer:e(`onPointer`),onClick:e(`onClick`),onOpen:e(`onOpen`),onFold:e(`onFold`),onMenu:e(`onMenu`),onRename:e(`onRename`),onDragStart:e(`onDragStart`),onDragEnd:e(`onDragEnd`),onDragOver:e(`onDragOver`),onDrop:e(`onDrop`),onKeyDown:e(`onKeyDown`)}},[]);Wt.current={onPointer:e=>{Ye.current=e},onClick:(e,t)=>{e?Ye.current===`touch`&&T.size===0?yt(e):(A(e),t.shiftKey?E(new Set(go(mt,D??e,e))):(O(e),t.ctrlKey||t.metaKey||Ye.current===`touch`&&T.size>0?E(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n}):E(new Set([e])))):(E(new Set),A(null))},onOpen:e=>yt(e),onFold:(e,t)=>u({type:`fold`,folder:e,open:t}),onMenu:(e,t,n)=>Ut(t,n,e?Vt(e):Ht(!1)),onRename:(e,t)=>void Et(e,t),onDragStart:(e,t)=>{let n=T.has(e)?[...T]:[e];T.has(e)||(E(new Set([e])),O(e)),Xe.current=n,t.dataTransfer.effectAllowed=p?`copy`:`copyMove`,t.dataTransfer.setData(Bc,JSON.stringify(n)),t.dataTransfer.setData(`text/plain`,n.join(`
|
|
61
|
+
`));let r=X.get(e);n.length===1&&r?.kind===`file`&&t.dataTransfer.setData(`DownloadURL`,`application/octet-stream:${r.name}:${new URL(K.downloadUrl([e]),location.href).href}`)},onDragEnd:()=>{Xe.current=null,Se(null),Ee(!1)},onDragOver:(e,t)=>Kt(e,t),onDrop:(e,t)=>qt(e,t),onKeyDown:(e,t)=>Jt(e,t)};let Kt=(e,t)=>{let n=t.dataTransfer.types,r=n.includes(Bc);if(p||!r&&!n.includes(`Files`)||!Y)return;let i=e??Y;t.stopPropagation(),r&&Xe.current?.some(e=>Ya(i,e))?(Se(null),Ee(!1)):(t.preventDefault(),t.dataTransfer.dropEffect=r&&!t.ctrlKey?`move`:`copy`,Se(e),Ee(e===null))},qt=(e,t)=>{t.preventDefault(),t.stopPropagation(),Se(null),Ee(!1);let n=e??Y;if(!n||p)return;let r=t.dataTransfer.getData(Bc);r?Ct(t.ctrlKey?`copy`:`move`,JSON.parse(r),n):t.dataTransfer.types.includes(`Files`)&&Xo(t.dataTransfer).then(e=>void At(e,n),e=>G(`Cannot read what was dropped: ${Yo(e)}`,`error`))},Jt=(e,t)=>{if(ce)return;let n=e.ctrlKey||e.metaKey,r=e.key,i=mt.filter(e=>e.type===`entry`),a=k?i.findIndex(e=>e.path===k):-1,o=i[a],s=t=>{e.preventDefault(),t()},c=t=>{if(i.length===0)return;let r=i[Math.min(i.length-1,Math.max(0,t))].path;A(r),e.shiftKey?E(new Set(go(mt,D??r,r))):n||(E(new Set([r])),O(r)),Oe(e=>({path:r,seq:(e?.seq??0)+1}))};if(!(e.altKey&&r.startsWith(`Arrow`))){if(e.altKey&&r===`Enter`)s(()=>oe(!0));else if(r===`ArrowDown`)s(()=>c(a+1));else if(r===`ArrowUp`)s(()=>c(a<0?0:a-1));else if(r===`PageDown`)s(()=>c(a+t));else if(r===`PageUp`)s(()=>c(a-t));else if(r===`Home`)s(()=>c(0));else if(r===`End`)s(()=>c(i.length-1));else if(r===`ArrowRight`&&o?.type===`entry`&&o.open!==null)s(()=>o.open?c(a+1):u({type:`fold`,folder:o.path,open:!0}));else if(r===`ArrowLeft`&&o?.type===`entry`)s(()=>{o.open?u({type:`fold`,folder:o.path,open:!1}):o.depth>0&&c(i.findIndex(e=>e.path===Ja(o.path)))});else if(r===`Enter`)s(()=>{let e=T.size>0?[...T]:k?[k]:[],t=e.filter(e=>X.get(e)?.kind===`dir`);e.filter(e=>X.get(e)?.kind!==`dir`).forEach(e=>yt(e)),t.length>0&&e.length===t.length&&yt(t[0])});else if(r===`Backspace`)s(()=>Bt&&_t(zt));else if(r===`Delete`)s(()=>void wt(Rt));else if(r===`F2`)s(()=>!p&&(k??Rt[0])&&B(k??Rt[0]));else if(r===`Escape`)s(()=>T.size>0?E(new Set):oe(!1));else if(r===` `&&k)s(()=>E(e=>{let t=new Set(e);return t.delete(k)||t.add(k),t}));else if(n&&r.toLowerCase()===`a`)s(()=>E(new Set(mt.flatMap(e=>e.type===`entry`&&e.depth===0?[e.path]:[]))));else if(n&&r.toLowerCase()===`c`)s(()=>Mt(Rt,!1));else if(n&&r.toLowerCase()===`x`)s(()=>Mt(Rt,!0));else if(n&&r.toLowerCase()===`v`)s(()=>jt(Y));else if(n&&r.toLowerCase()===`h`)s(()=>ne(e=>!e));else if(r.length===1&&!n&&!e.altKey){let e=Date.now(),t=(e-Ze.current.at<Vc?Ze.current.text:``)+r.toLowerCase();Ze.current={text:t,at:e};let n=i.findIndex((e,n)=>n>=(t.length>1?Math.max(0,a):a+1)&&e.type===`entry`&&e.entry.name.toLowerCase().startsWith(t)),o=n>=0?n:i.findIndex(e=>e.type===`entry`&&e.entry.name.toLowerCase().startsWith(t));o>=0&&s(()=>c(o))}}},Yt=(0,q.useRef)(new Set);(0,q.useEffect)(()=>{for(let e of c.tabs){let t=`${e.id}:${e.reads}`;e.kind!==`text`||Yt.current.has(t)||e.text!==null&&e.reads===0||(Yt.current.add(t),K.readText(e.path).then(t=>t&&u({type:`read`,id:e.id,file:t}),t=>u({type:`failed`,id:e.id,error:Yo(t)})))}},[c.tabs]),(0,q.useEffect)(()=>{let e=setInterval(()=>{if(document.visibilityState===`visible`)for(let e of et.current)e.kind!==`text`||e.stamp===null||e.missing||K.readText(e.path,e.stamp).then(t=>t&&u({type:`changed`,id:e.id,file:t}),t=>t instanceof Be&&t.status===404&&u({type:`missing`,id:e.id}))},Ko);return()=>clearInterval(e)},[]);let Xt=e=>e.eol===`\r
|
|
62
|
+
`?e.text.replace(/\n/g,`\r
|
|
63
|
+
`):e.text,Zt=async e=>{if(e.text===null||Me!==null||!lc(e))return;if(p){G(`This widget is read-only`,`error`);return}if(e.readOnly&&!e.missing){G(`${e.readOnly}: Save as…`,`error`);return}let t=e.text;Ne(e.id);try{let n=await K.saveText(e.path,Xt(e),e.missing?null:e.base,e.missing);n.conflict?(u({type:`conflict`,id:e.id,version:n.version,stamp:n.stamp}),G(`Not saved: the file changed on the robot since it was read`,`error`)):(u({type:`saved`,id:e.id,text:t,version:n.version,stamp:n.stamp}),G(`Saved ${$(e.path)}`),ut())}catch(t){G(`Could not save ${e.path}: ${Yo(t)}`,`error`)}finally{Ne(null)}},Qt=async e=>{(!lc(e)||await f.confirm({title:`Close ${$(e.path)}?`,message:`Its changes are not saved.`,confirmLabel:`Close it`,danger:!0}))&&u({type:`close`,id:e.id})},$t=async e=>{let t=Gs(e.text??``),n=await f.prompt({title:`Go to line`,label:`Line, 1 to ${t.length.toLocaleString()}`,initial:String(Ks(t,e.selection.end)+1),confirmLabel:`Go`}),r=Number(n);n&&Number.isFinite(r)&&Ge.current?.goToLine(Math.round(r))},Q=rt?.kind===`text`?rt:null;(0,q.useEffect)(()=>W(``),[rt?.id]);let en=e=>{let t=e.ctrlKey||e.metaKey,n=e.key.toLowerCase();if(Q&&t&&n===`s`)e.preventDefault(),Zt(Q);else if(it&&t&&n===`f`&&!e.target.closest(`input, textarea`))e.preventDefault(),We.current?.focus();else if(it&&t&&n===`l`)e.preventDefault(),je(Xa(Y,tt));else if(it&&e.altKey&&!e.target.closest(`input, textarea`)){let t={arrowup:()=>Bt&&_t(zt),arrowleft:()=>u({type:`back`}),arrowright:()=>u({type:`forward`})}[n];t&&(e.preventDefault(),t())}},tn;if(rt?.kind===`image`)tn=(0,J.jsx)(xc,{path:rt.path,reads:rt.reads,onSize:W});else if(Q)tn=Q.text===null?(0,J.jsxs)(`div`,{className:`widget-message${Q.error?` error`:``} fm-empty`,children:[(0,J.jsx)(`p`,{children:Q.error??`Reading…`}),Q.error&&(0,J.jsxs)(`div`,{className:`fm-empty-actions`,children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>kt([Q.path]),children:`Download it`}),` `,(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>u({type:`close`,id:Q.id}),children:`Close`})]})]}):(0,J.jsx)(Nc,{ref:Ge,tab:Q,wrap:I,readOnly:p,dispatch:u,onSave:()=>void Zt(Q),onGoToLine:()=>void $t(Q)},Q.id);else if(L===`overview`&&Y)tn=(0,J.jsx)(as,{folder:Y,home:tt,disks:e.confine?null:g,now:Ve,onGo:e=>{R(`list`),_t(e)},onReveal:vt,onRefreshDisks:()=>b(e=>e+1)});else{let e;e=ft?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`p`,{children:ft}),Bt&&(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>_t(zt),children:`Go up`}),` `,!Y&&tt&&(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>_t(tt),children:`Go home`})]}):dt?N?`No name contains “${N}”`:dt.entries.length>0?`Only hidden files: ${dt.entries.length.toLocaleString()} (Ctrl+H)`:p?`Empty folder`:`Empty folder: drop files here to upload them`:lt?`Cannot reach the robot`:`Reading…`,tn=(0,J.jsx)(`div`,{ref:Ue,className:`fm-files`,children:(0,J.jsx)(Bo,{rows:mt,version:Y,selected:T,focus:k,cut:Z,dropTarget:be,droppingHere:Ce,renaming:ce,sort:j,now:Ve,empty:e,reveal:De,handlers:Gt,onSort:e=>te(t=>({key:e,descending:t.key===e?!t.descending:e!==`name`}))})})}let nn=Fe-(at&&!nt?240:0),rn=it&&ae&&Y!==``,an=rn&&nn-Fc>=Ic,on=[];Q?.external&&on.push({text:Q.external.text===null?`Not saved: the file changed on the robot since it was read`:`The file changed on the robot, and this one has changes`,tone:`warning`,actions:[{label:`Load it`,run:()=>u({type:`reload`,id:Q.id})},{label:`Keep mine`,run:()=>u({type:`keep`,id:Q.id})}]}),Q?.missing&&on.push({text:`Deleted on the robot: saving makes it again`,tone:`warning`}),lt&&(dt||Q)&&on.push({text:`Cannot reach the robot: what is shown may be out of date`,tone:`error`}),dt&&dt.truncated>0&&it&&L===`list`&&on.push({text:`${dt.truncated.toLocaleString()} more entries are not listed: the folder is too large`,tone:`warning`});let sn=rt?rt.path:Y,cn=sn?Za(sn,tt,ot?x:`/`):[],ln=Fe>0&&Fe<Uc?2:Hc,un=cn.length<=ln?cn:ln===2?[{name:`…`,path:null},cn[cn.length-1]]:[cn[0],{name:`…`,path:null},...cn.slice(-(ln-2))],dn=Ae===null?(0,J.jsx)(`div`,{className:`fm-crumbs bt-path`,title:`Click to type a path (Ctrl+L)`,onClick:e=>e.target===e.currentTarget&&it&&je(Xa(Y,tt)),children:un.map((e,t)=>{let n=t===un.length-1,{path:r}=e;return r===null?(0,J.jsx)(`button`,{type:`button`,title:Xa(sn,tt),onClick:()=>je(Xa(rt?Ja(sn)??`/`:Y,tt)),children:`…`},`…`):(0,J.jsx)(`button`,{type:`button`,className:`${n?`current`:``}${be===r?` drop-into`:``}`,title:Xa(r,tt),onClick:()=>n&&rt?void 0:n?je(Xa(Y,tt)):_t(r),onDragOver:e=>Kt(r,e),onDrop:e=>qt(r,e),children:e.name},r)})}):(0,J.jsx)(`form`,{className:`fm-address`,onSubmit:e=>{e.preventDefault(),je(null),ht(),bt(Ae)},children:(0,J.jsx)(`input`,{value:Ae,autoFocus:!0,spellCheck:!1,"aria-label":`Go to the folder`,onChange:e=>je(e.target.value),onKeyDown:e=>{e.key===`Escape`&&(je(null),ht())},onBlur:()=>je(null)})}),fn=(e,t)=>{let n=e.currentTarget.getBoundingClientRect();Ut(n.left,n.bottom+4,t)},pn;if(Q){let e=lc(Q);pn=(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`button`,{type:`button`,className:`button bte-save${e?` primary`:``}`,disabled:!e||Me!==null||p||Q.readOnly!==null&&!Q.missing,title:Q.readOnly?`${Q.readOnly}: Save as…`:`Save (Ctrl+S)`,onClick:()=>void Zt(Q),children:[(0,J.jsx)(xe,{width:16,height:16}),(0,J.jsx)(`span`,{className:`bte-save-label`,children:`Save`})]}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Undo (Ctrl+Z)`,"aria-label":`Undo`,disabled:Q.history.past.length===0,onClick:()=>u({type:`undo`,id:Q.id}),children:(0,J.jsx)(l,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Redo (Ctrl+Shift+Z)`,"aria-label":`Redo`,disabled:Q.history.future.length===0,onClick:()=>u({type:`redo`,id:Q.id}),children:(0,J.jsx)(ke,{width:17,height:17})}),(0,J.jsx)(`span`,{className:`overlay-separator`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Find and replace (Ctrl+F, Ctrl+H)`,"aria-label":`Find`,disabled:Q.text===null,onClick:()=>Ge.current?.find(!1),children:(0,J.jsx)(ge,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,"aria-pressed":I,title:`Wrap long lines`,"aria-label":`Wrap long lines`,onClick:()=>re(e=>!e),children:(0,J.jsx)(a,{width:17,height:17})}),dn,(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-label":`File`,title:`File`,onClick:t=>fn(t,[{label:I?`Do not wrap the lines`:`Wrap long lines`,run:()=>re(e=>!e),narrow:!0},{label:`Save as…`,disabled:Q.text===null||p,run:()=>U(Q.id)},{label:`Download`,run:()=>kt([Q.path])},{label:`Go to line…`,keys:`Ctrl+I`,disabled:Q.text===null,run:()=>void $t(Q)},{label:e?`Discard the changes`:`Read it again`,danger:e,run:async()=>{(!e||await f.confirm({title:`Discard the changes?`,message:`The file is read again from the robot.`,confirmLabel:`Discard them`,danger:!0}))&&u({type:`reload`,id:Q.id})}},{label:`Show it in its folder`,run:()=>vt(Q.path),separated:!0},{label:`Copy its path`,run:()=>void Nt(Q.path)},{label:`Close`,run:()=>void Qt(Q),separated:!0}]),children:(0,J.jsx)(M,{width:17,height:17})})]})}else pn=rt?(0,J.jsxs)(J.Fragment,{children:[dn,(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Download`,"aria-label":`Download`,onClick:()=>kt([rt.path]),children:(0,J.jsx)(ee,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-label":`Image`,title:`Image`,onClick:e=>fn(e,[{label:`Open as text`,run:()=>u({type:`open`,path:rt.path,kind:`text`})},{label:`Show it in its folder`,run:()=>vt(rt.path)},{label:`Copy its path`,run:()=>void Nt(rt.path)},{label:`Close`,run:()=>void Qt(rt),separated:!0}]),children:(0,J.jsx)(M,{width:17,height:17})})]}):(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Back (Alt+←)`,"aria-label":`Back`,disabled:c.back.length===0,onClick:()=>u({type:`back`}),children:(0,J.jsx)(ye,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,title:`Forward (Alt+→)`,"aria-label":`Forward`,disabled:c.forward.length===0,onClick:()=>u({type:`forward`}),children:(0,J.jsx)(Te,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button${be===zt?` drop-into`:``}`,title:`Up (Alt+↑)`,"aria-label":`Up`,disabled:!Bt,onClick:()=>Bt&&_t(zt),onDragOver:e=>Bt&&Kt(zt,e),onDrop:e=>Bt&&qt(zt,e),children:(0,J.jsx)(ie,{width:17,height:17})}),dn,(0,J.jsxs)(`label`,{className:`fm-search fm-filter`,title:`Only the names containing these words (Ctrl+F)`,children:[(0,J.jsx)(ge,{width:14,height:14}),(0,J.jsx)(`input`,{ref:We,type:`search`,value:N,placeholder:`Filter…`,"aria-label":`Only the names containing`,spellCheck:!1,onChange:e=>{P(e.target.value),R(`list`)},onKeyDown:e=>{if(e.key===`Escape`)P(``),Ue.current?.querySelector(`.fm-list`)?.focus();else if(e.key===`ArrowDown`||e.key===`Enter`){e.preventDefault(),Ue.current?.querySelector(`.fm-list`)?.focus();let t=mt.find(e=>e.type===`entry`);t&&(gt(t.path),e.key===`Enter`&&mt.filter(e=>e.type===`entry`).length===1&&yt(t.path))}}})]}),!p&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,title:`New folder`,"aria-label":`New folder`,disabled:!Y,onClick:()=>void Dt(`mkdir`),children:(0,J.jsx)(y,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,title:`Upload files (or drop them here)`,"aria-label":`Upload files`,disabled:!Y||_e!==null,onClick:()=>qe.current?.click(),children:(0,J.jsx)(me,{width:17,height:17})})]}),(0,J.jsx)(`span`,{className:`overlay-separator bte-wide`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,"aria-pressed":L===`overview`,title:`What takes the space: the disks, this folder`,"aria-label":`What takes the space`,disabled:!Y,onClick:()=>R(L===`overview`?`list`:`overview`),children:(0,J.jsx)(we,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,"aria-pressed":ae,title:`Details (Alt+Enter)`,"aria-label":`Details`,disabled:!Y,onClick:()=>oe(e=>!e),children:(0,J.jsx)(o,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-label":`Folder`,title:`Folder`,disabled:!Y,onClick:e=>fn(e,Ht(!0)),children:(0,J.jsx)(M,{width:17,height:17})})]});return(0,J.jsxs)(`div`,{ref:He,className:`bt bte fm`,tabIndex:-1,onKeyDown:en,onDragLeave:e=>{e.currentTarget.contains(e.relatedTarget)||(Se(null),Ee(!1))},children:[on.map(e=>(0,J.jsxs)(`div`,{className:`bt-banner ${e.tone} bte-banner`,title:e.text,children:[(0,J.jsx)(`span`,{children:e.text}),e.actions?.map(e=>(0,J.jsx)(`button`,{type:`button`,className:`link-button`,onClick:e.run,children:e.label},e.label))]},e.text)),(0,J.jsxs)(`div`,{className:`bte-toolbar fm-toolbar`,role:`toolbar`,"aria-label":`Files`,children:[(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":at,title:`The places`,"aria-label":`The places`,onClick:()=>se(!at),children:(0,J.jsx)(le,{width:17,height:17})}),pn]}),c.tabs.length>0&&(0,J.jsx)(bc,{tabs:c.tabs,active:c.active,folder:Y,home:tt,onActivate:e=>u({type:`activate`,id:e}),onClose:e=>void Qt(e)}),(0,J.jsxs)(`div`,{className:`bte-body fm-body${nt?` narrow`:``}`,children:[at&&(0,J.jsx)(gc,{places:Ft,disks:e.confine?null:g,folder:sn,dropTarget:be,canBookmark:Y!==``&&!Pt.some(e=>e.path===Y),onGo:e=>{u({type:`activate`,id:null}),_t(e),nt&&se(!1)},onBookmark:It,onRemoveBookmark:Lt,onDragOver:(e,t)=>Kt(e,t),onDrop:(e,t)=>qt(e,t),onClose:()=>se(!1)}),(0,J.jsxs)(`div`,{className:`bt-main fm-main${an?` beside`:``}`,children:[tn,rn&&(0,J.jsx)(Go,{paths:Rt,folder:Y,entries:X,version:dt?.version??``,home:tt,readOnly:p,now:Ve,actions:{onOpen:e=>yt(e,X.get(e)??void 0),onGo:_t,onDownload:kt,onRename:e=>{R(`list`),B(e)},onMove:(e,t)=>pe({paths:e,copy:t}),onDelete:e=>void wt(e),onChmod:Ot},onClose:()=>oe(!1)})]})]}),(0,J.jsx)(yc,{uploads:_e,textTab:Q,saving:Q!==null&&Me===Q.id,image:rt?.kind===`image`?{path:rt.path,size:Pe}:null,folder:{path:Y,listing:dt,error:ft,offline:lt,shown:mt.filter(e=>e.type===`entry`&&e.depth===0).length,showHidden:F,selected:T.size,entries:Rt.flatMap(e=>X.get(e)??[])},readOnly:p,onSettings:e=>Q&&u({type:`settings`,id:Q.id,...e})}),(0,J.jsx)(`input`,{ref:qe,type:`file`,multiple:!0,hidden:!0,onChange:e=>{let t=[...e.target.files??[]].map(e=>({file:e,name:e.name}));e.target.value=``,At(t,Y)}}),(0,J.jsx)(`input`,{ref:e=>{Je.current=e,e?.setAttribute(`webkitdirectory`,``)},type:`file`,hidden:!0,onChange:e=>{let t=[...e.target.files??[]].map(e=>({file:e,name:e.webkitRelativePath||e.name}));e.target.value=``,At(t,Y)}}),ue&&(0,J.jsx)(Qo,{x:ue.x,y:ue.y,items:ue.items,onClose:()=>V(null)}),de&&(0,J.jsx)($o,{question:de,onDone:()=>fe(null)}),H&&(0,J.jsx)(Tt,{kind:`folder`,start:Y||`~`,onChoose:e=>{pe(null),Ct(H.copy?`copy`:`move`,H.paths,Qa(e,`/`,tt))},onClose:()=>pe(null)}),he!==null&&(()=>{let e=c.tabs.find(e=>e.id===he);return!e||e.kind!==`text`||e.text===null?null:(0,J.jsx)(es,{initial:Xa(e.path,tt),text:Xt(e),onSaved:(t,n,r)=>{U(null);let i=Qa(t,`/`,tt);u({type:`saved`,id:e.id,text:e.text,version:n,stamp:r,path:i}),G(`Saved as ${t}`),ut()},onClose:()=>U(null)})})()]})}var rl=Ve({type:`file-manager`,name:`File Manager`,description:`The robot’s files: browse, upload, download, rename, move and delete them, see what fills the disks, and edit text files.`,icon:_,defaultSize:{w:10,h:7},minSize:{w:4,h:4},component:nl,properties:[{key:`folder`,label:`Folder`,kind:`string`,default:`~`,placeholder:`~/maps`,help:`Where it opens: /…, ~/… or package://<package>/…`},{key:`bookmarks`,label:`Bookmarks`,kind:`text`,default:``,placeholder:`~/ros2_ws/src
|
|
64
|
+
~/maps
|
|
65
|
+
/var/log`,help:`Folders among its places, one a line. Its places also bookmark folders, in this browser`},{key:`confine`,label:`Stay in the folder`,kind:`boolean`,default:!1,help:`Its folder and those under it only, e.g. a widget for the maps. Not a protection: see Security in the README`},{key:`readOnly`,label:`Read only`,kind:`boolean`,default:!1,help:`Browses and downloads, changes nothing. Not a protection either`},{key:`showHidden`,label:`Show the hidden files`,kind:`boolean`,default:!1,help:`Those whose name starts with a dot. Ctrl+H shows and hides them`},{key:`wrap`,label:`Wrap long lines in the editor`,kind:`boolean`,default:!1,help:`Its toolbar switches it. Wrapped, the text is not highlighted`}]});function il({config:e}){let t=ze(e.image),[n,r]=(0,q.useState)(0),[i,a]=(0,q.useState)(!1);if((0,q.useEffect)(()=>a(!1),[t]),(0,q.useEffect)(()=>{if(!t||e.refreshSeconds<=0)return;let n=setInterval(()=>r(e=>e+1),e.refreshSeconds*1e3);return()=>clearInterval(n)},[t,e.refreshSeconds]),!e.image.trim())return(0,J.jsx)(`div`,{className:`widget-message`,children:`No image: choose one in edit mode`});if(!t)return(0,J.jsxs)(`div`,{className:`widget-message error`,children:[`“`,e.image,`” is not a path (/…, ~/…, package://…)`]});let o=n?`${t}${t.includes(`?`)?`&`:`?`}v=${n}`:t;return(0,J.jsxs)(`div`,{className:`image-viewer`,children:[(0,J.jsx)(`img`,{src:o,alt:e.image,style:{objectFit:e.fit},className:i?`failed`:void 0,onLoad:()=>a(!1),onError:()=>a(!0)}),i&&(0,J.jsxs)(`div`,{className:`widget-message error image-viewer-error`,children:[`Cannot load `,e.image]})]})}var al=Ve({type:`image`,name:`Image Viewer`,description:`A static image: a file of the robot, or one uploaded from here.`,icon:Le,defaultSize:{w:5,h:4},minSize:{w:1,h:1},component:il,properties:[{key:`image`,label:`Image`,kind:`image`,default:``,help:`A file of the robot (/…, ~/…, package://…), or upload one from this device`},{key:`fit`,label:`Fit`,kind:`select`,default:`contain`,options:[{value:`contain`,label:`Whole image`},{value:`cover`,label:`Fill the widget, cropped`},{value:`fill`,label:`Stretch`}]},{key:`refreshSeconds`,label:`Reload every (s)`,kind:`number`,default:0,min:0,step:1,help:`For an image the robot updates. 0: never`}]}),ol=22,sl=38,cl=8,ll=(0,q.memo)(function({entry:e,top:t,selected:n,time:r,showNode:i,onSelect:a}){let{level:o,tag:s}=Li[Ri(e.level)],c=e.msg.indexOf(`
|
|
26
66
|
`),l=c<0?0:e.msg.split(`
|
|
27
|
-
`).length-1;return(0,X.jsxs)(`div`,{role:`option`,"aria-selected":n,className:`log-row ${o}${n?` selected`:``}`,style:{top:t},onClick:()=>a(n?null:e.seq),children:[r!==`none`&&(0,X.jsx)(`time`,{className:`log-time`,children:r===`clock`?ki(e.stamp):Oi(e.stamp)}),(0,X.jsx)(`span`,{className:`log-level`,children:s}),i&&(0,X.jsx)(`span`,{className:`log-node`,children:e.name}),(0,X.jsx)(`span`,{className:`log-msg`,children:c<0?e.msg:e.msg.slice(0,c)}),l>0&&(0,X.jsxs)(`span`,{className:`log-more`,title:`${l} more line${l===1?``:`s`}`,children:[`+`,l]})]})});function Ii({entries:e,version:t,selected:n,follow:r,time:i,showNode:a,nodeWidth:o,compact:s,empty:c,onSelect:l,onFollow:u}){let d=s?Ni:Mi,f=(0,Y.useRef)(null),[p,m]=(0,Y.useState)({top:0,height:0}),h=(0,Y.useRef)(null),g=(0,Y.useRef)({entries:e,follow:r,rowPx:d});g.current={entries:e,follow:r,rowPx:d};let _=()=>{let e=f.current;if(!e)return;let{entries:t,follow:n,rowPx:r}=g.current;n?e.scrollTop=e.scrollHeight:h.current&&(e.scrollTop=Ci(t,h.current.seq)*r+Math.min(h.current.offset,r-1)),m({top:e.scrollTop,height:e.clientHeight})};(0,Y.useEffect)(()=>{h.current=null},[t]),(0,Y.useLayoutEffect)(_,[e,r,d]),(0,Y.useLayoutEffect)(()=>{let e=f.current;if(!e)return;let t=new ResizeObserver(_);return t.observe(e),()=>t.disconnect()},[]);let v=()=>{let t=f.current;if(!t)return;let n=t.scrollTop,i=Math.min(e.length-1,Math.floor(n/d));h.current=i>=0?{seq:e[i].seq,offset:n-i*d}:null;let a=t.scrollHeight-n-t.clientHeight<d/2;a!==r&&u(a),m({top:n,height:t.clientHeight})},y=e=>{let t=f.current;if(!t)return;let n=e*d;n<t.scrollTop?t.scrollTop=n:n+d>t.scrollTop+t.clientHeight&&(t.scrollTop=n+d-t.clientHeight)},b=t=>{if(e.length===0)return;let r=Math.max(1,Math.floor(p.height/d)-1),i=n===null?-1:Ci(e,n),a;switch(t.key){case`ArrowDown`:a=i<0?e.length-1:i+1;break;case`ArrowUp`:a=i<0?e.length-1:i-1;break;case`PageDown`:a=i+r;break;case`PageUp`:a=i-r;break;case`Home`:a=0;break;case`End`:a=e.length-1;break;default:return}t.preventDefault(),a=Math.min(e.length-1,Math.max(0,a)),l(e[a].seq),y(a)},x=Math.max(0,Math.floor(p.top/d)-Pi),S=Math.min(e.length,Math.ceil((p.top+p.height)/d)+Pi),C=[];for(let t=x;t<S;t++){let r=e[t];C.push((0,X.jsx)(Fi,{entry:r,top:t*d,selected:r.seq===n,time:i,showNode:a,onSelect:l},r.seq))}return(0,X.jsx)(`div`,{ref:f,className:`logs-list${s?` compact`:``}`,role:`listbox`,"aria-label":`Messages`,tabIndex:0,style:{"--log-row":`${d}px`,"--log-node":`${o}ch`},onScroll:v,onKeyDown:b,children:e.length>0?(0,X.jsx)(`div`,{className:`logs-rows`,style:{height:e.length*d},children:C}):(0,X.jsx)(`p`,{className:`logs-empty`,children:c})})}var Li=560,Ri=420,zi=300,Bi={min:6,max:22};async function Vi(e){if(navigator.clipboard&&window.isSecureContext)return navigator.clipboard.writeText(e);let t=document.createElement(`textarea`);t.value=e,t.setAttribute(`readonly`,``),t.style.position=`fixed`,t.style.opacity=`0`,document.body.append(t),t.select();let n=document.execCommand(`copy`);if(t.remove(),!n)throw Error(`the browser does not allow it`)}function Hi(e,t){let n=URL.createObjectURL(new Blob([t],{type:`text/plain`})),r=document.createElement(`a`);r.href=n,r.download=e,r.click(),setTimeout(()=>URL.revokeObjectURL(n),1e3)}function Ui(){let e=new Date,t=e=>String(e).padStart(2,`0`),n=`${e.getFullYear()}${t(e.getMonth()+1)}${t(e.getDate())}`,r=`${t(e.getHours())}${t(e.getMinutes())}${t(e.getSeconds())}`;return`rosout_${R.hostname||`robot`}_${n}_${r}.log`}function Wi(e){return`${e.toLocaleString()} message${e===1?``:`s`}`}function Gi({nodes:e,chosen:t,overlay:n,onToggle:r,onAll:i,onClose:a}){return(0,X.jsxs)(`aside`,{className:`logs-nodes${n?` overlay`:``}`,"aria-label":`Nodes`,children:[(0,X.jsxs)(`header`,{className:`logs-nodes-header`,children:[(0,X.jsx)(`span`,{children:`Nodes`}),(0,X.jsx)(`button`,{type:`button`,className:`link-button`,disabled:t.size===0,onClick:i,children:`Show all`}),n&&(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-label":`Close`,onClick:a,children:(0,X.jsx)(U,{width:15,height:15})})]}),e.length===0?(0,X.jsx)(`p`,{className:`logs-nodes-empty`,children:`No node yet`}):(0,X.jsx)(`ul`,{children:e.map(e=>{let n=t.has(e.name),i=e.counts[3]+e.counts[4],a=e.counts[2];return(0,X.jsx)(`li`,{children:(0,X.jsxs)(`button`,{type:`button`,className:`logs-node${e.node?``:` gone`}`,"aria-pressed":n,title:`${e.node??`${e.name}: not running`} · ${Wi(e.total)}`,onClick:()=>r(e.name),children:[(0,X.jsx)(`span`,{className:`logs-node-dot`,"aria-hidden":`true`}),(0,X.jsx)(`span`,{className:`logs-node-name`,children:e.name}),i>0&&(0,X.jsx)(`span`,{className:`logs-node-badge error`,children:ji(i)}),a>0&&(0,X.jsx)(`span`,{className:`logs-node-badge warn`,children:ji(a)}),(0,X.jsx)(`span`,{className:`logs-node-count`,children:ji(e.total)})]})},e.name)})})]})}function Ki({entry:e,running:t,onOnly:n,onClose:r}){let{level:i,tag:a}=mi[hi(e.level)],o=yi(e.name,t),s=()=>Vi(Ai(e)).then(()=>G(`Copied the message`),e=>G(`Could not copy the message: ${e instanceof Error?e.message:e}`,`error`));return(0,X.jsxs)(`section`,{className:`logs-details ${i}`,"aria-label":`The message`,children:[(0,X.jsxs)(`header`,{className:`logs-details-header`,children:[(0,X.jsx)(`span`,{className:`logs-pill`,children:a}),(0,X.jsx)(`strong`,{className:`logs-details-node`,title:o??`${e.name}: not running`,children:e.name}),(0,X.jsx)(`span`,{className:`logs-toolbar-end`}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Only this node’s messages`,"aria-label":`Only this node’s messages`,onClick:n,children:(0,X.jsx)(A,{width:16,height:16})}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Copy`,"aria-label":`Copy`,onClick:()=>void s(),children:(0,X.jsx)(P,{width:16,height:16})}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Close (Esc)`,"aria-label":`Close`,onClick:r,children:(0,X.jsx)(U,{width:16,height:16})})]}),(0,X.jsx)(`pre`,{className:`logs-details-msg`,children:e.msg}),(0,X.jsxs)(`dl`,{className:`logs-details-facts`,children:[(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`dt`,{children:`Time`}),(0,X.jsxs)(`dd`,{children:[ki(e.stamp),` · `,Oi(e.stamp)]})]}),e.file&&(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`dt`,{children:`Where`}),(0,X.jsxs)(`dd`,{children:[e.file,`:`,e.line,e.function&&` · ${e.function}`]})]}),(0,X.jsxs)(`div`,{children:[(0,X.jsx)(`dt`,{children:`Node`}),(0,X.jsx)(`dd`,{children:o??`Not running`})]})]})]})}function qi({config:e}){let[t,n]=(0,Y.useReducer)(Si,_i),[r,i]=(0,Y.useState)({state:`waiting`,message:`Connecting…`}),[a,o]=(0,Y.useState)(()=>gi(e.level)),[s,l]=(0,Y.useState)(e.include),[u,d]=(0,Y.useState)(e.exclude),[p,m]=(0,Y.useState)(e.regex),[g,_]=(0,Y.useState)(new Set),[v,y]=(0,Y.useState)(!0),[b,x]=(0,Y.useState)(null),[S,C]=(0,Y.useState)(null),[w,T]=(0,Y.useState)({width:0,height:0}),E=(0,Y.useRef)(null);(0,Y.useEffect)(()=>o(gi(e.level)),[e.level]),(0,Y.useEffect)(()=>l(e.include),[e.include]),(0,Y.useEffect)(()=>d(e.exclude),[e.exclude]),(0,Y.useEffect)(()=>m(e.regex),[e.regex]);let D=e.topic.trim();(0,Y.useEffect)(()=>{if(n({type:`reset`}),!D)i({state:`error`,message:`No log topic: set one in edit mode`});else return i({state:`waiting`,message:`Connecting…`}),R.subscribeRosout({topic:D},{status:(e,t)=>i({state:e,message:t}),update:e=>n({type:`update`,update:e})})},[D]),(0,Y.useEffect)(()=>{x(null),y(!0)},[t.version]),(0,Y.useEffect)(()=>{let e=E.current;if(!e)return;let t=new ResizeObserver(([e])=>T({width:e.contentRect.width,height:e.contentRect.height}));return t.observe(e),()=>t.disconnect()},[]);let ee=(0,Y.useDeferredValue)(s),O=(0,Y.useDeferredValue)(u),k=(0,Y.useMemo)(()=>Ti(e.nodes),[e.nodes]),A=(0,Y.useMemo)(()=>wi(ee,p),[ee,p]),j=(0,Y.useMemo)(()=>wi(O,p),[O,p]),M=(0,Y.useMemo)(()=>Ei(t.entries,t.running,{scope:k,nodes:g,levels:a,include:A.test,exclude:j.test}),[t.entries,t.running,k,g,a,A,j]),P=(e,t)=>o(n=>{if(t)return new Set([e]);let r=new Set(n);return r.delete(e)||r.add(e),r}),I=(0,Y.useCallback)(e=>_(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n}),[]),te=b===null?void 0:t.entries[Ci(t.entries,b)],z=te?.seq===b?te:void 0,{width:B,height:ne}=w,re=B>=Li,V=S??re,ae=M.nodes.filter(e=>e.total>0),oe=Math.min(Bi.max,Math.max(Bi.min,...ae.map(e=>e.name.length))),se=`No message matches the filters`;t.received?t.entries.length===0?se=t.cleared?`Cleared: the new messages will show here`:`No message yet`:M.total===0&&(se=`No message of ${e.nodes.trim()} yet`):se=r.state===`error`?r.message:`Reading the log…`;let H;if(r.state===`error`)H={text:r.message,tone:`error`};else if(!t.received)H={text:r.message,tone:`idle`};else{let e=[M.shown.length===M.total?Wi(M.total):`${M.shown.length.toLocaleString()} of ${Wi(M.total)}`];g.size>0&&e.push(g.size===1?`of ${[...g][0]}`:`of ${g.size} nodes`),t.skipped>0&&e.push(`${t.skipped.toLocaleString()} skipped: too many at once`),t.paused&&e.push(t.pending.length>0?`paused, ${Wi(t.pending.length)} waiting`:`paused`),H={text:e.join(` · `),tone:t.paused?`paused`:r.state}}return(0,X.jsxs)(`div`,{ref:E,className:`logs${z&&ne>0&&ne<zi?` cramped`:``}`,onKeyDown:e=>{e.key===`Escape`&&b!==null&&x(null)},children:[(0,X.jsxs)(`div`,{className:`logs-toolbar`,role:`toolbar`,"aria-label":`Logs`,children:[(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":V,title:`The nodes`,"aria-label":`The nodes`,onClick:()=>C(!V),children:(0,X.jsx)(h,{width:17,height:17})}),(0,X.jsx)(`div`,{className:`logs-levels`,role:`group`,"aria-label":`Levels`,children:mi.map(({level:e,label:t,letter:n},r)=>(0,X.jsxs)(`button`,{type:`button`,className:`logs-level ${e}`,"aria-pressed":a.has(e),"aria-label":`${t}: ${M.levels[r]}`,title:`${t}: ${Wi(M.levels[r])}. Shift+click: this level only`,onClick:t=>P(e,t.shiftKey),children:[(0,X.jsx)(`span`,{className:`logs-level-dot`,"aria-hidden":`true`}),(0,X.jsx)(`span`,{className:`logs-level-name`,children:t}),(0,X.jsx)(`span`,{className:`logs-level-letter`,"aria-hidden":`true`,children:n}),(0,X.jsx)(`span`,{className:`logs-level-count`,children:ji(M.levels[r])})]},e))}),(0,X.jsxs)(`div`,{className:`logs-tools`,children:[(0,X.jsxs)(`label`,{className:`logs-search${A.error?` invalid`:``}`,title:A.error??`Only the messages containing any of these, separated by ;`,children:[(0,X.jsx)(f,{width:14,height:14}),(0,X.jsx)(`input`,{type:`search`,value:s,placeholder:`Include…`,"aria-label":`Only the messages containing`,spellCheck:!1,onChange:e=>l(e.target.value)})]}),(0,X.jsxs)(`label`,{className:`logs-search${j.error?` invalid`:``}`,title:j.error??`Not the messages containing any of these, separated by ;`,children:[(0,X.jsx)(ie,{width:14,height:14}),(0,X.jsx)(`input`,{type:`search`,value:u,placeholder:`Exclude…`,"aria-label":`Not the messages containing`,spellCheck:!1,onChange:e=>d(e.target.value)})]}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button logs-regex`,"aria-pressed":p,title:`As regular expressions`,"aria-label":`As regular expressions`,onClick:()=>m(e=>!e),children:`.*`}),(0,X.jsx)(`span`,{className:`overlay-separator`}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":t.paused,title:t.paused?`Resume`:`Pause: the new messages wait`,"aria-label":t.paused?`Resume`:`Pause`,onClick:()=>n({type:t.paused?`resume`:`pause`}),children:(0,X.jsx)(c,{width:17,height:17})}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":v,title:`Follow the newest`,"aria-label":`Follow the newest`,onClick:()=>y(e=>!e),children:(0,X.jsx)(L,{width:17,height:17})}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Download the messages shown`,"aria-label":`Download the messages shown`,disabled:M.shown.length===0,onClick:()=>Hi(Ui(),M.shown.map(Ai).join(`
|
|
67
|
+
`).length-1;return(0,J.jsxs)(`div`,{role:`option`,"aria-selected":n,className:`log-row ${o}${n?` selected`:``}`,style:{top:t},onClick:()=>a(n?null:e.seq),children:[r!==`none`&&(0,J.jsx)(`time`,{className:`log-time`,children:r===`clock`?Qi(e.stamp):Zi(e.stamp)}),(0,J.jsx)(`span`,{className:`log-level`,children:s}),i&&(0,J.jsx)(`span`,{className:`log-node`,children:e.name}),(0,J.jsx)(`span`,{className:`log-msg`,children:c<0?e.msg:e.msg.slice(0,c)}),l>0&&(0,J.jsxs)(`span`,{className:`log-more`,title:`${l} more line${l===1?``:`s`}`,children:[`+`,l]})]})});function ul({entries:e,version:t,selected:n,follow:r,time:i,showNode:a,nodeWidth:o,compact:s,empty:c,onSelect:l,onFollow:u}){let d=s?sl:ol,f=(0,q.useRef)(null),[p,m]=(0,q.useState)({top:0,height:0}),h=(0,q.useRef)(null),g=(0,q.useRef)({entries:e,follow:r,rowPx:d});g.current={entries:e,follow:r,rowPx:d};let _=()=>{let e=f.current;if(!e)return;let{entries:t,follow:n,rowPx:r}=g.current;n?e.scrollTop=e.scrollHeight:h.current&&(e.scrollTop=Ki(t,h.current.seq)*r+Math.min(h.current.offset,r-1)),m({top:e.scrollTop,height:e.clientHeight})};(0,q.useEffect)(()=>{h.current=null},[t]),(0,q.useLayoutEffect)(_,[e,r,d]),(0,q.useLayoutEffect)(()=>{let e=f.current;if(!e)return;let t=new ResizeObserver(_);return t.observe(e),()=>t.disconnect()},[]);let v=()=>{let t=f.current;if(!t)return;let n=t.scrollTop,i=Math.min(e.length-1,Math.floor(n/d));h.current=i>=0?{seq:e[i].seq,offset:n-i*d}:null;let a=t.scrollHeight-n-t.clientHeight<d/2;a!==r&&u(a),m({top:n,height:t.clientHeight})},y=e=>{let t=f.current;if(!t)return;let n=e*d;n<t.scrollTop?t.scrollTop=n:n+d>t.scrollTop+t.clientHeight&&(t.scrollTop=n+d-t.clientHeight)},b=t=>{if(e.length===0)return;let r=Math.max(1,Math.floor(p.height/d)-1),i=n===null?-1:Ki(e,n),a;switch(t.key){case`ArrowDown`:a=i<0?e.length-1:i+1;break;case`ArrowUp`:a=i<0?e.length-1:i-1;break;case`PageDown`:a=i+r;break;case`PageUp`:a=i-r;break;case`Home`:a=0;break;case`End`:a=e.length-1;break;default:return}t.preventDefault(),a=Math.min(e.length-1,Math.max(0,a)),l(e[a].seq),y(a)},x=Math.max(0,Math.floor(p.top/d)-cl),S=Math.min(e.length,Math.ceil((p.top+p.height)/d)+cl),C=[];for(let t=x;t<S;t++){let r=e[t];C.push((0,J.jsx)(ll,{entry:r,top:t*d,selected:r.seq===n,time:i,showNode:a,onSelect:l},r.seq))}return(0,J.jsx)(`div`,{ref:f,className:`logs-list${s?` compact`:``}`,role:`listbox`,"aria-label":`Messages`,tabIndex:0,style:{"--log-row":`${d}px`,"--log-node":`${o}ch`},onScroll:v,onKeyDown:b,children:e.length>0?(0,J.jsx)(`div`,{className:`logs-rows`,style:{height:e.length*d},children:C}):(0,J.jsx)(`p`,{className:`logs-empty`,children:c})})}var dl=560,fl=420,pl=300,ml={min:6,max:22};async function hl(e){if(navigator.clipboard&&window.isSecureContext)return navigator.clipboard.writeText(e);let t=document.createElement(`textarea`);t.value=e,t.setAttribute(`readonly`,``),t.style.position=`fixed`,t.style.opacity=`0`,document.body.append(t),t.select();let n=document.execCommand(`copy`);if(t.remove(),!n)throw Error(`the browser does not allow it`)}function gl(e,t){let n=URL.createObjectURL(new Blob([t],{type:`text/plain`})),r=document.createElement(`a`);r.href=n,r.download=e,r.click(),setTimeout(()=>URL.revokeObjectURL(n),1e3)}function _l(){let e=new Date,t=e=>String(e).padStart(2,`0`),n=`${e.getFullYear()}${t(e.getMonth()+1)}${t(e.getDate())}`,r=`${t(e.getHours())}${t(e.getMinutes())}${t(e.getSeconds())}`;return`rosout_${H.hostname||`robot`}_${n}_${r}.log`}function vl(e){return`${e.toLocaleString()} message${e===1?``:`s`}`}function yl({nodes:e,chosen:t,overlay:n,onToggle:r,onAll:i,onClose:a}){return(0,J.jsxs)(`aside`,{className:`logs-nodes${n?` overlay`:``}`,"aria-label":`Nodes`,children:[(0,J.jsxs)(`header`,{className:`logs-nodes-header`,children:[(0,J.jsx)(`span`,{children:`Nodes`}),(0,J.jsx)(`button`,{type:`button`,className:`link-button`,disabled:t.size===0,onClick:i,children:`Show all`}),n&&(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-label":`Close`,onClick:a,children:(0,J.jsx)(B,{width:15,height:15})})]}),e.length===0?(0,J.jsx)(`p`,{className:`logs-nodes-empty`,children:`No node yet`}):(0,J.jsx)(`ul`,{children:e.map(e=>{let n=t.has(e.name),i=e.counts[3]+e.counts[4],a=e.counts[2];return(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,className:`logs-node${e.node?``:` gone`}`,"aria-pressed":n,title:`${e.node??`${e.name}: not running`} · ${vl(e.total)}`,onClick:()=>r(e.name),children:[(0,J.jsx)(`span`,{className:`logs-node-dot`,"aria-hidden":`true`}),(0,J.jsx)(`span`,{className:`logs-node-name`,children:e.name}),i>0&&(0,J.jsx)(`span`,{className:`logs-node-badge error`,children:ea(i)}),a>0&&(0,J.jsx)(`span`,{className:`logs-node-badge warn`,children:ea(a)}),(0,J.jsx)(`span`,{className:`logs-node-count`,children:ea(e.total)})]})},e.name)})})]})}function bl({entry:e,running:t,onOnly:n,onClose:r}){let{level:i,tag:a}=Li[Ri(e.level)],o=Hi(e.name,t),s=()=>hl($i(e)).then(()=>G(`Copied the message`),e=>G(`Could not copy the message: ${e instanceof Error?e.message:e}`,`error`));return(0,J.jsxs)(`section`,{className:`logs-details ${i}`,"aria-label":`The message`,children:[(0,J.jsxs)(`header`,{className:`logs-details-header`,children:[(0,J.jsx)(`span`,{className:`logs-pill`,children:a}),(0,J.jsx)(`strong`,{className:`logs-details-node`,title:o??`${e.name}: not running`,children:e.name}),(0,J.jsx)(`span`,{className:`logs-toolbar-end`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Only this node’s messages`,"aria-label":`Only this node’s messages`,onClick:n,children:(0,J.jsx)(pe,{width:16,height:16})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Copy`,"aria-label":`Copy`,onClick:()=>void s(),children:(0,J.jsx)(N,{width:16,height:16})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Close (Esc)`,"aria-label":`Close`,onClick:r,children:(0,J.jsx)(B,{width:16,height:16})})]}),(0,J.jsx)(`pre`,{className:`logs-details-msg`,children:e.msg}),(0,J.jsxs)(`dl`,{className:`logs-details-facts`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:`Time`}),(0,J.jsxs)(`dd`,{children:[Qi(e.stamp),` · `,Zi(e.stamp)]})]}),e.file&&(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:`Where`}),(0,J.jsxs)(`dd`,{children:[e.file,`:`,e.line,e.function&&` · ${e.function}`]})]}),(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:`Node`}),(0,J.jsx)(`dd`,{children:o??`Not running`})]})]})]})}function xl({config:e}){let[t,n]=(0,q.useReducer)(Gi,Bi),[r,i]=(0,q.useState)({state:`waiting`,message:`Connecting…`}),[a,o]=(0,q.useState)(()=>zi(e.level)),[s,c]=(0,q.useState)(e.include),[l,u]=(0,q.useState)(e.exclude),[d,f]=(0,q.useState)(e.regex),[p,m]=(0,q.useState)(new Set),[h,g]=(0,q.useState)(!0),[_,v]=(0,q.useState)(null),[y,b]=(0,q.useState)(null),[x,S]=(0,q.useState)({width:0,height:0}),C=(0,q.useRef)(null);(0,q.useEffect)(()=>o(zi(e.level)),[e.level]),(0,q.useEffect)(()=>c(e.include),[e.include]),(0,q.useEffect)(()=>u(e.exclude),[e.exclude]),(0,q.useEffect)(()=>f(e.regex),[e.regex]);let w=e.topic.trim();(0,q.useEffect)(()=>{if(n({type:`reset`}),!w)i({state:`error`,message:`No log topic: set one in edit mode`});else return i({state:`waiting`,message:`Connecting…`}),H.subscribeRosout({topic:w},{status:(e,t)=>i({state:e,message:t}),update:e=>n({type:`update`,update:e})})},[w]),(0,q.useEffect)(()=>{v(null),g(!0)},[t.version]),(0,q.useEffect)(()=>{let e=C.current;if(!e)return;let t=new ResizeObserver(([e])=>S({width:e.contentRect.width,height:e.contentRect.height}));return t.observe(e),()=>t.disconnect()},[]);let E=(0,q.useDeferredValue)(s),D=(0,q.useDeferredValue)(l),O=(0,q.useMemo)(()=>Ji(e.nodes),[e.nodes]),k=(0,q.useMemo)(()=>qi(E,d),[E,d]),A=(0,q.useMemo)(()=>qi(D,d),[D,d]),j=(0,q.useMemo)(()=>Yi(t.entries,t.running,{scope:O,nodes:p,levels:a,include:k.test,exclude:A.test}),[t.entries,t.running,O,p,a,k,A]),M=(e,t)=>o(n=>{if(t)return new Set([e]);let r=new Set(n);return r.delete(e)||r.add(e),r}),te=(0,q.useCallback)(e=>m(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n}),[]),N=_===null?void 0:t.entries[Ki(t.entries,_)],P=N?.seq===_?N:void 0,{width:ne,height:I}=x,re=ne>=dl,ie=y??re,L=j.nodes.filter(e=>e.total>0),R=Math.min(ml.max,Math.max(ml.min,...L.map(e=>e.name.length))),ae=`No message matches the filters`;t.received?t.entries.length===0?ae=t.cleared?`Cleared: the new messages will show here`:`No message yet`:j.total===0&&(ae=`No message of ${e.nodes.trim()} yet`):ae=r.state===`error`?r.message:`Reading the log…`;let z;if(r.state===`error`)z={text:r.message,tone:`error`};else if(!t.received)z={text:r.message,tone:`idle`};else{let e=[j.shown.length===j.total?vl(j.total):`${j.shown.length.toLocaleString()} of ${vl(j.total)}`];p.size>0&&e.push(p.size===1?`of ${[...p][0]}`:`of ${p.size} nodes`),t.skipped>0&&e.push(`${t.skipped.toLocaleString()} skipped: too many at once`),t.paused&&e.push(t.pending.length>0?`paused, ${vl(t.pending.length)} waiting`:`paused`),z={text:e.join(` · `),tone:t.paused?`paused`:r.state}}return(0,J.jsxs)(`div`,{ref:C,className:`logs${P&&I>0&&I<pl?` cramped`:``}`,onKeyDown:e=>{e.key===`Escape`&&_!==null&&v(null)},children:[(0,J.jsxs)(`div`,{className:`logs-toolbar`,role:`toolbar`,"aria-label":`Logs`,children:[(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":ie,title:`The nodes`,"aria-label":`The nodes`,onClick:()=>b(!ie),children:(0,J.jsx)(T,{width:17,height:17})}),(0,J.jsx)(`div`,{className:`logs-levels`,role:`group`,"aria-label":`Levels`,children:Li.map(({level:e,label:t,letter:n},r)=>(0,J.jsxs)(`button`,{type:`button`,className:`logs-level ${e}`,"aria-pressed":a.has(e),"aria-label":`${t}: ${j.levels[r]}`,title:`${t}: ${vl(j.levels[r])}. Shift+click: this level only`,onClick:t=>M(e,t.shiftKey),children:[(0,J.jsx)(`span`,{className:`logs-level-dot`,"aria-hidden":`true`}),(0,J.jsx)(`span`,{className:`logs-level-name`,children:t}),(0,J.jsx)(`span`,{className:`logs-level-letter`,"aria-hidden":`true`,children:n}),(0,J.jsx)(`span`,{className:`logs-level-count`,children:ea(j.levels[r])})]},e))}),(0,J.jsxs)(`div`,{className:`logs-tools`,children:[(0,J.jsxs)(`label`,{className:`logs-search${k.error?` invalid`:``}`,title:k.error??`Only the messages containing any of these, separated by ;`,children:[(0,J.jsx)(ge,{width:14,height:14}),(0,J.jsx)(`input`,{type:`search`,value:s,placeholder:`Include…`,"aria-label":`Only the messages containing`,spellCheck:!1,onChange:e=>c(e.target.value)})]}),(0,J.jsxs)(`label`,{className:`logs-search${A.error?` invalid`:``}`,title:A.error??`Not the messages containing any of these, separated by ;`,children:[(0,J.jsx)(he,{width:14,height:14}),(0,J.jsx)(`input`,{type:`search`,value:l,placeholder:`Exclude…`,"aria-label":`Not the messages containing`,spellCheck:!1,onChange:e=>u(e.target.value)})]}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button logs-regex`,"aria-pressed":d,title:`As regular expressions`,"aria-label":`As regular expressions`,onClick:()=>f(e=>!e),children:`.*`}),(0,J.jsx)(`span`,{className:`overlay-separator`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":t.paused,title:t.paused?`Resume`:`Pause: the new messages wait`,"aria-label":t.paused?`Resume`:`Pause`,onClick:()=>n({type:t.paused?`resume`:`pause`}),children:(0,J.jsx)(oe,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":h,title:`Follow the newest`,"aria-label":`Follow the newest`,onClick:()=>g(e=>!e),children:(0,J.jsx)(F,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Download the messages shown`,"aria-label":`Download the messages shown`,disabled:j.shown.length===0,onClick:()=>gl(_l(),j.shown.map($i).join(`
|
|
28
68
|
`)+`
|
|
29
|
-
`),children:(0,X.jsx)(F,{width:17,height:17})}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Clear the messages`,"aria-label":`Clear the messages`,disabled:t.entries.length===0&&t.pending.length===0,onClick:()=>{x(null),n({type:`clear`})},children:(0,X.jsx)(N,{width:17,height:17})})]})]}),(0,X.jsxs)(`div`,{className:`logs-main`,children:[V&&(0,X.jsx)(Gi,{nodes:M.nodes,chosen:g,overlay:!re,onToggle:I,onAll:()=>_(new Set),onClose:()=>C(!1)}),(0,X.jsx)(Ii,{entries:M.shown,version:t.version,selected:b,follow:v,time:e.time,showNode:g.size!==1&&ae.length!==1,nodeWidth:oe,compact:B>0&&B<Ri,empty:se,onSelect:x,onFollow:y})]}),z&&(0,X.jsx)(Ki,{entry:z,running:t.running,onOnly:()=>_(new Set([z.name])),onClose:()=>x(null)}),(0,X.jsxs)(`div`,{className:`logs-status ${H.tone}`,title:H.text,children:[(0,X.jsx)(`span`,{className:`logs-dot`,"aria-hidden":`true`}),(0,X.jsx)(`span`,{className:`logs-status-text`,children:H.text})]})]})}var Ji=J({type:`logs`,name:`Logs`,description:`The ROS log of every node (/rosout), coloured by level, filtered by node, level and text.`,icon:z,defaultSize:{w:10,h:6},minSize:{w:4,h:3},component:qi,properties:[{key:`topic`,label:`Log topic`,kind:`topic`,default:`/rosout`,topicTypes:[`rcl_interfaces/msg/Log`],help:`rcl_interfaces/Log: every node’s logger publishes on /rosout`},{key:`nodes`,label:`Nodes`,kind:`string`,default:``,placeholder:`amcl, *_server`,help:`Only these nodes, with their child loggers: names or globs (*), separated by commas or spaces. All if empty`},{key:`level`,label:`Levels shown`,kind:`select`,default:`debug`,options:[{value:`debug`,label:`All`},{value:`info`,label:`Info and above`},{value:`warn`,label:`Warnings and above`},{value:`error`,label:`Errors and above`}],help:`When the panel opens: its toolbar shows and hides each level`},{key:`include`,label:`Include`,kind:`string`,default:``,placeholder:`goal; path`,help:`Only the messages containing any of these, separated by ;. The toolbar changes it`},{key:`exclude`,label:`Exclude`,kind:`string`,default:``,placeholder:`Publishing`,help:`Not the messages containing any of these, separated by ;. The toolbar changes it`},{key:`regex`,label:`Filters as regular expressions`,kind:`boolean`,default:!1},{key:`time`,label:`Time`,kind:`select`,default:`clock`,options:[{value:`clock`,label:`Clock time, 14:03:27.512`},{value:`stamp`,label:`ROS stamp, in seconds`},{value:`none`,label:`Hidden`}],help:`Of the messages’ stamps, on their nodes’ clocks: seconds on sim time`}]}),Yi=[`map`,`global`,`local`],Xi=2,Zi=2e3,Qi=.25,$i=8,ea=34,ta=6,na=2e3,ra=.25,ia={robot:`#4f8cff`,stale:`#8b95a7`,goal:`#2fbf71`,plan:`#2fbf71`,pose:`#f0a020`},aa=e=>e*180/Math.PI;function oa(e){return`x ${e.x.toFixed(2)} y ${e.y.toFixed(2)} θ ${Math.round(aa(e.yaw))}°`}function sa(e,t,n){return new DOMMatrix().translate(t/2,n/2).scale(e.scale,-e.scale).translate(-e.x,-e.y)}function ca(e){return new DOMMatrix().translate(e.x,e.y).rotate(aa(e.yaw))}function la(e,t){return ca(t).translate(e.originX,e.originY).rotate(aa(e.originYaw)).scale(e.resolution,e.resolution)}function ua(e,t,n,r){let i=t.transformPoint({x:n.x,y:n.y}),a=-n.yaw;e.save(),e.translate(i.x,i.y),e.rotate(a),e.strokeStyle=r,e.fillStyle=r,e.lineWidth=3,e.lineCap=`round`,e.beginPath(),e.moveTo(0,0),e.lineTo(26,0),e.stroke(),e.beginPath(),e.moveTo(ea,0),e.lineTo(23,-7),e.lineTo(23,7),e.closePath(),e.fill(),e.beginPath(),e.arc(0,0,5,0,2*Math.PI),e.fill(),e.lineWidth=2,e.strokeStyle=`#fff`,e.stroke(),e.restore()}function da(e,t,n,r,i){let a=t.transformPoint({x:n.x,y:n.y}),o=Math.max($i,Qi*r),s=i?ia.stale:ia.robot;e.save(),e.translate(a.x,a.y),e.rotate(-n.yaw),e.beginPath(),e.arc(0,0,o,0,2*Math.PI),e.fillStyle=`${s}55`,e.fill(),e.lineWidth=2,e.strokeStyle=s,e.stroke(),e.beginPath(),e.moveTo(o+6,0),e.lineTo(-o*.35,-o*.55),e.lineTo(-o*.1,0),e.lineTo(-o*.35,o*.55),e.closePath(),e.fillStyle=s,e.fill(),e.lineWidth=1.5,e.strokeStyle=`#fff`,e.stroke(),e.restore()}function fa(e,t,n){if(!(n.length<4)){e.save(),e.beginPath();for(let r=0;r<n.length;r+=2){let i=t.transformPoint({x:n[r],y:n[r+1]});r===0?e.moveTo(i.x,i.y):e.lineTo(i.x,i.y)}e.lineCap=`round`,e.lineJoin=`round`,e.strokeStyle=`rgb(0 0 0 / 35%)`,e.lineWidth=6,e.stroke(),e.strokeStyle=ia.plan,e.lineWidth=3,e.stroke(),e.restore()}}function pa(e,t,n){let r=window.devicePixelRatio||1,i=e.clientWidth,a=e.clientHeight;(e.width!==Math.round(i*r)||e.height!==Math.round(a*r))&&(e.width=Math.round(i*r),e.height=Math.round(a*r));let o=e.getContext(`2d`);if(!o||(o.setTransform(1,0,0,1,0,0),o.clearRect(0,0,e.width,e.height),!t))return;let s=sa(t,i,a),c=new DOMMatrix().scale(r,r).multiply(s);for(let e of Yi){let i=n.layers[e],a=n.placements[e];i&&a&&(o.imageSmoothingEnabled=i.info.resolution*t.scale*r<1,o.setTransform(c.multiply(la(i.info,a))),o.drawImage(i.image,0,0))}o.setTransform(r,0,0,r,0,0),n.plan&&fa(o,s.multiply(ca(n.plan.placement)),n.plan.points),n.goal&&ua(o,s,n.goal,ia.goal),n.robot?.transform&&da(o,s,n.robot.transform,t.scale,n.robot.ageMs>na),n.preview&&ua(o,s,n.preview.pose,ia[n.preview.tool])}function ma(e,t,n,r){let i=la(e.info,t),a=e.info.known??{x:0,y:0,width:e.info.width,height:e.info.height},o=[[a.x,a.y],[a.x+a.width,a.y],[a.x,a.y+a.height],[a.x+a.width,a.y+a.height]].map(([e,t])=>i.transformPoint({x:e,y:t})),s=o.map(e=>e.x),c=o.map(e=>e.y),[l,u,d,f]=[Math.min(...s),Math.max(...s),Math.min(...c),Math.max(...c)],p=.94*Math.min(n/(u-l||1),r/(f-d||1));return{x:(l+u)/2,y:(d+f)/2,scale:Math.min(Zi,Math.max(Xi,p))}}function ha({config:e,editing:t}){let n=(0,Y.useRef)(null),r=(0,Y.useRef)(null),a=(0,Y.useRef)(null),o=(0,Y.useRef)({}),[s,c]=(0,Y.useState)({map:``,global:``,local:``}),[l,u]=(0,Y.useState)({state:`waiting`,message:`Connecting…`}),[d,f]=(0,Y.useState)(null),[p,h]=(0,Y.useState)(!1),_=(0,Y.useRef)(null),v=(0,Y.useRef)(null),[y,x]=(0,Y.useState)(``),S=(0,Y.useRef)(null),C=(0,Y.useRef)(new Map),w=(0,Y.useRef)(null),T=e.mapFrame.trim(),E=ue(T,e.robotFrame),D=e=>s[e]&&s[e]!==T?s[e]:``,ee={map:ue(T,D(`map`)),global:ue(T,D(`global`)),local:ue(T,D(`local`))},O={};for(let e of Yi)O[e]=D(e)?ee[e]?.transform??null:{x:0,y:0,yaw:0};let k=ue(T,y&&y!==T?y:``),A=y&&y!==T?k?.transform??null:{x:0,y:0,yaw:0},j=(0,Y.useRef)({layers:o.current,placements:O,planPlacement:A,robot:E});j.current={layers:o.current,placements:O,planPlacement:A,robot:E};let M=(0,Y.useRef)(0),N=(0,Y.useCallback)(()=>{M.current||=requestAnimationFrame(()=>{M.current=0;let e=n.current,{planPlacement:t,...i}=j.current;e&&pa(e,r.current,{...i,plan:v.current&&t?{points:v.current.points,placement:t}:null,goal:_.current,preview:S.current})})},[]);(0,Y.useEffect)(N),(0,Y.useEffect)(()=>()=>cancelAnimationFrame(M.current),[]);let P=()=>({width:n.current?.clientWidth??1,height:n.current?.clientHeight??1}),F=(0,Y.useCallback)(()=>{let{width:e,height:t}=P();for(let n of Yi){let i=o.current[n],s=j.current.placements[n];if(i&&s)return r.current=ma(i,s,e,t),a.current=n===`map`?`map`:`costmap`,N(),!0}let n=j.current.robot?.transform;return n?(r.current={x:n.x,y:n.y,scale:50},a.current=`robot`,N(),!0):!1},[N]),I=(0,Y.useCallback)((e,t,n,r)=>{let i=!0,s=R.subscribeGrid({topic:t,style:n,maxFps:r},{status:(t,n)=>e===`map`&&u({state:t,message:n}),frame:async(t,{meta:n})=>{let r=await createImageBitmap(t);if(!i){r.close();return}let s=n;o.current[e]?.image.close(),o.current[e]={image:r,info:s},c(t=>t[e]===s.frameId?t:{...t,[e]:s.frameId});let l=a.current;(e===`map`?l!==`map`&&l!==`user`:l===null||l===`robot`)&&F(),N()}});return()=>{i=!1,s(),o.current[e]?.image.close(),delete o.current[e],N()}},[F,N]),L=e.mapTopic.trim();(0,Y.useEffect)(()=>{if(!L)u({state:`error`,message:`No map topic: set one in edit mode`});else return u({state:`waiting`,message:`Connecting…`}),I(`map`,L,`map`,1)},[L,I]);let te=e.showGlobalCostmap?e.globalCostmapTopic.trim():``;(0,Y.useEffect)(()=>te?I(`global`,te,`costmap`,1):void 0,[te,I]);let z=e.showLocalCostmap?e.localCostmapTopic.trim():``;(0,Y.useEffect)(()=>z?I(`local`,z,`costmap`,4):void 0,[z,I]);let B=e.showPlan?e.planTopic.trim():``;(0,Y.useEffect)(()=>{if(!B)return;let e=R.subscribePath({topic:B},e=>{v.current=e,x(e.frameId),N()});return()=>{e(),v.current=null,x(``),N()}},[B,N]),(0,Y.useEffect)(()=>{let e=E?.transform;e&&_.current&&Math.hypot(e.x-_.current.x,e.y-_.current.y)<ra&&(_.current=null),p&&e&&r.current?r.current={...r.current,x:e.x,y:e.y}:!r.current&&e&&F()},[E,p,F]),(0,Y.useEffect)(()=>{let e=n.current;if(!e)return;let t=new ResizeObserver(N);return t.observe(e),()=>t.disconnect()},[N]);let ne=(0,Y.useCallback)((e,t)=>{let n=r.current;if(!n)return;let{width:i,height:o}=P(),s=Math.min(Zi,Math.max(Xi,n.scale*t));a.current=`user`;let c=sa(n,i,o).inverse().transformPoint(e);r.current={scale:s,x:c.x-(e.x-i/2)/s,y:c.y+(e.y-o/2)/s},N()},[N]);(0,Y.useEffect)(()=>{let e=n.current;if(!e)return;let t=t=>{t.preventDefault();let n=e.getBoundingClientRect();ne({x:t.clientX-n.left,y:t.clientY-n.top},Math.exp(-t.deltaY*.0015))};return e.addEventListener(`wheel`,t,{passive:!1}),()=>e.removeEventListener(`wheel`,t)},[ne]),(0,Y.useEffect)(()=>{if(!d)return;let e=e=>e.key===`Escape`&&f(null);return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[d]);let re=e=>{let t=n.current.getBoundingClientRect();return{x:e.clientX-t.left,y:e.clientY-t.top}},V=e=>{let{width:t,height:n}=P(),{x:i,y:a}=sa(r.current,t,n).inverse().transformPoint(e);return{x:i,y:a}},ie=()=>{let[e,t]=[...C.current.values()];return{distance:Math.hypot(e.x-t.x,e.y-t.y),center:{x:(e.x+t.x)/2,y:(e.y+t.y)/2}}},ae=(t,n)=>{R.send({type:`pose`,topic:t===`goal`?e.goalTopic.trim():e.poseTopic.trim(),covariance:t===`pose`,frameId:T,...n})?(t===`goal`&&(_.current=n),G(`${t===`goal`?`Goal`:`Pose estimate`} sent: ${oa(n)}`)):G(`Not connected to the robot`,`error`)},oe=e=>{if(!r.current||e.pointerType===`mouse`&&e.button!==0)return;e.currentTarget.setPointerCapture(e.pointerId);let t=re(e);if(C.current.set(e.pointerId,t),C.current.size===2)S.current=null,w.current={kind:`pinch`,...ie()};else if(C.current.size===1&&d){let n=V(t);w.current={kind:`place`,tool:d,pointerId:e.pointerId,anchor:n,start:t},S.current={tool:d,pose:{x:n.x,y:n.y,yaw:0}}}else C.current.size===1&&(w.current={kind:`pan`});N()},se=e=>{let t=C.current.get(e.pointerId),n=r.current;if(!t||!n)return;let i=re(e);C.current.set(e.pointerId,i);let o=w.current;if(o?.kind===`place`){let e=V(i),t=Math.hypot(i.x-o.start.x,i.y-o.start.y)>ta;S.current={tool:o.tool,pose:{...o.anchor,yaw:t?Math.atan2(e.y-o.anchor.y,e.x-o.anchor.x):0}}}else if(o?.kind===`pan`)a.current=`user`,r.current={...n,x:n.x-(i.x-t.x)/n.scale,y:n.y+(i.y-t.y)/n.scale},h(!1);else if(o?.kind===`pinch`&&C.current.size===2){let e=ie();r.current={...n,x:n.x-(e.center.x-o.center.x)/n.scale,y:n.y+(e.center.y-o.center.y)/n.scale},ne(e.center,e.distance/(o.distance||1)),w.current={kind:`pinch`,...e}}N()},H=e=>{if(!C.current.delete(e.pointerId))return;let t=w.current;if(t?.kind===`place`&&t.pointerId===e.pointerId){let n=S.current;S.current=null,w.current=null,e.type===`pointerup`&&n&&(ae(t.tool,n.pose),f(null))}else C.current.size===1?w.current={kind:`pan`}:C.current.size===0&&(w.current=null);N()},ce=E?.transform,le;if(!T||!e.robotFrame.trim())le={text:`Set the TF frames in edit mode`,className:`error`};else if(ce){let e=E.ageMs>na;le={text:`${oa(ce)}${e?` (stale)`:``}`,className:e?`stale`:``}}else le={text:E?.error??`Locating the robot…`,className:`error`};let de=(e,t,n)=>(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":d===e,title:t,"aria-label":t,onClick:()=>f(t=>t===e?null:e),children:(0,X.jsx)(n,{width:17,height:17})});return(0,X.jsxs)(`div`,{className:`navigation`,children:[(0,X.jsx)(`canvas`,{ref:n,className:d?`placing`:void 0,onPointerDown:oe,onPointerMove:se,onPointerUp:H,onPointerCancel:H}),l.state!==`streaming`&&(0,X.jsxs)(`div`,{className:`nav-overlay ${l.state}`,children:[(0,X.jsx)(i,{width:28,height:28}),(0,X.jsx)(`span`,{children:l.message})]}),(0,X.jsxs)(`div`,{className:`overlay-toolbar`,children:[de(`pose`,`Set the pose estimate`,g),de(`goal`,`Send a navigation goal`,b),(0,X.jsx)(`span`,{className:`overlay-separator`}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Fit the map`,"aria-label":`Fit the map`,onClick:()=>{h(!1),F()},children:(0,X.jsx)(he,{width:17,height:17})}),(0,X.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":p,title:`Follow the robot`,"aria-label":`Follow the robot`,disabled:!ce,onClick:()=>h(e=>!e),children:(0,X.jsx)(m,{width:17,height:17})})]}),d&&!t&&(0,X.jsx)(`div`,{className:`nav-hint`,children:d===`goal`?`Press where the robot should go, drag towards where it should face`:`Press where the robot is, drag towards where it faces`}),(0,X.jsx)(`div`,{className:`nav-readout ${le.className}`,children:le.text})]})}var ga=J({type:`navigation`,name:`Navigation`,description:`The map, the costmaps and the robot on them; set its pose and send it goals.`,icon:i,defaultSize:{w:8,h:6},minSize:{w:3,h:3},component:ha,properties:[{key:`mapTopic`,label:`Map topic`,kind:`topic`,default:`/map`,topicTypes:[`nav_msgs/msg/OccupancyGrid`]},{key:`showGlobalCostmap`,label:`Show the global costmap`,kind:`boolean`,default:!1},{key:`globalCostmapTopic`,label:`Global costmap topic`,kind:`topic`,default:`/global_costmap/costmap`,topicTypes:[`nav_msgs/msg/OccupancyGrid`],visible:e=>e.showGlobalCostmap},{key:`showLocalCostmap`,label:`Show the local costmap`,kind:`boolean`,default:!0},{key:`localCostmapTopic`,label:`Local costmap topic`,kind:`topic`,default:`/local_costmap/costmap`,topicTypes:[`nav_msgs/msg/OccupancyGrid`],visible:e=>e.showLocalCostmap},{key:`showPlan`,label:`Show the planned path`,kind:`boolean`,default:!0},{key:`planTopic`,label:`Plan topic`,kind:`topic`,default:`/plan`,topicTypes:[`nav_msgs/msg/Path`],help:`nav_msgs/Path: Nav2’s planner publishes its plan on /plan`,visible:e=>e.showPlan},{key:`goalTopic`,label:`Goal topic`,kind:`topic`,default:`/goal_pose`,topicTypes:[`geometry_msgs/msg/PoseStamped`],help:`geometry_msgs/PoseStamped, which Nav2’s bt_navigator follows`},{key:`poseTopic`,label:`Pose estimate topic`,kind:`topic`,default:`/initialpose`,topicTypes:[`geometry_msgs/msg/PoseWithCovarianceStamped`],help:`geometry_msgs/PoseWithCovarianceStamped, which AMCL starts from`},{key:`mapFrame`,label:`Map frame`,kind:`string`,default:`map`,help:`The frame the map is drawn in, and the goals and poses are set in`},{key:`robotFrame`,label:`Robot frame`,kind:`string`,default:`base_footprint`,help:`Where the robot is, from TF`}]}),_a=`modulepreload`,va=function(e){return`/`+e},ya={},ba=function(e){return e.pathname.endsWith(`.css`)},xa=function(e,t,n){if(t in e)return e[t];let r=n();if(!r){e[t]=void 0;return}let i=r.then(()=>{e[t]=void 0},n=>{throw e[t]=void 0,n});return e[t]=i,i},Sa=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e,i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?new URL(import.meta.resolve(e)):new URL(e,import.meta.url)}r=o(t.map(t=>{t=va(t,n);let r=s(t),i=ba(r);return xa(ya,r.href,()=>{if(e===void 0){e={all:new Set,styles:new Set};let t=document.getElementsByTagName(`link`);for(let n=t.length-1;n>=0;n--){let r=t[n];e.all.add(r.href),r.rel===`stylesheet`&&e.styles.add(r.href)}}if((i?e.styles:e.all).has(r.href))return;let t=document.createElement(`link`);if(t.rel=i?`stylesheet`:_a,i||(t.as=`script`),t.crossOrigin=``,t.href=r.href,a&&t.setAttribute(`nonce`,a),document.head.appendChild(t),i)return new Promise((e,n)=>{t.addEventListener(`load`,e),t.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${r}`)))})})}).filter(e=>e!==void 0))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},Ca=(0,Y.lazy)(()=>Sa(()=>import(`./RobotModelView.js`),__vite__mapDeps([0,1,2,3,4])));function wa({config:e}){return(0,X.jsx)(Y.Suspense,{fallback:(0,X.jsx)(`div`,{className:`widget-message`,children:`Loading the 3D view…`}),children:(0,X.jsx)(Ca,{config:e})})}var Ta=J({type:`robot-model`,name:`Robot Model`,description:`The robot in 3D, its moving joints highlighted, and its TF frames.`,icon:oe,defaultSize:{w:6,h:5},minSize:{w:3,h:3},component:wa,properties:[{key:`descriptionTopic`,label:`Robot description topic`,kind:`topic`,default:`/robot_description`,topicTypes:[`std_msgs/msg/String`],help:`The URDF, as robot_state_publisher publishes it. Its package:// meshes come from the robot`},{key:`jointStatesTopic`,label:`Joint states topic`,kind:`topic`,default:`/joint_states`,topicTypes:[`sensor_msgs/msg/JointState`],help:`Where the joints are, and how they move`},{key:`showFrames`,label:`Show the TF frames`,kind:`boolean`,default:!1},{key:`highlightMotion`,label:`Highlight the moving joints`,kind:`boolean`,default:!0,help:`Their links take another colour, with an arrow in the direction of the motion`}]}),Ea={x:0,y:0,z:0};function Da(e){return e.x===0&&e.y===0&&e.z===0}function Oa(e,t){R.send({type:`twist`,topic:e.topic,stamped:e.stamped,frameId:e.frameId,linear:{x:t.x*e.maxLinear,y:t.y*e.maxLinear},angular:{z:t.z*e.maxAngular}})}function ka({config:e,editing:t}){let n=ae()===`open`,[r,i]=(0,Y.useState)(Ea),a=(0,Y.useRef)(Ea),o=(0,Y.useRef)(e);o.current=e;let s=(0,Y.useRef)(!1),c=(0,Y.useCallback)(e=>{let t={...a.current,...e};a.current=t,i(t),!Da(t)&&!s.current?(s.current=!0,Oa(o.current,t)):Da(t)&&s.current&&(s.current=!1,Oa(o.current,Ea))},[]);(0,Y.useEffect)(()=>{let t=setInterval(()=>s.current&&Oa(o.current,a.current),1e3/Math.min(50,Math.max(1,e.rate)));return()=>clearInterval(t)},[e.rate]);let{topic:l,stamped:u}=e;(0,Y.useEffect)(()=>()=>{s.current&&(s.current=!1,Oa({...o.current,topic:l,stamped:u},Ea))},[l,u]);let d=t||!n,{maxLinear:f,maxAngular:p}=e;return(0,X.jsxs)(`div`,{className:`teleop`,children:[(0,X.jsx)(`div`,{className:`teleop-pads${e.omnidirectional?` two`:``}`,children:e.omnidirectional?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(be,{axes:`xy`,label:`x · y`,disabled:d,onMove:(e,t)=>c({x:t,y:-e})}),(0,X.jsx)(be,{axes:`x`,label:`z`,disabled:d,onMove:e=>c({z:-e})})]}):(0,X.jsx)(be,{axes:`xy`,label:`x · z`,disabled:d,onMove:(e,t)=>c({x:t,y:0,z:-e})})}),(0,X.jsx)(`div`,{className:`teleop-readout`,children:n||t?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`span`,{children:[`x `,(r.x*f).toFixed(3)]}),e.omnidirectional&&(0,X.jsxs)(`span`,{children:[`y `,(r.y*f).toFixed(3)]}),(0,X.jsxs)(`span`,{children:[`z `,(r.z*p).toFixed(3)]}),(0,X.jsx)(`span`,{className:`teleop-topic`,children:e.topic})]}):(0,X.jsx)(`span`,{className:`offline`,children:`Disconnected`})})]})}var Aa=J({type:`teleop`,name:`Teleop`,description:`Drive the robot with on-screen pads, publishing velocity commands.`,icon:me,defaultSize:{w:6,h:4},minSize:{w:3,h:3},component:ka,properties:[{key:`topic`,label:`Topic`,kind:`topic`,default:`cmd_vel`,topicTypes:[`geometry_msgs/msg/Twist`,`geometry_msgs/msg/TwistStamped`],help:`With twist_mux, one of its inputs, above autonomous navigation and below the joysticks`},{key:`omnidirectional`,label:`Omnidirectional`,kind:`boolean`,default:!1,help:`Two pads: x and y, and z. Otherwise one: x and z`},{key:`stamped`,label:`TwistStamped`,kind:`boolean`,default:!1,help:`Publish geometry_msgs/TwistStamped instead of Twist`},{key:`frameId`,label:`Frame id`,kind:`string`,default:`base_link`,visible:e=>e.stamped},{key:`maxLinear`,label:`Max linear speed (m/s)`,kind:`number`,default:.2,min:0,step:.01},{key:`maxAngular`,label:`Max angular speed (rad/s)`,kind:`number`,default:.5,min:0,step:.01},{key:`rate`,label:`Rate (Hz)`,kind:`number`,default:10,min:1,max:50,step:1,help:`How often the command is published while a pad is held`}]});function ja(e,t){return typeof t==typeof e.default&&(e.kind!==`select`||e.options.some(e=>e.value===t))&&(typeof t!=`number`||Number.isFinite(t))}var Ma=class{registered;defaults=new Map;current;constructor(e){this.registered=e.map(e=>({definition:e,plugin:null})),this.current=this.registered}registerPlugin(e,t){let n=[];for(let r of t.widgets??[]){let t=this.registered.find(e=>e.definition.type===r.type);t?n.push(`its widget type "${r.type}" is already ${t.plugin?`${t.plugin}'s`:`Tassello's`}`):this.registered=[...this.registered,{definition:r,plugin:e}]}for(let[e,r]of Object.entries(t.defaults??{})){let t=this.defaults.get(e)??new Map;for(let[i,a]of Object.entries(r)){t.set(i,a);let r=this.registered.find(t=>t.definition.type===e)?.definition,o=r?.properties.find(e=>e.key===i);r&&(!o||!ja(o,a))&&n.push(`its default of ${e}.${i} is not one of the property's values`)}this.defaults.set(e,t)}return this.current=this.registered.map(e=>({...e,definition:this.withDefaults(e.definition)})),n}entries(){return this.current}definition(e){return this.current.find(t=>t.definition.type===e)?.definition}withDefaults(e){let t=this.defaults.get(e.type);return t?{...e,properties:e.properties.map(e=>t.has(e.key)&&ja(e,t.get(e.key))?{...e,default:t.get(e.key)}:e)}:e}};function Na(e,t){let n={};for(let r of e.properties){let e=t[r.key];n[r.key]=ja(r,e)?e:r.default}return n}var Pa=new Ma([Aa,ga,Ta,Re,di,pi,oi,Ae,ei,Ur,Ji]);function Fa(e,t){return Pa.registerPlugin(e,t)}function Ia(){return Pa.entries()}function La(e){return Pa.definition(e)}function Ra(e,t){return e.x<t.x+t.w&&t.x<e.x+e.w&&e.y<t.y+t.h&&t.y<e.y+e.h}function za(e,t,n){return e.x>=0&&e.y>=0&&!t.some(t=>t.id!==n&&Ra(e,t))}function Ba(e){return{cols:Math.max(0,...e.map(e=>e.x+e.w)),rows:Math.max(0,...e.map(e=>e.y+e.h))}}function Va(e,t,n){let{rows:r}=Ba(e);for(let i=0;i<=r;i++)for(let r=0;r+t.w<=Math.max(n,t.w);r++){let n={x:r,y:i,...t};if(za(n,e))return n}return{x:0,y:r,...t}}function Ha(e,t=64){return{left:e.x*t+4,top:e.y*t+4,width:e.w*t-8,height:e.h*t-8}}var Ua={desktop:{label:`Desktop`,columns:null,previewWidth:null},tablet:{label:`Tablet`,columns:12,previewWidth:820},phone:{label:`Phone`,columns:6,previewWidth:390}};function Wa(e){return e<640?`phone`:e<1100?`tablet`:`desktop`}function Ga(e,t){return e.x<t.x+t.w&&t.x<e.x+e.w&&e.y<t.y+t.h&&t.y<e.y+e.h}function Ka(e,t,n,r){if(e.x<0||e.y<0||n!==null&&e.x+e.w>n)return!1;for(let[n,i]of t.rects)if(n!==r&&Ga(e,i))return!1;return!0}function qa(e,t,n,r,i){for(let a=i;;a++)for(let i=0;i+t<=r;i++){let r={x:i,y:a,w:t,h:n};if(![...e.values()].some(e=>Ga(r,e)))return r}}function Ja(e,t,n){let r=Ua[t].columns;if(r===null)return{rects:new Map(e.widgets.map(e=>[e.id,{x:e.x,y:e.y,w:e.w,h:e.h}])),hidden:[],custom:!0};let i=e.layouts?.[t],a=new Set(i?.hidden??[]),o=new Map;for(let t of e.widgets){let e=i?.rects[t.id];if(e&&!a.has(t.id)){let n=Math.min(e.w,r);o.set(t.id,{x:Math.min(e.x,r-n),y:e.y,w:n,h:e.h})}}let s=Math.max(0,...[...o.values()].map(e=>e.y+e.h)),c=e.widgets.filter(e=>!a.has(e.id)&&!o.has(e.id)).sort((e,t)=>e.y-t.y||e.x-t.x);for(let e of c){let t=qa(o,Math.min(e.w,r),e.w>r?Math.max(n(e.type).h,Math.round(e.h*r/e.w)):e.h,r,s);o.set(e.id,t),s=t.y}return{rects:o,hidden:[...a],custom:Object.keys(i?.rects??{}).length>0}}function Ya(e,t,n){return{...e,layouts:{...e.layouts,[t]:n}}}function Xa(e,t,n,r,i){if(t===`desktop`)return{...e,widgets:e.widgets.map(e=>e.id===r?{...e,...i}:e)};let a=Object.fromEntries(n.rects);return a[r]=i,Ya(e,t,{rects:a,hidden:n.hidden})}function Za(e,t,n,r,i){return Ya(e,t,{rects:n.custom?Object.fromEntries([...n.rects].filter(([e])=>e!==r)):{},hidden:i?[...new Set([...n.hidden,r])]:n.hidden.filter(e=>e!==r)})}function Qa(e,t){let{[t]:n,...r}=e.layouts??{},{layouts:i,...a}=e;return Object.keys(r).length>0?{...a,layouts:r}:a}var $a=4,eo=4,to=100,no=32;function ro(e){let[t,n]=(0,Y.useState)({width:0,height:0});return(0,Y.useEffect)(()=>{let t=e.current;if(!t)return;let r=new ResizeObserver(()=>n({width:t.clientWidth,height:t.clientHeight}));return r.observe(t),()=>r.disconnect()},[e]),t}function io({panel:e,device:t,layout:n,previewWidth:r,editing:i,selectedId:a,onSelect:o,onPlace:s,onRemove:c,onHide:l,onVisibleColumns:u}){let d=(0,Y.useRef)(null),f=ro(d),[p,m]=(0,Y.useState)(null),h=Ua[t].columns,g=(r??f.width)-32,_=h===null?64:Math.max(no,Math.floor(g/h)),v=h??Math.max(1,Math.floor(g/_)),y=Math.max(1,Math.floor((f.height-32)/_));(0,Y.useEffect)(()=>u?.(v),[v,u]);let b=[...n.rects.values()],x=Ba(p?[...b,p.rect]:b),S=h??(i?Math.max(x.cols+$a,v):x.cols),w=i?Math.max(x.rows+$a,y):x.rows,T=(e,t,r)=>{let a=n.rects.get(t.id);if(!i||e.button!==0||p||!a)return;e.stopPropagation(),e.currentTarget.setPointerCapture(e.pointerId);let s=d.current;m({id:t.id,kind:r,pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,startScrollLeft:s.scrollLeft,startScrollTop:s.scrollTop,origin:a,rect:a,dx:0,dy:0,moved:!1}),o(t.id)},E=t=>{if(!p||t.pointerId!==p.pointerId)return;let n=d.current,r=t.clientX-p.startX+n.scrollLeft-p.startScrollLeft,i=t.clientY-p.startY+n.scrollTop-p.startScrollTop,{origin:a}=p,o;if(p.kind===`move`){let e=Math.max(0,a.x+Math.round(r/_));o={...a,x:h===null?e:Math.min(h-a.w,e),y:Math.max(0,a.y+Math.round(i/_))}}else{let t=La(e.widgets.find(e=>e.id===p.id)?.type??``)?.minSize,n=h===null?to:h-a.x;o={...a,w:Math.min(n,Math.max(Math.min(t?.w??1,n),a.w+Math.round(r/_))),h:Math.min(to,Math.max(t?.h??1,a.h+Math.round(i/_)))}}m({...p,dx:r,dy:i,rect:o,moved:p.moved||Math.hypot(r,i)>eo})},D=e=>{if(!p||e.pointerId!==p.pointerId)return;let{id:t,rect:r,origin:i,moved:a}=p;m(null);let o=r.x!==i.x||r.y!==i.y||r.w!==i.w||r.h!==i.h;a&&o&&Ka(r,n,h,t)&&s(t,r)},ee=!p||Ka(p.rect,n,h,p.id);return(0,X.jsx)(`div`,{ref:d,className:`board-scroll${h===null?``:` columns`}`,onPointerDown:e=>{i&&!e.target.closest(`.widget`)&&o(null)},children:(0,X.jsxs)(`div`,{className:`board${i?` editing`:``}${r?` preview`:``}`,style:{width:S*_,height:w*_,"--cell":`${_}px`},children:[p?.moved&&(0,X.jsx)(`div`,{className:`drop-target${ee?``:` invalid`}`,style:Ha(p.rect,_)}),e.widgets.map(r=>{let o=n.rects.get(r.id);if(!o)return null;let s=p?.id===r.id&&p.moved?p:null,u=Ha(o,_);s?.kind===`move`?u.transform=`translate(${s.dx}px, ${s.dy}px)`:s?.kind===`resize`&&(u.width=Math.max(_-8,o.w*_-8+s.dx),u.height=Math.max(_-8,o.h*_-8+s.dy));let d=La(r.type),f=d?.icon??C;return(0,X.jsxs)(`div`,{className:[`widget`,i&&`editing`,a===r.id&&`selected`,s&&`dragging`].filter(Boolean).join(` `),style:u,onPointerDown:e=>T(e,r,`move`),onPointerMove:E,onPointerUp:D,onPointerCancel:D,children:[(0,X.jsx)(ao,{instance:r,panelId:e.id,editing:i}),i&&(0,X.jsxs)(`div`,{className:`widget-chrome`,children:[(0,X.jsxs)(`span`,{className:`widget-tag`,children:[(0,X.jsx)(f,{width:14,height:14}),d?.name??r.type]}),(0,X.jsxs)(`div`,{className:`widget-buttons`,children:[l&&(0,X.jsx)(`button`,{type:`button`,className:`widget-button`,title:`Hide on ${Ua[t].label.toLowerCase()}s`,"aria-label":`Hide on ${Ua[t].label.toLowerCase()}s`,onPointerDown:e=>e.stopPropagation(),onClick:()=>l(r.id),children:(0,X.jsx)(pe,{width:14,height:14})}),(0,X.jsx)(`button`,{type:`button`,className:`widget-button remove`,title:`Remove widget`,"aria-label":`Remove widget`,onPointerDown:e=>e.stopPropagation(),onClick:()=>c(r.id),children:(0,X.jsx)(N,{width:14,height:14})})]}),(0,X.jsx)(`div`,{className:`resize-handle`,title:`Resize`,onPointerDown:e=>T(e,r,`resize`)})]})]},r.id)})]})})}var ao=(0,Y.memo)(function({instance:e,panelId:t,editing:n}){let r=La(e.type),i=(0,Y.useMemo)(()=>r?Na(r,e.config):{},[r,e.config]);return(0,X.jsxs)(`div`,{className:`widget-card`,children:[e.title&&(0,X.jsx)(`div`,{className:`widget-title`,children:e.title}),(0,X.jsx)(`div`,{className:`widget-body`,children:r?(0,X.jsx)(oo,{resetKey:i,children:(0,X.jsx)(r.component,{config:i,instance:e,panelId:t,editing:n})}):(0,X.jsxs)(`div`,{className:`widget-message`,children:[`Unknown widget type “`,e.type,`”: is the plugin that adds it installed?`]})})]})}),oo=class extends Y.Component{state={error:null};static getDerivedStateFromError(e){return{error:e}}componentDidUpdate(e){this.state.error&&e.resetKey!==this.props.resetKey&&this.setState({error:null})}render(){return this.state.error?(0,X.jsxs)(`div`,{className:`widget-message error`,children:[`This widget failed: `,this.state.error.message]}):this.props.children}};function so({widget:e,onChange:t,onDuplicate:n,onRemove:r,onClose:i}){let a=La(e.type),o=a?Na(a,e.config):e.config,s=a?.icon??C,c=(n,r)=>t({...e,config:{...e.config,[n]:r}});return(0,X.jsxs)(`aside`,{className:`properties`,"aria-label":`Widget properties`,children:[(0,X.jsxs)(`header`,{className:`properties-header`,children:[(0,X.jsx)(s,{}),(0,X.jsx)(`h2`,{children:a?.name??e.type}),(0,X.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Close`,onClick:i,children:(0,X.jsx)(U,{})})]}),(0,X.jsxs)(`div`,{className:`properties-body`,children:[(0,X.jsx)(co,{label:`Title`,help:`Shown above the widget, if set`,children:n=>(0,X.jsx)(uo,{id:n,value:e.title,onCommit:n=>t({...e,title:n})})}),a?.properties.filter(e=>!e.visible||e.visible(o)).map(e=>(0,X.jsx)(lo,{property:e,value:o[e.key],onChange:t=>c(e.key,t)},e.key)),(0,X.jsxs)(`p`,{className:`properties-meta`,children:[e.w,`×`,e.h,` cells at column `,e.x+1,`, row `,e.y+1]})]}),(0,X.jsxs)(`footer`,{className:`properties-footer`,children:[(0,X.jsxs)(`button`,{type:`button`,className:`button`,onClick:n,children:[(0,X.jsx)(P,{}),` Duplicate`]}),(0,X.jsxs)(`button`,{type:`button`,className:`button danger`,onClick:r,children:[(0,X.jsx)(N,{}),` Remove`]})]})]})}function co({label:e,help:t,children:n}){let r=(0,Y.useId)();return(0,X.jsxs)(`div`,{className:`field`,children:[(0,X.jsx)(`label`,{className:`field-label`,htmlFor:r,children:e}),n(r),t&&(0,X.jsx)(`p`,{className:`field-help`,children:t})]})}function lo({property:e,value:t,onChange:n}){return e.kind===`boolean`?(0,X.jsxs)(`div`,{className:`field`,children:[(0,X.jsxs)(`label`,{className:`toggle`,children:[(0,X.jsx)(`input`,{type:`checkbox`,checked:t===!0,onChange:e=>n(e.target.checked)}),(0,X.jsx)(`span`,{className:`toggle-switch`,"aria-hidden":`true`}),(0,X.jsx)(`span`,{className:`field-label`,children:e.label})]}),e.help&&(0,X.jsx)(`p`,{className:`field-help`,children:e.help})]}):(0,X.jsx)(co,{label:e.label,help:e.help,children:r=>{switch(e.kind){case`number`:return(0,X.jsx)(uo,{id:r,type:`number`,min:e.min,max:e.max,step:e.step??`any`,value:String(t),onCommit:t=>{let r=Number(t);t.trim()&&Number.isFinite(r)&&n(Math.min(e.max??1/0,Math.max(e.min??-1/0,r)))}});case`select`:return(0,X.jsx)(`select`,{id:r,value:String(t),onChange:e=>n(e.target.value),children:e.options.map(e=>(0,X.jsx)(`option`,{value:e.value,children:e.label},e.value))});case`color`:return(0,X.jsxs)(`div`,{className:`color-field`,children:[(0,X.jsx)(`input`,{id:r,type:`color`,value:String(t),onChange:e=>n(e.target.value)}),(0,X.jsx)(`code`,{children:String(t)})]});case`text`:return(0,X.jsx)(uo,{id:r,multiline:!0,value:String(t),placeholder:e.placeholder,onCommit:n});case`image`:case`behavior-tree`:return(0,X.jsx)(Qe,{id:r,kind:e.kind,value:String(t),placeholder:e.placeholder,onCommit:n,children:e=>(0,X.jsx)(uo,{...e})});case`topic`:return(0,X.jsx)(fo,{id:r,value:String(t),types:e.topicTypes,placeholder:e.placeholder,onCommit:n});default:return(0,X.jsx)(uo,{id:r,value:String(t),placeholder:e.placeholder,onCommit:n})}}})}function uo({value:e,onCommit:t,multiline:n=!1,...r}){let[i,a]=(0,Y.useState)(e);(0,Y.useEffect)(()=>a(e),[e]);let o=()=>i!==e&&t(i),s={...r,value:i,spellCheck:!1,onBlur:o,onChange:e=>a(e.target.value)};return n?(0,X.jsx)(`textarea`,{...s,rows:4,onKeyDown:t=>{t.key===`Enter`&&(t.ctrlKey||t.metaKey)?o():t.key===`Escape`&&a(e)}}):(0,X.jsx)(`input`,{...s,onKeyDown:t=>{t.key===`Enter`?o():t.key===`Escape`&&a(e)}})}function fo({id:e,value:t,types:n,placeholder:r,onCommit:i}){let[a,o]=(0,Y.useState)([]),s=`${e}-topics`,c=()=>q.listTopics().then(o).catch(()=>o([])),l=a.filter(e=>e.types.some(e=>n.includes(e)));return(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(uo,{id:e,value:t,placeholder:r,list:s,onFocus:c,onCommit:i}),(0,X.jsx)(`datalist`,{id:s,children:l.map(e=>(0,X.jsx)(`option`,{value:e.name,children:e.types.join(`, `)},e.name))})]})}function po(){let e=new Map;for(let t of Ia())e.set(t.plugin,[...e.get(t.plugin)??[],t]);return[...e].map(([e,t])=>({plugin:e,entries:t}))}function mo({onAdd:e,onClose:t}){let n=po();return(0,X.jsx)(ye,{title:`Add a widget`,onClose:t,wide:!0,children:(0,X.jsx)(`div`,{className:`palette-scroll`,children:n.map(({plugin:t,entries:r})=>(0,X.jsxs)(`section`,{children:[n.length>1&&(0,X.jsx)(`h3`,{className:`palette-heading`,children:t??`Tassello`}),(0,X.jsx)(`div`,{className:`palette`,children:r.map(({definition:t})=>(0,X.jsxs)(`button`,{type:`button`,className:`palette-item`,onClick:()=>e(t),children:[(0,X.jsx)(`span`,{className:`palette-icon`,children:(0,X.jsx)(t.icon,{width:24,height:24})}),(0,X.jsxs)(`span`,{className:`palette-text`,children:[(0,X.jsx)(`strong`,{children:t.name}),(0,X.jsx)(`span`,{children:t.description})]})]},t.type))})]},t??``))})})}var ho=500,go=18,_o={desktop:ne,tablet:D,phone:p},vo=e=>La(e)?.minSize??{w:1,h:1};function yo(){let[e,t]=(0,Y.useState)(()=>Wa(window.innerWidth));return(0,Y.useEffect)(()=>{let e=()=>t(Wa(window.innerWidth));return window.addEventListener(`resize`,e),()=>window.removeEventListener(`resize`,e)},[]),e}function bo(){return decodeURIComponent(location.hash.replace(/^#\/?/,``))}function xo(e,t=!1){let n=`#/${encodeURIComponent(e)}`;t?(history.replaceState(null,``,n),window.dispatchEvent(new HashChangeEvent(`hashchange`))):location.hash=n}function So(e){return`${e.replace(/[^A-Za-z0-9_-]+/g,`-`).slice(-48)}-${Math.random().toString(36).slice(2,8)}`}function Co(e){return e instanceof Error?e.message:String(e)}function wo(){let[e,t]=(0,Y.useState)(`saved`),n=(0,Y.useRef)(null),r=(0,Y.useRef)(null),i=(0,Y.useRef)(Promise.resolve()),a=(0,Y.useCallback)(()=>{r.current&&=(clearTimeout(r.current),null);let e=n.current;return n.current=null,e&&(i.current=i.current.then(()=>q.savePanel(e).then(()=>{n.current||t(`saved`)},n=>{t(`failed`),G(`Could not save “${e.name}”: ${Co(n)}`,`error`)}))),i.current},[]),o=(0,Y.useCallback)(e=>{n.current=e,t(`saving`),r.current&&clearTimeout(r.current),r.current=setTimeout(a,ho)},[a]);return(0,Y.useEffect)(()=>{let e=()=>{let e=n.current;e&&(n.current=null,fetch(`/api/panels/${encodeURIComponent(e.id)}`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e),keepalive:!0}))};return window.addEventListener(`pagehide`,e),()=>window.removeEventListener(`pagehide`,e)},[]),[e,(0,Y.useMemo)(()=>({schedule:o,flush:a,isPending:()=>n.current!==null}),[o,a])]}function To(){let e=ae(),t=_e(),[n,r]=wo(),[i,a]=(0,Y.useState)(null),[o,s]=(0,Y.useState)(bo),c=(0,Y.useRef)(o);c.current=o;let[l,u]=(0,Y.useState)(null),f=(0,Y.useRef)(null),[p,m]=(0,Y.useState)(null),[h,g]=(0,Y.useState)(`view`),[_,y]=(0,Y.useState)(null),[b,x]=(0,Y.useState)(!1),[S,C]=(0,Y.useState)(!1),w=(0,Y.useRef)([]),[T,E]=(0,Y.useState)(!1),D=(0,Y.useRef)(12),O=(0,Y.useCallback)(e=>{D.current=e},[]),k=h===`edit`,A=yo(),[j,M]=(0,Y.useState)(null),N=k?j??A:A,P=(0,Y.useRef)(N);P.current=N;let F=(0,Y.useMemo)(()=>l?Ja(l,N,vo):null,[l,N]),I=(0,Y.useCallback)(e=>{f.current=e,u(e)},[]),L=(0,Y.useCallback)(async()=>{try{a(await q.listPanels())}catch(e){G(`Could not list the panels: ${Co(e)}`,`error`)}},[]),z=(0,Y.useCallback)(e=>{let t=f.current;if(!t)return;let n=e(t);w.current=[...w.current.slice(-49),t],E(!0),I(n),r.schedule(n)},[r,I]),B=(0,Y.useCallback)(()=>{let e=w.current.pop();E(w.current.length>0),e&&(I(e),r.schedule(e),y(t=>t&&e.widgets.some(e=>e.id===t)?t:null))},[r,I]);(0,Y.useEffect)(()=>{let e=()=>s(bo());return window.addEventListener(`hashchange`,e),()=>window.removeEventListener(`hashchange`,e)},[]),(0,Y.useEffect)(()=>{e!==`closed`&&L()},[L,e]),(0,Y.useEffect)(()=>{i&&i.length>0&&!i.some(e=>e.id===o)&&xo(i[0].id,!0)},[i,o]);let ne=(0,Y.useCallback)(async e=>{try{let t=await q.getPanel(e);e===c.current&&(I(t),m(null))}catch(t){e===c.current&&m(Co(t))}},[I]),re=i?.some(e=>e.id===o)??!1;(0,Y.useEffect)(()=>{if(!re)return;let e=!0;return r.flush().then(()=>{e&&(w.current=[],E(!1),y(null),ne(o))}),()=>{e=!1}},[o,re,ne,r]),(0,Y.useEffect)(()=>R.onServerMessage(e=>{e.type===`error`&&G(e.message,`error`),e.type===`panels.changed`&&e.origin!==R.clientId&&(L(),e.id===f.current?.id&&!e.deleted&&!r.isPending()&&ne(e.id))}),[L,ne,r]);let V=async e=>{e===`view`&&(y(null),M(null),await r.flush()),g(e),C(!1)},ie=e=>{x(!1);let t=f.current;if(!t)return;let n=P.current===`desktop`?D.current:go,r=Va(t.widgets,e.defaultSize,n),i={id:So(e.type),type:e.type,title:``,...r,config:{}};z(e=>({...e,widgets:[...e.widgets,i]})),y(i.id)},oe=(0,Y.useCallback)((e,t)=>z(n=>Xa(n,P.current,Ja(n,P.current,vo),e,t)),[z]),se=(0,Y.useCallback)((e,t=!0)=>{let n=P.current;n!==`desktop`&&(z(r=>Za(r,n,Ja(r,n,vo),e,t)),y(t=>t===e?null:t))},[z]),H=(0,Y.useCallback)(e=>{let t=f.current?.widgets.find(t=>t.id===e);if(z(t=>({...t,widgets:t.widgets.filter(t=>t.id!==e)})),y(t=>t===e?null:t),t){let e=t.title||La(t.type)?.name||t.type;G(`Removed “${e}”`,`info`,{label:`Undo`,run:B})}},[z,B]),le=e=>{let t=f.current,n=t?.widgets.find(t=>t.id===e);if(!t||!n)return;let r=P.current===`desktop`?D.current:go,i=Va(t.widgets,{w:n.w,h:n.h},r),a={...n,...i,id:So(n.type),config:structuredClone(n.config)};z(e=>({...e,widgets:[...e.widgets,a]})),y(a.id)},ue=async()=>{C(!1);let e=await t.prompt({title:`New panel`,label:`Name`,confirmLabel:`Create`});if(e)try{let t=await q.createPanel({name:e,widgets:[]});await L(),xo(t.id),g(`edit`)}catch(e){G(`Could not create the panel: ${Co(e)}`,`error`)}},de=async()=>{C(!1);let e=f.current;if(!e)return;let n=await t.prompt({title:`Rename panel`,label:`Name`,initial:e.name,confirmLabel:`Rename`});n&&n!==e.name&&(z(e=>({...e,name:n})),await r.flush(),await L())},U=async()=>{C(!1);let e=f.current;if(e)try{await r.flush();let t=await q.createPanel({name:`${e.name} (copy)`,widgets:e.widgets});await L(),xo(t.id)}catch(e){G(`Could not duplicate the panel: ${Co(e)}`,`error`)}},fe=async()=>{C(!1);let e=f.current;if(e&&await t.confirm({title:`Delete “${e.name}”?`,message:`The panel and its widgets are deleted for good.`,confirmLabel:`Delete`,danger:!0}))try{await r.flush(),await q.deletePanel(e.id),I(null),await L()}catch(e){G(`Could not delete the panel: ${Co(e)}`,`error`)}};(0,Y.useEffect)(()=>{if(!k)return;let e=e=>{if(e.target.closest(`input, textarea, select, [role="dialog"]`))return;if(e.key===`z`&&(e.ctrlKey||e.metaKey)&&!e.shiftKey){e.preventDefault(),B();return}let t=f.current?.widgets.find(e=>e.id===_);if(!t)return;if(e.key===`Delete`||e.key===`Backspace`){e.preventDefault(),H(t.id);return}let n={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]}[e.key],r=Ja(f.current,P.current,vo),i=r.rects.get(t.id);if(n&&i){e.preventDefault();let a={...i,x:i.x+n[0],y:i.y+n[1]};Ka(a,r,Ua[P.current].columns,t.id)&&oe(t.id,a)}};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[k,_,B,H,oe]);let pe=k?l?.widgets.find(e=>e.id===_):void 0,me={connecting:`Connecting…`,open:`Connected to ${R.hostname}`,closed:`Disconnected, reconnecting…`}[e];return(0,X.jsxs)(`div`,{className:`app${k?` editing`:``}`,children:[(0,X.jsxs)(`header`,{className:`topbar`,children:[(0,X.jsxs)(`div`,{className:`brand`,title:me,children:[(0,X.jsx)(v,{width:22,height:22}),(0,X.jsx)(`span`,{className:`brand-name`,children:R.hostname||`Tassello`}),(0,X.jsx)(`span`,{className:`connection-dot ${e}`,"aria-label":me})]}),i&&i.length>0&&(0,X.jsx)(`select`,{className:`panel-select`,"aria-label":`Panel`,value:o,onChange:e=>xo(e.target.value),children:i.map(e=>(0,X.jsx)(`option`,{value:e.id,children:e.name},e.id))}),(0,X.jsx)(`div`,{className:`topbar-spacer`}),k&&l&&(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(`span`,{className:`save-state ${n}`,children:{saved:`Saved`,saving:`Saving…`,failed:`Not saved`}[n]}),(0,X.jsx)(`button`,{type:`button`,className:`icon-button`,title:`Undo (Ctrl+Z)`,"aria-label":`Undo`,disabled:!T,onClick:B,children:(0,X.jsx)(ce,{})}),(0,X.jsxs)(`button`,{type:`button`,className:`button primary`,"aria-label":`Add widget`,onClick:()=>x(!0),children:[(0,X.jsx)(ge,{}),` `,(0,X.jsx)(`span`,{className:`hide-narrow`,children:`Add widget`})]})]}),k&&(0,X.jsx)(`div`,{className:`mode-switch device-switch`,role:`group`,"aria-label":`Layout of`,children:Object.keys(Ua).map(e=>{let t=_o[e];return(0,X.jsx)(`button`,{type:`button`,"aria-pressed":N===e,title:`The ${Ua[e].label.toLowerCase()} layout`,"aria-label":`${Ua[e].label} layout`,onClick:()=>{M(e),y(null)},children:(0,X.jsx)(t,{})},e)})}),k&&(0,X.jsxs)(`div`,{className:`menu`,children:[(0,X.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Panel actions`,"aria-expanded":S,onClick:()=>C(e=>!e),children:(0,X.jsx)(te,{})}),S&&(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(`div`,{className:`menu-backdrop`,onPointerDown:()=>C(!1)}),(0,X.jsxs)(`div`,{className:`menu-list`,role:`menu`,children:[(0,X.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:ue,children:`New panel…`}),l&&(0,X.jsxs)(X.Fragment,{children:[(0,X.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:de,children:`Rename panel…`}),(0,X.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:U,children:`Duplicate panel`}),(0,X.jsx)(`button`,{type:`button`,role:`menuitem`,className:`danger`,onClick:fe,children:`Delete panel…`})]})]})]})]}),(0,X.jsxs)(`div`,{className:`mode-switch`,role:`group`,"aria-label":`Mode`,children:[(0,X.jsxs)(`button`,{type:`button`,"aria-label":`View`,title:`View`,"aria-pressed":!k,onClick:()=>V(`view`),children:[(0,X.jsx)(ee,{}),` `,(0,X.jsx)(`span`,{className:`hide-narrow`,children:`View`})]}),(0,X.jsxs)(`button`,{type:`button`,"aria-label":`Edit`,title:`Edit`,"aria-pressed":k,onClick:()=>V(`edit`),children:[(0,X.jsx)(d,{}),` `,(0,X.jsx)(`span`,{className:`hide-narrow`,children:`Edit`})]})]})]}),(0,X.jsx)(`main`,{className:`workspace`,children:i===null?(0,X.jsx)(`div`,{className:`empty-state`,children:`Loading…`}):i.length===0?(0,X.jsxs)(`div`,{className:`empty-state`,children:[(0,X.jsx)(`h1`,{children:`No panels yet`}),(0,X.jsx)(`p`,{children:`A panel is a board of widgets: create one for each task, e.g. teleoperation or navigation.`}),(0,X.jsxs)(`button`,{type:`button`,className:`button primary`,onClick:ue,children:[(0,X.jsx)(ge,{}),` Create a panel`]})]}):p?(0,X.jsxs)(`div`,{className:`empty-state`,children:[(0,X.jsx)(`h1`,{children:`Cannot open this panel`}),(0,X.jsx)(`p`,{children:p})]}):l?(0,X.jsxs)(X.Fragment,{children:[(0,X.jsxs)(`div`,{className:`board-column`,children:[k&&N!==`desktop`&&F&&(0,X.jsxs)(`div`,{className:`layout-bar`,children:[(0,X.jsxs)(`span`,{children:[(0,X.jsxs)(`strong`,{children:[Ua[N].label,` layout`]}),F.custom?` · arranged for this device`:` · automatic, from the desktop’s: moving a widget arranges it for this device`]}),F.hidden.length>0&&(0,X.jsxs)(`span`,{className:`layout-hidden`,children:[`Hidden:`,F.hidden.map(e=>{let t=l.widgets.find(t=>t.id===e);return(0,X.jsxs)(`button`,{type:`button`,className:`layout-chip`,title:`Show it again`,onClick:()=>se(e,!1),children:[t?.title||La(t?.type??``)?.name||e,` +`]},e)})]}),(F.custom||F.hidden.length>0)&&(0,X.jsx)(`button`,{type:`button`,className:`link-button`,onClick:()=>z(e=>Qa(e,N)),children:`Back to automatic`})]}),F&&(0,X.jsx)(io,{panel:l,device:N,layout:F,previewWidth:N===A?null:Ua[N].previewWidth,editing:k,selectedId:_,onSelect:y,onPlace:oe,onRemove:H,onHide:N===`desktop`?void 0:se,onVisibleColumns:O},N)]}),l.widgets.length===0&&(0,X.jsx)(`div`,{className:`board-hint`,children:k?(0,X.jsxs)(X.Fragment,{children:[`This panel is empty: add widgets with `,(0,X.jsx)(`strong`,{children:`Add widget`}),`.`]}):(0,X.jsxs)(X.Fragment,{children:[`This panel is empty: switch to `,(0,X.jsx)(`strong`,{children:`Edit`}),` to add widgets.`]})}),pe&&(0,X.jsx)(so,{widget:pe,onChange:e=>z(t=>({...t,widgets:t.widgets.map(t=>t.id===e.id?e:t)})),onDuplicate:()=>le(pe.id),onRemove:()=>H(pe.id),onClose:()=>y(null)},pe.id)]}):null}),b&&(0,X.jsx)(mo,{onAdd:ie,onClose:()=>x(!1)}),(0,X.jsx)(K,{})]})}var Eo=[];function Do(e){return e instanceof Error?e.message:String(e)}async function Oo(){try{Eo=await q.listPlugins()}catch(e){return[`The plugins could not be listed: ${Do(e)}`]}let e=Eo.flatMap(e=>e.error?[`Plugin ${e.name}: its server side did not start: ${e.error}`]:[]);for(let e of Eo)for(let t of e.styles){let e=document.createElement(`link`);e.rel=`stylesheet`,e.href=t,document.head.append(e)}return(await Promise.allSettled(Eo.map(e=>e.client?Sa(()=>import(e.client),[]):Promise.resolve(null)))).forEach((t,n)=>{let{name:r}=Eo[n];if(t.status===`rejected`){e.push(`Plugin ${r} did not load: ${Do(t.reason)}`);return}if(t.value===null)return;let i=t.value.default;if(typeof i!=`object`||!i)e.push(`Plugin ${r}: its client module has no default export (definePlugin({ widgets }))`);else for(let t of Fa(r,i))e.push(`Plugin ${r}: ${t}`)}),e}R.connect();var ko=await Oo();(0,Ce.createRoot)(document.getElementById(`root`)).render((0,X.jsx)(Y.StrictMode,{children:(0,X.jsx)(ve,{children:(0,X.jsx)(To,{})})}));for(let e of ko)console.error(e),G(e,`error`);
|
|
69
|
+
`),children:(0,J.jsx)(ee,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Clear the messages`,"aria-label":`Clear the messages`,disabled:t.entries.length===0&&t.pending.length===0,onClick:()=>{v(null),n({type:`clear`})},children:(0,J.jsx)(Ne,{width:17,height:17})})]})]}),(0,J.jsxs)(`div`,{className:`logs-main`,children:[ie&&(0,J.jsx)(yl,{nodes:j.nodes,chosen:p,overlay:!re,onToggle:te,onAll:()=>m(new Set),onClose:()=>b(!1)}),(0,J.jsx)(ul,{entries:j.shown,version:t.version,selected:_,follow:h,time:e.time,showNode:p.size!==1&&L.length!==1,nodeWidth:R,compact:ne>0&&ne<fl,empty:ae,onSelect:v,onFollow:g})]}),P&&(0,J.jsx)(bl,{entry:P,running:t.running,onOnly:()=>m(new Set([P.name])),onClose:()=>v(null)}),(0,J.jsxs)(`div`,{className:`logs-status ${z.tone}`,title:z.text,children:[(0,J.jsx)(`span`,{className:`logs-dot`,"aria-hidden":`true`}),(0,J.jsx)(`span`,{className:`logs-status-text`,children:z.text})]})]})}var Sl=Ve({type:`logs`,name:`Logs`,description:`The ROS log of every node (/rosout), coloured by level, filtered by node, level and text.`,icon:m,defaultSize:{w:10,h:6},minSize:{w:4,h:3},component:xl,properties:[{key:`topic`,label:`Log topic`,kind:`topic`,default:`/rosout`,topicTypes:[`rcl_interfaces/msg/Log`],help:`rcl_interfaces/Log: every node’s logger publishes on /rosout`},{key:`nodes`,label:`Nodes`,kind:`string`,default:``,placeholder:`amcl, *_server`,help:`Only these nodes, with their child loggers: names or globs (*), separated by commas or spaces. All if empty`},{key:`level`,label:`Levels shown`,kind:`select`,default:`debug`,options:[{value:`debug`,label:`All`},{value:`info`,label:`Info and above`},{value:`warn`,label:`Warnings and above`},{value:`error`,label:`Errors and above`}],help:`When the panel opens: its toolbar shows and hides each level`},{key:`include`,label:`Include`,kind:`string`,default:``,placeholder:`goal; path`,help:`Only the messages containing any of these, separated by ;. The toolbar changes it`},{key:`exclude`,label:`Exclude`,kind:`string`,default:``,placeholder:`Publishing`,help:`Not the messages containing any of these, separated by ;. The toolbar changes it`},{key:`regex`,label:`Filters as regular expressions`,kind:`boolean`,default:!1},{key:`time`,label:`Time`,kind:`select`,default:`clock`,options:[{value:`clock`,label:`Clock time, 14:03:27.512`},{value:`stamp`,label:`ROS stamp, in seconds`},{value:`none`,label:`Hidden`}],help:`Of the messages’ stamps, on their nodes’ clocks: seconds on sim time`}]}),Cl=[`map`,`global`,`local`],wl=2,Tl=2e3,El=.25,Dl=8,Ol=34,kl=6,Al=2e3,jl=.25,Ml={robot:`#4f8cff`,stale:`#8b95a7`,goal:`#2fbf71`,plan:`#2fbf71`,pose:`#f0a020`},Nl=e=>e*180/Math.PI;function Pl(e){return`x ${e.x.toFixed(2)} y ${e.y.toFixed(2)} θ ${Math.round(Nl(e.yaw))}°`}function Fl(e,t,n){return new DOMMatrix().translate(t/2,n/2).scale(e.scale,-e.scale).translate(-e.x,-e.y)}function Il(e){return new DOMMatrix().translate(e.x,e.y).rotate(Nl(e.yaw))}function Ll(e,t){return Il(t).translate(e.originX,e.originY).rotate(Nl(e.originYaw)).scale(e.resolution,e.resolution)}function Rl(e,t,n,r){let i=t.transformPoint({x:n.x,y:n.y}),a=-n.yaw;e.save(),e.translate(i.x,i.y),e.rotate(a),e.strokeStyle=r,e.fillStyle=r,e.lineWidth=3,e.lineCap=`round`,e.beginPath(),e.moveTo(0,0),e.lineTo(26,0),e.stroke(),e.beginPath(),e.moveTo(Ol,0),e.lineTo(23,-7),e.lineTo(23,7),e.closePath(),e.fill(),e.beginPath(),e.arc(0,0,5,0,2*Math.PI),e.fill(),e.lineWidth=2,e.strokeStyle=`#fff`,e.stroke(),e.restore()}function zl(e,t,n,r,i){let a=t.transformPoint({x:n.x,y:n.y}),o=Math.max(Dl,El*r),s=i?Ml.stale:Ml.robot;e.save(),e.translate(a.x,a.y),e.rotate(-n.yaw),e.beginPath(),e.arc(0,0,o,0,2*Math.PI),e.fillStyle=`${s}55`,e.fill(),e.lineWidth=2,e.strokeStyle=s,e.stroke(),e.beginPath(),e.moveTo(o+6,0),e.lineTo(-o*.35,-o*.55),e.lineTo(-o*.1,0),e.lineTo(-o*.35,o*.55),e.closePath(),e.fillStyle=s,e.fill(),e.lineWidth=1.5,e.strokeStyle=`#fff`,e.stroke(),e.restore()}function Bl(e,t,n){if(!(n.length<4)){e.save(),e.beginPath();for(let r=0;r<n.length;r+=2){let i=t.transformPoint({x:n[r],y:n[r+1]});r===0?e.moveTo(i.x,i.y):e.lineTo(i.x,i.y)}e.lineCap=`round`,e.lineJoin=`round`,e.strokeStyle=`rgb(0 0 0 / 35%)`,e.lineWidth=6,e.stroke(),e.strokeStyle=Ml.plan,e.lineWidth=3,e.stroke(),e.restore()}}function Vl(e,t,n){let r=window.devicePixelRatio||1,i=e.clientWidth,a=e.clientHeight;(e.width!==Math.round(i*r)||e.height!==Math.round(a*r))&&(e.width=Math.round(i*r),e.height=Math.round(a*r));let o=e.getContext(`2d`);if(!o||(o.setTransform(1,0,0,1,0,0),o.clearRect(0,0,e.width,e.height),!t))return;let s=Fl(t,i,a),c=new DOMMatrix().scale(r,r).multiply(s);for(let e of Cl){let i=n.layers[e],a=n.placements[e];i&&a&&(o.imageSmoothingEnabled=i.info.resolution*t.scale*r<1,o.setTransform(c.multiply(Ll(i.info,a))),o.drawImage(i.image,0,0))}o.setTransform(r,0,0,r,0,0),n.plan&&Bl(o,s.multiply(Il(n.plan.placement)),n.plan.points),n.goal&&Rl(o,s,n.goal,Ml.goal),n.robot?.transform&&zl(o,s,n.robot.transform,t.scale,n.robot.ageMs>Al),n.preview&&Rl(o,s,n.preview.pose,Ml[n.preview.tool])}function Hl(e,t,n,r){let i=Ll(e.info,t),a=e.info.known??{x:0,y:0,width:e.info.width,height:e.info.height},o=[[a.x,a.y],[a.x+a.width,a.y],[a.x,a.y+a.height],[a.x+a.width,a.y+a.height]].map(([e,t])=>i.transformPoint({x:e,y:t})),s=o.map(e=>e.x),c=o.map(e=>e.y),[l,u,d,f]=[Math.min(...s),Math.max(...s),Math.min(...c),Math.max(...c)],p=.94*Math.min(n/(u-l||1),r/(f-d||1));return{x:(l+u)/2,y:(d+f)/2,scale:Math.min(Tl,Math.max(wl,p))}}function Ul({config:e,editing:t}){let n=(0,q.useRef)(null),r=(0,q.useRef)(null),a=(0,q.useRef)(null),o=(0,q.useRef)({}),[s,c]=(0,q.useState)({map:``,global:``,local:``}),[l,u]=(0,q.useState)({state:`waiting`,message:`Connecting…`}),[d,f]=(0,q.useState)(null),[p,m]=(0,q.useState)(!1),h=(0,q.useRef)(null),g=(0,q.useRef)(null),[_,v]=(0,q.useState)(``),y=(0,q.useRef)(null),b=(0,q.useRef)(new Map),x=(0,q.useRef)(null),S=e.mapFrame.trim(),C=w(S,e.robotFrame),T=e=>s[e]&&s[e]!==S?s[e]:``,E={map:w(S,T(`map`)),global:w(S,T(`global`)),local:w(S,T(`local`))},D={};for(let e of Cl)D[e]=T(e)?E[e]?.transform??null:{x:0,y:0,yaw:0};let ee=w(S,_&&_!==S?_:``),O=_&&_!==S?ee?.transform??null:{x:0,y:0,yaw:0},k=(0,q.useRef)({layers:o.current,placements:D,planPlacement:O,robot:C});k.current={layers:o.current,placements:D,planPlacement:O,robot:C};let A=(0,q.useRef)(0),M=(0,q.useCallback)(()=>{A.current||=requestAnimationFrame(()=>{A.current=0;let e=n.current,{planPlacement:t,...i}=k.current;e&&Vl(e,r.current,{...i,plan:g.current&&t?{points:g.current.points,placement:t}:null,goal:h.current,preview:y.current})})},[]);(0,q.useEffect)(M),(0,q.useEffect)(()=>()=>cancelAnimationFrame(A.current),[]);let N=()=>({width:n.current?.clientWidth??1,height:n.current?.clientHeight??1}),P=(0,q.useCallback)(()=>{let{width:e,height:t}=N();for(let n of Cl){let i=o.current[n],s=k.current.placements[n];if(i&&s)return r.current=Hl(i,s,e,t),a.current=n===`map`?`map`:`costmap`,M(),!0}let n=k.current.robot?.transform;return n?(r.current={x:n.x,y:n.y,scale:50},a.current=`robot`,M(),!0):!1},[M]),F=(0,q.useCallback)((e,t,n,r)=>{let i=!0,s=H.subscribeGrid({topic:t,style:n,maxFps:r},{status:(t,n)=>e===`map`&&u({state:t,message:n}),frame:async(t,{meta:n})=>{let r=await createImageBitmap(t);if(!i){r.close();return}let s=n;o.current[e]?.image.close(),o.current[e]={image:r,info:s},c(t=>t[e]===s.frameId?t:{...t,[e]:s.frameId});let l=a.current;(e===`map`?l!==`map`&&l!==`user`:l===null||l===`robot`)&&P(),M()}});return()=>{i=!1,s(),o.current[e]?.image.close(),delete o.current[e],M()}},[P,M]),ne=e.mapTopic.trim();(0,q.useEffect)(()=>{if(!ne)u({state:`error`,message:`No map topic: set one in edit mode`});else return u({state:`waiting`,message:`Connecting…`}),F(`map`,ne,`map`,1)},[ne,F]);let I=e.showGlobalCostmap?e.globalCostmapTopic.trim():``;(0,q.useEffect)(()=>I?F(`global`,I,`costmap`,1):void 0,[I,F]);let re=e.showLocalCostmap?e.localCostmapTopic.trim():``;(0,q.useEffect)(()=>re?F(`local`,re,`costmap`,4):void 0,[re,F]);let ie=e.showPlan?e.planTopic.trim():``;(0,q.useEffect)(()=>{if(!ie)return;let e=H.subscribePath({topic:ie},e=>{g.current=e,v(e.frameId),M()});return()=>{e(),g.current=null,v(``),M()}},[ie,M]),(0,q.useEffect)(()=>{let e=C?.transform;e&&h.current&&Math.hypot(e.x-h.current.x,e.y-h.current.y)<jl&&(h.current=null),p&&e&&r.current?r.current={...r.current,x:e.x,y:e.y}:!r.current&&e&&P()},[C,p,P]),(0,q.useEffect)(()=>{let e=n.current;if(!e)return;let t=new ResizeObserver(M);return t.observe(e),()=>t.disconnect()},[M]);let L=(0,q.useCallback)((e,t)=>{let n=r.current;if(!n)return;let{width:i,height:o}=N(),s=Math.min(Tl,Math.max(wl,n.scale*t));a.current=`user`;let c=Fl(n,i,o).inverse().transformPoint(e);r.current={scale:s,x:c.x-(e.x-i/2)/s,y:c.y+(e.y-o/2)/s},M()},[M]);(0,q.useEffect)(()=>{let e=n.current;if(!e)return;let t=t=>{t.preventDefault();let n=e.getBoundingClientRect();L({x:t.clientX-n.left,y:t.clientY-n.top},Math.exp(-t.deltaY*.0015))};return e.addEventListener(`wheel`,t,{passive:!1}),()=>e.removeEventListener(`wheel`,t)},[L]),(0,q.useEffect)(()=>{if(!d)return;let e=e=>e.key===`Escape`&&f(null);return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[d]);let R=e=>{let t=n.current.getBoundingClientRect();return{x:e.clientX-t.left,y:e.clientY-t.top}},ae=e=>{let{width:t,height:n}=N(),{x:i,y:a}=Fl(r.current,t,n).inverse().transformPoint(e);return{x:i,y:a}},oe=()=>{let[e,t]=[...b.current.values()];return{distance:Math.hypot(e.x-t.x,e.y-t.y),center:{x:(e.x+t.x)/2,y:(e.y+t.y)/2}}},z=(t,n)=>{H.send({type:`pose`,topic:t===`goal`?e.goalTopic.trim():e.poseTopic.trim(),covariance:t===`pose`,frameId:S,...n})?(t===`goal`&&(h.current=n),G(`${t===`goal`?`Goal`:`Pose estimate`} sent: ${Pl(n)}`)):G(`Not connected to the robot`,`error`)},se=e=>{if(!r.current||e.pointerType===`mouse`&&e.button!==0)return;e.currentTarget.setPointerCapture(e.pointerId);let t=R(e);if(b.current.set(e.pointerId,t),b.current.size===2)y.current=null,x.current={kind:`pinch`,...oe()};else if(b.current.size===1&&d){let n=ae(t);x.current={kind:`place`,tool:d,pointerId:e.pointerId,anchor:n,start:t},y.current={tool:d,pose:{x:n.x,y:n.y,yaw:0}}}else b.current.size===1&&(x.current={kind:`pan`});M()},ce=e=>{let t=b.current.get(e.pointerId),n=r.current;if(!t||!n)return;let i=R(e);b.current.set(e.pointerId,i);let o=x.current;if(o?.kind===`place`){let e=ae(i),t=Math.hypot(i.x-o.start.x,i.y-o.start.y)>kl;y.current={tool:o.tool,pose:{...o.anchor,yaw:t?Math.atan2(e.y-o.anchor.y,e.x-o.anchor.x):0}}}else if(o?.kind===`pan`)a.current=`user`,r.current={...n,x:n.x-(i.x-t.x)/n.scale,y:n.y+(i.y-t.y)/n.scale},m(!1);else if(o?.kind===`pinch`&&b.current.size===2){let e=oe();r.current={...n,x:n.x-(e.center.x-o.center.x)/n.scale,y:n.y+(e.center.y-o.center.y)/n.scale},L(e.center,e.distance/(o.distance||1)),x.current={kind:`pinch`,...e}}M()},le=e=>{if(!b.current.delete(e.pointerId))return;let t=x.current;if(t?.kind===`place`&&t.pointerId===e.pointerId){let n=y.current;y.current=null,x.current=null,e.type===`pointerup`&&n&&(z(t.tool,n.pose),f(null))}else b.current.size===1?x.current={kind:`pan`}:b.current.size===0&&(x.current=null);M()},B=C?.transform,ue;if(!S||!e.robotFrame.trim())ue={text:`Set the TF frames in edit mode`,className:`error`};else if(B){let e=C.ageMs>Al;ue={text:`${Pl(B)}${e?` (stale)`:``}`,className:e?`stale`:``}}else ue={text:C?.error??`Locating the robot…`,className:`error`};let V=(e,t,n)=>(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":d===e,title:t,"aria-label":t,onClick:()=>f(t=>t===e?null:e),children:(0,J.jsx)(n,{width:17,height:17})});return(0,J.jsxs)(`div`,{className:`navigation`,children:[(0,J.jsx)(`canvas`,{ref:n,className:d?`placing`:void 0,onPointerDown:se,onPointerMove:ce,onPointerUp:le,onPointerCancel:le}),l.state!==`streaming`&&(0,J.jsxs)(`div`,{className:`nav-overlay ${l.state}`,children:[(0,J.jsx)(Se,{width:28,height:28}),(0,J.jsx)(`span`,{children:l.message})]}),(0,J.jsxs)(`div`,{className:`overlay-toolbar`,children:[V(`pose`,`Set the pose estimate`,j),V(`goal`,`Send a navigation goal`,fe),(0,J.jsx)(`span`,{className:`overlay-separator`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Fit the map`,"aria-label":`Fit the map`,onClick:()=>{m(!1),P()},children:(0,J.jsx)(i,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":p,title:`Follow the robot`,"aria-label":`Follow the robot`,disabled:!B,onClick:()=>m(e=>!e),children:(0,J.jsx)(te,{width:17,height:17})})]}),d&&!t&&(0,J.jsx)(`div`,{className:`nav-hint`,children:d===`goal`?`Press where the robot should go, drag towards where it should face`:`Press where the robot is, drag towards where it faces`}),(0,J.jsx)(`div`,{className:`nav-readout ${ue.className}`,children:ue.text})]})}var Wl=Ve({type:`navigation`,name:`Navigation`,description:`The map, the costmaps and the robot on them; set its pose and send it goals.`,icon:Se,defaultSize:{w:8,h:6},minSize:{w:3,h:3},component:Ul,properties:[{key:`mapTopic`,label:`Map topic`,kind:`topic`,default:`/map`,topicTypes:[`nav_msgs/msg/OccupancyGrid`]},{key:`showGlobalCostmap`,label:`Show the global costmap`,kind:`boolean`,default:!1},{key:`globalCostmapTopic`,label:`Global costmap topic`,kind:`topic`,default:`/global_costmap/costmap`,topicTypes:[`nav_msgs/msg/OccupancyGrid`],visible:e=>e.showGlobalCostmap},{key:`showLocalCostmap`,label:`Show the local costmap`,kind:`boolean`,default:!0},{key:`localCostmapTopic`,label:`Local costmap topic`,kind:`topic`,default:`/local_costmap/costmap`,topicTypes:[`nav_msgs/msg/OccupancyGrid`],visible:e=>e.showLocalCostmap},{key:`showPlan`,label:`Show the planned path`,kind:`boolean`,default:!0},{key:`planTopic`,label:`Plan topic`,kind:`topic`,default:`/plan`,topicTypes:[`nav_msgs/msg/Path`],help:`nav_msgs/Path: Nav2’s planner publishes its plan on /plan`,visible:e=>e.showPlan},{key:`goalTopic`,label:`Goal topic`,kind:`topic`,default:`/goal_pose`,topicTypes:[`geometry_msgs/msg/PoseStamped`],help:`geometry_msgs/PoseStamped, which Nav2’s bt_navigator follows`},{key:`poseTopic`,label:`Pose estimate topic`,kind:`topic`,default:`/initialpose`,topicTypes:[`geometry_msgs/msg/PoseWithCovarianceStamped`],help:`geometry_msgs/PoseWithCovarianceStamped, which AMCL starts from`},{key:`mapFrame`,label:`Map frame`,kind:`string`,default:`map`,help:`The frame the map is drawn in, and the goals and poses are set in`},{key:`robotFrame`,label:`Robot frame`,kind:`string`,default:`base_footprint`,help:`Where the robot is, from TF`}]}),Gl=`modulepreload`,Kl=function(e){return`/`+e},ql={},Jl=function(e){return e.pathname.endsWith(`.css`)},Yl=function(e,t,n){if(t in e)return e[t];let r=n();if(!r){e[t]=void 0;return}let i=r.then(()=>{e[t]=void 0},n=>{throw e[t]=void 0,n});return e[t]=i,i},Xl=function(e,t,n){let r=Promise.resolve();if(t&&t.length>0){let e,i=document.querySelector(`meta[property=csp-nonce]`),a=i?.nonce||i?.getAttribute(`nonce`);function o(e){return Promise.all(e.map(e=>Promise.resolve(e).then(e=>({status:`fulfilled`,value:e}),e=>({status:`rejected`,reason:e}))))}function s(e){return import.meta.resolve?new URL(import.meta.resolve(e)):new URL(e,import.meta.url)}r=o(t.map(t=>{t=Kl(t,n);let r=s(t),i=Jl(r);return Yl(ql,r.href,()=>{if(e===void 0){e={all:new Set,styles:new Set};let t=document.getElementsByTagName(`link`);for(let n=t.length-1;n>=0;n--){let r=t[n];e.all.add(r.href),r.rel===`stylesheet`&&e.styles.add(r.href)}}if((i?e.styles:e.all).has(r.href))return;let t=document.createElement(`link`);if(t.rel=i?`stylesheet`:Gl,i||(t.as=`script`),t.crossOrigin=``,t.href=r.href,a&&t.setAttribute(`nonce`,a),document.head.appendChild(t),i)return new Promise((e,n)=>{t.addEventListener(`load`,e),t.addEventListener(`error`,()=>n(Error(`Unable to preload CSS for ${r}`)))})})}).filter(e=>e!==void 0))}function i(e){let t=new Event(`vite:preloadError`,{cancelable:!0});if(t.payload=e,window.dispatchEvent(t),!t.defaultPrevented)throw e}return r.then(t=>{for(let e of t||[])e.status===`rejected`&&i(e.reason);return e().catch(i)})},Zl=(0,q.lazy)(()=>Xl(()=>import(`./RobotModelView.js`),__vite__mapDeps([0,1,2,3,4])));function Ql({config:e}){return(0,J.jsx)(q.Suspense,{fallback:(0,J.jsx)(`div`,{className:`widget-message`,children:`Loading the 3D view…`}),children:(0,J.jsx)(Zl,{config:e})})}var $l=Ve({type:`robot-model`,name:`Robot Model`,description:`The robot in 3D, its moving joints highlighted, and its TF frames.`,icon:Ae,defaultSize:{w:6,h:5},minSize:{w:3,h:3},component:Ql,properties:[{key:`descriptionTopic`,label:`Robot description topic`,kind:`topic`,default:`/robot_description`,topicTypes:[`std_msgs/msg/String`],help:`The URDF, as robot_state_publisher publishes it. Its package:// meshes come from the robot`},{key:`jointStatesTopic`,label:`Joint states topic`,kind:`topic`,default:`/joint_states`,topicTypes:[`sensor_msgs/msg/JointState`],help:`Where the joints are, and how they move`},{key:`showFrames`,label:`Show the TF frames`,kind:`boolean`,default:!1},{key:`highlightMotion`,label:`Highlight the moving joints`,kind:`boolean`,default:!0,help:`Their links take another colour, with an arrow in the direction of the motion`}]}),eu={x:0,y:0,z:0};function tu(e){return e.x===0&&e.y===0&&e.z===0}function nu(e,t){H.send({type:`twist`,topic:e.topic,stamped:e.stamped,frameId:e.frameId,linear:{x:t.x*e.maxLinear,y:t.y*e.maxLinear},angular:{z:t.z*e.maxAngular}})}function ru({config:e,editing:t}){let n=b()===`open`,[r,i]=(0,q.useState)(eu),a=(0,q.useRef)(eu),o=(0,q.useRef)(e);o.current=e;let s=(0,q.useRef)(!1),c=(0,q.useCallback)(e=>{let t={...a.current,...e};a.current=t,i(t),!tu(t)&&!s.current?(s.current=!0,nu(o.current,t)):tu(t)&&s.current&&(s.current=!1,nu(o.current,eu))},[]);(0,q.useEffect)(()=>{let t=setInterval(()=>s.current&&nu(o.current,a.current),1e3/Math.min(50,Math.max(1,e.rate)));return()=>clearInterval(t)},[e.rate]);let{topic:l,stamped:u}=e;(0,q.useEffect)(()=>()=>{s.current&&(s.current=!1,nu({...o.current,topic:l,stamped:u},eu))},[l,u]);let d=t||!n,{maxLinear:f,maxAngular:p}=e;return(0,J.jsxs)(`div`,{className:`teleop`,children:[(0,J.jsx)(`div`,{className:`teleop-pads${e.omnidirectional?` two`:``}`,children:e.omnidirectional?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(Ue,{axes:`xy`,label:`x · y`,disabled:d,onMove:(e,t)=>c({x:t,y:-e})}),(0,J.jsx)(Ue,{axes:`x`,label:`z`,disabled:d,onMove:e=>c({z:-e})})]}):(0,J.jsx)(Ue,{axes:`xy`,label:`x · z`,disabled:d,onMove:(e,t)=>c({x:t,y:0,z:-e})})}),(0,J.jsx)(`div`,{className:`teleop-readout`,children:n||t?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`span`,{children:[`x `,(r.x*f).toFixed(3)]}),e.omnidirectional&&(0,J.jsxs)(`span`,{children:[`y `,(r.y*f).toFixed(3)]}),(0,J.jsxs)(`span`,{children:[`z `,(r.z*p).toFixed(3)]}),(0,J.jsx)(`span`,{className:`teleop-topic`,children:e.topic})]}):(0,J.jsx)(`span`,{className:`offline`,children:`Disconnected`})})]})}var iu=Ve({type:`teleop`,name:`Teleop`,description:`Drive the robot with on-screen pads, publishing velocity commands.`,icon:d,defaultSize:{w:6,h:4},minSize:{w:3,h:3},component:ru,properties:[{key:`topic`,label:`Topic`,kind:`topic`,default:`cmd_vel`,topicTypes:[`geometry_msgs/msg/Twist`,`geometry_msgs/msg/TwistStamped`],help:`With twist_mux, one of its inputs, above autonomous navigation and below the joysticks`},{key:`omnidirectional`,label:`Omnidirectional`,kind:`boolean`,default:!1,help:`Two pads: x and y, and z. Otherwise one: x and z`},{key:`stamped`,label:`TwistStamped`,kind:`boolean`,default:!1,help:`Publish geometry_msgs/TwistStamped instead of Twist`},{key:`frameId`,label:`Frame id`,kind:`string`,default:`base_link`,visible:e=>e.stamped},{key:`maxLinear`,label:`Max linear speed (m/s)`,kind:`number`,default:.2,min:0,step:.01},{key:`maxAngular`,label:`Max angular speed (rad/s)`,kind:`number`,default:.5,min:0,step:.01},{key:`rate`,label:`Rate (Hz)`,kind:`number`,default:10,min:1,max:50,step:1,help:`How often the command is published while a pad is held`}]}),au=(0,q.lazy)(()=>Xl(()=>import(`./TerminalView.js`),__vite__mapDeps([5,1,2,3,4,6,7,8])));function ou({config:e,instance:t,panelId:n,editing:r}){return(0,J.jsx)(q.Suspense,{fallback:(0,J.jsx)(`div`,{className:`widget-message`,children:`Loading the terminal…`}),children:(0,J.jsx)(au,{config:e,panelId:n,widgetId:t.id,editing:r})})}var su=Ve({type:`terminal`,name:`Terminal`,description:`A shell on the robot, or a command. On touch screens, the keys phones lack: Esc, Tab, Ctrl, Alt, arrows.`,icon:ue,defaultSize:{w:8,h:6},minSize:{w:3,h:3},component:ou,properties:[{key:`command`,label:`Command`,kind:`text`,default:``,placeholder:`htop`,help:`Run instead of a shell, by the login shell: e.g. htop, or tmux new -A -s robot for one session that every page shares. Empty: the shell`},{key:`folder`,label:`Folder`,kind:`string`,default:`~`,placeholder:`~/ros2_ws`,help:`Where it starts: /…, ~/… or package://<package>/…`},{key:`fontSize`,label:`Text size`,kind:`number`,default:13,min:7,max:32,step:1,help:`In pixels. Each device changes it with the toolbar, or by pinching`},{key:`theme`,label:`Colours`,kind:`select`,default:`auto`,options:[{value:`auto`,label:`The page’s, dark or light`},{value:`dark`,label:`Dark`},{value:`light`,label:`Light`}]},{key:`extraKeys`,label:`Extra keys`,kind:`select`,default:`touch`,options:[{value:`touch`,label:`On touch screens`},{value:`always`,label:`Always`},{value:`never`,label:`Never`}],help:`Keys the on-screen keyboard lacks, under the terminal. Ctrl, Alt and Shift apply to the next key, of the row or of the keyboard: tap twice, or hold, to keep them. Swiping up on a key types what its corner shows`},{key:`keys`,label:`Extra keys’ layout`,kind:`text`,default:Je,help:`A line per row, keys separated by spaces: ESC TAB CTRL ALT SHIFT HOME END PGUP PGDN UP DOWN LEFT RIGHT INS DEL BKSP ENTER SPACE F1…F12 KEYBOARD PASTE, or what to type (~, |, ros2). What swiping up types follows a colon: -:|`,visible:e=>e.extraKeys!==`never`},{key:`fullScreenTyping`,label:`Full screen while typing`,kind:`boolean`,default:!0,help:`On touch screens: while the on-screen keyboard is open, the terminal fills the screen above it, the extra keys right above it`}]});function cu(e,t){return typeof t==typeof e.default&&(e.kind!==`select`||e.options.some(e=>e.value===t))&&(typeof t!=`number`||Number.isFinite(t))}var lu=class{registered;defaults=new Map;current;constructor(e){this.registered=e.map(e=>({definition:e,plugin:null})),this.current=this.registered}registerPlugin(e,t){let n=[];for(let r of t.widgets??[]){let t=this.registered.find(e=>e.definition.type===r.type);t?n.push(`its widget type "${r.type}" is already ${t.plugin?`${t.plugin}'s`:`Tassello's`}`):this.registered=[...this.registered,{definition:r,plugin:e}]}for(let[e,r]of Object.entries(t.defaults??{})){let t=this.defaults.get(e)??new Map;for(let[i,a]of Object.entries(r)){t.set(i,a);let r=this.registered.find(t=>t.definition.type===e)?.definition,o=r?.properties.find(e=>e.key===i);r&&(!o||!cu(o,a))&&n.push(`its default of ${e}.${i} is not one of the property's values`)}this.defaults.set(e,t)}return this.current=this.registered.map(e=>({...e,definition:this.withDefaults(e.definition)})),n}entries(){return this.current}definition(e){return this.current.find(t=>t.definition.type===e)?.definition}withDefaults(e){let t=this.defaults.get(e.type);return t?{...e,properties:e.properties.map(e=>t.has(e.key)&&cu(e,t.get(e.key))?{...e,default:t.get(e.key)}:e)}:e}};function uu(e,t){let n={};for(let r of e.properties){let e=t[r.key];n[r.key]=cu(r,e)?e:r.default}return n}var du=new lu([iu,Wl,$l,ut,Ii,al,ji,Y,Ti,mi,Sl,Ka,rl,su]);function fu(e,t){return du.registerPlugin(e,t)}function pu(){return du.entries()}function mu(e){return du.definition(e)}function hu(e,t){return e.x<t.x+t.w&&t.x<e.x+e.w&&e.y<t.y+t.h&&t.y<e.y+e.h}function gu(e,t,n){return e.x>=0&&e.y>=0&&!t.some(t=>t.id!==n&&hu(e,t))}function _u(e){return{cols:Math.max(0,...e.map(e=>e.x+e.w)),rows:Math.max(0,...e.map(e=>e.y+e.h))}}function vu(e,t,n){let{rows:r}=_u(e);for(let i=0;i<=r;i++)for(let r=0;r+t.w<=Math.max(n,t.w);r++){let n={x:r,y:i,...t};if(gu(n,e))return n}return{x:0,y:r,...t}}function yu(e,t=64){return{left:e.x*t+4,top:e.y*t+4,width:e.w*t-8,height:e.h*t-8}}var bu={desktop:{label:`Desktop`,columns:null,previewWidth:null},tablet:{label:`Tablet`,columns:12,previewWidth:820},phone:{label:`Phone`,columns:6,previewWidth:390}};function xu(e){return e<640?`phone`:e<1100?`tablet`:`desktop`}function Su(e,t){return e.x<t.x+t.w&&t.x<e.x+e.w&&e.y<t.y+t.h&&t.y<e.y+e.h}function Cu(e,t,n,r){if(e.x<0||e.y<0||n!==null&&e.x+e.w>n)return!1;for(let[n,i]of t.rects)if(n!==r&&Su(e,i))return!1;return!0}function wu(e,t,n,r,i){for(let a=i;;a++)for(let i=0;i+t<=r;i++){let r={x:i,y:a,w:t,h:n};if(![...e.values()].some(e=>Su(r,e)))return r}}function Tu(e,t,n){let r=bu[t].columns;if(r===null)return{rects:new Map(e.widgets.map(e=>[e.id,{x:e.x,y:e.y,w:e.w,h:e.h}])),hidden:[],custom:!0};let i=e.layouts?.[t],a=new Set(i?.hidden??[]),o=new Map;for(let t of e.widgets){let e=i?.rects[t.id];if(e&&!a.has(t.id)){let n=Math.min(e.w,r);o.set(t.id,{x:Math.min(e.x,r-n),y:e.y,w:n,h:e.h})}}let s=Math.max(0,...[...o.values()].map(e=>e.y+e.h)),c=e.widgets.filter(e=>!a.has(e.id)&&!o.has(e.id)).sort((e,t)=>e.y-t.y||e.x-t.x);for(let e of c){let t=wu(o,Math.min(e.w,r),e.w>r?Math.max(n(e.type).h,Math.round(e.h*r/e.w)):e.h,r,s);o.set(e.id,t),s=t.y}return{rects:o,hidden:[...a],custom:Object.keys(i?.rects??{}).length>0}}function Eu(e,t,n){return{...e,layouts:{...e.layouts,[t]:n}}}function Du(e,t,n,r,i){if(t===`desktop`)return{...e,widgets:e.widgets.map(e=>e.id===r?{...e,...i}:e)};let a=Object.fromEntries(n.rects);return a[r]=i,Eu(e,t,{rects:a,hidden:n.hidden})}function Ou(e,t,n,r,i){return Eu(e,t,{rects:n.custom?Object.fromEntries([...n.rects].filter(([e])=>e!==r)):{},hidden:i?[...new Set([...n.hidden,r])]:n.hidden.filter(e=>e!==r)})}function ku(e,t){let{[t]:n,...r}=e.layouts??{},{layouts:i,...a}=e;return Object.keys(r).length>0?{...a,layouts:r}:a}var Au=4,ju=4,Mu=100,Nu=32;function Pu(e){let[t,n]=(0,q.useState)({width:0,height:0});return(0,q.useEffect)(()=>{let t=e.current;if(!t)return;let r=new ResizeObserver(()=>n({width:t.clientWidth,height:t.clientHeight}));return r.observe(t),()=>r.disconnect()},[e]),t}function Fu({panel:e,device:t,layout:n,previewWidth:r,editing:i,selectedId:a,onSelect:o,onPlace:s,onRemove:c,onHide:l,onVisibleColumns:u}){let d=(0,q.useRef)(null),f=Pu(d),[p,m]=(0,q.useState)(null),h=bu[t].columns,g=(r??f.width)-32,_=h===null?64:Math.max(Nu,Math.floor(g/h)),v=h??Math.max(1,Math.floor(g/_)),y=Math.max(1,Math.floor((f.height-32)/_));(0,q.useEffect)(()=>u?.(v),[v,u]);let b=[...n.rects.values()],x=_u(p?[...b,p.rect]:b),S=h??(i?Math.max(x.cols+Au,v):x.cols),C=i?Math.max(x.rows+Au,y):x.rows,w=(e,t,r)=>{let a=n.rects.get(t.id);if(!i||e.button!==0||p||!a)return;e.stopPropagation(),e.currentTarget.setPointerCapture(e.pointerId);let s=d.current;m({id:t.id,kind:r,pointerId:e.pointerId,startX:e.clientX,startY:e.clientY,startScrollLeft:s.scrollLeft,startScrollTop:s.scrollTop,origin:a,rect:a,dx:0,dy:0,moved:!1}),o(t.id)},T=t=>{if(!p||t.pointerId!==p.pointerId)return;let n=d.current,r=t.clientX-p.startX+n.scrollLeft-p.startScrollLeft,i=t.clientY-p.startY+n.scrollTop-p.startScrollTop,{origin:a}=p,o;if(p.kind===`move`){let e=Math.max(0,a.x+Math.round(r/_));o={...a,x:h===null?e:Math.min(h-a.w,e),y:Math.max(0,a.y+Math.round(i/_))}}else{let t=mu(e.widgets.find(e=>e.id===p.id)?.type??``)?.minSize,n=h===null?Mu:h-a.x;o={...a,w:Math.min(n,Math.max(Math.min(t?.w??1,n),a.w+Math.round(r/_))),h:Math.min(Mu,Math.max(t?.h??1,a.h+Math.round(i/_)))}}m({...p,dx:r,dy:i,rect:o,moved:p.moved||Math.hypot(r,i)>ju})},E=e=>{if(!p||e.pointerId!==p.pointerId)return;let{id:t,rect:r,origin:i,moved:a}=p;m(null);let o=r.x!==i.x||r.y!==i.y||r.w!==i.w||r.h!==i.h;a&&o&&Cu(r,n,h,t)&&s(t,r)},D=!p||Cu(p.rect,n,h,p.id);return(0,J.jsx)(`div`,{ref:d,className:`board-scroll${h===null?``:` columns`}`,onPointerDown:e=>{i&&!e.target.closest(`.widget`)&&o(null)},children:(0,J.jsxs)(`div`,{className:`board${i?` editing`:``}${r?` preview`:``}`,style:{width:S*_,height:C*_,"--cell":`${_}px`},children:[p?.moved&&(0,J.jsx)(`div`,{className:`drop-target${D?``:` invalid`}`,style:yu(p.rect,_)}),e.widgets.map(r=>{let o=n.rects.get(r.id);if(!o)return null;let s=p?.id===r.id&&p.moved?p:null,u=yu(o,_);s?.kind===`move`?u.transform=`translate(${s.dx}px, ${s.dy}px)`:s?.kind===`resize`&&(u.width=Math.max(_-8,o.w*_-8+s.dx),u.height=Math.max(_-8,o.h*_-8+s.dy));let d=mu(r.type),f=d?.icon??Ee;return(0,J.jsxs)(`div`,{className:[`widget`,i&&`editing`,a===r.id&&`selected`,s&&`dragging`].filter(Boolean).join(` `),style:u,onPointerDown:e=>w(e,r,`move`),onPointerMove:T,onPointerUp:E,onPointerCancel:E,children:[(0,J.jsx)(Iu,{instance:r,panelId:e.id,editing:i}),i&&(0,J.jsxs)(`div`,{className:`widget-chrome`,children:[(0,J.jsxs)(`span`,{className:`widget-tag`,children:[(0,J.jsx)(f,{width:14,height:14}),d?.name??r.type]}),(0,J.jsxs)(`div`,{className:`widget-buttons`,children:[l&&(0,J.jsx)(`button`,{type:`button`,className:`widget-button`,title:`Hide on ${bu[t].label.toLowerCase()}s`,"aria-label":`Hide on ${bu[t].label.toLowerCase()}s`,onPointerDown:e=>e.stopPropagation(),onClick:()=>l(r.id),children:(0,J.jsx)(Me,{width:14,height:14})}),(0,J.jsx)(`button`,{type:`button`,className:`widget-button remove`,title:`Remove widget`,"aria-label":`Remove widget`,onPointerDown:e=>e.stopPropagation(),onClick:()=>c(r.id),children:(0,J.jsx)(Ne,{width:14,height:14})})]}),(0,J.jsx)(`div`,{className:`resize-handle`,title:`Resize`,onPointerDown:e=>w(e,r,`resize`)})]})]},r.id)})]})})}var Iu=(0,q.memo)(function({instance:e,panelId:t,editing:n}){let r=mu(e.type),i=(0,q.useMemo)(()=>r?uu(r,e.config):{},[r,e.config]);return(0,J.jsxs)(`div`,{className:`widget-card`,children:[e.title&&(0,J.jsx)(`div`,{className:`widget-title`,children:e.title}),(0,J.jsx)(`div`,{className:`widget-body`,children:r?(0,J.jsx)(Lu,{resetKey:i,children:(0,J.jsx)(r.component,{config:i,instance:e,panelId:t,editing:n})}):(0,J.jsxs)(`div`,{className:`widget-message`,children:[`Unknown widget type “`,e.type,`”: is the plugin that adds it installed?`]})})]})}),Lu=class extends q.Component{state={error:null};static getDerivedStateFromError(e){return{error:e}}componentDidUpdate(e){this.state.error&&e.resetKey!==this.props.resetKey&&this.setState({error:null})}render(){return this.state.error?(0,J.jsxs)(`div`,{className:`widget-message error`,children:[`This widget failed: `,this.state.error.message]}):this.props.children}};function Ru({widget:e,onChange:t,onDuplicate:n,onRemove:r,onClose:i}){let a=mu(e.type),o=a?uu(a,e.config):e.config,s=a?.icon??Ee,c=(n,r)=>t({...e,config:{...e.config,[n]:r}});return(0,J.jsxs)(`aside`,{className:`properties`,"aria-label":`Widget properties`,children:[(0,J.jsxs)(`header`,{className:`properties-header`,children:[(0,J.jsx)(s,{}),(0,J.jsx)(`h2`,{children:a?.name??e.type}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Close`,onClick:i,children:(0,J.jsx)(B,{})})]}),(0,J.jsxs)(`div`,{className:`properties-body`,children:[(0,J.jsx)(zu,{label:`Title`,help:`Shown above the widget, if set`,children:n=>(0,J.jsx)(Vu,{id:n,value:e.title,onCommit:n=>t({...e,title:n})})}),a?.properties.filter(e=>!e.visible||e.visible(o)).map(e=>(0,J.jsx)(Bu,{property:e,value:o[e.key],onChange:t=>c(e.key,t)},e.key)),(0,J.jsxs)(`p`,{className:`properties-meta`,children:[e.w,`×`,e.h,` cells at column `,e.x+1,`, row `,e.y+1]})]}),(0,J.jsxs)(`footer`,{className:`properties-footer`,children:[(0,J.jsxs)(`button`,{type:`button`,className:`button`,onClick:n,children:[(0,J.jsx)(N,{}),` Duplicate`]}),(0,J.jsxs)(`button`,{type:`button`,className:`button danger`,onClick:r,children:[(0,J.jsx)(Ne,{}),` Remove`]})]})]})}function zu({label:e,help:t,children:n}){let r=(0,q.useId)();return(0,J.jsxs)(`div`,{className:`field`,children:[(0,J.jsx)(`label`,{className:`field-label`,htmlFor:r,children:e}),n(r),t&&(0,J.jsx)(`p`,{className:`field-help`,children:t})]})}function Bu({property:e,value:t,onChange:n}){return e.kind===`boolean`?(0,J.jsxs)(`div`,{className:`field`,children:[(0,J.jsxs)(`label`,{className:`toggle`,children:[(0,J.jsx)(`input`,{type:`checkbox`,checked:t===!0,onChange:e=>n(e.target.checked)}),(0,J.jsx)(`span`,{className:`toggle-switch`,"aria-hidden":`true`}),(0,J.jsx)(`span`,{className:`field-label`,children:e.label})]}),e.help&&(0,J.jsx)(`p`,{className:`field-help`,children:e.help})]}):(0,J.jsx)(zu,{label:e.label,help:e.help,children:r=>{switch(e.kind){case`number`:return(0,J.jsx)(Vu,{id:r,type:`number`,min:e.min,max:e.max,step:e.step??`any`,value:String(t),onCommit:t=>{let r=Number(t);t.trim()&&Number.isFinite(r)&&n(Math.min(e.max??1/0,Math.max(e.min??-1/0,r)))}});case`select`:return(0,J.jsx)(`select`,{id:r,value:String(t),onChange:e=>n(e.target.value),children:e.options.map(e=>(0,J.jsx)(`option`,{value:e.value,children:e.label},e.value))});case`color`:return(0,J.jsxs)(`div`,{className:`color-field`,children:[(0,J.jsx)(`input`,{id:r,type:`color`,value:String(t),onChange:e=>n(e.target.value)}),(0,J.jsx)(`code`,{children:String(t)})]});case`text`:return(0,J.jsx)(Vu,{id:r,multiline:!0,value:String(t),placeholder:e.placeholder,onCommit:n});case`image`:case`behavior-tree`:return(0,J.jsx)(wt,{id:r,kind:e.kind,value:String(t),placeholder:e.placeholder,onCommit:n,children:e=>(0,J.jsx)(Vu,{...e})});case`topic`:return(0,J.jsx)(Hu,{id:r,value:String(t),types:e.topicTypes,placeholder:e.placeholder,onCommit:n});default:return(0,J.jsx)(Vu,{id:r,value:String(t),placeholder:e.placeholder,onCommit:n})}}})}function Vu({value:e,onCommit:t,multiline:n=!1,...r}){let[i,a]=(0,q.useState)(e);(0,q.useEffect)(()=>a(e),[e]);let o=()=>i!==e&&t(i),s={...r,value:i,spellCheck:!1,onBlur:o,onChange:e=>a(e.target.value)};return n?(0,J.jsx)(`textarea`,{...s,rows:4,onKeyDown:t=>{t.key===`Enter`&&(t.ctrlKey||t.metaKey)?o():t.key===`Escape`&&a(e)}}):(0,J.jsx)(`input`,{...s,onKeyDown:t=>{t.key===`Enter`?o():t.key===`Escape`&&a(e)}})}function Hu({id:e,value:t,types:n,placeholder:r,onCommit:i}){let[a,o]=(0,q.useState)([]),s=`${e}-topics`,c=()=>He.listTopics().then(o).catch(()=>o([])),l=a.filter(e=>e.types.some(e=>n.includes(e)));return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(Vu,{id:e,value:t,placeholder:r,list:s,onFocus:c,onCommit:i}),(0,J.jsx)(`datalist`,{id:s,children:l.map(e=>(0,J.jsx)(`option`,{value:e.name,children:e.types.join(`, `)},e.name))})]})}function Uu(){let e=new Map;for(let t of pu())e.set(t.plugin,[...e.get(t.plugin)??[],t]);return[...e].map(([e,t])=>({plugin:e,entries:t}))}function Wu({onAdd:e,onClose:t}){let n=Uu();return(0,J.jsx)(Ge,{title:`Add a widget`,onClose:t,wide:!0,children:(0,J.jsx)(`div`,{className:`palette-scroll`,children:n.map(({plugin:t,entries:r})=>(0,J.jsxs)(`section`,{children:[n.length>1&&(0,J.jsx)(`h3`,{className:`palette-heading`,children:t??`Tassello`}),(0,J.jsx)(`div`,{className:`palette`,children:r.map(({definition:t})=>(0,J.jsxs)(`button`,{type:`button`,className:`palette-item`,onClick:()=>e(t),children:[(0,J.jsx)(`span`,{className:`palette-icon`,children:(0,J.jsx)(t.icon,{width:24,height:24})}),(0,J.jsxs)(`span`,{className:`palette-text`,children:[(0,J.jsx)(`strong`,{children:t.name}),(0,J.jsx)(`span`,{children:t.description})]})]},t.type))})]},t??``))})})}var Gu=500,Ku=18,qu={desktop:Fe,tablet:Ie,phone:ve},Ju=e=>mu(e)?.minSize??{w:1,h:1};function Yu(){let[e,t]=(0,q.useState)(()=>xu(window.innerWidth));return(0,q.useEffect)(()=>{let e=()=>t(xu(window.innerWidth));return window.addEventListener(`resize`,e),()=>window.removeEventListener(`resize`,e)},[]),e}function Xu(){return decodeURIComponent(location.hash.replace(/^#\/?/,``))}function Zu(e,t=!1){let n=`#/${encodeURIComponent(e)}`;t?(history.replaceState(null,``,n),window.dispatchEvent(new HashChangeEvent(`hashchange`))):location.hash=n}function Qu(e){return`${e.replace(/[^A-Za-z0-9_-]+/g,`-`).slice(-48)}-${Math.random().toString(36).slice(2,8)}`}function $u(e){return e instanceof Error?e.message:String(e)}function ed(){let[e,t]=(0,q.useState)(`saved`),n=(0,q.useRef)(null),r=(0,q.useRef)(null),i=(0,q.useRef)(Promise.resolve()),a=(0,q.useCallback)(()=>{r.current&&=(clearTimeout(r.current),null);let e=n.current;return n.current=null,e&&(i.current=i.current.then(()=>He.savePanel(e).then(()=>{n.current||t(`saved`)},n=>{t(`failed`),G(`Could not save “${e.name}”: ${$u(n)}`,`error`)}))),i.current},[]),o=(0,q.useCallback)(e=>{n.current=e,t(`saving`),r.current&&clearTimeout(r.current),r.current=setTimeout(a,Gu)},[a]);return(0,q.useEffect)(()=>{let e=()=>{let e=n.current;e&&(n.current=null,fetch(`/api/panels/${encodeURIComponent(e.id)}`,{method:`PUT`,headers:{"Content-Type":`application/json`},body:JSON.stringify(e),keepalive:!0}))};return window.addEventListener(`pagehide`,e),()=>window.removeEventListener(`pagehide`,e)},[]),[e,(0,q.useMemo)(()=>({schedule:o,flush:a,isPending:()=>n.current!==null}),[o,a])]}function td(){let e=b(),t=Ke(),[n,r]=ed(),[i,a]=(0,q.useState)(null),[o,c]=(0,q.useState)(Xu),u=(0,q.useRef)(o);u.current=o;let[d,f]=(0,q.useState)(null),p=(0,q.useRef)(null),[m,h]=(0,q.useState)(null),[g,_]=(0,q.useState)(`view`),[v,y]=(0,q.useState)(null),[x,S]=(0,q.useState)(!1),[C,w]=(0,q.useState)(!1),T=(0,q.useRef)([]),[E,D]=(0,q.useState)(!1),ee=(0,q.useRef)(12),O=(0,q.useCallback)(e=>{ee.current=e},[]),k=g===`edit`,A=Yu(),[j,te]=(0,q.useState)(null),N=k?j??A:A,P=(0,q.useRef)(N);P.current=N;let F=(0,q.useMemo)(()=>d?Tu(d,N,Ju):null,[d,N]),I=(0,q.useCallback)(e=>{p.current=e,f(e)},[]),ie=(0,q.useCallback)(async()=>{try{a(await He.listPanels())}catch(e){G(`Could not list the panels: ${$u(e)}`,`error`)}},[]),L=(0,q.useCallback)(e=>{let t=p.current;if(!t)return;let n=e(t);T.current=[...T.current.slice(-49),t],D(!0),I(n),r.schedule(n)},[r,I]),R=(0,q.useCallback)(()=>{let e=T.current.pop();D(T.current.length>0),e&&(I(e),r.schedule(e),y(t=>t&&e.widgets.some(e=>e.id===t)?t:null))},[r,I]);(0,q.useEffect)(()=>{let e=()=>c(Xu());return window.addEventListener(`hashchange`,e),()=>window.removeEventListener(`hashchange`,e)},[]),(0,q.useEffect)(()=>{e!==`closed`&&ie()},[ie,e]),(0,q.useEffect)(()=>{i&&i.length>0&&!i.some(e=>e.id===o)&&Zu(i[0].id,!0)},[i,o]);let ae=(0,q.useCallback)(async e=>{try{let t=await He.getPanel(e);e===u.current&&(I(t),h(null))}catch(t){e===u.current&&h($u(t))}},[I]),oe=i?.some(e=>e.id===o)??!1;(0,q.useEffect)(()=>{if(!oe)return;let e=!0;return r.flush().then(()=>{e&&(T.current=[],D(!1),y(null),ae(o))}),()=>{e=!1}},[o,oe,ae,r]),(0,q.useEffect)(()=>H.onServerMessage(e=>{e.type===`error`&&G(e.message,`error`),e.type===`panels.changed`&&e.origin!==H.clientId&&(ie(),e.id===p.current?.id&&!e.deleted&&!r.isPending()&&ae(e.id))}),[ie,ae,r]);let z=async e=>{e===`view`&&(y(null),te(null),await r.flush()),_(e),w(!1)},se=e=>{S(!1);let t=p.current;if(!t)return;let n=P.current===`desktop`?ee.current:Ku,r=vu(t.widgets,e.defaultSize,n),i={id:Qu(e.type),type:e.type,title:``,...r,config:{}};L(e=>({...e,widgets:[...e.widgets,i]})),y(i.id)},ce=(0,q.useCallback)((e,t)=>L(n=>Du(n,P.current,Tu(n,P.current,Ju),e,t)),[L]),le=(0,q.useCallback)((e,t=!0)=>{let n=P.current;n!==`desktop`&&(L(r=>Ou(r,n,Tu(r,n,Ju),e,t)),y(t=>t===e?null:t))},[L]),B=(0,q.useCallback)(e=>{let t=p.current?.widgets.find(t=>t.id===e);if(L(t=>({...t,widgets:t.widgets.filter(t=>t.id!==e)})),y(t=>t===e?null:t),t){let e=t.title||mu(t.type)?.name||t.type;G(`Removed “${e}”`,`info`,{label:`Undo`,run:R})}},[L,R]),ue=e=>{let t=p.current,n=t?.widgets.find(t=>t.id===e);if(!t||!n)return;let r=P.current===`desktop`?ee.current:Ku,i=vu(t.widgets,{w:n.w,h:n.h},r),a={...n,...i,id:Qu(n.type),config:structuredClone(n.config)};L(e=>({...e,widgets:[...e.widgets,a]})),y(a.id)},V=async()=>{w(!1);let e=await t.prompt({title:`New panel`,label:`Name`,confirmLabel:`Create`});if(e)try{let t=await He.createPanel({name:e,widgets:[]});await ie(),Zu(t.id),_(`edit`)}catch(e){G(`Could not create the panel: ${$u(e)}`,`error`)}},de=async()=>{w(!1);let e=p.current;if(!e)return;let n=await t.prompt({title:`Rename panel`,label:`Name`,initial:e.name,confirmLabel:`Rename`});n&&n!==e.name&&(L(e=>({...e,name:n})),await r.flush(),await ie())},fe=async()=>{w(!1);let e=p.current;if(e)try{await r.flush();let t=await He.createPanel({name:`${e.name} (copy)`,widgets:e.widgets});await ie(),Zu(t.id)}catch(e){G(`Could not duplicate the panel: ${$u(e)}`,`error`)}},pe=async()=>{w(!1);let e=p.current;if(e&&await t.confirm({title:`Delete “${e.name}”?`,message:`The panel and its widgets are deleted for good.`,confirmLabel:`Delete`,danger:!0}))try{await r.flush(),await He.deletePanel(e.id),I(null),await ie()}catch(e){G(`Could not delete the panel: ${$u(e)}`,`error`)}};(0,q.useEffect)(()=>{if(!k)return;let e=e=>{if(e.target.closest(`input, textarea, select, [role="dialog"]`))return;if(e.key===`z`&&(e.ctrlKey||e.metaKey)&&!e.shiftKey){e.preventDefault(),R();return}let t=p.current?.widgets.find(e=>e.id===v);if(!t)return;if(e.key===`Delete`||e.key===`Backspace`){e.preventDefault(),B(t.id);return}let n={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]}[e.key],r=Tu(p.current,P.current,Ju),i=r.rects.get(t.id);if(n&&i){e.preventDefault();let a={...i,x:i.x+n[0],y:i.y+n[1]};Cu(a,r,bu[P.current].columns,t.id)&&ce(t.id,a)}};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[k,v,R,B,ce]);let me=k?d?.widgets.find(e=>e.id===v):void 0,he={connecting:`Connecting…`,open:`Connected to ${H.hostname}`,closed:`Disconnected, reconnecting…`}[e];return(0,J.jsxs)(`div`,{className:`app${k?` editing`:``}`,children:[(0,J.jsxs)(`header`,{className:`topbar`,children:[(0,J.jsxs)(`div`,{className:`brand`,title:he,children:[(0,J.jsx)(re,{width:22,height:22}),(0,J.jsx)(`span`,{className:`brand-name`,children:H.hostname||`Tassello`}),(0,J.jsx)(`span`,{className:`connection-dot ${e}`,"aria-label":he})]}),i&&i.length>0&&(0,J.jsx)(`select`,{className:`panel-select`,"aria-label":`Panel`,value:o,onChange:e=>Zu(e.target.value),children:i.map(e=>(0,J.jsx)(`option`,{value:e.id,children:e.name},e.id))}),(0,J.jsx)(`div`,{className:`topbar-spacer`}),k&&d&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`span`,{className:`save-state ${n}`,children:{saved:`Saved`,saving:`Saving…`,failed:`Not saved`}[n]}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,title:`Undo (Ctrl+Z)`,"aria-label":`Undo`,disabled:!E,onClick:R,children:(0,J.jsx)(l,{})}),(0,J.jsxs)(`button`,{type:`button`,className:`button primary`,"aria-label":`Add widget`,onClick:()=>S(!0),children:[(0,J.jsx)(ne,{}),` `,(0,J.jsx)(`span`,{className:`hide-narrow`,children:`Add widget`})]})]}),k&&(0,J.jsx)(`div`,{className:`mode-switch device-switch`,role:`group`,"aria-label":`Layout of`,children:Object.keys(bu).map(e=>{let t=qu[e];return(0,J.jsx)(`button`,{type:`button`,"aria-pressed":N===e,title:`The ${bu[e].label.toLowerCase()} layout`,"aria-label":`${bu[e].label} layout`,onClick:()=>{te(e),y(null)},children:(0,J.jsx)(t,{})},e)})}),k&&(0,J.jsxs)(`div`,{className:`menu`,children:[(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Panel actions`,"aria-expanded":C,onClick:()=>w(e=>!e),children:(0,J.jsx)(M,{})}),C&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`div`,{className:`menu-backdrop`,onPointerDown:()=>w(!1)}),(0,J.jsxs)(`div`,{className:`menu-list`,role:`menu`,children:[(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:V,children:`New panel…`}),d&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:de,children:`Rename panel…`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:fe,children:`Duplicate panel`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,className:`danger`,onClick:pe,children:`Delete panel…`})]})]})]})]}),(0,J.jsxs)(`div`,{className:`mode-switch`,role:`group`,"aria-label":`Mode`,children:[(0,J.jsxs)(`button`,{type:`button`,"aria-label":`View`,title:`View`,"aria-pressed":!k,onClick:()=>z(`view`),children:[(0,J.jsx)(s,{}),` `,(0,J.jsx)(`span`,{className:`hide-narrow`,children:`View`})]}),(0,J.jsxs)(`button`,{type:`button`,"aria-label":`Edit`,title:`Edit`,"aria-pressed":k,onClick:()=>z(`edit`),children:[(0,J.jsx)(De,{}),` `,(0,J.jsx)(`span`,{className:`hide-narrow`,children:`Edit`})]})]})]}),(0,J.jsx)(`main`,{className:`workspace`,children:i===null?(0,J.jsx)(`div`,{className:`empty-state`,children:`Loading…`}):i.length===0?(0,J.jsxs)(`div`,{className:`empty-state`,children:[(0,J.jsx)(`h1`,{children:`No panels yet`}),(0,J.jsx)(`p`,{children:`A panel is a board of widgets: create one for each task, e.g. teleoperation or navigation.`}),(0,J.jsxs)(`button`,{type:`button`,className:`button primary`,onClick:V,children:[(0,J.jsx)(ne,{}),` Create a panel`]})]}):m?(0,J.jsxs)(`div`,{className:`empty-state`,children:[(0,J.jsx)(`h1`,{children:`Cannot open this panel`}),(0,J.jsx)(`p`,{children:m})]}):d?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`div`,{className:`board-column`,children:[k&&N!==`desktop`&&F&&(0,J.jsxs)(`div`,{className:`layout-bar`,children:[(0,J.jsxs)(`span`,{children:[(0,J.jsxs)(`strong`,{children:[bu[N].label,` layout`]}),F.custom?` · arranged for this device`:` · automatic, from the desktop’s: moving a widget arranges it for this device`]}),F.hidden.length>0&&(0,J.jsxs)(`span`,{className:`layout-hidden`,children:[`Hidden:`,F.hidden.map(e=>{let t=d.widgets.find(t=>t.id===e);return(0,J.jsxs)(`button`,{type:`button`,className:`layout-chip`,title:`Show it again`,onClick:()=>le(e,!1),children:[t?.title||mu(t?.type??``)?.name||e,` +`]},e)})]}),(F.custom||F.hidden.length>0)&&(0,J.jsx)(`button`,{type:`button`,className:`link-button`,onClick:()=>L(e=>ku(e,N)),children:`Back to automatic`})]}),F&&(0,J.jsx)(Fu,{panel:d,device:N,layout:F,previewWidth:N===A?null:bu[N].previewWidth,editing:k,selectedId:v,onSelect:y,onPlace:ce,onRemove:B,onHide:N===`desktop`?void 0:le,onVisibleColumns:O},N)]}),d.widgets.length===0&&(0,J.jsx)(`div`,{className:`board-hint`,children:k?(0,J.jsxs)(J.Fragment,{children:[`This panel is empty: add widgets with `,(0,J.jsx)(`strong`,{children:`Add widget`}),`.`]}):(0,J.jsxs)(J.Fragment,{children:[`This panel is empty: switch to `,(0,J.jsx)(`strong`,{children:`Edit`}),` to add widgets.`]})}),me&&(0,J.jsx)(Ru,{widget:me,onChange:e=>L(t=>({...t,widgets:t.widgets.map(t=>t.id===e.id?e:t)})),onDuplicate:()=>ue(me.id),onRemove:()=>B(me.id),onClose:()=>y(null)},me.id)]}):null}),x&&(0,J.jsx)(Wu,{onAdd:se,onClose:()=>S(!1)}),(0,J.jsx)(Re,{})]})}var nd=[];function rd(e){return e instanceof Error?e.message:String(e)}async function id(){try{nd=await He.listPlugins()}catch(e){return[`The plugins could not be listed: ${rd(e)}`]}let e=nd.flatMap(e=>e.error?[`Plugin ${e.name}: its server side did not start: ${e.error}`]:[]);for(let e of nd)for(let t of e.styles){let e=document.createElement(`link`);e.rel=`stylesheet`,e.href=t,document.head.append(e)}return(await Promise.allSettled(nd.map(e=>e.client?Xl(()=>import(e.client),[]):Promise.resolve(null)))).forEach((t,n)=>{let{name:r}=nd[n];if(t.status===`rejected`){e.push(`Plugin ${r} did not load: ${rd(t.reason)}`);return}if(t.value===null)return;let i=t.value.default;if(typeof i!=`object`||!i)e.push(`Plugin ${r}: its client module has no default export (definePlugin({ widgets }))`);else for(let t of fu(r,i))e.push(`Plugin ${r}: ${t}`)}),e}H.connect();var ad=await id();(0,Ye.createRoot)(document.getElementById(`root`)).render((0,J.jsx)(q.StrictMode,{children:(0,J.jsx)(qe,{children:(0,J.jsx)(td,{})})}));for(let e of ad)console.error(e),G(e,`error`);
|