tassello 0.3.0 → 0.4.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 +15 -0
- package/README.md +70 -7
- package/dist/server/networking.d.ts +41 -0
- package/dist/server/networking.js +508 -0
- package/dist/server/networking_format.d.ts +38 -0
- package/dist/server/networking_format.js +651 -0
- package/dist/server/server.js +5 -1
- package/dist/server/session.d.ts +4 -1
- package/dist/server/session.js +23 -2
- package/dist/shared/networking.d.ts +178 -0
- package/dist/shared/networking.js +248 -0
- package/dist/shared/protocol.d.ts +18 -2
- package/dist/types/client/connection.d.ts +9 -1
- package/dist/types/client/icons.d.ts +6 -0
- package/dist/types/client/sdk/index.d.ts +2 -1
- package/dist/types/shared/networking.d.ts +178 -0
- package/dist/types/shared/protocol.d.ts +18 -2
- package/dist/www/assets/Joystick.js +1 -1
- package/dist/www/assets/RobotModelView.js +2 -2
- package/dist/www/assets/TerminalView.js +2 -2
- package/dist/www/assets/icons.js +1 -1
- package/dist/www/assets/index.css +1 -1
- package/dist/www/assets/index.js +42 -42
- package/dist/www/assets/shared/tassello-sdk.js +1 -1
- package/docs/plugins.md +2 -0
- package/package.json +1 -1
package/dist/www/assets/index.js
CHANGED
|
@@ -1,69 +1,69 @@
|
|
|
1
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(`
|
|
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,Bt as s,C as c,Ct as l,E as u,F as d,Ft as f,G as p,H as m,I as h,It as g,J as _,K as v,L as y,Lt as b,M as x,Mt as S,N as C,Nt as w,O as T,Ot as E,P as D,Pt as O,Q as k,R as A,Rt as j,S as M,St as N,T as P,Tt as F,Ut as I,V as L,W as R,Wt as ee,Y as te,_ as z,_t as ne,a as re,at as ie,b as ae,bt as oe,c as se,ct as ce,d as B,dt as le,et as ue,f as de,ft as V,g as fe,gt as pe,h as H,ht as U,i as me,it as he,j as ge,jt as _e,k as ve,kt as ye,l as be,mt as xe,n as Se,nt as Ce,o as we,ot as Te,p as Ee,pt as De,q as Oe,r as ke,rt as Ae,s as je,st as Me,tt as Ne,u as W,ut as Pe,v as Fe,vt as Ie,w as Le,wt as Re,x as ze,xt as Be,y as Ve,yt as He,z as Ue,zt as We}from"./icons.js";import{a as G,c as Ge,i as Ke,l as qe,o as Je,r as Ye,s as Xe,t as Ze}from"./Joystick.js";import{t as Qe}from"./jsx-runtime.js";import{n as $e,r as et,t as tt}from"./dialogs.js";import{t as nt}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 K=e(n(),1),q=e(t(),1),J=e(Qe(),1),rt={start:`Starting…`,stop:`Stopping…`,restart:`Restarting…`};function it(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 at(e,t){let n=e.since?` · ${it(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 ot(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 st({service:e}){let[t,n]=(0,q.useState)(``),r=(0,q.useRef)(null),{unit:i,scope:a}=e;return(0,q.useEffect)(()=>(n(``),b.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 ct({config:e}){let t=et(),[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 b.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=ot(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 b.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=b.serverNow();return(0,J.jsx)(`ul`,{className:`services`,children:n.services.map(e=>{let t=u(e),n=o[t],r=n?{text:rt[n],tone:`busy`}:at(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:[ot(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)(xe,{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)(N,{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)(Me,{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)(F,{width:16,height:16})})]})]}),c&&(0,J.jsx)(st,{service:e})]},t)})})}var lt=Ye({type:`applications`,name:`Application Manager`,description:`The robot’s systemd services: their state, start and stop them, see their output.`,icon:Se,defaultSize:{w:6,h:6},minSize:{w:4,h:2},component:ct,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`}]}),ut={x:0,y:0,z:0},dt=.06;function ft(e){return`${(e*180/Math.PI).toFixed(1).replace(/^-(0\.0)$/,`$1`)}°`}function pt(e){return e.split(/[\s,]+/).filter(Boolean)}function mt({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)-dt)/.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 ht({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:`${ft(n)} … ${ft(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 gt({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)(mt,{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?`–`:ft(e.position)}),(0,J.jsx)(ht,{joint:e})]})]})}function _t({config:e,editing:t}){let n=We()===`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)(ut),l=(0,q.useRef)(!1),{controllers:u,jointStatesTopic:d,descriptionTopic:f,calibrationTopic:p}=e;(0,q.useEffect)(()=>{i(null);let{id:e,unsubscribe:t}=b.subscribeArm({controllers:pt(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;b.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=ut,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=pt(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)(Ze,{axes:`xy`,label:`x · y`,disabled:y||!w,onMove:(e,t)=>v({x:t,y:-e})}),(0,J.jsx)(Ze,{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)(gt,{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 vt=Ye({type:`arm-teleop`,name:`Arm Teleop`,description:`Jog the arm: a slider per joint, or the end effector along x, y and z.`,icon:me,defaultSize:{w:5,h:5},minSize:{w:3,h:3},component:_t,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`}]}),yt={Action:`action`,Condition:`condition`,Control:`control`,Decorator:`decorator`,SubTree:`subtree`,SubTreePlus:`subtree`},bt={Action:`action`,Condition:`condition`,Control:`control`,Decorator:`decorator`,SubTree:`subtree`},xt={input_port:`input`,output_port:`output`,inout_port:`inout`};function St(e){let t=[];for(let n of e.children.filter(e=>e.name===`TreeNodesModel`))for(let e of n.children){let n=bt[e.name];if(!n||!e.attributes.ID)continue;let r=[];for(let t of e.children){let e=xt[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 Y=(e,t,n,r=null,i=`input`)=>({name:e,direction:i,type:t,default:r,description:n}),X=(e,t,n,r=[],i)=>({id:e,kind:t,ports:r,description:n,format:i}),Ct=e=>[Y(`variable`,`std::string`,`The value compared to the cases`),...Array.from({length:e},(e,t)=>Y(`case_${t+1}`,`std::string`,`Ticks child ${t+1} if equal`))],wt=(e,t)=>X(`Loop${e}`,`decorator`,`Ticks its child once for each value of a queue, popped from it`,[Y(`queue`,`std::shared_ptr<std::deque<${t}>>`,`The queue of values`),Y(`if_empty`,`NodeStatus`,`What it returns when the queue is empty`,`SUCCESS`),Y(`value`,t,`The value popped`,null,`output`)],4),Tt=[X(`Sequence`,`control`,`Ticks its children in order while they succeed; restarts from the first after a failure`),X(`ReactiveSequence`,`control`,`As Sequence, but ticks again from the first child each time: conditions are checked while an action runs`),X(`SequenceWithMemory`,`control`,`As Sequence, but resumes from the child that failed`,[],4),X(`SequenceStar`,`control`,`As Sequence, but resumes from the child that failed`,[],3),X(`Fallback`,`control`,`Ticks its children in order until one succeeds`),X(`ReactiveFallback`,`control`,`As Fallback, but ticks again from the first child each time`),X(`Parallel`,`control`,`Ticks all its children at once, until enough succeed or fail`,[Y(`success_count`,`int`,`Successes needed to succeed; -1: all`,`-1`),Y(`failure_count`,`int`,`Failures needed to fail; -1: all`,`1`)],4),X(`Parallel`,`control`,`Ticks all its children at once, until enough succeed or fail`,[Y(`success_threshold`,`int`,`Successes needed to succeed; -1: all`),Y(`failure_threshold`,`int`,`Failures needed to fail; -1: all`,`1`)],3),X(`ParallelAll`,`control`,`Ticks all its children at once until they are all done`,[Y(`max_failures`,`int`,`Failures that make it fail; -1: all`,`1`)],4),X(`IfThenElse`,`control`,`Ticks its second child if its first succeeds, else its third`),X(`WhileDoElse`,`control`,`Reactive: ticks its second child while its first succeeds, else its third`),...[2,3,4,5,6].map(e=>X(`Switch${e}`,`control`,`Ticks the child of the case equal to the variable, else the last (default) of its ${e+1}`,Ct(e))),X(`Inverter`,`decorator`,`Succeeds when its child fails, and fails when it succeeds`),X(`ForceSuccess`,`decorator`,`Succeeds when its child is done, however it ends`),X(`ForceFailure`,`decorator`,`Fails when its child is done, however it ends`),X(`Repeat`,`decorator`,`Ticks its child again each time it succeeds, num_cycles times`,[Y(`num_cycles`,`int`,`Times to repeat; -1: forever`)]),X(`RetryUntilSuccessful`,`decorator`,`Ticks its child again each time it fails, up to num_attempts times`,[Y(`num_attempts`,`int`,`Attempts; -1: forever`)]),X(`KeepRunningUntilFailure`,`decorator`,`Ticks its child again each time it succeeds, until it fails`),X(`Delay`,`decorator`,`Ticks its child after a delay`,[Y(`delay_msec`,`unsigned int`,`The delay, ms`)]),X(`Timeout`,`decorator`,`Halts its child, and fails, if it runs longer than msec`,[Y(`msec`,`unsigned int`,`The time allowed, ms`)]),X(`RunOnce`,`decorator`,`Ticks its child once only; then returns what it returned, or skips`,[Y(`then_skip`,`bool`,`Skips once done, else returns its result again`,`true`)],4),X(`Precondition`,`decorator`,`Ticks its child if the script is true, else returns else`,[Y(`if`,`std::string`,`The condition, a script`),Y(`else`,`NodeStatus`,`What it returns if the condition is false`,`FAILURE`)],4),X(`SkipUnlessUpdated`,`decorator`,`Skips its child unless the blackboard entry changed since its last tick`,[Y(`entry`,`std::string`,`The blackboard entry`)],4),X(`WaitValueUpdate`,`decorator`,`Runs until the blackboard entry changes, then ticks its child`,[Y(`entry`,`std::string`,`The blackboard entry`)],4),wt(`Int`,`int`),wt(`Double`,`double`),wt(`String`,`std::string`),wt(`Bool`,`bool`),...[`Int`,`Double`,`String`].map(e=>X(`BlackboardCheck${e}`,`decorator`,`Ticks its child if the two values are equal, else returns return_on_mismatch`,[Y(`value_A`,`std::string`,`A value, or a blackboard entry`),Y(`value_B`,`std::string`,`A value, or a blackboard entry`),Y(`return_on_mismatch`,`NodeStatus`,`What it returns if they differ`,`FAILURE`)],3)),X(`AlwaysSuccess`,`action`,`Succeeds`),X(`AlwaysFailure`,`action`,`Fails`),X(`Script`,`action`,`Runs a script on the blackboard`,[Y(`code`,`std::string`,`The script, e.g. counter += 1`)],4),X(`SetBlackboard`,`action`,`Writes a value into a blackboard entry`,[Y(`value`,`std::string`,`The value, or another entry`),Y(`output_key`,`std::string`,`The entry written`,null,`inout`)]),X(`UnsetBlackboard`,`action`,`Removes a blackboard entry`,[Y(`key`,`std::string`,`The entry`)],4),X(`Sleep`,`action`,`Runs for a while, then succeeds`,[Y(`msec`,`unsigned int`,`How long, ms`)],4),X(`ScriptCondition`,`condition`,`Succeeds if the script is true`,[Y(`code`,`std::string`,`The condition, a script`)],4),X(`WasEntryUpdated`,`condition`,`Succeeds if the blackboard entry changed since its last tick`,[Y(`entry`,`std::string`,`The blackboard entry`)],4)];function Et(e){return Tt.filter(t=>!t.format||t.format===e).map(({format:e,...t})=>t)}var Dt=new Map([...Tt.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`])]),Ot=/^(Is|Are|Has|Was|Would|Can|Check)[A-Z]|Condition/;function kt(e,t){return Dt.get(e)||(t>1?`control`:t===1?`decorator`:Ot.test(e)?`condition`:`action`)}var At={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:`📁`}},jt={image:{placeholder:`~/pictures/map.png`,accept:`image/*`},"behavior-tree":{placeholder:`package://my_robot/behavior_trees/main.xml`,accept:`.xml,text/xml,application/xml`}};function Mt({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`?qe(n.value):null,l=async e=>{if(e){o(!0);try{n.onCommit(await Xe.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??jt[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:jt[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)(Nt,{kind:e,start:n.value,onChoose:e=>{i(!1),n.onCommit(e)},onClose:()=>i(!1)})]})}function Nt({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}=At[e],g=e===`image`,_=e===`folder`;(0,q.useEffect)(()=>{let t=!0;return l(null),d(null),Xe.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)($e,{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:qe(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 Pt(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 Ft=e=>Math.round(e*10)/10;function It(e,t,n,r,i,a){let o=(e,t)=>a?`${Ft(t)},${Ft(e)}`:`${Ft(e)},${Ft(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 Lt(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=Pt(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=Pt(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?It(f,m.y+d,n.x+n.width/2,n.y,b,!0):It(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 Rt={received:!1,version:0,treeId:``,nodes:[],treeSize:0,children:[],depths:[],states:[],transitions:[],nextId:0,error:null,warnings:[],mismatch:null};function zt(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 Bt(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 Vt(e,t){switch(t.type){case`reset`:return{...Rt,version:e.version+1};case`tree`:{let{treeId:n,nodes:r,error:i,warnings:a}=t.tree;return zt(e,t.tree)?{...e,error:i,warnings:a}:Bt({...Rt,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=Bt(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 Ht(e){switch(e){case`RUNNING`:return`running`;case`SUCCESS`:return`success`;case`FAILURE`:return`failure`;case`SKIPPED`:return`skipped`;default:return`idle`}}function Ut(e){return e.charAt(0)+e.slice(1).toLowerCase()}function Wt(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 Gt(e){return e.name===e.type?e.type:`${e.type} · ${e.name}`}function Kt(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 qt(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 Jt=.1,Yt=2.5,Xt=.55,Zt=16,Qt=54,$t=5,en=24,Z=280,tn=36,nn=14,rn=()=>window.matchMedia?.(`(prefers-reduced-motion: reduce)`).matches??!1;function an(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=en*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||rn()){l.current=e,g();return}let n=performance.now(),r=i=>{let a=Math.min(1,(i-n)/Z),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(Jt,Math.min((a-32)/t.width,(o-Qt-Zt)/t.height)));u.current=!1,_();let d=n===void 0?void 0:t.boxes.get(n);if(e||c>=Xt||!d)l.current={k:c,x:(a-t.width*c)/2,y:Qt+Math.max(0,(o-Qt-Zt-t.height*c)/2)};else{let e=Xt;l.current=r?{k:e,x:a/2-(d.x+d.width/2)*e,y:Qt}:{k:e,x:Zt,y:(Qt+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>=Zt&&f*y+g<=m-Zt&&d*y+_>=Qt&&p*y+_<=h-Zt&&!n||v({k:y,x:m/2-(c+f)/2*y,y:(Qt+h-Zt)/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(Yt,Math.max(Jt,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+tn?nn*(e+tn-n)/tn:n>t-tn?-14*(n-t+tn)/tn: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(nn,a)),y:n.y+Math.max(-14,Math.min(nn,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)},O=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})},k=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)>$t&&(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()}},A=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)},j=(0,q.useCallback)(()=>{m.current?.kind===`drag`&&(m.current=null,cancelAnimationFrame(f.current),o.current.onDragEnd?.(null))},[]);return{viewportRef:s,layerRef:c,handlers:{onPointerDown:O,onPointerMove:k,onPointerUp:A,onPointerCancel:A},fit:y,reveal:b,keepInPlace:x,toLayout:S,cancelDrag:j}}function on(e){switch(e.kind){case`control`:return/Sequence/.test(e.type)?je:/Fallback/.test(e.type)?le:/Parallel/.test(e.type)?Ce:/Recovery|Retry/.test(e.type)?xe:d;case`decorator`:return/Retry|Repeat|Loop/.test(e.type)?xe:ze;case`action`:return W;case`condition`:return Ee;case`subtree`:return a;default:return null}}function sn({node:e,size:t=14}){let n=on(e);return n&&(0,J.jsx)(n,{className:`bt-kind`,width:t,height:t})}function cn(e){return e.kind?e.kind.charAt(0).toUpperCase()+e.kind.slice(1):`Not in the tree file`}var ln=40,un=15,dn=11,fn=45,pn=88,mn=240,hn=320,gn={siblings:18,levels:46},_n=null;function vn(e,t){return _n??=document.createElement(`canvas`).getContext(`2d`),_n?(_n.font=t,_n.measureText(e).width):e.length*7}function yn(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(vn(e.type,`650 12px ${r}`),e.name===e.type?0:vn(e.name,`11px ${r}`)),a=Math.min(mn,Math.max(pn,Math.ceil(n+fn))),o=ln,s=t?Object.entries(e.ports):[];if(s.length>0){let e=Math.max(...s.map(([e,t])=>vn(`${e} ${t}`,`10.5px ${i}`)));a=Math.max(a,Math.min(hn,Math.ceil(e+24))),o+=s.length*un+dn}return{width:a,height:o}})}var bn={running:`240 160 32`,success:`47 191 113`,failure:`240 82 82`,skipped:`139 149 167`,idle:`139 149 167`},xn=(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=Ht(r?.status),p=f===`idle`&&r?.result?Ht(r.result):null;(0,q.useEffect)(()=>{if(u!==d.current&&(d.current=u,!rn())){let e=bn[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=`${cn(t)}: ${t.type}${t.name===t.type?``:` “${t.name}”`}${r?.status?` · ${Ut(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)(sn,{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}`})]})}),Sn=(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 Cn({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)(()=>yn(p.slice(0,m),n),[p,m,n]),y=(0,q.useMemo)(()=>Lt(_,e=>r.has(e)?[]:h[e],e=>v[e],t,gn),[_,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=Wt(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:O,reveal:k,keepInPlace:A}=an({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=A,(0,q.useEffect)(()=>{a&&S&&k(S.split(`,`).map(Number),!1)},[a,S,k]),(0,q.useEffect)(()=>{o&&k([x(o.node)],!0)},[o]),(0,q.useEffect)(()=>{i!==null&&c>0&&k([x(i)],!1)},[i,c]),(0,q.useEffect)(()=>{s>0&&O(!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)(Sn,{links:y.links,running:C,width:y.width,height:y.height}),[...y.boxes].map(([e,t])=>(0,J.jsx)(xn,{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 wn=/<([A-Za-z_:][-\w:.]*)((?:\s+[A-Za-z_:][-\w:.]*\s*=\s*(?:"[^"]*"|'[^']*'))*)\s*(\/?)>/y,Tn=/<\/([A-Za-z_:][-\w:.]*)\s*>/y,En=/([A-Za-z_:][-\w:.]*)\s*=\s*(?:"([^"]*)"|'([^']*)')/g,Dn=/&(?:(lt|gt|amp|quot|apos)|#(\d+)|#x([0-9A-Fa-f]+));/g,On={lt:`<`,gt:`>`,amp:`&`,quot:`"`,apos:`'`};function kn(e){return e.replace(Dn,(e,t,n,r)=>{if(t)return On[t];let i=n?Number(n):parseInt(r,16);return i<=1114111?String.fromCodePoint(i):e})}function An(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]===`/`){Tn.lastIndex=c;let t=Tn.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=Tn.lastIndex,n.end=c}else{wn.lastIndex=c;let t=wn.exec(e)??r(c,`Malformed tag`),i={};for(let e of t[2].matchAll(En))i[e[1]]=kn(e[2]??e[3]);let s=t[3]===`/`,l={type:`element`,name:t[1],attributes:i,children:[],line:n(c),start:c,openEnd:wn.lastIndex-(s?2:1),end:wn.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=wn.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 jn=1;function Mn(e){return`name`in e}function Nn(e,t={},n=[]){return{key:jn++,name:e,attributes:t,children:n,blank:!1,source:null}}function Pn(e){return{...e,key:jn++,blank:!1,source:null,children:e.children.map(e=>Mn(e)?Pn(e):{...e,key:jn++})}}function Fn(e){let t=An(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:jn++,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:jn++,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,J.jsxs)(`div`,{"data-node":e,className:`bt-node bte-node${
|
|
8
|
+
`}}var In={"&":`&`,"<":`<`,'"':`"`,"\n":` `,"\r":` `," ":`	`};function Ln(e){return e.replace(/[&<"\n\r\t]/g,e=>In[e])}function Rn(e){return`<${e.name}${Object.entries(e.attributes).map(([e,t])=>` ${e}="${Ln(t)}"`).join(``)}`}function zn(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:Rn(e);if(e.children.length===0)return`${s}/>`;if(e.children.every(e=>!Mn(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}${Mn(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 Bn(e,t){let n=[],r=e=>{if(e.key===t)return e;n.push(e);for(let t of e.children){let e=Mn(t)?r(t):null;if(e)return e}return n.pop(),null},i=r(e.root);return i&&{node:i,ancestors:n}}function Vn(e,t,n){let r=e=>{if(e.key===t)return n(e);let i=!1,a=e.children.map(e=>{let t=Mn(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 Hn(e,t){let n=e=>{let r=!1,i=e.children.map(e=>{let t=Mn(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 Un(e,t,n,r){return Vn(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 Wn(e,t,n,r){return Vn(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 Gn(e,t,n){return Vn(e,t,e=>({...n,key:e.key,blank:e.blank}))}function Kn(e,t,n){return Vn(e,t,e=>({...e,children:n(e.children)}))}function qn(e,t){let n=t;for(;n>0&&!e[n].blank;){let t=e[n-1];if(Mn(t)||t.kind!==`comment`)break;n--}return n}function Jn(e,t){let n=0;for(let r=0;r<e.length;r++)if(Mn(e[r])&&n++===t)return qn(e,r);return e.length}function Yn(e,t){let n=e.findIndex(e=>e.key===t);if(n===-1)return null;let r=qn(e,n);return{rest:[...e.slice(0,r),...e.slice(n+1)],taken:e.slice(r,n+1)}}function Xn(e,t){let n=Bn(e,t)?.ancestors.at(-1);return n?Kn(e,n.key,e=>Yn(e,t)?.rest??[...e]):e}function Zn(e,t,n,r){return Kn(e,t,e=>{let t=Jn(e,n);return[...e.slice(0,t),r,...e.slice(t)]})}function Qn(e,t,n,r){let i=Bn(e,t),a=Bn(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(Mn).findIndex(e=>e.key===t)<r&&s--;let c=[];return Kn(Kn(e,o.key,e=>{let n=Yn(e,t);return c=n.taken,n.rest}),n,e=>{let t=Jn(e,s);return[...e.slice(0,t),...c,...e.slice(t)]})}function $n(e,t,n){let r=Bn(e,t)?.ancestors.at(-1);return r?Kn(e,r.key,e=>e.map(e=>e.key===t?{...n,blank:e.blank,children:[{...e,blank:!1}]}:e)):e}function er(e,t){let n=Bn(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 Kn(e,r.key,e=>e.flatMap(e=>e.key===t?a:[e]))}function tr(e){return e.root.children.flatMap(e=>Mn(e)&&e.name===`BehaviorTree`?[{key:e.key,id:e.attributes.ID??``,node:e}]:[])}function nr(e){return e.root.attributes.BTCPP_format?.trim()===`4`?4:3}function rr(e,t){yt[e.name]===`subtree`&&e.attributes.ID&&t.add(e.attributes.ID);for(let n of e.children)Mn(n)&&rr(n,t);return t}function ir(e){let t=tr(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=rr(e.root,new Set);return t.find(e=>!i.has(e.id))??t[0]}function ar(e){let t=yt[e.name];return t===`subtree`?`SubTree`:t&&e.attributes.ID?e.attributes.ID:e.name}function or(e){let t={...e.attributes};delete t.name;let n=yt[e.name];return n&&n!==`subtree`&&delete t.ID,t}function sr(e){let t=e=>({name:e.name,attributes:e.attributes,children:e.children.filter(Mn).map(t),text:e.children.flatMap(e=>!Mn(e)&&e.kind===`text`?[e.raw]:[]).join(` `)});return St(t(e.root))}function cr(e,t,n){let r=new Map;for(let t of Et(nr(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 sr(e))r.set(t.id,{model:t,library:`This file`});let i=tr(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 lr={action:`An action`,condition:`A condition`,control:`A control node`,decorator:`A decorator`,subtree:`A subtree`};function ur(e,t){let n=[],r=[],i=0,a=(e,o)=>{let s=n.length,c=e.children.filter(Mn),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=ar(e),r=t.byId.get(n)??null,i=yt[e.name],a=i===`subtree`?`subtree`:r?.model.kind??i??kt(n,c.length);if(Object.assign(l,{type:n,name:e.attributes.name??(a===`subtree`?e.attributes.ID??n:n),kind:a,ports:or(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(`${lr[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 dr(e,t){return e.kind===`subtree`?Nn(`SubTree`,{ID:e.id,...t===4?{_autoremap:`true`}:{__shared_blackboard:`true`}}):Nn(e.id)}function fr(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 pr(e,t,n){for(let r=t;r>=0;r=e.nodes[r].parent)if(r===n)return!0;return!1}function mr(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&&pr(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=fr(e,o,r),d=l>=0&&fr(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 hr(e,t){let n=t??0;if(fr(e,n,null))return{parent:n,index:e.children[n].length};let r=e.nodes[n].parent;return r>=0&&fr(e,r,null)?{parent:r,index:e.children[r].indexOf(n)+1}:null}function gr(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 _r(e,t){let n=new Set(tr(e).map(e=>e.id)),r=t;for(let e=2;n.has(r);e++)r=`${t}${e}`;return r}function vr(e,t){let n=Nn(`BehaviorTree`,{ID:t}),r=e.root.children.filter(Mn).findLastIndex(e=>e.name===`BehaviorTree`)+1;return{document:Zn(e,e.root.key,r,n),key:n.key}}function yr(e,t,n){let r=tr(e).find(e=>e.key===t)?.id;if(r===void 0||r===n)return e;let i=Un(e,t,`ID`,n);return r&&(i=Hn(i,e=>yt[e.name]===`subtree`&&e.attributes.ID===r?{...e,attributes:{...e.attributes,ID:n}}:e),i.root.attributes.main_tree_to_execute===r&&(i=Un(i,i.root.key,`main_tree_to_execute`,n))),i}function br(e,t){return Un(e,e.root.key,`main_tree_to_execute`,t)}function xr(e,t){let n=tr(e).find(e=>e.key===t)?.id,r=Xn(e,t);return n&&r.root.attributes.main_tree_to_execute===n?Un(r,r.root.key,`main_tree_to_execute`,null):r}function Sr(e,t,n){let r=dr(t,n),i={...e.attributes};return yt[e.name]&&delete i.ID,{...e,name:r.name,attributes:{...i,...r.attributes}}}var Cr=-1,wr={width:150,height:40},Tr=400,Er=22,Dr=(0,q.memo)(function({index:e,node:t,box:n,selected:r,showPorts:i,vertical:o,folded:s,dropInto:c,dragged:l}){let u=t.kind===null,d=i?Object.entries(t.ports):[],f=u?`BehaviorTree`:t.type,p=u?t.name||`Unnamed`:t.name===t.type?``:t.name,m=[u?`The tree ${t.name}`:`${cn(t)}: ${t.type}${p?` “${p}”`:``}`,!u&&!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${u?` tree`:``}${r?` selected`:``}${t.problems.length>0?` problem`:``}${!u&&!t.model?` unknown`:``}${c?` drop-into`:``}${l?` 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:[u?(0,J.jsx)(a,{className:`bt-kind`,width:14,height:14}):(0,J.jsx)(sn,{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))}),s>=0&&(0,J.jsx)(`span`,{"data-fold":e,className:`bt-fold${o?``:` side`}`,title:s===0?`Fold its children away`:`Show its children`,children:s===0?`−`:`+${s}`})]})});function Or({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)(()=>yn(g,r).map((e,t)=>g[t].problems.length>0?{...e,width:e.width+Er}:e),[g,r]),b=(0,q.useMemo)(()=>Lt([0],e=>e===0&&v?[Cr]:e>=0&&i.has(g[e].key)?[]:_[e]??[],e=>e===Cr?wr:y[e],n,gn),[g,_,v,i,y,n]),x=(0,q.useMemo)(()=>new Map([...b.boxes].filter(([e])=>e!==Cr)),[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,O=(t,n)=>{let r=b.boxes.get(Cr);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}:mr(e,x,t,n,h)},k=(0,q.useRef)(()=>{}),A=an({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`));k.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<Tr?(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:O(e,t.node),at:e}),onDragEnd:e=>{let t=w?.node;T(null);let n=e&&t!==void 0?O(e,t):null;t!==void 0&&n&&p(g[t].key,n)}});k.current=A.keepInPlace,(0,q.useImperativeHandle)(m,()=>({dragNew:e=>{let t=e&&A.toLayout(e),n=t?O(t,null):null;return T(e?{node:-1,target:n,at:null}:null),n}}),[A.toLayout,e,x,b,h]),(0,q.useEffect)(()=>{if(!w)return;let e=e=>e.key===`Escape`&&(A.cancelDrag(),T(null));return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[w!==null,A.cancelDrag]),(0,q.useEffect)(()=>{let e=s&&S.get(s.key);e!=null&&A.reveal([j(e)],!1)},[s]),(0,q.useEffect)(()=>{D!==null&&l>0&&A.reveal([j(D)],!1)},[D,l]),(0,q.useEffect)(()=>{c>0&&A.fit(!0)},[c]);function j(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 M=w?.target??null,N=null;if(M&&M.mode!==`into`){let e=b.boxes.get(M.node),t=gn.siblings/2;N=h?{x:M.mode===`before`?e.x-t-2:e.x+e.width+t-2,y:e.y,width:4,height:e.height}:{x:e.x,y:M.mode===`before`?e.y-t-2:e.y+e.height+t-2,width:e.width,height:4}}let P=b.boxes.get(Cr),F=w&&w.node>0&&w.at?b.boxes.get(w.node):void 0;return(0,J.jsx)(`div`,{ref:A.viewportRef,className:`bt-graph bte-graph${w?` dragging`:``}`,...A.handlers,children:(0,J.jsxs)(`div`,{ref:A.layerRef,className:`bt-layer`,style:{width:b.width,height:b.height},children:[(0,J.jsx)(Sn,{links:b.links.filter(e=>e.child!==Cr),running:``,width:b.width,height:b.height}),P&&(0,J.jsx)(`div`,{className:`bte-slot${M?.node===0?` drop-into`:``}`,style:{left:P.x,top:P.y,width:P.width,height:P.height},children:o?`Empty`:`Add a node from the palette`}),[...x].map(([e,t])=>(0,J.jsx)(Dr,{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:M?.mode===`into`&&M.node===e&&e!==0,dragged:w?.node===e},g[e].key)),N&&(0,J.jsx)(`div`,{className:`bte-drop-bar`,style:{left:N.x,top:N.y,width:N.width,height:N.height}}),F&&w?.at&&(0,J.jsx)(`div`,{className:`bt-node bte-ghost${M?``:` nowhere`}`,style:{left:w.at.x-F.width/2,top:w.at.y-F.height/2,width:F.width,height:F.height},children:(0,J.jsxs)(`div`,{className:`bt-node-head`,children:[(0,J.jsx)(sn,{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 kr=[.1,.25,.5,1,2,4,8,16],Ar=120;function jr(e){return e.playing?Math.min(e.end,e.time+(Date.now()-e.at)*e.speed):e.time}function Mr(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 Nr(e){return e.replace(/\/+$/,``).replace(/^.*\//,``)||e}function Pr(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 Fr({topic:e,folder:t,onRecording:n,onClose:r}){let i=(0,q.useId)(),[a,o]=(0,q.useState)(()=>Pr(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 b.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)($e,{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)(Nt,{kind:`folder`,start:a.replace(/\/[^/]*$/,``)||`~`,onChoose:e=>{c(!1),o(`${e.replace(/\/+$/,``)}/${Nr(a)}`)},onClose:()=>c(!1)})]})}function Ir({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+Ar-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??jr(e),_=kr.includes(m)?kr:[...kr,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)(Ae,{width:16,height:16}):(0,J.jsx)(Me,{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:[Mr(g-d),` / `,Mr(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)(H,{width:16,height:16})})]})}function Lr(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,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)(
|
|
16
|
+
`}function Rr(e){return e.replace(/\/[^/]*$/,``)||`~`}function zr({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`?Lr(c):n;p(!0),h(null);try{r(i,a,(await b.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)($e,{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)(Nt,{kind:`folder`,start:Rr(o.trim()),onChoose:e=>{d(!1),s(`${e.replace(/\/+$/,``)}/${Nr(o.trim())||`tree.xml`}`)},onClose:()=>d(!1)})]})}function Br({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(Fn(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 Vr(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 Hr=new WeakMap;function Ur(e){let t=Hr.get(e);return t===void 0&&(t=zn(e),Hr.set(e,t)),t}function Wr(e){return e.document!==null&&Ur(e.document)!==e.savedText}function Gr(e,t,n){let r=t&&n!==null?tr(t).find(e=>e.key===n)?.id:void 0;return((r===void 0?void 0:tr(e).find(e=>e.id===r))??ir(e))?.key??null}function Kr(e,t,n){let r={...e,savedText:t,base:n,external:null,past:[],future:[],tag:null};try{let n=Fn(t);return{...r,document:n,error:null,tree:Gr(n,e.document,e.tree)}}catch(e){return{...r,document:null,error:`Not XML: ${e instanceof Error?e.message:e}`,tree:null}}}function qr(e,t){switch(t.type){case`open`:return Vr(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?Kr(o,n,r):r===e.base?o:(e.document?Ur(e.document):e.savedText)===n?{...o,savedText:n,base:r,external:null}:!Wr(e)&&e.document!==null?Kr(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:Gr(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:Gr(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:Gr(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:Kr(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 Jr=new Map;function Yr(){return[...Jr.values()].some(e=>Wr(e.state))}var Xr=[{kind:`control`,title:`Controls`},{kind:`decorator`,title:`Decorators`},{kind:`action`,title:`Actions`},{kind:`condition`,title:`Conditions`},{kind:`subtree`,title:`Subtrees`}],Zr=5;function Qr(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 $r({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 Xr.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)>Zr,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)(H,{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:Qr(e),onPointerDown:t=>g(e,t),onPointerMove:_,onPointerUp:v,onPointerCancel:v,onClick:()=>{m.current?m.current=!1:r(e)},children:[(0,J.jsx)(sn,{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)(H,{width:14,height:14})})]},e)),(0,J.jsxs)(`button`,{type:`button`,className:`button`,onClick:o,children:[(0,J.jsx)(ce,{width:16,height:16}),` Load a library…`]})]})]})}var ei=[`_skipIf`,`_successIf`,`_failureIf`,`_while`,`_onSuccess`,`_onFailure`,`_onHalted`,`_post`],ti={input:`in`,output:`out`,inout:`in/out`};function ni({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
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
|
|
21
|
-
`).map(e=>e.trim()).filter(Boolean)}function
|
|
22
|
-
`);(0,q.useEffect)(()=>{if(
|
|
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(`
|
|
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 ri({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 ii=/^[A-Za-z_:][-\w:.]*$/;function ai({title:e,children:t}){return(0,J.jsxs)(`section`,{children:[(0,J.jsx)(`h3`,{children:e}),t]})}function oi({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?ei.filter(t=>!(t in e.ports)):[]],b=d.name&&!ii.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)(sn,{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:[cn(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)(H,{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)(je,{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)(je,{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)(z,{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)(E,{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)(ni,{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)(ai,{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:ti[e.direction]}),e.type&&(0,J.jsx)(`span`,{className:`bt-muted bte-port-type`,children:e.type})]}),(0,J.jsx)(ni,{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)(ai,{title:p?`Other attributes`:`Attributes`,children:v.map(e=>(0,J.jsxs)(`div`,{className:`bte-attribute`,children:[(0,J.jsx)(ri,{value:e,label:`Its name`,validate:e=>ii.test(e)?e in t.attributes?`It has it already`:null:`Not an attribute name`,onCommit:t=>o(e,t)}),(0,J.jsx)(ni,{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)(H,{width:14,height:14})})]},e))}),(0,J.jsxs)(ai,{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)(ce,{width:16,height:16})})]}),b&&(0,J.jsx)(`p`,{className:`field-help error`,children:b})]})]})]})}function si({id:e,isMain:t,trees:n,problems:r,onRename:i,onMain:o,onRemove:s,onClose:c}){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)(a,{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:c,children:(0,J.jsx)(H,{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)(ri,{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:o}),`The main tree: the one BT.CPP runs (main_tree_to_execute)`]}),s&&(0,J.jsxs)(`button`,{type:`button`,className:`button danger`,onClick:s,children:[(0,J.jsx)(E,{width:16,height:16}),` Delete the tree`]})]})]})}function ci({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)($e,{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)(sn,{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 li=620,ui=316,di=240,fi=`tassello.behaviorTreeEditor.libraries`,pi=null,mi=!1;function hi(){mi||(mi=!0,window.addEventListener(`beforeunload`,e=>{Yr()&&e.preventDefault()}))}function gi(e){return e.split(`
|
|
21
|
+
`).map(e=>e.trim()).filter(Boolean)}function _i(e){try{let t=JSON.parse(localStorage.getItem(fi)??`{}`);return Array.isArray(t[e])?t[e]:[]}catch{return[]}}function vi(e,t){try{let n=JSON.parse(localStorage.getItem(fi)??`{}`);t.length>0?n[e]=t:delete n[e],localStorage.setItem(fi,JSON.stringify(n))}catch{}}function yi(e,t){return zn({...e,prolog:``,epilog:``,root:{...t,source:null}})}function bi(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 xi({config:e,instance:t,panelId:n}){let r=`${n}/${t.id}`,i=e.tree.trim(),[a]=(0,q.useState)(()=>{let e=Jr.get(r);return e?.config===i?e:{config:i,state:Vr(i),libraries:_i(r)}}),[o,s]=(0,q.useReducer)(qr,a.state),[c,l]=(0,q.useState)(a.libraries),[u,d]=(0,q.useState)(null),[f,p]=(0,q.useState)(null),[m,h]=(0,q.useState)(new Set),[g,_]=(0,q.useState)(null),[v,y]=(0,q.useState)(0),[x,S]=(0,q.useState)(e.showPorts),[C,w]=(0,q.useState)(!1),[T,E]=(0,q.useState)(0),[D,O]=(0,q.useState)(null),[A,j]=(0,q.useState)(!1),[M,N]=(0,q.useState)(!1),[P,F]=(0,q.useState)(null),[I,L]=(0,q.useState)(null),[R,ee]=(0,q.useState)([]),[te,z]=(0,q.useState)(null),ne=(0,q.useRef)(null),re=(0,q.useRef)(null),ie=(0,q.useRef)(a.config),ae=et();(0,q.useEffect)(hi,[]),(0,q.useEffect)(()=>{i!==ie.current&&(ie.current=i,s({type:`open`,path:i}))},[i]),(0,q.useEffect)(()=>{Jr.set(r,{config:ie.current,state:o,libraries:c})},[r,o,c]);let oe=(0,q.useMemo)(()=>[...new Set([...gi(e.libraries),...c])],[e.libraries,c]),se=oe.join(`
|
|
22
|
+
`);(0,q.useEffect)(()=>{if(o.path)return b.subscribeBehaviorTreeFile({path:o.path,libraries:se?se.split(`
|
|
23
|
+
`):[]},{file:e=>s({type:`file`,file:e}),models:d})},[o.path,o.opened,se]),(0,q.useEffect)(()=>{let e=ne.current;if(!e)return;let t=new ResizeObserver(([e])=>E(e.contentRect.width));return t.observe(e),()=>t.disconnect()},[]);let{document:B}=o,le=B?nr(B):4,ue=(0,q.useMemo)(()=>B?tr(B):[],[B]),de=(0,q.useMemo)(()=>B?ir(B):void 0,[B]),V=ue.find(e=>e.key===o.tree)??de,H=(0,q.useMemo)(()=>B?cr(B,u?.libraries??[],u?.trees??[]):null,[B,u]),U=(0,q.useMemo)(()=>V&&H?ur(V.node,H):null,[V,H]),me=(0,q.useMemo)(()=>new Map(U?.nodes.map((e,t)=>[e.key,t])??[]),[U]),he=f===null?null:me.get(f)??null,ve=Wr(o),ye=T>0&&T<li,be=!C&&B!==null&&(D??!ye),xe=T-(be&&!ye?240:0),Ce=!C&&U!==null&&he!==null,we=Ce&&xe-ui>=di?ui:0;(0,q.useEffect)(()=>{h(new Set),ee(e=>e.filter(e=>ue.some(t=>t.key===e)))},[V?.key]);let Te=(0,q.useMemo)(()=>{if(!H||!B)return[];let e=[...H.byId.values()].map(({model:e,library:t})=>({model:e,library:t})),t=H.trees.filter(e=>e!==V?.id).map(e=>({model:{id:e,kind:`subtree`,ports:[],description:H.treeFiles.has(e)?`In ${H.treeFiles.get(e)}`:`A tree of this file`},library:H.treeFiles.has(e)?Nr(H.treeFiles.get(e)):`This file`})),n=new Map,r=(e,t)=>{let i=ar(e);if(t>1&&i!==`SubTree`&&!H.byId.has(i)&&!n.has(i)){let t=e.children.filter(Mn).length;n.set(i,{model:{id:i,kind:kt(i,t),ports:[],description:`Used in this file, in no library`},library:`Used here`})}e.children.forEach(e=>Mn(e)&&r(e,t+1))};return ue.forEach(e=>r(e.node,1)),[...e,...t,...n.values()]},[H,B,V?.id,ue]),Ee=e=>{p(e),_(t=>({key:e,seq:(t?.seq??0)+1}))},Oe=(0,q.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})))},[]),ke=async()=>{if(!B||M||!ve)return;if(o.readOnly){G(`${o.readOnly}: Save as…`,`error`);return}let e=Ur(B);N(!0);try{let t=await b.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 ${Nr(o.path)}`))}catch(e){G(`Could not save ${o.path}: ${e instanceof Error?e.message:e}`,`error`)}finally{N(!1)}},Ae=async e=>{(!ve||await ae.confirm({title:`Discard the changes?`,message:`${Nr(o.path)} has changes not saved.`,confirmLabel:`Discard them`,danger:!0}))&&(p(null),ee([]),s({type:`open`,path:e}))},Me=(e,t)=>{if(!B||!U)return;let n=t??hr(U,he);if(!n){G(`Select where it goes: a control node, or a node in one`,`error`);return}let r=dr(e.model,le);Oe(Zn(B,U.nodes[n.parent].key,n.index,r),{select:r.key}),ye&&O(!1)},Ne=(e,t)=>{if(!B||!U)return;let n=Qn(B,e,U.nodes[t.parent].key,t.index);n&&Oe(n,{select:e})},W=U&&he!==null&&he>0?U.nodes[he]:null,Pe=W&&B?Bn(B,W.key)?.node??null:null,Fe=W&&U?W.parent:-1,Ie=U&&Fe>=0?U.children[Fe]:[],Le=W?Ie.indexOf(he):-1,Re=U&&Fe>=0?U.nodes[Fe].capacity>Ie.length:!1,ze=()=>{B&&W&&U&&Oe(Xn(B,W.key),{select:U.nodes[Fe].key})},Ve=()=>{B&&Pe&&(pi=Pe,navigator.clipboard?.writeText(yi(B,Pe)).catch(()=>{}))},He=()=>{if(!B||!U||!pi)return;let e=hr(U,he);if(!e){G(`Select where it goes: a control node, or a node in one`,`error`);return}let t=Pn(pi);Oe(Zn(B,U.nodes[e.parent].key,e.index,t),{select:t.key})},Ue={moveEarlier:W&&Le>0?()=>Ne(W.key,{parent:Fe,index:Le-1,mode:`before`,node:Fe}):null,moveLater:W&&Le>=0&&Le<Ie.length-1?()=>Ne(W.key,{parent:Fe,index:Le+2,mode:`after`,node:Fe}):null,duplicate:B&&Pe&&Re&&U?()=>{let e=Pn(Pe);Oe(Zn(B,U.nodes[Fe].key,Le+1,e),{select:e.key})}:null,wrap:W?()=>L(`wrap`):null,replace:W&&W.kind!==`subtree`?()=>L(`replace`):null,unwrap:B&&W&&U&&gr(U,he)?()=>Oe(er(B,W.key),{select:U.nodes[U.children[he][0]].key}):null,remove:ze},We=async e=>{let t=ue.find(t=>t.id===e);if(t&&V){ee(e=>[...e,V.key]),p(null),s({type:`tree`,key:t.key});return}let n=H?.treeFiles.get(e);n?await Ae(n):G(`No tree ${e}, in the file nor its includes`,`error`)},Ge=async()=>{if(!B)return;let e=await ae.prompt({title:`New tree`,label:`Its ID`,initial:_r(B,`Subtree`),confirmLabel:`Add`});if(!e)return;if(ue.some(t=>t.id===e)){G(`There is a tree ${e} already`,`error`);return}let t=vr(B,e);p(null),Oe(t.document,{tree:t.key})},Ke=t=>{let n=t.target,r=t.ctrlKey||t.metaKey,i=t.key.toLowerCase();if(r&&i===`s`){t.preventDefault(),ke();return}if(n.closest(`input, textarea, select, [role="dialog"]`)||!B)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(Ve);else if(r&&i===`x`)a(W&&(()=>(Ve(),ze())));else if(r&&i===`v`)a(He);else if(r&&i===`d`)a(Ue.duplicate);else if((i===`delete`||i===`backspace`)&&W)a(ze);else if(i===`escape`)p(null);else if((i===`f2`||i===`enter`)&&W)a(()=>ne.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=he??0;if(t.altKey){a(i===o?Ue.moveEarlier:i===s?Ue.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=m.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(()=>Ee(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>(he??-1))??qe[0];Ee(U.nodes[e].key)}},Ye;Ye=o.path?C||!B&&o.savedText!==null?(0,J.jsx)(Br,{text:B?Ur(B):o.savedText??``,readOnly:!1,onDocument:e=>Oe(e,{tag:`xml`}),onDone:()=>s({type:`seal`})}):B?U?(0,J.jsx)(Or,{ref:re,graph:U,version:`${o.path}#${V?.key}`,direction:e.direction,showPorts:x,folded:m,selected:f,readOnly:!1,focus:g,fitRequest:v,covered:we,onSelect:p,onOpen:e=>{let t=me.get(e),n=t===void 0?void 0:U.nodes[t];n?.kind===`subtree`&&n.ports.ID?We(n.ports.ID):n&&t>0&&ne.current?.querySelector(`.bte-properties input`)?.focus()},onFold:e=>h(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n}),onMove:Ne}):(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 Ge(),children:`Add a tree`})]}):(0,J.jsx)(`div`,{className:`widget-message`,children:o.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;Ce&&B&&U&&H&&he!==null&&(he===0&&V?Xe=(0,J.jsx)(si,{id:V.id,isMain:de?.key===V.key,trees:ue.filter(e=>e.key!==V.key).map(e=>e.id),problems:U.nodes[0].problems,onRename:e=>Oe(yr(B,V.key,e)),onMain:()=>Oe(br(B,V.id)),onRemove:ue.length>1?()=>{p(null),Oe(xr(B,V.key),{tree:ue.find(e=>e.key!==V.key).key})}:null,onClose:()=>p(null)}):W&&Pe&&(Xe=(0,J.jsx)(oi,{node:W,element:Pe,catalog:H,format:le,actions:Ue,onAttribute:(e,t,n)=>Oe(Un(B,W.key,e,t),n?{tag:`${W.key}:${e}`}:{}),onRenameAttribute:(e,t)=>Oe(Wn(B,W.key,e,t)),onSeal:()=>s({type:`seal`}),onOpenTree:e=>void We(e),onClose:()=>p(null)},W.key)));let Ze=[];o.error&&(B||o.savedText!==null)&&Ze.push({text:o.error,tone:`error`}),o.external&&Ze.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?M?{text:`Saving ${Nr(o.path)}…`,tone:`running`}:ve?{text:`${Nr(o.path)} · changed`,tone:`changed`}:o.readOnly&&B?{text:`${Nr(o.path)} · read-only: ${o.readOnly}`,tone:`idle`}:{text:B?`${Nr(o.path)} · saved`:Nr(o.path),tone:B?`success`:`idle`}:{text:`No file`,tone:`idle`};return(0,J.jsxs)(`div`,{ref:ne,className:`bt bte`,tabIndex:-1,onKeyDown:Ke,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(),ne.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":be,title:`The nodes to add`,"aria-label":`The nodes to add`,disabled:!B||C,onClick:()=>O(!be),children:(0,J.jsx)(Se,{width:17,height:17})}),R.length>0&&(0,J.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:R.at(-1)}),ee(e=>e.slice(0,-1))},children:(0,J.jsx)(je,{width:17,height:17,style:{transform:`scaleX(-1)`}})}),(0,J.jsx)(`select`,{className:`bte-tree-select`,"aria-label":`The tree shown`,value:V?.key??``,disabled:ue.length===0||C,onChange:e=>{p(null),ee([]),s({type:`tree`,key:Number(e.target.value)})},children:ue.map(e=>(0,J.jsxs)(`option`,{value:e.key,children:[e.id||`Unnamed tree`,e.key===de?.key?` (main)`:``]},e.key))}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`New tree`,"aria-label":`New tree`,disabled:!B||C,onClick:()=>void Ge(),children:(0,J.jsx)(ce,{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:o.past.length===0,onClick:()=>s({type:`undo`}),children:(0,J.jsx)(_e,{width:17,height:17})}),(0,J.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,J.jsx)(De,{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||C,onClick:()=>y(e=>e+1),children:(0,J.jsx)(ge,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,"aria-pressed":x,title:`The ports on the nodes`,"aria-label":`The ports on the nodes`,disabled:!U||C,onClick:()=>S(e=>!e),children:(0,J.jsx)(Be,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,"aria-pressed":C,title:`The XML`,"aria-label":`The XML`,disabled:!o.path||!B&&o.savedText===null,onClick:()=>w(e=>!e),children:(0,J.jsx)(fe,{width:17,height:17})}),(0,J.jsx)(`span`,{className:`bte-toolbar-end`}),(0,J.jsxs)(`button`,{type:`button`,className:`button bte-save${ve?` primary`:``}`,disabled:!ve||M||o.readOnly!==null,title:o.readOnly??`Save (Ctrl+S)`,onClick:()=>void ke(),children:[(0,J.jsx)(pe,{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":A,onClick:()=>j(e=>!e),children:(0,J.jsx)(k,{width:17,height:17})}),A&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`div`,{className:`menu-backdrop`,onPointerDown:()=>j(!1)}),(0,J.jsxs)(`div`,{className:`menu-list`,role:`menu`,onClick:()=>j(!1),children:[(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,className:`bte-narrow`,disabled:!U||C,onClick:()=>y(e=>e+1),children:`Fit the tree`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,className:`bte-narrow`,disabled:!U||C,onClick:()=>S(e=>!e),children:x?`Hide the ports`:`Show the ports`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,className:`bte-narrow`,disabled:!o.path||!B&&o.savedText===null,onClick:()=>w(e=>!e),children:C?`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:!B,onClick:()=>F(`save-as`),children:`Save as…`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,disabled:!B,onClick:()=>B&&bi(Nr(o.path)||`tree.xml`,Ur(B)),children:`Download`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,disabled:!ve,onClick:async()=>{await ae.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,J.jsxs)(`div`,{className:`bte-body${ye?` narrow`:``}`,children:[be&&(0,J.jsx)($r,{items:Te,libraries:oe.map(t=>({path:t,removable:c.includes(t)&&!gi(e.libraries).includes(t)})),warnings:u?.warnings??[],onAdd:e=>Me(e),onDrag:(e,t)=>{z({item:e,at:t}),re.current?.dragNew(t)},onDrop:(e,t)=>{let n=t?re.current?.dragNew(t)??null:null;re.current?.dragNew(null),z(null),n&&Me(e,n)},onLoadLibrary:()=>F(`library`),onRemoveLibrary:e=>{let t=c.filter(t=>t!==e);l(t),vi(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:o.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&&!C&&(0,J.jsxs)(`button`,{type:`button`,className:`bte-problems-chip`,onClick:Je,title:`Show the next`,children:[qe.length,` `,qe.length===1?`problem`:`problems`]})]}),te&&(0,J.jsx)(`div`,{className:`bt-node bte-palette-ghost`,style:{left:te.at.x+12,top:te.at.y+8},children:(0,J.jsxs)(`div`,{className:`bt-node-head`,children:[(0,J.jsx)(sn,{node:{kind:te.item.model.kind,type:te.item.model.id}}),(0,J.jsx)(`span`,{className:`bt-node-type`,children:te.item.model.id})]})}),I&&B&&W&&Pe&&H&&(0,J.jsx)(ci,{title:I===`wrap`?`Wrap ${W.type} in`:`Replace ${W.type} with`,models:[...H.byId.values()],kinds:I===`wrap`?[`decorator`,`control`]:W.kind===`control`||W.kind===`decorator`?[W.kind]:[`action`,`condition`],onPick:e=>{if(L(null),I===`wrap`){let t=dr(e,le);Oe($n(B,W.key,t),{select:t.key})}else Oe(Gn(B,Pe.key,Sr(Pe,e,le)),{select:Pe.key})},onClose:()=>L(null)}),(P===`open`||P===`library`)&&(0,J.jsx)(Nt,{kind:`behavior-tree`,start:o.path.startsWith(`/`)||o.path.startsWith(`~/`)?o.path:`~`,onChoose:e=>{if(F(null),P===`open`)Ae(e);else if(!oe.includes(e)){let t=[...c,e];l(t),vi(r,t)}},onClose:()=>F(null)}),(P===`new`||P===`save-as`)&&(0,J.jsx)(zr,{mode:P,initial:P===`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`):`~/${Nr(o.path)}`,text:B?Ur(B):Lr(4),onSaved:(e,t,n)=>{F(null),P===`save-as`?(s({type:`saved`,text:t,version:n,path:e}),G(`Saved as ${e}`)):Ae(e)},onClose:()=>F(null)})]})}var Si=Ye({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:ye,defaultSize:{w:10,h:7},minSize:{w:4,h:4},component:xi,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`}]}),Ci=(0,q.memo)(function({index:e,node:t,depth:n,state:r,selected:i,folded:a,now:o,onSelect:s,onFold:c}){let l=Ht(r?.status),u=l===`idle`&&r?.result?Ht(r.result):null,d=``;return r?.status&&(d=Ut(r.status),l===`running`&&r.since&&o?d+=` · ${Kt(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:`${cn(t)}: ${t.type}`,onClick:()=>s(e),children:[(0,J.jsx)(`span`,{className:`bt-dot`,"aria-hidden":`true`}),(0,J.jsx)(sn,{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 wi({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=Wt(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)(Ci,{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 Ti=420,Ei=316,Di=240;function Oi(e){let[t,n]=(0,q.useState)(()=>b.serverNow());return(0,q.useEffect)(()=>{let t=setInterval(()=>n(b.serverNow()),e);return()=>clearInterval(t)},[e]),t}function ki(e,t,n){if(t.state===`error`)return{text:t.message,tone:`error`};let r=t=>+![`action`,`condition`].includes(e.nodes[t].kind??``),i=Wt(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?` · ${Kt(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:Ht(a.status)}:a?.result?{text:`Idle · its last run ${a.result===`SUCCESS`?`succeeded`:`failed`}${a.since?`, ${Kt(n-a.since)} ago`:``}`,tone:`idle`}:t.state===`waiting`?{text:t.message,tone:`idle`}:{text:`Idle`,tone:`idle`}}function Ai({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 ${Kt(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)(sn,{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} · `,cn(a)]})]}),(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Close`,onClick:i,children:(0,J.jsx)(H,{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 ${Ht(o.status)}`,children:Ut(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 ${Ht(o.result)}`,children:Ut(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:qt(e.time)}),(0,J.jsx)(`span`,{className:`bt-pill ${Ht(e.from)}`,children:Ut(e.from)}),`→`,(0,J.jsx)(`span`,{className:`bt-pill ${Ht(e.to)}`,children:Ut(e.to)})]},e.id))}):(0,J.jsx)(`p`,{className:`bt-muted`,children:`None seen`})]})]})]})}function ji({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:qt(n.time)}),(0,J.jsx)(`span`,{className:`bt-log-node`,children:Gt(e.nodes[n.node])}),(0,J.jsx)(`span`,{className:`bt-pill ${Ht(n.from)}`,children:Ut(n.from)}),`→`,(0,J.jsx)(`span`,{className:`bt-pill ${Ht(n.to)}`,children:Ut(n.to)})]})},n.id))})})}function Mi({config:e,editing:t}){let[n,i]=(0,q.useReducer)(Vt,Rt),[o,s]=(0,q.useState)({state:`waiting`,message:`Connecting…`}),[c,l]=(0,q.useState)(null),[u,d]=(0,q.useState)(!0),[f,m]=(0,q.useState)(!1),[h,g]=(0,q.useState)(null),[_,v]=(0,q.useState)(new Set),[y,x]=(0,q.useState)(null),[S,C]=(0,q.useState)(0),[w,T]=(0,q.useState)(0),E=(0,q.useRef)(null),[D,O]=(0,q.useState)(null),[k,j]=(0,q.useState)(null),M=(0,q.useRef)(null),[N,P]=(0,q.useState)(null),[F,I]=(0,q.useState)(!1),[L,R]=(0,q.useState)(!1),ee=(0,q.useRef)(null),te=Oi(k?.playing?250:1e3),z=e.topic.trim(),ne=e.tree.trim();(0,q.useEffect)(()=>{if(i({type:`reset`}),P(null),j(null),M.current=null,!z&&!D){s({state:`error`,message:`No log topic: set one in edit mode`});return}s({state:`waiting`,message:`Connecting…`});let e={status:(e,t)=>s({state:e,message:t}),tree:e=>i({type:`tree`,tree:e}),update:e=>i({type:`update`,update:e}),recording:P,playback:e=>j({...e,at:Date.now()})};if(D){let{id:t,unsubscribe:n}=b.subscribeBehaviorTreePlayback({bag:D,topic:z,tree:ne},e);return M.current=t,n}return b.subscribeBehaviorTree({topic:z,tree:ne},e)},[z,ne,D]);let re=(0,q.useCallback)(e=>{M.current!==null&&(j(t=>t&&{...t,time:e.time??jr(t),playing:e.playing??t.playing,speed:e.speed??t.speed,at:Date.now()}),b.controlBehaviorTreePlayback(M.current,e))},[]),ie=async()=>{try{let e=await b.recordBehaviorTree(z,null);e&&(ee.current=e,G(`Recorded ${z} into ${e}`))}catch(e){G(`Could not stop recording ${z}: ${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(h===null)return;let e=e=>e.key===`Escape`&&g(null);return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[h]);let ae=(0,q.useCallback)(e=>{v(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n})},[]),oe=(0,q.useCallback)(e=>{g(e),x(t=>({node:e,seq:(t?.seq??0)+1}))},[]),se=n.treeSize>0,ce=se?c??(e.view===`auto`?w<Ti?`list`:`graph`:e.view):`list`,B=h!==null&&n.nodes[h]!==void 0,le=B&&w-Ei>=Di?Ei:0,ue=k?jr(k):te,de=ki(n,o,ue);D&&k&&!k.error&&(de.text=`${Nr(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:ne?`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`}):ce===`graph`?(0,J.jsx)(Cn,{model:n,direction:e.direction,showPorts:e.showPorts,folded:_,selected:h,follow:u,focus:y,fitRequest:S,covered:le,onSelect:g,onFold:ae,onPan:()=>d(!1)}):(0,J.jsx)(wi,{model:n,folded:_,selected:h,follow:u,now:ue,onSelect:g,onFold:ae}):(0,J.jsx)(`div`,{className:`widget-message`,children:o.state===`error`?o.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 ${ce}`,children:[pe,(0,J.jsxs)(`div`,{className:`overlay-toolbar`,children:[ce===`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)(ge,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":u,title:`Follow the running nodes`,"aria-label":`Follow the running nodes`,onClick:()=>d(e=>!e),children:(0,J.jsx)(r,{width:17,height:17})}),(0,J.jsx)(`span`,{className:`overlay-separator`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":ce===`graph`,title:se?`As a graph`:`As a graph: needs the tree’s file`,"aria-label":`As a graph`,disabled:!se,onClick:()=>l(`graph`),children:(0,J.jsx)(a,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":ce===`list`,title:`As a list`,"aria-label":`As a list`,onClick:()=>l(`list`),children:(0,J.jsx)(p,{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:()=>m(e=>!e),children:(0,J.jsx)(A,{width:17,height:17})}),(0,J.jsx)(`span`,{className:`overlay-separator`}),!D&&(0,J.jsx)(`button`,{type:`button`,className:`overlay-button${N?` recording`:``}`,"aria-pressed":N!==null,title:N?`Stop recording into ${N.path}`:`Record the log into a rosbag`,"aria-label":N?`Stop recording`:`Record the log`,disabled:!z||t,onClick:()=>N?void ie():I(!0),children:(0,J.jsx)(V,{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?O(null):R(!0),children:(0,J.jsx)(ve,{width:17,height:17})})]}),B&&(0,J.jsx)(Ai,{model:n,index:h,now:ue,onSelect:oe,onClose:()=>g(null)})]}),f&&(0,J.jsx)(ji,{model:n,onSelect:oe}),D&&k&&(0,J.jsx)(Ir,{playback:k,onControl:re,onClose:()=>O(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}),N&&!D&&(0,J.jsxs)(`span`,{className:`bt-rec`,title:`Recording into ${N.path}`,children:[`REC `,Kt(te-N.since)]})]}),F&&(0,J.jsx)(Fr,{topic:z,folder:e.recordFolder,onRecording:e=>ee.current=e,onClose:()=>I(!1)}),L&&(0,J.jsx)(Nt,{kind:`bag`,start:ee.current?.replace(/\/+[^/]+\/*$/,``)||e.recordFolder,onChoose:e=>{R(!1),ee.current=e,O(e)},onClose:()=>R(!1)})]})}var Ni=Ye({type:`behavior-tree`,name:`Behavior Tree Inspector`,description:`What a behavior tree is doing: its running branch, its nodes’ status, and their transitions.`,icon:a,defaultSize:{w:8,h:6},minSize:{w:3,h:3},component:Mi,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`}]}),Pi=5e3;function Fi(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 Ii(e){let t=Math.max(0,Math.floor(e/1e3));return`${Math.floor(t/60)}:${String(t%60).padStart(2,`0`)}`}function Li(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 Ri({config:e,instance:t,panelId:n,editing:r}){let i=j(n,t.id),a=et(),[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>Pi?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})&&b.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`}))&&(b.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?Ii(b.serverNow()-i.startedAt):``}${u&&e.allowStop?` · press to stop`:``}`,className:``};else if(i){let{text:e,ok:t}=Li(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:Fi(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 zi=Ye({type:`button`,name:`Button`,description:`Run a bash command on the robot, e.g. start a service or a launch file.`,icon:F,defaultSize:{w:3,h:1},minSize:{w:1,h:1},component:Ri,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`}]}),Bi=3e3,Vi=2e3;function Hi(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,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=b.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&&Hi(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]>Vi;)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&&Hi(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>Bi)},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)(de,{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 Wi=Ye({type:`camera`,name:`Camera`,description:`Show an image topic, raw or compressed.`,icon:de,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}]}),Gi=[{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 Ki(e){return Math.min(Gi.length-1,Math.max(0,Math.floor(e/10)-1))}function qi(e){let t=Gi.findIndex(t=>t.level===e);return new Set(Gi.slice(Math.max(0,t)).map(e=>e.level))}var Ji={received:!1,started:0,entries:[],pending:[],paused:!1,skipped:0,running:new Map,cleared:null,version:0};function Yi(e){return e.replace(/^\/+/,``).replaceAll(`/`,`.`)}function Xi(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 Zi(e){return e.length>1e4?e.slice(-ee):e}function Qi(e){return e.entries.at(-1)?.seq??e.cleared?.seq??0}function $i(e,t){switch(t.type){case`reset`:return{...Ji,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=>[Yi(e),e])):e.running;if(!n)return e.paused?{...e,running:s,pending:Zi([...e.pending,...i]),skipped:e.skipped+a}:{...e,running:s,entries:Zi([...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?Qi(e):1/0;return{...e,received:!0,started:r,running:s,cleared:l,entries:Zi(u.filter(e=>e.seq<=d)),pending:Zi(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:Zi([...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 ea(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 ta(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 na(e){let t=e.split(/[;,\s]+/).filter(Boolean).map(e=>{let t=Yi(e).split(`*`).map(e=>e.replace(/[.+?^${}()|[\]\\]/g,`\\$&`)).join(`.*`);return RegExp(`^${t}(\\..+)?$`)});return t.length>0?e=>t.some(t=>t.test(e)):null}function ra(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:Xi(e,t),counts:Gi.map(()=>0),total:0},a.set(e,n)),n},s=Gi.map(()=>0),c=[],l=0;for(let t of e){if(!i(t.name))continue;l++;let e=Ki(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(Gi[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 ia=Date.UTC(2001,0,1);function aa(e){return(e/1e3).toFixed(6)}function oa(e){if(e<ia)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 sa(e){return`[${Gi[Ki(e.level)].tag}] [${aa(e.stamp)}] [${e.name}]: ${e.msg}`}function ca(e){return e<1e3?String(e):e<1e4?`${(e/1e3).toFixed(1).replace(/\.0$/,``)}k`:`${Math.round(e/1e3)}k`}var la=[{level:`ok`,label:`OK`,tag:`OK`},{level:`warn`,label:`Warn`,tag:`WARN`},{level:`error`,label:`Error`,tag:`ERROR`},{level:`stale`,label:`Stale`,tag:`STALE`}],ua={ok:0,warn:1,stale:2,error:3};function da(e){return la.find(t=>t.level===e)}function fa(e){switch(e){case 0:return`ok`;case 1:return`warn`;case 3:return`stale`;default:return`error`}}function pa(e){return e.stale?`stale`:fa(e.level)}function ma(e){return new Set(la.filter(({level:t})=>ua[t]>=ua[e]).map(({level:e})=>e))}function ha(e,t){return e===null||t===null?e??t:ua[e]>=ua[t]?e:t}var ga={received:!1,started:0,statuses:new Map,changes:[],frozen:null,forgotten:new Map,version:0};function _a(e){return e.length>1e3?e.slice(-I):e}function va(e){return e.frozen??e}function ya(e,t){return e.get(t.id)===t.since}function ba(e,t){switch(t.type){case`reset`:return{...ga,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:_a([...e.changes,...a])}}let o=e.received&&r===e.started,s={statuses:new Map(i.map(e=>[e.id,e])),changes:_a(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}=va(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 xa(e){let t=(e.startsWith(`/`)?e.split(`/`).map(e=>e.replace(/:\s*$/,``).trim()):Sa(e)).filter(Boolean);return t.length>0?t:[e.trim()||`(no name)`]}function Sa(e){let t=e.indexOf(`: `);return t>0?[e.slice(0,t).trim(),e.slice(t+2).trim()]:[e.trim()]}function Ca(e){let t=e.split(/[,;]/).map(e=>e.trim()).filter(Boolean).map(e=>{let t=e.includes(`/`)?e.split(`/`).filter(Boolean):Sa(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 wa=new Intl.Collator(void 0,{numeric:!0,sensitivity:`base`});function Ta(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=xa(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)=>wa.compare(e.label,t.label));let t=null;for(let n of e.children)i(n),t=ha(t,n.worst);let n=e.entry?pa(e.entry):null;n===`error`&&t===`stale`&&(n=`stale`),e.own=n,e.worst=ha(n,t)??`ok`,e.counted=n!==null&&(t===null||ua[n]>ua[t])};return t.sort((e,t)=>wa.compare(e.label,t.label)),t.forEach(i),{roots:t,nodes:n}}var Ea={mode:`auto`,chosen:new Map};function Da(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 Oa(){return{ok:0,warn:0,error:0,stale:0}}function ka(e,t){let{entry:n}=e;return n?t(n.name)||t(n.message)||t(n.hardwareId):t(e.label)}function Aa(e,t,n){let r=[];for(let n of e)(!t.scope||t.scope(xa(n.name)))&&r.push(n);let{roots:i,nodes:a}=Ta(r),o=t.text!==null||la.some(({level:e})=>!t.levels.has(e)),s=new Set,c=new Set,l=new Map,u=Oa(),d=(e,n)=>{let r=n||!t.text||ka(e,t.text),i=Oa(),a=!1;for(let t of e.children){let e=d(t,r);for(let{level:t}of la)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=Oa(),p=null;for(let e of i){let t=d(e,!1);for(let{level:e}of la)f[e]+=t[e];p=ha(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)=>ua[t.own]-ua[e.own]||wa.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:la.reduce((e,{level:t})=>e+u[t],0),matching:s.size,worst:p,nodes:a,keys:v,filtering:o}}function ja(e,t,n){let r=new Map,i=e=>{let t=r.get(e.id);return t===void 0&&(t=!n.scope||n.scope(xa(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(fa(o.level))&&(!n.text||n.text(s.name)||n.text(o.message))&&a.push(o)}return a}var Ma=/^(ok|warn(ing)?|error|stale|all stale)$/i;function Na(e){let t=e.entry?.message.trim()??``;return e.children.length>0&&Ma.test(t)?``:t}function Pa(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 Fa(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 Ia(e){let t=pa(e),n=da(t).tag;t===`stale`&&fa(e.level)!==`stale`&&(n+=` (${da(fa(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 La(e,t){let n=da(fa(e.level)).tag,r=e.message?`: ${e.message}`:``;return`[${Pa(e.time,!0)}] [${n}] ${t?.name??`?`}${r}`}function Ra({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 za=16,Ba=26,Va=(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*za},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)(Ra,{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:ca(t)},e))]})});function Ha({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)/Ba)-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)(Va,{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 Ua=640,Wa=300,Ga=[{level:`error`,one:`error`,many:`errors`},{level:`stale`,one:`stale`,many:`stale`},{level:`warn`,one:`warning`,many:`warnings`}];function Ka(e){return`${e.toLocaleString()} status${e===1?``:`es`}`}async function qa(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 Ja(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 Ya(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}_${b.hostname||`robot`}_${r}_${i}.txt`}function Xa(e){let[t,n]=(0,q.useState)(()=>b.serverNow());return(0,q.useEffect)(()=>{let t=setInterval(()=>n(b.serverNow()),e);return()=>clearInterval(t)},[e]),t}function Za({entry:e,label:t,changes:n,onClose:r}){let i=Xa(1e3),a=pa(e),o=fa(e.level),s=(0,q.useMemo)(()=>n.filter(t=>t.status===e.id).slice(-10).reverse(),[n,e.id]),c=()=>qa(Ia(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)(Ra,{level:a,size:16}),(0,J.jsx)(`span`,{className:`diag-pill`,children:da(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)(z,{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)(H,{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:[Pa(e.since),` · `,Fa(i-e.since)]})]}),e.stale&&(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:`Last received`}),(0,J.jsxs)(`dd`,{children:[Pa(e.updated),` · `,Fa(i-e.updated),` ago`,o!==`stale`&&`, at ${da(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=fa(e.level);return(0,J.jsxs)(`li`,{className:t,children:[(0,J.jsx)(`time`,{title:new Date(e.time).toLocaleString(),children:Pa(e.time)}),(0,J.jsx)(`span`,{className:`diag-pill`,children:da(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 Qa({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=fa(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:Pa(e.time)}),(0,J.jsx)(Ra,{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 $a({config:e}){let[t,n]=(0,q.useReducer)(ba,ga),[r,i]=(0,q.useState)({state:`waiting`,message:`Connecting…`}),[o,s]=(0,q.useState)(()=>ma(e.level)),[c,l]=(0,q.useState)(e.filter),[u,d]=(0,q.useState)(e.regex),[f,m]=(0,q.useState)(e.view),[h,g]=(0,q.useState)(Ea),[_,v]=(0,q.useState)(null),[y,x]=(0,q.useState)({width:0,height:0}),C=(0,q.useRef)(null);(0,q.useEffect)(()=>s(ma(e.level)),[e.level]),(0,q.useEffect)(()=>l(e.filter),[e.filter]),(0,q.useEffect)(()=>d(e.regex),[e.regex]),(0,q.useEffect)(()=>m(e.view),[e.view]);let w=e.topic.trim();(0,q.useEffect)(()=>{if(n({type:`reset`}),!w)i({state:`error`,message:`No diagnostics topic: set one in edit mode`});else return i({state:`waiting`,message:`Connecting…`}),b.subscribeDiagnostics({topic:w},{status:(e,t)=>i({state:e,message:t}),update:e=>n({type:`update`,update:e})})},[w]),(0,q.useEffect)(()=>{v(null),g(Ea)},[t.version]),(0,q.useEffect)(()=>{let e=C.current;if(!e)return;let t=new ResizeObserver(([e])=>x({width:e.contentRect.width,height:e.contentRect.height}));return t.observe(e),()=>t.disconnect()},[]);let T=(0,q.useDeferredValue)(c),D=(0,q.useMemo)(()=>Ca(e.statuses),[e.statuses]),O=(0,q.useMemo)(()=>ta(T,u),[T,u]),k=(0,q.useMemo)(()=>({scope:D,levels:o,text:O.test}),[D,o,O]),{statuses:j,changes:N}=va(t),P=(0,q.useMemo)(()=>[...j.values()].filter(e=>!ya(t.forgotten,e)),[j,t.forgotten]),F=(0,q.useMemo)(()=>Aa(P,k,h),[P,k,h]);(0,q.useEffect)(()=>g(e=>Da(F,e)),[F]);let I=(0,q.useMemo)(()=>f===`changes`?ja(N,j,k):[],[f,N,j,k]),L=(0,q.useMemo)(()=>f===`list`?F.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})):F.rows.map(({node:e,depth:t,open:n,dim:r,counts:i})=>({key:e.key,depth:t,label:e.label,level:e.worst,message:Na(e),open:n,dim:r,status:e.entry!==null,problems:n===!1?i:null})),[f,F]),R=(0,q.useCallback)((e,t)=>g(n=>({...n,chosen:new Map(n.chosen).set(e,!t)})),[]),ee=(e,t)=>s(n=>{if(t)return new Set([e]);let r=new Set(n);return r.delete(e)||r.add(e),r}),te=_===null?void 0:F.nodes.get(_),z=te?.entry?{entry:te.entry,label:te.label}:null,re=[...F.nodes.values()].flatMap(e=>e.entry?.stale?[e.entry.id]:[]),{width:ie,height:ae}=y,oe=ie>=Ua,se=f===`changes`?`No change matches the filters`:`No status matches the filters`;t.received?F.nodes.size===0?se=P.length<j.size?`The statuses no longer published are forgotten: they show again once published`:D?`No status of ${e.statuses.trim()} yet`:`No status yet`:f===`changes`&&N.length===0&&(se=`No change of level yet`):se=r.state===`error`?r.message:`Reading the diagnostics…`;let ce;if(r.state===`error`)ce={text:r.message,tone:`failed`};else if(!t.received)ce={text:r.message,tone:`idle`};else{let e=[];if(r.state===`waiting`&&e.push(r.message),F.total>0){let t=Ga.filter(({level:e})=>F.totals[e]>0).map(({level:e,one:t,many:n})=>`${F.totals[e].toLocaleString()} ${F.totals[e]===1?t:n}`);e.push(t.length>0?t.join(`, `):`All OK`),e.push(F.filtering&&f!==`changes`?`${F.matching.toLocaleString()} of ${Ka(F.total)} shown`:Ka(F.total))}t.frozen&&e.push(`paused`),ce={text:e.join(` · `)||`No status yet`,tone:t.frozen?`paused`:F.worst??`idle`}}let B;return B=f===`changes`?(0,J.jsx)(Qa,{changes:I,entries:j,selected:z?.entry.id??null,empty:se,onSelect:e=>v(F.keys.get(e)??null)}):(0,J.jsx)(Ha,{kind:f,rows:L,selected:_,empty:se,onSelect:v,onFold:R}),(0,J.jsxs)(`div`,{ref:C,className:`diag${z&&!oe&&ae>0&&ae<Wa?` 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:la.map(({level:e,label:t})=>(0,J.jsxs)(`button`,{type:`button`,className:`diag-level ${e}`,"aria-pressed":o.has(e),"aria-label":`${t}: ${F.counts[e]}`,title:`${t}: ${Ka(F.counts[e])}. Shift+click: this level only`,onClick:t=>ee(e,t.shiftKey),children:[(0,J.jsx)(Ra,{level:e,size:13}),(0,J.jsx)(`span`,{className:`diag-level-name`,children:t}),(0,J.jsx)(`span`,{className:`diag-level-count`,children:ca(F.counts[e])})]},e))}),(0,J.jsxs)(`div`,{className:`diag-filter`,children:[(0,J.jsxs)(`label`,{className:`diag-search${O.error?` invalid`:``}`,title:O.error??`Only the statuses whose name, message or hardware ID contain any of these, separated by ;`,children:[(0,J.jsx)(ne,{width:14,height:14}),(0,J.jsx)(`input`,{type:`search`,value:c,placeholder:`Filter…`,"aria-label":`Only the statuses containing`,spellCheck:!1,onChange:e=>l(e.target.value)})]}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button diag-regex`,"aria-pressed":u,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:()=>m(`tree`),children:(0,J.jsx)(a,{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:()=>m(`list`),children:(0,J.jsx)(p,{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:()=>m(`changes`),children:(0,J.jsx)(A,{width:17,height:17})}),(0,J.jsx)(`span`,{className:`overlay-separator`}),f===`tree`&&(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":h.mode===`all`,title:h.mode===`all`?`Unfold only the groups with problems`:`Unfold all the groups`,"aria-label":`Unfold all the groups`,onClick:()=>g({mode:h.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)(Ae,{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`?I.length===0:F.list.length===0,onClick:()=>{if(f===`changes`){let e=I.map(e=>La(e,j.get(e.status))).reverse();Ja(Ya(`diagnostics_changes`),e.join(`
|
|
27
27
|
`)+`
|
|
28
|
-
`)}else
|
|
28
|
+
`)}else Ja(Ya(`diagnostics`),F.list.map(e=>Ia(e.entry)).join(`
|
|
29
29
|
|
|
30
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
|
|
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
|
|
31
|
+
`)},children:(0,J.jsx)(M,{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)(E,{width:17,height:17})})]})]}),(0,J.jsxs)(`div`,{className:`diag-body${oe?` beside`:``}`,children:[(0,J.jsx)(`div`,{className:`diag-main`,children:B}),z&&(0,J.jsx)(Za,{entry:z.entry,label:z.label,changes:N,onClose:()=>v(null)})]}),(0,J.jsxs)(`div`,{className:`diag-status ${ce.tone}`,title:ce.text,children:[ce.tone===`ok`||ce.tone===`warn`||ce.tone===`error`||ce.tone===`stale`?(0,J.jsx)(Ra,{level:ce.tone,size:12}):(0,J.jsx)(`span`,{className:`diag-dot`,"aria-hidden":`true`}),(0,J.jsx)(`span`,{className:`diag-status-text`,children:ce.text})]})]})}var eo=Ye({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:ae,defaultSize:{w:8,h:6},minSize:{w:3,h:3},component:$a,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 to(e,t){return e===`/`?`/${t}`:`${e}/${t}`}function no(e){if(e===`/`)return null;let t=e.lastIndexOf(`/`);return t<=0?`/`:e.slice(0,t)}function Q(e){return e===`/`?`/`:e.slice(e.lastIndexOf(`/`)+1)}function ro(e,t){return e===t||e.startsWith(t===`/`?`/`:`${t}/`)}function io(e,t){return t&&t!==`/`&&ro(e,t)?`~${e.slice(t.length)}`:e}function ao(e,t,n=`/`){let r=n,i=n===`/`?`/`:Q(n);if(n===`/`&&t&&t!==`/`&&ro(e,t)&&(r=t,i=`~`),!ro(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=to(o,t),a.push({name:t,path:o});return a}function oo(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 so(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 co=new Intl.DateTimeFormat(void 0,{hour:`2-digit`,minute:`2-digit`}),lo=new Intl.DateTimeFormat(void 0,{day:`numeric`,month:`short`}),uo=new Intl.DateTimeFormat(void 0,{day:`numeric`,month:`short`,year:`numeric`}),fo=new Intl.DateTimeFormat(void 0,{dateStyle:`medium`,timeStyle:`medium`});function po(e,t){let n=new Date(e),r=new Date(t);return n.toDateString()===r.toDateString()?co.format(n):(n.getFullYear()===r.getFullYear()?lo:uo).format(n)}function mo(e){return fo.format(new Date(e))}function ho(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 go(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 _o(e){return(e&4095).toString(8).padStart(3,`0`)}function vo(e){return e.startsWith(`.`)}var yo=new Intl.Collator(void 0,{numeric:!0,sensitivity:`base`});function bo(e,t){return yo.compare(e,t)||(e<t?-1:+(e>t))}function xo(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||bo(e.name,n.name))})}function So(e,{hidden:t,text:n}){let r=n.toLowerCase().split(/\s+/).filter(Boolean);return e.filter(e=>(t||!vo(e.name))&&r.every(t=>e.name.toLowerCase().includes(t)))}function Co(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=xo(So(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=to(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 wo(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 To(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 Eo=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(` `)),Do=new Set([`makefile`,`dockerfile`,`license`,`readme`,`authors`,`changelog`,`colcon_ignore`,`ament_ignore`,`catkin_ignore`,`vagrantfile`,`gemfile`,`rakefile`,`procfile`,`cmakelists.txt`]),Oo=new Set([`png`,`jpg`,`jpeg`,`gif`,`webp`,`bmp`,`svg`,`ico`,`pgm`,`ppm`,`pnm`]),ko=new Set([`zip`,`tar`,`gz`,`tgz`,`bz2`,`xz`,`zst`,`7z`,`rar`,`deb`,`whl`]),Ao=new Set([`mp4`,`webm`,`mkv`,`avi`,`mov`,`mp3`,`wav`,`ogg`,`flac`,`pdf`]),jo=new Set([`mcap`,`db3`,`bag`]);function Mo(e){let t=e.lastIndexOf(`.`);return t>0?e.slice(t+1).toLowerCase():``}function No(e){if(e.kind===`dir`)return e.bag?`bag`:`folder`;let t=Mo(e.name);return Oo.has(t)?`image`:jo.has(t)?`bag`:ko.has(t)?`archive`:Ao.has(t)?`media`:Eo.has(t)||Do.has(e.name.toLowerCase())?`text`:e.kind===`file`&&(!t||t===`so`)?e.mode&73||t===`so`?`program`:`text`:`other`}function Po(e){return Oo.has(Mo(e))}function Fo(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`}[No(e)],n=Mo(e.name);return`${t}${e.kind===`file`&&n?` (${n.toUpperCase()})`:``}${e.link===null?``:`, a link`}`}function Io(e,t){let n=new Set((e??[]).map(e=>e.name));return t.filter(e=>n.has(e))}function Lo(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 Ro(e,t,n=`${t}s`){return`${e.toLocaleString()} ${e===1?t:n}`}function zo(e){return Ro(e,`item`)}function Bo(e,t){let n=t>0?e/t:0;return n>=.95?`full`:n>=.85?`warn`:`ok`}var Vo=16,Ho=10,Uo={folder:C,bag:ve,text:T,image:L,archive:ke,media:ve,program:F,other:u};function Wo({entry:e,size:t=16}){let n=e.kind===`other`?`other`:No(e),r=n===`text`&&/\.(py|cpp|hpp|h|c|cc|js|ts|sh)$/i.test(e.name)?fe:Uo[n];return(0,J.jsx)(r,{className:`fm-icon ${n}`,width:t,height:t})}function Go({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 Ko=(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*Vo+20},children:e.text});let{entry:u,path:d,depth:f,open:p}=e,m=u.kind===`dir`;return(0,J.jsxs)(`div`,{role:`treeitem`,"aria-level":f+1,"aria-expanded":p??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${Fo(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:m?e=>l.onDragOver(d,e):void 0,onDrop:m?e=>l.onDrop(d,e):void 0,children:[(0,J.jsx)(`span`,{className:`bt-row-indent`,style:{width:f*Vo}}),p===null?(0,J.jsx)(`span`,{className:`bt-row-fold`}):(0,J.jsx)(`button`,{type:`button`,className:`bt-row-fold`,tabIndex:-1,"aria-label":p?`Fold ${u.name}`:`Unfold ${u.name}`,"aria-expanded":p,onClick:e=>{e.stopPropagation(),l.onFold(d,!p)},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)(Wo,{entry:u}),s?(0,J.jsx)(Go,{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)(R,{className:`fm-link`,width:12,height:12,"aria-label":`A link`})]}),(0,J.jsx)(`span`,{className:`fm-size`,children:m?``:so(u.size)}),(0,J.jsx)(`span`,{className:`fm-date`,children:po(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)(k,{width:15,height:15})})]})}),qo=[{key:`name`,label:`Name`,className:`fm-head-name`},{key:`size`,label:`Size`,className:`fm-size`},{key:`modified`,label:`Modified`,className:`fm-date`}];function Jo({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)-Ho),y=Math.min(e.length,Math.ceil((h.top+h.height)/28)+Ho),b=[];for(let t=v;t<y;t++){let o=e[t];b.push((0,J.jsx)(Ko,{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:[qo.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 Yo=[{who:`Owner`,shift:6},{who:`Group`,shift:3},{who:`Others`,shift:0}];function Xo({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:Yo.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 Zo({term:e,children:t}){return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`dt`,{children:e}),(0,J.jsx)(`dd`,{children:t})]})}function Qo({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}),Ge.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 `:``,so(a.size),` in `,Ro(a.files,`file`),`, `,Ro(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 $o({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 Ge.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=Q(l);v=(0,J.jsxs)(J.Fragment,{children:[r&&(0,J.jsx)(Wo,{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?Fo(r):`Reading…`,c?`, shown`:``]})]})]});let p=async e=>{h(!0),await s.onChmod(l,e),h(!1),_(e=>e+1)},g=r?No(r):`other`;y=(0,J.jsxs)(J.Fragment,{children:[f&&(0,J.jsx)(`p`,{className:`fm-error`,children:f}),r&&Po(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:Ge.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)(Zo,{term:`Where`,children:no(l)?(0,J.jsx)(`button`,{type:`button`,className:`link-button fm-inline-button`,onClick:()=>s.onGo(no(l)),children:io(no(l),i)}):`The root`}),e.kind===`dir`?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(Zo,{term:`Holds`,children:[e.items===null?`Cannot be read`:zo(e.items),e.hidden?(0,J.jsxs)(`span`,{className:`bt-muted`,children:[` (`,e.hidden,` hidden)`]}):null]}),(0,J.jsx)(Zo,{term:`Size`,children:(0,J.jsx)(Qo,{path:l})})]}):(0,J.jsxs)(Zo,{term:`Size`,children:[so(e.size),e.size>=1e3&&(0,J.jsxs)(`span`,{className:`bt-muted`,children:[` (`,e.size.toLocaleString(),` bytes)`]})]}),(0,J.jsx)(Zo,{term:`Modified`,children:(0,J.jsx)(`span`,{title:mo(e.modified),children:ho(e.modified,o)})}),e.created!==null&&(0,J.jsx)(Zo,{term:`Created`,children:(0,J.jsx)(`span`,{title:mo(e.created),children:ho(e.created,o)})}),(0,J.jsxs)(Zo,{term:`Owner`,children:[e.owner,(0,J.jsxs)(`span`,{className:`bt-muted`,children:[`, group `,e.group]})]}),(0,J.jsxs)(Zo,{term:`Mode`,children:[(0,J.jsx)(`code`,{children:go(e.mode,e.kind,e.link!==null)}),` `,(0,J.jsx)(`span`,{className:`bt-muted`,children:_o(e.mode)})]}),e.link!==null&&(0,J.jsx)(Zo,{term:`Links to`,children:e.link||`?`}),e.realPath&&(0,J.jsx)(Zo,{term:`Is at`,children:io(e.realPath,i)}),e.space&&(0,J.jsxs)(Zo,{term:`Disk`,children:[so(e.space.free),` free of `,so(e.space.total),(0,J.jsxs)(`span`,{className:`bt-muted`,children:[` on `,e.space.mount]})]}),!e.writable&&(0,J.jsx)(Zo,{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)(Xo,{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=>no(t)===no(e[0]));v=(0,J.jsxs)(`div`,{className:`bt-details-title`,children:[(0,J.jsxs)(`strong`,{children:[zo(e.length),` selected`]}),(0,J.jsx)(`span`,{children:c?`In ${io(no(e[0])??`/`,i)}`:`In several folders`})]}),y=(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`dl`,{className:`bt-facts`,children:[(0,J.jsx)(Zo,{term:`Files`,children:r.length.toLocaleString()}),(0,J.jsx)(Zo,{term:`Folders`,children:o.toLocaleString()}),(0,J.jsxs)(Zo,{term:`Size`,children:[so(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)(H,{width:16,height:16})})]}),(0,J.jsx)(`div`,{className:`bt-details-body`,children:y})]})}var es=3e3;async function ts(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 ns(e){let t=document.createElement(`a`);t.href=e,t.download=``,t.click()}function rs(e){return e instanceof Error?e.message:String(e)}function is(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 as(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 Ge.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 Je?(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(),es))};return c(),()=>{t=!0,clearTimeout(r)}},[u,s]),{listings:t,errors:r,offline:a,refresh:(0,q.useCallback)(()=>c(e=>e+1),[])}}function os({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 ss({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)($e,{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:Lo(n)}),` in `,(0,J.jsx)(`code`,{children:Q(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 cs({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 Ge.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 Je&&e.status===409}),u(!1)}};return(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)($e,{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)(Nt,{kind:`folder`,start:no(a.trim())??`~`,onChoose:e=>{c(!1),o(`${e.replace(/\/+$/,``)}/${Q(a.trim())||`untitled.txt`}`)},onClose:()=>c(!1)})]})}function ls({used:e,total:t}){let n=t>0?Math.min(1,e/t):0;return(0,J.jsx)(`span`,{className:`fm-usage ${Bo(e,t)}`,role:`meter`,"aria-valuemin":0,"aria-valuemax":100,"aria-valuenow":Math.round(n*100),title:`${so(e)} used of ${so(t)}`,children:(0,J.jsx)(`span`,{style:{width:`${n*100}%`}})})}var us=new Map;function ds(e,t){return t>0?`${Math.round(e/t*100)}%`:``}function fs({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:so(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 ps({folder:e,home:t,disks:n,now:r,onGo:i,onReveal:a,onRefreshDisks:o}){let[s,c]=(0,q.useState)(()=>us.get(e)??null),[l,u]=(0,q.useState)(!1),[d,f]=(0,q.useState)(null),[p,m]=(0,q.useState)(e);p!==e&&(m(e),c(us.get(e)??null),f(null));let h=()=>{u(!0),f(null),Ge.analyze(e).then(t=>{let n={result:t,at:Date.now()};us.set(t.path,n),t.path===e&&c(n),u(!1)},e=>{f(e instanceof Error?e.message:String(e)),u(!1)})},g=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)(xe,{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 ${Bo(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)(y,{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)(ls,{used:e.used,total:t}),(0,J.jsxs)(`span`,{className:`fm-disk-numbers`,children:[(0,J.jsxs)(`span`,{children:[(0,J.jsx)(`strong`,{children:so(e.free)}),` free of `,so(e.total)]}),(0,J.jsxs)(`span`,{children:[so(e.used),` used, `,ds(e.used,t)]})]}),n&&Bo(r,n.total)!==`ok`&&(0,J.jsxs)(`span`,{className:`fm-error`,children:[ds(r,n.total),` of its inodes used: `,Ro(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:io(e,t)}),!g&&(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${g?``:` primary`}`,disabled:l,onClick:h,children:[(0,J.jsx)(Te,{width:16,height:16}),l?`Analyzing…`:g?`Analyze again`:`Analyze this folder`]}),s&&!l&&(0,J.jsxs)(`span`,{className:`bt-muted`,children:[`Analyzed `,ho(s.at,r)]})]}),d&&(0,J.jsx)(`p`,{className:`fm-error`,children:d}),g&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`p`,{className:`fm-summary`,children:[(0,J.jsx)(`strong`,{children:so(g.size)}),` in `,Ro(g.files,`file`),` and `,Ro(g.folders,`folder`),(0,J.jsxs)(`span`,{className:`bt-muted`,children:[` `,`(`,so(g.disk),` on the disk`,g.links>0?`, ${Ro(g.links,`link`)} not followed`:``,`)`]})]}),(g.partial||g.unreadable>0||g.mounts>0)&&(0,J.jsx)(`p`,{className:`fm-error`,children:[g.partial&&`${g.partial}: at least as much`,g.unreadable>0&&`${Ro(g.unreadable,`folder`)} not readable`,g.mounts>0&&`${Ro(g.mounts,`other disk`)} left out`].filter(Boolean).join(`; `)}),g.children.length>0&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`h4`,{children:`Largest inside`}),(0,J.jsx)(fs,{rows:g.children.filter(e=>e.size>0).slice(0,12).map(e=>({key:e.name,label:`${e.name}${e.kind===`dir`?`/`:``}`,size:e.size,note:`${ds(e.size,g.size)}${e.kind===`dir`?` · ${Ro(e.files,`file`)}`:``}`})),onPick:e=>{let t=g.children.find(t=>t.name===e),n=to(g.path,e);t?.kind===`dir`?i(n):a(n)}})]}),g.types.length>0&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`h4`,{children:`By type`}),(0,J.jsx)(fs,{rows:g.types.map(e=>({key:e.type,label:e.type?e.type.slice(1):`No extension`,size:e.size,note:`${ds(e.size,g.size)} · ${Ro(e.files,`file`)}`}))})]}),g.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:g.largest.map(e=>(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,className:`fm-file-row`,title:e.path,onClick:()=>a(to(g.path,e.path)),children:[(0,J.jsx)(`span`,{className:`fm-bar-label`,children:Q(e.path)}),(0,J.jsx)(`span`,{className:`bt-muted fm-file-where`,children:e.path.includes(`/`)?no(e.path):``}),(0,J.jsx)(`span`,{className:`fm-bar-size`,children:so(e.size)})]})},e.path))})]}),g.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:g.recent.map(e=>(0,J.jsx)(`li`,{children:(0,J.jsxs)(`button`,{type:`button`,className:`fm-file-row`,title:e.path,onClick:()=>a(to(g.path,e.path)),children:[(0,J.jsx)(`span`,{className:`fm-bar-label`,children:Q(e.path)}),(0,J.jsx)(`span`,{className:`bt-muted fm-file-where`,children:e.path.includes(`/`)?no(e.path):``}),(0,J.jsx)(`span`,{className:`fm-bar-size`,children:ho(e.modified,r)})]})},e.path))})]})]})]})]})}var ms={re:/\s+/y,keepStart:!0},hs=/"(?:[^"\\]|\\.)*"?/y,gs=/'(?:[^'\\]|\\.)*'?/y,_s=/(?:0[xX][\da-fA-F_]+|0[bB][01_]+|0[oO][0-7_]+|(?:\d[\d_]*(?:\.[\d_]*)?|\.\d[\d_]*)(?:[eE][+-]?\d+)?)[a-zA-Z]*/y;function vs(e){return new Set(e.split(` `))}function ys(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 bs(e,t,n=0){return{fill:t,rules:[{re:e,token:t,next:n}]}}var xs=vs(`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`),Ss=vs(`bool bytes dict float int list object set str tuple type self cls super print len range open isinstance`),Cs=vs(`True False None NotImplemented Ellipsis __name__ __file__`),ws=vs(`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`),Ts=vs(`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`),Es=vs(`true false nullptr NULL`),Ds=vs(`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`),Os=vs(`any boolean never number object string symbol unknown bigint Array Map Set Promise Record`),ks=vs(`true false null undefined NaN Infinity`),As=vs(`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`),js=vs(`echo printf cd ls cat grep sed awk test read eval exec ros2 colcon sudo apt source`),Ms=new Set,Ns={python:{label:`Python`,comment:`#`,states:[{rules:[ms,{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:_s,token:`number`},ys(xs,Ss,Cs)]},bs(/(?:[^"\\]|\\.|"(?!""))*"""/y,`string`),bs(/(?:[^'\\]|\\.|'(?!''))*'''/y,`string`)]},cpp:{label:`C, C++`,comment:`//`,states:[{rules:[ms,{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:_s,token:`number`},{re:/[A-Za-z_]\w*_t\b/y,token:`type`},ys(ws,Ts,Es,/[A-Za-z_]\w*/y)]},bs(/.*?\*\//y,`comment`)]},javascript:{label:`JavaScript, TypeScript`,comment:`//`,states:[{rules:[ms,{re:/\/\/.*/y,token:`comment`},{re:/\/\*/y,token:`comment`,next:1},{re:hs,token:`string`},{re:gs,token:`string`},{re:/`(?:[^`\\]|\\.)*`?/y,token:`string`},{re:_s,token:`number`},{re:/(function)(\s+)([A-Za-z_$][\w$]*)/y,groups:[`keyword`,``,`function`]},ys(Ds,Os,ks)]},bs(/.*?\*\//y,`comment`)]},json:{label:`JSON`,comment:null,states:[{rules:[ms,{re:/"(?:[^"\\]|\\.)*"(?=\s*:)/y,token:`key`},{re:hs,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:[ms,{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:hs,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:[ms,{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}]},bs(/.*?-->/y,`comment`),{fill:``,rules:[{re:/(.*?)(\]\]>)/y,groups:[``,`meta`],next:0}]},{rules:[ms,{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}]},bs(/[^"]*"/y,`string`,3),bs(/[^']*'/y,`string`,3)]},shell:{label:`Shell`,comment:`#`,states:[{rules:[ms,{re:/#!.*/y,token:`meta`,start:!0},{re:/#.*/y,token:`comment`},{re:hs,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`},ys(As,js,Ms,/[A-Za-z_][\w.-]*/y),{re:/[^\s"'$#\w]+/y}]}]},cmake:{label:`CMake`,comment:`#`,states:[{rules:[ms,{re:/#\[\[/y,token:`comment`,next:1},{re:/#.*/y,token:`comment`},{re:hs,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}]},bs(/.*?\]\]/y,`comment`)]},ini:{label:`INI, TOML, systemd`,comment:`#`,states:[{rules:[ms,{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:hs,token:`string`},{re:gs,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},ms,{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:[ms,{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:hs,token:`string`},{re:gs,token:`string`},{re:/-?(?:\d+\.?\d*|\.\d+)(?:[eE][+-]?\d+)?/y,token:`number`},{re:/[A-Za-z_]\w*/y}]}]}},Ps=[{id:`plain`,label:`Plain text`},...Object.entries(Ns).map(([e,t])=>({id:e,label:t.label})).sort((e,t)=>e.label.localeCompare(t.label))],Fs={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`},Is={"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 Ls(e,t=``){let n=e.toLowerCase();if(Is[n])return Is[n];let r=n.lastIndexOf(`.`);return(r>0?Fs[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 Rs(e){return e===`plain`?null:Ns[e].comment}var zs=4e3;function Bs(e,t,n){if(e===`plain`||t.length===0)return{spans:t.length>0?[[t.length,``]]:[],state:n};let{states:r}=Ns[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,zs),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 Vs={past:[],future:[],last:null},Hs=1e3,Us=2e7,Ws=1500;function Gs(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 Ks(e,{from:t,removed:n,inserted:r}){return e.slice(0,t)+r+e.slice(t+n.length)}function qs({from:e,removed:t,inserted:n}){return{from:e,removed:n,inserted:t}}function Js(e){return/^\s+$/.test(e)}function Ys(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 Js(i.inserted)&&r.inserted&&!Js(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 Xs(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<Ws?Ys(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<Hs;){let{change:e}=o[c-1];if(s+=e.removed.length+e.inserted.length,s>Us)break;c--}return{past:o.slice(c),future:[],last:{kind:n,time:r}}}function Zs(e,t){let n=t.past[t.past.length-1];return n?{text:Ks(e,qs(n.change)),history:{past:t.past.slice(0,-1),future:[...t.future,n],last:null},selection:n.before}:null}function Qs(e,t){let n=t.future[t.future.length-1];return n?{text:Ks(e,n.change),history:{past:[...t.past,n],future:t.future.slice(0,-1),last:null},selection:n.after}:null}function $s(e){let t=[0];for(let n=e.indexOf(`
|
|
34
34
|
`);n>=0;n=e.indexOf(`
|
|
35
|
-
`,n+1))t.push(n+1);return t}function
|
|
35
|
+
`,n+1))t.push(n+1);return t}function ec(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 tc(e){let t=(e.match(/\n/g)??[]).length,n=(e.match(/\r\n/g)??[]).length;return n>0&&n*2>=t?`\r
|
|
36
36
|
`:`
|
|
37
|
-
`}function
|
|
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
|
|
37
|
+
`}function nc(e){return e===`tab`?` `:` `.repeat(e)}function rc(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 ic(e,{start:t,end:n}){let r=e.lastIndexOf(`
|
|
39
39
|
`,t-1)+1,i=n>t&&e[n-1]===`
|
|
40
40
|
`?n-1:n,a=e.indexOf(`
|
|
41
|
-
`,i);return{from:r,to:a<0?e.length:a}}function
|
|
41
|
+
`,i);return{from:r,to:a<0?e.length:a}}function ac(e,t,n,r){let{from:i,to:a}=ic(e,t),o=nc(n),s=o===` `?1:o.length,c=e.slice(i,a).split(`
|
|
42
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
|
|
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 oc(e,t,n){let{from:r,to:i}=ic(e,t),a=e.slice(r,i).split(`
|
|
44
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
|
|
46
|
-
`,t-1)+1;return`\n${/^[ \t]*/.exec(e.slice(n,t))?.[0]??``}`}function
|
|
47
|
-
`)}function
|
|
48
|
-
`,1)[0]):e.language,indent:e.text===null?
|
|
49
|
-
`,readOnly:null,error:null,missing:!1,external:null,history:
|
|
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 sc(e,t){let n=e.lastIndexOf(`
|
|
46
|
+
`,t-1)+1;return`\n${/^[ \t]*/.exec(e.slice(n,t))?.[0]??``}`}function cc(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 lc(e,t,n){if(!t)return{matches:[],error:null,capped:!1};let r;try{r=cc(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 uc(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 dc(e,t,n,r,i){let a=cc(n,i);a.lastIndex=t;let o=a.exec(e);return!o||o.index!==t||o[0].length===0?null:i.regex?uc(r,o):r}function fc(e,t,n,r){if(!t)return{text:e,count:0};let i=cc(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?uc(n,t):n),o=t.index+t[0].length,s++);return{text:a+e.slice(o),count:s}}function pc(e){return{folder:e,back:[],forward:[],expanded:new Set,tabs:[],active:null,nextId:1}}function mc(e){return e.replace(/\r\n/g,`
|
|
47
|
+
`)}function hc(e,t){return{start:Math.min(e.start,t),end:Math.min(e.end,t)}}function gc(e,t,n){let r=mc(t.text);return{...e,text:r,saved:r,base:t.version,stamp:t.stamp,eol:tc(t.text),readOnly:t.readOnly,error:null,missing:!1,external:null,history:Vs,selection:n?hc(e.selection,r.length):{start:0,end:0},scroll:n?e.scroll:{top:0,left:0},language:e.text===null?Ls(Q(e.path),r.split(`
|
|
48
|
+
`,1)[0]):e.language,indent:e.text===null?rc(r,e.language===`python`?4:2):e.indent}}function _c(e){return e.kind===`text`&&e.text!==null&&(e.text!==e.saved||e.missing)}function vc(e,t,n){return ro(e,t)?n+e.slice(t.length):e}function yc(e,t,n){return{...e,tabs:e.tabs.map(e=>e.id===t&&e.kind===`text`?n(e):e)}}function bc(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)ro(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:Vs,selection:{start:0,end:0},scroll:{top:0,left:0},language:Ls(Q(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 yc(e,t.id,e=>gc(e,t.file,e.text!==null));case`changed`:return yc(e,t.id,e=>t.file.version===e.base?{...e,stamp:t.file.stamp}:e.text===null||!_c(e)?gc(e,t.file,!0):{...e,stamp:t.file.stamp,external:{text:mc(t.file.text),version:t.file.version,stamp:t.file.stamp}});case`failed`:return yc(e,t.id,e=>({...e,error:t.error}));case`missing`:return yc(e,t.id,e=>({...e,missing:e.text!==null,error:e.text===null?`No file ${e.path}`:null}));case`edit`:return yc(e,t.id,e=>({...e,text:t.text,history:Xs(e.history,t.step,t.kind,t.time),selection:t.step.after}));case`undo`:case`redo`:return yc(e,t.id,e=>{let n=e.text===null?null:(t.type===`undo`?Zs:Qs)(e.text,e.history);return n?{...e,text:n.text,history:n.history,selection:n.selection}:e});case`view`:return yc(e,t.id,e=>({...e,selection:t.selection,scroll:t.scroll??e.scroll}));case`saved`:return yc(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 yc(e,t.id,e=>({...e,external:{text:null,version:t.version,stamp:t.stamp}}));case`reload`:return yc(e,t.id,e=>e.external?.text==null?{...e,external:null,reads:e.reads+1}:gc(e,{path:e.path,text:e.external.text,version:e.external.version,stamp:e.external.stamp??``,readOnly:e.readOnly},!0));case`keep`:return yc(e,t.id,e=>e.external?{...e,base:e.external.version,stamp:e.external.stamp??e.stamp,external:null}:e);case`settings`:return yc(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=>vc(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=>ro(e.path,t.from)?{...e,path:n(e.path)}:e)}}case`deleted`:{let n=e=>t.paths.some(t=>ro(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 xc=new Map;function Sc(){return[...xc.values()].some(e=>e.state.tabs.some(_c))}var Cc={home:Ue,root:y,folder:C,ros:U,bookmark:B};function wc({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),p=e.reduce((e,t)=>ro(n,t.path)&&(!e||t.path.length>e.path.length)?t:e,null),m=(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})]}),h=e=>({onDragOver:t=>c(e,t),onDrop:t=>l(e,t)}),g=[{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)(H,{width:16,height:16})})]}),(0,J.jsxs)(`div`,{className:`bte-palette-body`,children:[g.map(({key:e,title:t,list:n})=>n.length>0&&(0,J.jsxs)(`section`,{children:[e!==`places`&&m(e,t,n.length),!d.has(e)&&(0,J.jsx)(`ul`,{children:n.map(e=>{let t=Cc[e.kind];return(0,J.jsxs)(`li`,{className:`fm-place-item`,children:[(0,J.jsxs)(`button`,{type:`button`,className:`bte-palette-item fm-place${p===e?` active`:``}${r===e.path?` drop-into`:``}`,title:e.path,onClick:()=>a(e.path),...h(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)(H,{width:13,height:13})})]},`${e.kind}:${e.path}`)})})]},e)),t&&t.length>0&&(0,J.jsxs)(`section`,{children:[m(`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),...h(e.mount),children:[(0,J.jsxs)(`span`,{className:`fm-disk-name`,children:[(0,J.jsx)(y,{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:[so(e.free),` free`]})]}),(0,J.jsx)(ls,{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)(ce,{width:16,height:16}),` Bookmark this folder`]})})]})}var Tc=[{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 Ec({tab:e,readOnly:t,onSettings:n}){let r=(0,q.useMemo)(()=>$s(e.text),[e.text]),i=ec(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:Ps.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:Tc.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
50
|
`?`\r
|
|
51
51
|
`:`
|
|
52
52
|
`}),children:[(0,J.jsx)(`option`,{value:`
|
|
53
53
|
`,children:`LF`}),(0,J.jsx)(`option`,{value:`\r
|
|
54
|
-
`,children:`CRLF`})]})]})}function
|
|
55
|
-
`),[c]),
|
|
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()})},
|
|
57
|
-
`)){let t=
|
|
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},
|
|
59
|
-
`).map(e=>e.trim()).filter(Boolean)}function
|
|
60
|
-
`)).catch(()=>{}),G(`${t?`Cut`:`Copied`} ${
|
|
61
|
-
`));let r=
|
|
54
|
+
`,children:`CRLF`})]})]})}function Dc({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=Q(t.path);s=n?{text:`Saving ${e}…`,tone:`running`}:t.text===null?{text:e,tone:t.error?`error`:`idle`}:_c(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)(Ec,{tab:t,readOnly:a,onSettings:o}))}else if(r)s={text:`${Q(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=>vo(e.name)).length,n=[`${zo(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?`, ${so(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 ${Bo(r.total-r.free,r.total)}`,title:`${so(r.free)} free of ${so(r.total)} on ${r.mount}`,children:[so(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 Oc({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?io(n,r):void 0,onClick:()=>i(null),children:[(0,J.jsx)(C,{className:`fm-icon folder`,width:14,height:14}),(0,J.jsx)(`span`,{className:`fm-tab-name`,children:n?Q(io(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:io(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)(Wo,{entry:{name:Q(e.path),kind:`file`,bag:!1,mode:420,link:null},size:14}),(0,J.jsx)(`span`,{className:`fm-tab-name`,children:Q(e.path)}),_c(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 ${Q(e.path)}`,title:`Close`,onClick:t=>{t.stopPropagation(),a(e)},children:(0,J.jsx)(H,{width:12,height:12})})]},e.id))]})}function kc({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:Ge.viewUrl(e,String(t)),alt:Q(e),onLoad:e=>n(`${e.currentTarget.naturalWidth} × ${e.currentTarget.naturalHeight}`),onError:()=>o(!0)})})}var Ac=20,jc=6,Mc=10,Nc=4,Pc=30,Fc=5e4,Ic={open:!1,replace:!1,query:``,replacement:``,options:{caseSensitive:!1,regex:!1,wholeWord:!1}};function Lc(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(Bs(t,n[i],e.states[i]).state);return e.states}function Rc(e,t){let n=0;for(let r=0;r<t&&r<e.length;r++)n=e[r]===` `?(Math.floor(n/Nc)+1)*Nc:n+1;return n}function zc(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 Bc({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)(re,{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)(re,{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)(H,{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 Vc=(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)({...Ic,open:!1}),[E,D]=(0,q.useState)(-1),O=(0,q.useMemo)(()=>c.split(`
|
|
55
|
+
`),[c]),k=(0,q.useMemo)(()=>$s(c),[c]),A=(0,q.useMemo)(()=>w.open&&w.query?lc(c,w.query,w.options):{matches:[],error:null,capped:!1},[w.open,w.query,w.options,c]),{matches:j}=A;(0,q.useEffect)(()=>{Ic=w},[w]);let M=()=>{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-jc)/Ac),a=Math.ceil((t+r)/Ac);C(e=>i>=e.first&&a<=e.last&&e.last-e.first<=a-i+120?e:{first:Math.max(0,i-Pc),last:a+Pc})},N=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=ec(k,e),r=jc+t*Ac;r<n.scrollTop+jc?n.scrollTop=r-jc:r+Ac>n.scrollTop+n.clientHeight-jc&&(n.scrollTop=r+Ac-n.clientHeight+12);let i=Mc+Rc(O[t]??``,e-k[t])*y.current;i<n.scrollLeft+Mc?n.scrollLeft=Math.max(0,i-Mc-4*y.current):i>n.scrollLeft+n.clientWidth-4*y.current&&(n.scrollLeft=i-n.clientWidth+8*y.current)}M()}},P=(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,P.current?N(r):(P.current=!0,t.scrollTop=e.scroll.top,t.scrollLeft=e.scroll.left,M())}),(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(M);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)(M,[t]),(0,q.useImperativeHandle)(o,()=>({focus:()=>d.current?.focus({preventScroll:!0}),goToLine:e=>{let t=Math.min(O.length,Math.max(1,e))-1;F({start:k[t],end:k[t]}),d.current?.focus({preventScroll:!0})},find:e=>R(e)}));let F=e=>{let t=d.current;t&&(t.setSelectionRange(e.start,e.end),v.current=e,r({type:`view`,id:s,selection:e}),N(e.end))},I=(t,i,a=`other`)=>{let o=Gs(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()})},L=(e,t=`other`)=>{let n=d.current;if(!n)return;let{selectionStart:r,selectionEnd:i}=n,a=r+e.length;I(c.slice(0,r)+e+c.slice(i),{start:a,end:a},t)},R=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()})},ee=()=>{T({...w,open:!1}),D(-1),d.current?.focus({preventScroll:!0})},te=e=>{if(j.length===0)return;let t=e>0?v.current.end:v.current.start,n;E>=0&&j[E][0]===v.current.start&&j[E][1]===v.current.end?n=(E+e+j.length)%j.length:e>0?(n=j.findIndex(([e])=>e>=t),n=n<0?0:n):(n=j.findLastIndex(([,e])=>e<=t),n=n<0?j.length-1:n),D(n),F({start:j[n][0],end:j[n][1]})};(0,q.useEffect)(()=>{if(!w.open||j.length===0){D(-1);return}let e=j.findIndex(([e])=>e>=v.current.start),t=e<0?0:e;D(t),N(j[t][0])},[w.query,w.options,w.open]);let z=()=>{let e=j[E];if(!e||n){te(1);return}let t=dc(c,e[0],w.query,w.replacement,w.options);if(t===null)return;let r=e[0]+t.length;I(c.slice(0,e[0])+t+c.slice(e[1]),{start:r,end:r})},ne=()=>{if(!n)try{let e=fc(c,w.query,w.replacement,w.options);if(e.count>0){let t=Math.min(v.current.start,e.text.length);I(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`)}},re=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(()=>R(!1));else if(t&&o===`h`)f(()=>R(!0));else if(t&&o===`g`||e.key===`F3`)f(()=>w.open&&w.query?te(e.shiftKey?-1:1):R(!1));else if(t&&o===`i`)f(a);else if(e.key===`Escape`&&w.open)f(ee);else if(n)return;else if(t&&(o===`/`||e.code===`Slash`)){let e=Rs(l);e&&f(()=>{let t=oc(c,v.current,e);I(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=ac(c,n,u,e.shiftKey);I(t.text,t.selection)}else L(nc(u),`type`)}):e.key===`Enter`&&!t&&!e.shiftKey&&!e.altKey&&!e.nativeEvent.isComposing&&f(()=>L(sc(c,d.current.selectionStart)))},ie=()=>{let e=d.current;if(!e||n)return;let t=e.value,i=g.current,a=Gs(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},ae=()=>{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})))},oe=O.length<=Fc?l:`plain`,se=ec(k,e.selection.end),ce=Math.min(S.first,O.length),B=Math.min(S.last,O.length),le=t?[]:Lc(b.current,oe,O,B),ue=[],de=[];if(!t){let e=0,t=j.length;for(;e<t;){let n=e+t>>1;j[n][1]<=k[ce]?e=n+1:t=n}let n=e;for(let e=ce;e<B;e++){let t=O[e],r=k[e];for(;n<j.length&&j[n][1]<=r;)n++;let{spans:i}=Bs(oe,t,le[e]??0);ue.push((0,J.jsx)(`div`,{className:`fm-line`,style:{top:jc+e*Ac},children:zc(t,r,i,j,E,n)},e)),de.push((0,J.jsx)(`div`,{className:`fm-number${e===se?` current`:``}`,style:{top:jc+e*Ac},onPointerDown:t=>{t.preventDefault();let n=e+1<k.length?k[e+1]:c.length;F({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)(Bc,{find:w,count:j.length,current:E,capped:A.capped,error:A.error,readOnly:n,inputRef:m,onChange:T,onStep:te,onReplace:z,onReplaceAll:ne,onClose:ee}),(0,J.jsxs)(`div`,{className:`fm-text${t?` wrap`:``}`,style:{"--fm-gutter":`${String(O.length).length+2}ch`,"--fm-tab":Nc},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+O.length*Ac},children:de})}),(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:jc+se*Ac}}),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:ie,onKeyDown:re,onSelect:ae,onScroll:M})]})]})]})}),Hc=620,Uc=316,Wc=420,Gc=3e4,Kc=12,qc=`tassello.fileManager.bookmarks`,Jc=`application/x-tassello-files`,Yc=800,Xc=5,Zc=520,Qc=null,$c=new Set;function el(e){Qc=e,$c.forEach(e=>e())}function tl(e){return $c.add(e),()=>$c.delete(e)}var nl=new Set;function rl(e){nl.forEach(t=>t(e))}var il=!1;function al(){il||(il=!0,window.addEventListener(`beforeunload`,e=>{Sc()&&e.preventDefault()}))}function ol(e){return e.split(`
|
|
59
|
+
`).map(e=>e.trim()).filter(Boolean)}function sl(e){try{let t=JSON.parse(localStorage.getItem(qc)??`{}`);return Array.isArray(t[e])?t[e]:[]}catch{return[]}}function cl(e,t){try{let n=JSON.parse(localStorage.getItem(qc)??`{}`);t.length>0?n[e]=t:delete n[e],localStorage.setItem(qc,JSON.stringify(n))}catch{}}function ll(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 ul({config:e,instance:t,panelId:n}){let r=`${n}/${t.id}`,i=e.folder.trim()||`~`,[a]=(0,q.useState)(()=>{let e=xc.get(r);return e?.config===i?e:{config:i,state:pc(i)}}),[o,s]=(0,q.useReducer)(bc,a.state),c=(0,q.useRef)(a.config),l=et(),u=e.readOnly,[d,f]=(0,q.useState)(null),[p,h]=(0,q.useState)(null),[_,v]=(0,q.useState)(0),[y,b]=(0,q.useState)(null),[x,S]=(0,q.useState)(null),[C,T]=(0,q.useState)(new Set),[E,O]=(0,q.useState)(null),[A,j]=(0,q.useState)(null),[N,P]=(0,q.useState)({key:`name`,descending:!1}),[F,I]=(0,q.useState)(``),[L,R]=(0,q.useState)(e.showHidden),[ee,te]=(0,q.useState)(e.wrap),[z,re]=(0,q.useState)(`list`),[ie,ae]=(0,q.useState)(!1),[ce,B]=(0,q.useState)(null),[le,ue]=(0,q.useState)(null),[de,V]=(0,q.useState)(null),[fe,H]=(0,q.useState)(null),[U,me]=(0,q.useState)(null),[he,ge]=(0,q.useState)(null),[ve,ye]=(0,q.useState)(null),[be,xe]=(0,q.useState)(null),[Se,Ce]=(0,q.useState)(!1),[Ee,Oe]=(0,q.useState)(null),[ke,Ae]=(0,q.useState)(null),[Me,Ne]=(0,q.useState)(null),[W,Pe]=(0,q.useState)(``),[Fe,Ie]=(0,q.useState)(0),[Le,Re]=(0,q.useState)(()=>sl(r)),ze=(0,q.useSyncExternalStore)(tl,()=>Qc),Be=ll(3e4),Ve=(0,q.useRef)(null),He=(0,q.useRef)(null),Ue=(0,q.useRef)(null),We=(0,q.useRef)(null),Ke=(0,q.useRef)(null),qe=(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)(o.folder);$e.current=o.folder;let tt=(0,q.useRef)(o.tabs);tt.current=o.tabs,(0,q.useEffect)(al,[]),(0,q.useEffect)(()=>(nl.add(s),()=>void nl.delete(s)),[]),(0,q.useEffect)(()=>{xc.set(r,{config:c.current,state:o})},[r,o]),(0,q.useEffect)(()=>{i!==c.current&&(c.current=i,s({type:`go`,folder:i}))},[i]),(0,q.useEffect)(()=>R(e.showHidden),[e.showHidden]),(0,q.useEffect)(()=>te(e.wrap),[e.wrap]),(0,q.useEffect)(()=>{Ge.places().then(f,()=>f({home:``,user:``,ros:[]}))},[]),(0,q.useEffect)(()=>{if(o.folder.startsWith(`/`)){S(null);return}let e=!0;return Ge.list(o.folder).then(t=>e&&t&&s({type:`resolved`,from:o.folder,folder:t.path}),t=>e&&S(rs(t))),()=>{e=!1}},[o.folder]),(0,q.useEffect)(()=>{e.confine?i.startsWith(`/`)?b(oo(i,`/`,``)):Ge.list(i).then(e=>e&&b(e.path),()=>b(null)):b(null)},[e.confine,i]),(0,q.useEffect)(()=>{let e=Ve.current;if(!e)return;let t=new ResizeObserver(([e])=>Ie(e.contentRect.width));return t.observe(e),()=>t.disconnect()},[]);let nt=d?.home??``,K=o.folder.startsWith(`/`)?o.folder:``,rt=Fe>0&&Fe<Hc,it=o.tabs.find(e=>e.id===o.active)??null,at=it===null,ot=ce??!rt,st=e.confine&&y!==null;(0,q.useEffect)(()=>{if(!(ot||z===`overview`)||e.confine)return;let t=!0,n=()=>{document.visibilityState===`visible`&&Ge.disks().then(e=>t&&h(e),()=>{})};n();let r=setInterval(n,Gc);return()=>{t=!1,clearInterval(r)}},[ot,z,e.confine,_]);let{listings:ct,errors:lt,offline:ut,refresh:dt}=as((0,q.useMemo)(()=>K?[K,...[...o.expanded].filter(e=>e!==K&&ro(e,K)).slice(0,Kc)]:[],[K,o.expanded])),ft=ct.get(K)??null,pt=K?lt.get(K)??null:x,mt=(0,q.useMemo)(()=>({hidden:L,text:F}),[L,F]),ht=(0,q.useMemo)(()=>ft?Co(K,ct,lt,o.expanded,N,mt):[],[ft,K,ct,lt,o.expanded,N,mt]),gt=(0,q.useMemo)(()=>{let e=new Map;for(let t of ht)t.type===`entry`&&e.set(t.path,t.entry);return e},[ht]),_t=(0,q.useMemo)(()=>new Set(ze?.cut?ze.paths:[]),[ze]);(0,q.useEffect)(()=>{ue(null),I(``);let e=Qe.current;e&&no(e)===K?(Qe.current=null,T(new Set([e])),O(e),j(e),Oe(t=>({path:e,seq:(t?.seq??0)+1}))):(T(new Set),O(null),j(null))},[K]),(0,q.useEffect)(()=>{ft&&T(e=>{let t=[...e].filter(e=>gt.has(e));return t.length===e.size?e:new Set(t)})},[gt,ft]);let vt=()=>requestAnimationFrame(()=>(Ve.current?.querySelector(`.fm-list, .fm-area`)??Ve.current)?.focus({preventScroll:!0})),yt=e=>{T(new Set([e])),O(e),j(e),Oe(t=>({path:e,seq:(t?.seq??0)+1}))},bt=e=>{st&&!ro(e,y)?G(`This widget stays in ${io(y,nt)}`,`error`):s({type:`go`,folder:e})},xt=e=>{let t=no(e);t&&(re(`list`),t===K?(s({type:`activate`,id:null}),yt(e)):(Qe.current=e,bt(t)))},St=(e,t=gt.get(e))=>{if(!t)return;if(t.kind===`dir`){bt(e);return}let n=No(t);n===`image`?s({type:`open`,path:e,kind:`image`}):n===`text`?s({type:`open`,path:e,kind:`text`}):(yt(e),ae(!0))},Y=async e=>{let t=oo(e,K||`/`,nt);try{let e=await Ge.details(t);e.kind===`dir`?bt(e.path):(xt(e.path),St(e.path,e))}catch(e){G(rs(e),`error`)}},X=(e,t,n)=>new Promise(r=>H({names:e,folder:t,verb:n,resolve:r})),Ct=async e=>{try{return await Ge.operate(e)}catch(e){return G(rs(e),`error`),null}finally{dt()}},wt=async(e,t,n)=>{let r=t.filter(t=>e===`copy`||no(t)!==n);if(u||r.length===0)return;let i=`ask`,a=await Ct({op:e,paths:r,to:n,conflict:i});if(a&&a.conflicts.length>0){let t=await X(a.conflicts,n,e===`move`?`moved`:`copied`);if(!t)return;i=t,a=await Ct({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=to(n,Q(e));o.includes(t)&&rl({type:`moved`,from:e,to:t})}let s=no(r[0]),c=s!==null&&r.every(e=>no(e)===s)&&i!==`replace`?{label:`Undo`,run:()=>void(e===`move`?wt(`move`,o,s):Tt(o,!1))}:void 0;G(`${e===`move`?`Moved`:`Copied`} ${Lo(o.map(Q),2)} into ${Q(n)}`,`info`,c),n===$e.current&&(T(new Set(o)),Oe(e=>({path:o[0],seq:(e?.seq??0)+1})))},Tt=async(e,t=!0)=>{if(u||e.length===0)return;let n=e.filter(e=>gt.get(e)?.kind===`dir`).length,r=o.tabs.filter(t=>_c(t)&&e.some(e=>ro(t.path,e))).length;(!t||await l.confirm({title:e.length===1?`Delete ${Q(e[0])}?`:`Delete ${zo(e.length)}?`,message:(0,J.jsxs)(J.Fragment,{children:[e.length>1&&(0,J.jsx)(`p`,{children:(0,J.jsx)(`strong`,{children:Lo(e.map(Q),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?` ${Ro(r,`file`)} open here ${r===1?`has`:`have`} changes not saved.`:``]})]}),confirmLabel:`Delete`,danger:!0}))&&await Ct({op:`delete`,paths:e})&&(rl({type:`deleted`,paths:e}),T(new Set),G(`Deleted ${Lo(e.map(Q),2)}`))},Et=async(e,t)=>{if(ue(null),vt(),t===null||!t||t===Q(e)||u)return;if(t.includes(`/`)){G(`A name has no /: move it with Cut and Paste instead`,`error`);return}let n=await Ct({op:`rename`,path:e,name:t});if(n){let t=n.paths[0];rl({type:`moved`,from:e,to:t}),yt(t)}},Dt=async e=>{if(u||!K)return;let t=await l.prompt({title:e===`mkdir`?`New folder`:`New file`,label:`Its name`,initial:To(ft?.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=to(K,t);await Ct({op:e,path:n})&&(re(`list`),yt(n),e===`create`&&s({type:`open`,path:n,kind:`text`}))},Ot=async(e,t)=>{await Ct({op:`chmod`,path:e,mode:t})},kt=e=>{e.length!==0&&(e.every(t=>no(t)===no(e[0]))?ns(Ge.downloadUrl(e)):G(`Download entries of one folder at a time`,`error`))},At=async(e,t)=>{if(u||e.length===0)return;if(ve){G(`Uploading already: wait for it, or cancel it`,`error`);return}let n=ct.get(t)?.entries??(await Ge.list(t).catch(()=>void 0))?.entries,r=Io(n,[...new Set(e.map(({name:e})=>e.split(`/`)[0]))]),i=`ask`,a=new Map;if(r.length>0){let o=await X(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,To(n??[],t))}let o=e.reduce((e,{file:t})=>e+t.size,0),s=0,c=!1,l=null,d=()=>{c=!0,l?.abort()},f=[],p=0,m=null;for(let n=0;n<e.length&&!c;n++){let{file:r,name:c}=e[n],[u,...h]=c.split(`/`),g=h.length>0&&a.has(u)?[a.get(u),...h].join(`/`):c;ye({name:Q(g),index:n,count:e.length,sent:s,total:o,abort:d});let _=s;l=Ge.upload(t,g,r,i,e=>ye(t=>t&&{...t,sent:_+e}));try{let e=await l.result;f.push(...e.paths),p+=e.conflicts.length}catch(e){if(!(e instanceof DOMException&&e.name===`AbortError`)){m=`${Q(g)}: ${rs(e)}`;break}}s+=r.size}ye(null),dt(),m?G(`Upload stopped at ${m}`,`error`):G(c?`Upload cancelled: ${f.length} of ${Ro(e.length,`file`)} uploaded`:`Uploaded ${Ro(f.length,`file`)} into ${Q(t)}${p>0?`, ${p} skipped`:``}`);let h=[...new Set(f.map(e=>(t===`/`?``:t)+`/`+e.slice(t.length).split(`/`).filter(Boolean)[0]))];t===$e.current&&h.length>0&&(T(new Set(h)),Oe(e=>({path:h[0],seq:(e?.seq??0)+1})))},jt=e=>{if(!Qc||u)return;let{paths:t,cut:n}=Qc;n&&el(null),wt(n?`move`:`copy`,t,e)},Mt=(e,t)=>{e.length===0||t&&u||(el({paths:e,cut:t}),ts(e.join(`
|
|
60
|
+
`)).catch(()=>{}),G(`${t?`Cut`:`Copied`} ${Lo(e.map(Q),2)}: paste ${e.length===1?`it`:`them`} into a folder`))},Pt=e=>ts(e).then(()=>G(`Copied ${e}`),e=>G(`Could not copy the path: ${rs(e)}`,`error`)),Ft=(0,q.useMemo)(()=>[...ol(e.bookmarks).map(e=>({path:e,removable:!1})),...Le.map(e=>({path:e,removable:!0}))].map(({path:e,removable:t})=>({path:oo(e,`/`,nt),removable:t})),[e.bookmarks,Le,nt]),It=(0,q.useMemo)(()=>{let e=[],t=t=>{(!st||ro(t.path,y))&&!e.some(e=>e.path===t.path&&e.kind===t.kind)&&e.push({removable:!1,...t})};nt&&t({name:d?.user?`Home (${d.user})`:`Home`,path:nt,kind:`home`}),st||t({name:`The root`,path:`/`,kind:`root`});let n=y??(i.startsWith(`/`)?i:null);n&&n!==nt&&n!==`/`&&t({name:Q(n),path:n,kind:`folder`});for(let e of d?.ros??[])t({name:e.name,path:e.path,kind:`ros`});for(let{path:e,removable:n}of Ft)t({name:Q(e),path:e,kind:`bookmark`,removable:n});return e},[nt,d,st,y,i,Ft]),Lt=()=>{if(!K||Ft.some(e=>e.path===K))return;let e=[...Le,io(K,nt)];Re(e),cl(r,e)},Rt=e=>{let t=Le.filter(t=>oo(t,`/`,nt)!==e);Re(t),cl(r,t)},zt=[...C],Bt=K?no(K):null,Vt=Bt!==null&&(!st||ro(Bt,y)),Ht=e=>{let t=gt.get(e),n=C.has(e)?[...C]:[e];C.has(e)||(T(new Set([e])),O(e),j(e));let r=n.length===1,i=t?No(t):`other`,a=[];return r&&t&&(a.push({label:t.kind===`dir`?`Open`:i===`text`?`Edit`:i===`image`?`View`:`Details`,run:()=>St(e)}),t.kind===`file`&&i!==`text`&&a.push({label:`Open as text`,run:()=>s({type:`open`,path:e,kind:`text`})})),a.push({label:r&&t?.kind===`dir`?`Download as .tar.gz`:`Download`,run:()=>kt(n)}),u||(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`&&Qc&&a.push({label:`Paste into it`,run:()=>jt(e)}),a.push({label:`Duplicate`,run:()=>void wt(`copy`,n,no(n[0])??`/`)},{label:`Move to…`,run:()=>me({paths:n,copy:!1})},{label:`Copy to…`,run:()=>me({paths:n,copy:!0})}),r&&a.push({label:`Rename`,keys:`F2`,run:()=>ue(e),separated:!0})),r&&a.push({label:`Copy the path`,run:()=>void Pt(e),separated:u}),a.push({label:`Details`,keys:`Alt+Enter`,run:()=>ae(!0)}),u||a.push({label:`Delete`,keys:`Delete`,danger:!0,separated:!0,run:()=>void Tt(n)}),a},Ut=e=>[...u?[]:[{label:`New folder…`,run:()=>void Dt(`mkdir`),narrow:e},{label:`New file…`,run:()=>void Dt(`create`)},{label:`Upload files…`,run:()=>Ke.current?.click(),narrow:e},{label:`Upload a folder…`,run:()=>qe.current?.click()},{label:`Paste`,keys:`Ctrl+V`,disabled:!Qc,run:()=>jt(K)}],{label:`Select all`,keys:`Ctrl+A`,run:()=>T(new Set(ht.flatMap(e=>e.type===`entry`&&e.depth===0?[e.path]:[]))),separated:!u},{label:L?`Hide the hidden files`:`Show the hidden files`,keys:`Ctrl+H`,run:()=>R(e=>!e)},{label:`Read again`,run:dt},{label:z===`overview`?`Back to the files`:`What takes the space`,run:()=>re(z===`overview`?`list`:`overview`),narrow:e,separated:!0},{label:ie?`Hide the details`:`Details`,run:()=>ae(e=>!e),narrow:e},{label:`Download this folder`,run:()=>kt([K]),separated:!0},{label:`Copy its path`,run:()=>void Pt(K)},{label:`Bookmark this folder`,disabled:Ft.some(e=>e.path===K),run:Lt}],Wt=(e,t,n)=>V({x:e,y:t,items:n}),Gt=(0,q.useRef)(null),Kt=(0,q.useMemo)(()=>{let e=e=>((...t)=>Gt.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`)}},[]);Gt.current={onPointer:e=>{Ye.current=e},onClick:(e,t)=>{e?Ye.current===`touch`&&C.size===0?St(e):(j(e),t.shiftKey?T(new Set(wo(ht,E??e,e))):(O(e),t.ctrlKey||t.metaKey||Ye.current===`touch`&&C.size>0?T(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n}):T(new Set([e])))):(T(new Set),j(null))},onOpen:e=>St(e),onFold:(e,t)=>s({type:`fold`,folder:e,open:t}),onMenu:(e,t,n)=>Wt(t,n,e?Ht(e):Ut(!1)),onRename:(e,t)=>void Et(e,t),onDragStart:(e,t)=>{let n=C.has(e)?[...C]:[e];C.has(e)||(T(new Set([e])),O(e)),Xe.current=n,t.dataTransfer.effectAllowed=u?`copy`:`copyMove`,t.dataTransfer.setData(Jc,JSON.stringify(n)),t.dataTransfer.setData(`text/plain`,n.join(`
|
|
61
|
+
`));let r=gt.get(e);n.length===1&&r?.kind===`file`&&t.dataTransfer.setData(`DownloadURL`,`application/octet-stream:${r.name}:${new URL(Ge.downloadUrl([e]),location.href).href}`)},onDragEnd:()=>{Xe.current=null,xe(null),Ce(!1)},onDragOver:(e,t)=>qt(e,t),onDrop:(e,t)=>Jt(e,t),onKeyDown:(e,t)=>Yt(e,t)};let qt=(e,t)=>{let n=t.dataTransfer.types,r=n.includes(Jc);if(u||!r&&!n.includes(`Files`)||!K)return;let i=e??K;t.stopPropagation(),r&&Xe.current?.some(e=>ro(i,e))?(xe(null),Ce(!1)):(t.preventDefault(),t.dataTransfer.dropEffect=r&&!t.ctrlKey?`move`:`copy`,xe(e),Ce(e===null))},Jt=(e,t)=>{t.preventDefault(),t.stopPropagation(),xe(null),Ce(!1);let n=e??K;if(!n||u)return;let r=t.dataTransfer.getData(Jc);r?wt(t.ctrlKey?`copy`:`move`,JSON.parse(r),n):t.dataTransfer.types.includes(`Files`)&&is(t.dataTransfer).then(e=>void At(e,n),e=>G(`Cannot read what was dropped: ${rs(e)}`,`error`))},Yt=(e,t)=>{if(le)return;let n=e.ctrlKey||e.metaKey,r=e.key,i=ht.filter(e=>e.type===`entry`),a=A?i.findIndex(e=>e.path===A):-1,o=i[a],c=t=>{e.preventDefault(),t()},l=t=>{if(i.length===0)return;let r=i[Math.min(i.length-1,Math.max(0,t))].path;j(r),e.shiftKey?T(new Set(wo(ht,E??r,r))):n||(T(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`)c(()=>ae(!0));else if(r===`ArrowDown`)c(()=>l(a+1));else if(r===`ArrowUp`)c(()=>l(a<0?0:a-1));else if(r===`PageDown`)c(()=>l(a+t));else if(r===`PageUp`)c(()=>l(a-t));else if(r===`Home`)c(()=>l(0));else if(r===`End`)c(()=>l(i.length-1));else if(r===`ArrowRight`&&o?.type===`entry`&&o.open!==null)c(()=>o.open?l(a+1):s({type:`fold`,folder:o.path,open:!0}));else if(r===`ArrowLeft`&&o?.type===`entry`)c(()=>{o.open?s({type:`fold`,folder:o.path,open:!1}):o.depth>0&&l(i.findIndex(e=>e.path===no(o.path)))});else if(r===`Enter`)c(()=>{let e=C.size>0?[...C]:A?[A]:[],t=e.filter(e=>gt.get(e)?.kind===`dir`);e.filter(e=>gt.get(e)?.kind!==`dir`).forEach(e=>St(e)),t.length>0&&e.length===t.length&&St(t[0])});else if(r===`Backspace`)c(()=>Vt&&bt(Bt));else if(r===`Delete`)c(()=>void Tt(zt));else if(r===`F2`)c(()=>!u&&(A??zt[0])&&ue(A??zt[0]));else if(r===`Escape`)c(()=>C.size>0?T(new Set):ae(!1));else if(r===` `&&A)c(()=>T(e=>{let t=new Set(e);return t.delete(A)||t.add(A),t}));else if(n&&r.toLowerCase()===`a`)c(()=>T(new Set(ht.flatMap(e=>e.type===`entry`&&e.depth===0?[e.path]:[]))));else if(n&&r.toLowerCase()===`c`)c(()=>Mt(zt,!1));else if(n&&r.toLowerCase()===`x`)c(()=>Mt(zt,!0));else if(n&&r.toLowerCase()===`v`)c(()=>jt(K));else if(n&&r.toLowerCase()===`h`)c(()=>R(e=>!e));else if(r.length===1&&!n&&!e.altKey){let e=Date.now(),t=(e-Ze.current.at<Yc?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&&c(()=>l(o))}}},Xt=(0,q.useRef)(new Set);(0,q.useEffect)(()=>{for(let e of o.tabs){let t=`${e.id}:${e.reads}`;e.kind!==`text`||Xt.current.has(t)||e.text!==null&&e.reads===0||(Xt.current.add(t),Ge.readText(e.path).then(t=>t&&s({type:`read`,id:e.id,file:t}),t=>s({type:`failed`,id:e.id,error:rs(t)})))}},[o.tabs]),(0,q.useEffect)(()=>{let e=setInterval(()=>{if(document.visibilityState===`visible`)for(let e of tt.current)e.kind!==`text`||e.stamp===null||e.missing||Ge.readText(e.path,e.stamp).then(t=>t&&s({type:`changed`,id:e.id,file:t}),t=>t instanceof Je&&t.status===404&&s({type:`missing`,id:e.id}))},es);return()=>clearInterval(e)},[]);let Zt=e=>e.eol===`\r
|
|
62
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
|
|
63
|
+
`):e.text,Qt=async e=>{if(e.text===null||Me!==null||!_c(e))return;if(u){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 Ge.saveText(e.path,Zt(e),e.missing?null:e.base,e.missing);n.conflict?(s({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`)):(s({type:`saved`,id:e.id,text:t,version:n.version,stamp:n.stamp}),G(`Saved ${Q(e.path)}`),dt())}catch(t){G(`Could not save ${e.path}: ${rs(t)}`,`error`)}finally{Ne(null)}},$t=async e=>{(!_c(e)||await l.confirm({title:`Close ${Q(e.path)}?`,message:`Its changes are not saved.`,confirmLabel:`Close it`,danger:!0}))&&s({type:`close`,id:e.id})},en=async e=>{let t=$s(e.text??``),n=await l.prompt({title:`Go to line`,label:`Line, 1 to ${t.length.toLocaleString()}`,initial:String(ec(t,e.selection.end)+1),confirmLabel:`Go`}),r=Number(n);n&&Number.isFinite(r)&&We.current?.goToLine(Math.round(r))},Z=it?.kind===`text`?it:null;(0,q.useEffect)(()=>Pe(``),[it?.id]);let tn=e=>{let t=e.ctrlKey||e.metaKey,n=e.key.toLowerCase();if(Z&&t&&n===`s`)e.preventDefault(),Qt(Z);else if(at&&t&&n===`f`&&!e.target.closest(`input, textarea`))e.preventDefault(),Ue.current?.focus();else if(at&&t&&n===`l`)e.preventDefault(),Ae(io(K,nt));else if(at&&e.altKey&&!e.target.closest(`input, textarea`)){let t={arrowup:()=>Vt&&bt(Bt),arrowleft:()=>s({type:`back`}),arrowright:()=>s({type:`forward`})}[n];t&&(e.preventDefault(),t())}},nn;if(it?.kind===`image`)nn=(0,J.jsx)(kc,{path:it.path,reads:it.reads,onSize:Pe});else if(Z)nn=Z.text===null?(0,J.jsxs)(`div`,{className:`widget-message${Z.error?` error`:``} fm-empty`,children:[(0,J.jsx)(`p`,{children:Z.error??`Reading…`}),Z.error&&(0,J.jsxs)(`div`,{className:`fm-empty-actions`,children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>kt([Z.path]),children:`Download it`}),` `,(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>s({type:`close`,id:Z.id}),children:`Close`})]})]}):(0,J.jsx)(Vc,{ref:We,tab:Z,wrap:ee,readOnly:u,dispatch:s,onSave:()=>void Qt(Z),onGoToLine:()=>void en(Z)},Z.id);else if(z===`overview`&&K)nn=(0,J.jsx)(ps,{folder:K,home:nt,disks:e.confine?null:p,now:Be,onGo:e=>{re(`list`),bt(e)},onReveal:xt,onRefreshDisks:()=>v(e=>e+1)});else{let e;e=pt?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`p`,{children:pt}),Vt&&(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>bt(Bt),children:`Go up`}),` `,!K&&nt&&(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>bt(nt),children:`Go home`})]}):ft?F?`No name contains “${F}”`:ft.entries.length>0?`Only hidden files: ${ft.entries.length.toLocaleString()} (Ctrl+H)`:u?`Empty folder`:`Empty folder: drop files here to upload them`:ut?`Cannot reach the robot`:`Reading…`,nn=(0,J.jsx)(`div`,{ref:He,className:`fm-files`,children:(0,J.jsx)(Jo,{rows:ht,version:K,selected:C,focus:A,cut:_t,dropTarget:be,droppingHere:Se,renaming:le,sort:N,now:Be,empty:e,reveal:Ee,handlers:Kt,onSort:e=>P(t=>({key:e,descending:t.key===e?!t.descending:e!==`name`}))})})}let rn=Fe-(ot&&!rt?240:0),an=at&&ie&&K!==``,on=an&&rn-Uc>=Wc,sn=[];Z?.external&&sn.push({text:Z.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`,id:Z.id})},{label:`Keep mine`,run:()=>s({type:`keep`,id:Z.id})}]}),Z?.missing&&sn.push({text:`Deleted on the robot: saving makes it again`,tone:`warning`}),ut&&(ft||Z)&&sn.push({text:`Cannot reach the robot: what is shown may be out of date`,tone:`error`}),ft&&ft.truncated>0&&at&&z===`list`&&sn.push({text:`${ft.truncated.toLocaleString()} more entries are not listed: the folder is too large`,tone:`warning`});let cn=it?it.path:K,ln=cn?ao(cn,nt,st?y:`/`):[],un=Fe>0&&Fe<Zc?2:Xc,dn=ln.length<=un?ln:un===2?[{name:`…`,path:null},ln[ln.length-1]]:[ln[0],{name:`…`,path:null},...ln.slice(-(un-2))],fn=ke===null?(0,J.jsx)(`div`,{className:`fm-crumbs bt-path`,title:`Click to type a path (Ctrl+L)`,onClick:e=>e.target===e.currentTarget&&at&&Ae(io(K,nt)),children:dn.map((e,t)=>{let n=t===dn.length-1,{path:r}=e;return r===null?(0,J.jsx)(`button`,{type:`button`,title:io(cn,nt),onClick:()=>Ae(io(it?no(cn)??`/`:K,nt)),children:`…`},`…`):(0,J.jsx)(`button`,{type:`button`,className:`${n?`current`:``}${be===r?` drop-into`:``}`,title:io(r,nt),onClick:()=>n&&it?void 0:n?Ae(io(K,nt)):bt(r),onDragOver:e=>qt(r,e),onDrop:e=>Jt(r,e),children:e.name},r)})}):(0,J.jsx)(`form`,{className:`fm-address`,onSubmit:e=>{e.preventDefault(),Ae(null),vt(),Y(ke)},children:(0,J.jsx)(`input`,{value:ke,autoFocus:!0,spellCheck:!1,"aria-label":`Go to the folder`,onChange:e=>Ae(e.target.value),onKeyDown:e=>{e.key===`Escape`&&(Ae(null),vt())},onBlur:()=>Ae(null)})}),pn=(e,t)=>{let n=e.currentTarget.getBoundingClientRect();Wt(n.left,n.bottom+4,t)},mn;if(Z){let e=_c(Z);mn=(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`button`,{type:`button`,className:`button bte-save${e?` primary`:``}`,disabled:!e||Me!==null||u||Z.readOnly!==null&&!Z.missing,title:Z.readOnly?`${Z.readOnly}: Save as…`:`Save (Ctrl+S)`,onClick:()=>void Qt(Z),children:[(0,J.jsx)(pe,{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:Z.history.past.length===0,onClick:()=>s({type:`undo`,id:Z.id}),children:(0,J.jsx)(_e,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Redo (Ctrl+Shift+Z)`,"aria-label":`Redo`,disabled:Z.history.future.length===0,onClick:()=>s({type:`redo`,id:Z.id}),children:(0,J.jsx)(De,{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:Z.text===null,onClick:()=>We.current?.find(!1),children:(0,J.jsx)(ne,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,"aria-pressed":ee,title:`Wrap long lines`,"aria-label":`Wrap long lines`,onClick:()=>te(e=>!e),children:(0,J.jsx)(g,{width:17,height:17})}),fn,(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-label":`File`,title:`File`,onClick:t=>pn(t,[{label:ee?`Do not wrap the lines`:`Wrap long lines`,run:()=>te(e=>!e),narrow:!0},{label:`Save as…`,disabled:Z.text===null||u,run:()=>ge(Z.id)},{label:`Download`,run:()=>kt([Z.path])},{label:`Go to line…`,keys:`Ctrl+I`,disabled:Z.text===null,run:()=>void en(Z)},{label:e?`Discard the changes`:`Read it again`,danger:e,run:async()=>{(!e||await l.confirm({title:`Discard the changes?`,message:`The file is read again from the robot.`,confirmLabel:`Discard them`,danger:!0}))&&s({type:`reload`,id:Z.id})}},{label:`Show it in its folder`,run:()=>xt(Z.path),separated:!0},{label:`Copy its path`,run:()=>void Pt(Z.path)},{label:`Close`,run:()=>void $t(Z),separated:!0}]),children:(0,J.jsx)(k,{width:17,height:17})})]})}else mn=it?(0,J.jsxs)(J.Fragment,{children:[fn,(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Download`,"aria-label":`Download`,onClick:()=>kt([it.path]),children:(0,J.jsx)(M,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-label":`Image`,title:`Image`,onClick:e=>pn(e,[{label:`Open as text`,run:()=>s({type:`open`,path:it.path,kind:`text`})},{label:`Show it in its folder`,run:()=>xt(it.path)},{label:`Copy its path`,run:()=>void Pt(it.path)},{label:`Close`,run:()=>void $t(it),separated:!0}]),children:(0,J.jsx)(k,{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:o.back.length===0,onClick:()=>s({type:`back`}),children:(0,J.jsx)(we,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,title:`Forward (Alt+→)`,"aria-label":`Forward`,disabled:o.forward.length===0,onClick:()=>s({type:`forward`}),children:(0,J.jsx)(je,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button${be===Bt?` drop-into`:``}`,title:`Up (Alt+↑)`,"aria-label":`Up`,disabled:!Vt,onClick:()=>Vt&&bt(Bt),onDragOver:e=>Vt&&qt(Bt,e),onDrop:e=>Vt&&Jt(Bt,e),children:(0,J.jsx)(se,{width:17,height:17})}),fn,(0,J.jsxs)(`label`,{className:`fm-search fm-filter`,title:`Only the names containing these words (Ctrl+F)`,children:[(0,J.jsx)(ne,{width:14,height:14}),(0,J.jsx)(`input`,{ref:Ue,type:`search`,value:F,placeholder:`Filter…`,"aria-label":`Only the names containing`,spellCheck:!1,onChange:e=>{I(e.target.value),re(`list`)},onKeyDown:e=>{if(e.key===`Escape`)I(``),He.current?.querySelector(`.fm-list`)?.focus();else if(e.key===`ArrowDown`||e.key===`Enter`){e.preventDefault(),He.current?.querySelector(`.fm-list`)?.focus();let t=ht.find(e=>e.type===`entry`);t&&(yt(t.path),e.key===`Enter`&&ht.filter(e=>e.type===`entry`).length===1&&St(t.path))}}})]}),!u&&(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:!K,onClick:()=>void Dt(`mkdir`),children:(0,J.jsx)(D,{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:!K||ve!==null,onClick:()=>Ke.current?.click(),children:(0,J.jsx)(w,{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":z===`overview`,title:`What takes the space: the disks, this folder`,"aria-label":`What takes the space`,disabled:!K,onClick:()=>re(z===`overview`?`list`:`overview`),children:(0,J.jsx)(Te,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button bte-wide`,"aria-pressed":ie,title:`Details (Alt+Enter)`,"aria-label":`Details`,disabled:!K,onClick:()=>ae(e=>!e),children:(0,J.jsx)(m,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-label":`Folder`,title:`Folder`,disabled:!K,onClick:e=>pn(e,Ut(!0)),children:(0,J.jsx)(k,{width:17,height:17})})]});return(0,J.jsxs)(`div`,{ref:Ve,className:`bt bte fm`,tabIndex:-1,onKeyDown:tn,onDragLeave:e=>{e.currentTarget.contains(e.relatedTarget)||(xe(null),Ce(!1))},children:[sn.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":ot,title:`The places`,"aria-label":`The places`,onClick:()=>B(!ot),children:(0,J.jsx)(oe,{width:17,height:17})}),mn]}),o.tabs.length>0&&(0,J.jsx)(Oc,{tabs:o.tabs,active:o.active,folder:K,home:nt,onActivate:e=>s({type:`activate`,id:e}),onClose:e=>void $t(e)}),(0,J.jsxs)(`div`,{className:`bte-body fm-body${rt?` narrow`:``}`,children:[ot&&(0,J.jsx)(wc,{places:It,disks:e.confine?null:p,folder:cn,dropTarget:be,canBookmark:K!==``&&!Ft.some(e=>e.path===K),onGo:e=>{s({type:`activate`,id:null}),bt(e),rt&&B(!1)},onBookmark:Lt,onRemoveBookmark:Rt,onDragOver:(e,t)=>qt(e,t),onDrop:(e,t)=>Jt(e,t),onClose:()=>B(!1)}),(0,J.jsxs)(`div`,{className:`bt-main fm-main${on?` beside`:``}`,children:[nn,an&&(0,J.jsx)($o,{paths:zt,folder:K,entries:gt,version:ft?.version??``,home:nt,readOnly:u,now:Be,actions:{onOpen:e=>St(e,gt.get(e)??void 0),onGo:bt,onDownload:kt,onRename:e=>{re(`list`),ue(e)},onMove:(e,t)=>me({paths:e,copy:t}),onDelete:e=>void Tt(e),onChmod:Ot},onClose:()=>ae(!1)})]})]}),(0,J.jsx)(Dc,{uploads:ve,textTab:Z,saving:Z!==null&&Me===Z.id,image:it?.kind===`image`?{path:it.path,size:W}:null,folder:{path:K,listing:ft,error:pt,offline:ut,shown:ht.filter(e=>e.type===`entry`&&e.depth===0).length,showHidden:L,selected:C.size,entries:zt.flatMap(e=>gt.get(e)??[])},readOnly:u,onSettings:e=>Z&&s({type:`settings`,id:Z.id,...e})}),(0,J.jsx)(`input`,{ref:Ke,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,K)}}),(0,J.jsx)(`input`,{ref:e=>{qe.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,K)}}),de&&(0,J.jsx)(os,{x:de.x,y:de.y,items:de.items,onClose:()=>V(null)}),fe&&(0,J.jsx)(ss,{question:fe,onDone:()=>H(null)}),U&&(0,J.jsx)(Nt,{kind:`folder`,start:K||`~`,onChoose:e=>{me(null),wt(U.copy?`copy`:`move`,U.paths,oo(e,`/`,nt))},onClose:()=>me(null)}),he!==null&&(()=>{let e=o.tabs.find(e=>e.id===he);return!e||e.kind!==`text`||e.text===null?null:(0,J.jsx)(cs,{initial:io(e.path,nt),text:Zt(e),onSaved:(t,n,r)=>{ge(null);let i=oo(t,`/`,nt);s({type:`saved`,id:e.id,text:e.text,version:n,stamp:r,path:i}),G(`Saved as ${t}`),dt()},onClose:()=>ge(null)})})()]})}var dl=Ye({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:C,defaultSize:{w:10,h:7},minSize:{w:4,h:4},component:ul,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
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
|
|
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 fl({config:e}){let t=qe(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 pl=Ye({type:`image`,name:`Image Viewer`,description:`A static image: a file of the robot, or one uploaded from here.`,icon:L,defaultSize:{w:5,h:4},minSize:{w:1,h:1},component:fl,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`}]}),ml=22,hl=38,gl=8,_l=(0,q.memo)(function({entry:e,top:t,selected:n,time:r,showNode:i,onSelect:a}){let{level:o,tag:s}=Gi[Ki(e.level)],c=e.msg.indexOf(`
|
|
66
66
|
`),l=c<0?0:e.msg.split(`
|
|
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(`
|
|
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`?oa(e.stamp):aa(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 vl({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?hl:ml,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=ea(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:ea(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)-gl),S=Math.min(e.length,Math.ceil((p.top+p.height)/d)+gl),C=[];for(let t=x;t<S;t++){let r=e[t];C.push((0,J.jsx)(_l,{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 yl=560,bl=420,xl=300,Sl={min:6,max:22};async function Cl(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 wl(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 Tl(){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_${b.hostname||`robot`}_${n}_${r}.log`}function El(e){return`${e.toLocaleString()} message${e===1?``:`s`}`}function Dl({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)(H,{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`} · ${El(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:ca(i)}),a>0&&(0,J.jsx)(`span`,{className:`logs-node-badge warn`,children:ca(a)}),(0,J.jsx)(`span`,{className:`logs-node-count`,children:ca(e.total)})]})},e.name)})})]})}function Ol({entry:e,running:t,onOnly:n,onClose:r}){let{level:a,tag:o}=Gi[Ki(e.level)],s=Xi(e.name,t),c=()=>Cl(sa(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 ${a}`,"aria-label":`The message`,children:[(0,J.jsxs)(`header`,{className:`logs-details-header`,children:[(0,J.jsx)(`span`,{className:`logs-pill`,children:o}),(0,J.jsx)(`strong`,{className:`logs-details-node`,title:s??`${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)(i,{width:16,height:16})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Copy`,"aria-label":`Copy`,onClick:()=>void c(),children:(0,J.jsx)(z,{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)(H,{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:[oa(e.stamp),` · `,aa(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:s??`Not running`})]})]})]})}function kl({config:e}){let[t,n]=(0,q.useReducer)($i,Ji),[r,i]=(0,q.useState)({state:`waiting`,message:`Connecting…`}),[a,o]=(0,q.useState)(()=>qi(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,x]=(0,q.useState)(null),[S,C]=(0,q.useState)({width:0,height:0}),w=(0,q.useRef)(null);(0,q.useEffect)(()=>o(qi(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 T=e.topic.trim();(0,q.useEffect)(()=>{if(n({type:`reset`}),!T)i({state:`error`,message:`No log topic: set one in edit mode`});else return i({state:`waiting`,message:`Connecting…`}),b.subscribeRosout({topic:T},{status:(e,t)=>i({state:e,message:t}),update:e=>n({type:`update`,update:e})})},[T]),(0,q.useEffect)(()=>{v(null),g(!0)},[t.version]),(0,q.useEffect)(()=>{let e=w.current;if(!e)return;let t=new ResizeObserver(([e])=>C({width:e.contentRect.width,height:e.contentRect.height}));return t.observe(e),()=>t.disconnect()},[]);let D=(0,q.useDeferredValue)(s),O=(0,q.useDeferredValue)(l),k=(0,q.useMemo)(()=>na(e.nodes),[e.nodes]),A=(0,q.useMemo)(()=>ta(D,d),[D,d]),j=(0,q.useMemo)(()=>ta(O,d),[O,d]),N=(0,q.useMemo)(()=>ra(t.entries,t.running,{scope:k,nodes:p,levels:a,include:A.test,exclude:j.test}),[t.entries,t.running,k,p,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}),F=(0,q.useCallback)(e=>m(t=>{let n=new Set(t);return n.delete(e)||n.add(e),n}),[]),I=_===null?void 0:t.entries[ea(t.entries,_)],L=I?.seq===_?I:void 0,{width:R,height:ee}=S,te=R>=yl,z=y??te,ie=N.nodes.filter(e=>e.total>0),ae=Math.min(Sl.max,Math.max(Sl.min,...ie.map(e=>e.name.length))),oe=`No message matches the filters`;t.received?t.entries.length===0?oe=t.cleared?`Cleared: the new messages will show here`:`No message yet`:N.total===0&&(oe=`No message of ${e.nodes.trim()} yet`):oe=r.state===`error`?r.message:`Reading the log…`;let se;if(r.state===`error`)se={text:r.message,tone:`error`};else if(!t.received)se={text:r.message,tone:`idle`};else{let e=[N.shown.length===N.total?El(N.total):`${N.shown.length.toLocaleString()} of ${El(N.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, ${El(t.pending.length)} waiting`:`paused`),se={text:e.join(` · `),tone:t.paused?`paused`:r.state}}return(0,J.jsxs)(`div`,{ref:w,className:`logs${L&&ee>0&&ee<xl?` 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":z,title:`The nodes`,"aria-label":`The nodes`,onClick:()=>x(!z),children:(0,J.jsx)(Ne,{width:17,height:17})}),(0,J.jsx)(`div`,{className:`logs-levels`,role:`group`,"aria-label":`Levels`,children:Gi.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}: ${N.levels[r]}`,title:`${t}: ${El(N.levels[r])}. Shift+click: this level only`,onClick:t=>P(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:ca(N.levels[r])})]},e))}),(0,J.jsxs)(`div`,{className:`logs-tools`,children:[(0,J.jsxs)(`label`,{className:`logs-search${A.error?` invalid`:``}`,title:A.error??`Only the messages containing any of these, separated by ;`,children:[(0,J.jsx)(ne,{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${j.error?` invalid`:``}`,title:j.error??`Not the messages containing any of these, separated by ;`,children:[(0,J.jsx)(be,{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)(Ae,{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)(re,{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:N.shown.length===0,onClick:()=>wl(Tl(),N.shown.map(sa).join(`
|
|
68
68
|
`)+`
|
|
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`);
|
|
69
|
+
`),children:(0,J.jsx)(M,{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)(E,{width:17,height:17})})]})]}),(0,J.jsxs)(`div`,{className:`logs-main`,children:[z&&(0,J.jsx)(Dl,{nodes:N.nodes,chosen:p,overlay:!te,onToggle:F,onAll:()=>m(new Set),onClose:()=>x(!1)}),(0,J.jsx)(vl,{entries:N.shown,version:t.version,selected:_,follow:h,time:e.time,showNode:p.size!==1&&ie.length!==1,nodeWidth:ae,compact:R>0&&R<bl,empty:oe,onSelect:v,onFollow:g})]}),L&&(0,J.jsx)(Ol,{entry:L,running:t.running,onOnly:()=>m(new Set([L.name])),onClose:()=>v(null)}),(0,J.jsxs)(`div`,{className:`logs-status ${se.tone}`,title:se.text,children:[(0,J.jsx)(`span`,{className:`logs-dot`,"aria-hidden":`true`}),(0,J.jsx)(`span`,{className:`logs-status-text`,children:se.text})]})]})}var Al=Ye({type:`logs`,name:`Logs`,description:`The ROS log of every node (/rosout), coloured by level, filtered by node, level and text.`,icon:_,defaultSize:{w:10,h:6},minSize:{w:4,h:3},component:kl,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`}]}),jl=[`map`,`global`,`local`],Ml=2,Nl=2e3,Pl=.25,Fl=8,Il=34,Ll=6,Rl=2e3,zl=.25,Bl={robot:`#4f8cff`,stale:`#8b95a7`,goal:`#2fbf71`,plan:`#2fbf71`,pose:`#f0a020`},Vl=e=>e*180/Math.PI;function Hl(e){return`x ${e.x.toFixed(2)} y ${e.y.toFixed(2)} θ ${Math.round(Vl(e.yaw))}°`}function Ul(e,t,n){return new DOMMatrix().translate(t/2,n/2).scale(e.scale,-e.scale).translate(-e.x,-e.y)}function Wl(e){return new DOMMatrix().translate(e.x,e.y).rotate(Vl(e.yaw))}function Gl(e,t){return Wl(t).translate(e.originX,e.originY).rotate(Vl(e.originYaw)).scale(e.resolution,e.resolution)}function Kl(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(Il,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 ql(e,t,n,r,i){let a=t.transformPoint({x:n.x,y:n.y}),o=Math.max(Fl,Pl*r),s=i?Bl.stale:Bl.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 Jl(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=Bl.plan,e.lineWidth=3,e.stroke(),e.restore()}}function Yl(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=Ul(t,i,a),c=new DOMMatrix().scale(r,r).multiply(s);for(let e of jl){let i=n.layers[e],a=n.placements[e];i&&a&&(o.imageSmoothingEnabled=i.info.resolution*t.scale*r<1,o.setTransform(c.multiply(Gl(i.info,a))),o.drawImage(i.image,0,0))}o.setTransform(r,0,0,r,0,0),n.plan&&Jl(o,s.multiply(Wl(n.plan.placement)),n.plan.points),n.goal&&Kl(o,s,n.goal,Bl.goal),n.robot?.transform&&ql(o,s,n.robot.transform,t.scale,n.robot.ageMs>Rl),n.preview&&Kl(o,s,n.preview.pose,Bl[n.preview.tool])}function Xl(e,t,n,r){let i=Gl(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(Nl,Math.max(Ml,p))}}function Zl({config:e,editing:t}){let n=(0,q.useRef)(null),i=(0,q.useRef)(null),a=(0,q.useRef)(null),o=(0,q.useRef)({}),[c,l]=(0,q.useState)({map:``,global:``,local:``}),[u,d]=(0,q.useState)({state:`waiting`,message:`Connecting…`}),[f,p]=(0,q.useState)(null),[m,h]=(0,q.useState)(!1),g=(0,q.useRef)(null),_=(0,q.useRef)(null),[y,S]=(0,q.useState)(``),C=(0,q.useRef)(null),w=(0,q.useRef)(new Map),T=(0,q.useRef)(null),E=e.mapFrame.trim(),D=s(E,e.robotFrame),O=e=>c[e]&&c[e]!==E?c[e]:``,k={map:s(E,O(`map`)),global:s(E,O(`global`)),local:s(E,O(`local`))},A={};for(let e of jl)A[e]=O(e)?k[e]?.transform??null:{x:0,y:0,yaw:0};let j=s(E,y&&y!==E?y:``),M=y&&y!==E?j?.transform??null:{x:0,y:0,yaw:0},N=(0,q.useRef)({layers:o.current,placements:A,planPlacement:M,robot:D});N.current={layers:o.current,placements:A,planPlacement:M,robot:D};let P=(0,q.useRef)(0),F=(0,q.useCallback)(()=>{P.current||=requestAnimationFrame(()=>{P.current=0;let e=n.current,{planPlacement:t,...r}=N.current;e&&Yl(e,i.current,{...r,plan:_.current&&t?{points:_.current.points,placement:t}:null,goal:g.current,preview:C.current})})},[]);(0,q.useEffect)(F),(0,q.useEffect)(()=>()=>cancelAnimationFrame(P.current),[]);let I=()=>({width:n.current?.clientWidth??1,height:n.current?.clientHeight??1}),L=(0,q.useCallback)(()=>{let{width:e,height:t}=I();for(let n of jl){let r=o.current[n],s=N.current.placements[n];if(r&&s)return i.current=Xl(r,s,e,t),a.current=n===`map`?`map`:`costmap`,F(),!0}let n=N.current.robot?.transform;return n?(i.current={x:n.x,y:n.y,scale:50},a.current=`robot`,F(),!0):!1},[F]),R=(0,q.useCallback)((e,t,n,r)=>{let i=!0,s=b.subscribeGrid({topic:t,style:n,maxFps:r},{status:(t,n)=>e===`map`&&d({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},l(t=>t[e]===s.frameId?t:{...t,[e]:s.frameId});let c=a.current;(e===`map`?c!==`map`&&c!==`user`:c===null||c===`robot`)&&L(),F()}});return()=>{i=!1,s(),o.current[e]?.image.close(),delete o.current[e],F()}},[L,F]),ee=e.mapTopic.trim();(0,q.useEffect)(()=>{if(!ee)d({state:`error`,message:`No map topic: set one in edit mode`});else return d({state:`waiting`,message:`Connecting…`}),R(`map`,ee,`map`,1)},[ee,R]);let z=e.showGlobalCostmap?e.globalCostmapTopic.trim():``;(0,q.useEffect)(()=>z?R(`global`,z,`costmap`,1):void 0,[z,R]);let ne=e.showLocalCostmap?e.localCostmapTopic.trim():``;(0,q.useEffect)(()=>ne?R(`local`,ne,`costmap`,4):void 0,[ne,R]);let re=e.showPlan?e.planTopic.trim():``;(0,q.useEffect)(()=>{if(!re)return;let e=b.subscribePath({topic:re},e=>{_.current=e,S(e.frameId),F()});return()=>{e(),_.current=null,S(``),F()}},[re,F]),(0,q.useEffect)(()=>{let e=D?.transform;e&&g.current&&Math.hypot(e.x-g.current.x,e.y-g.current.y)<zl&&(g.current=null),m&&e&&i.current?i.current={...i.current,x:e.x,y:e.y}:!i.current&&e&&L()},[D,m,L]),(0,q.useEffect)(()=>{let e=n.current;if(!e)return;let t=new ResizeObserver(F);return t.observe(e),()=>t.disconnect()},[F]);let ie=(0,q.useCallback)((e,t)=>{let n=i.current;if(!n)return;let{width:r,height:o}=I(),s=Math.min(Nl,Math.max(Ml,n.scale*t));a.current=`user`;let c=Ul(n,r,o).inverse().transformPoint(e);i.current={scale:s,x:c.x-(e.x-r/2)/s,y:c.y+(e.y-o/2)/s},F()},[F]);(0,q.useEffect)(()=>{let e=n.current;if(!e)return;let t=t=>{t.preventDefault();let n=e.getBoundingClientRect();ie({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)},[ie]),(0,q.useEffect)(()=>{if(!f)return;let e=e=>e.key===`Escape`&&p(null);return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[f]);let ae=e=>{let t=n.current.getBoundingClientRect();return{x:e.clientX-t.left,y:e.clientY-t.top}},oe=e=>{let{width:t,height:n}=I(),{x:r,y:a}=Ul(i.current,t,n).inverse().transformPoint(e);return{x:r,y:a}},se=()=>{let[e,t]=[...w.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}}},ce=(t,n)=>{b.send({type:`pose`,topic:t===`goal`?e.goalTopic.trim():e.poseTopic.trim(),covariance:t===`pose`,frameId:E,...n})?(t===`goal`&&(g.current=n),G(`${t===`goal`?`Goal`:`Pose estimate`} sent: ${Hl(n)}`)):G(`Not connected to the robot`,`error`)},B=e=>{if(!i.current||e.pointerType===`mouse`&&e.button!==0)return;e.currentTarget.setPointerCapture(e.pointerId);let t=ae(e);if(w.current.set(e.pointerId,t),w.current.size===2)C.current=null,T.current={kind:`pinch`,...se()};else if(w.current.size===1&&f){let n=oe(t);T.current={kind:`place`,tool:f,pointerId:e.pointerId,anchor:n,start:t},C.current={tool:f,pose:{x:n.x,y:n.y,yaw:0}}}else w.current.size===1&&(T.current={kind:`pan`});F()},le=e=>{let t=w.current.get(e.pointerId),n=i.current;if(!t||!n)return;let r=ae(e);w.current.set(e.pointerId,r);let o=T.current;if(o?.kind===`place`){let e=oe(r),t=Math.hypot(r.x-o.start.x,r.y-o.start.y)>Ll;C.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`,i.current={...n,x:n.x-(r.x-t.x)/n.scale,y:n.y+(r.y-t.y)/n.scale},h(!1);else if(o?.kind===`pinch`&&w.current.size===2){let e=se();i.current={...n,x:n.x-(e.center.x-o.center.x)/n.scale,y:n.y+(e.center.y-o.center.y)/n.scale},ie(e.center,e.distance/(o.distance||1)),T.current={kind:`pinch`,...e}}F()},ue=e=>{if(!w.current.delete(e.pointerId))return;let t=T.current;if(t?.kind===`place`&&t.pointerId===e.pointerId){let n=C.current;C.current=null,T.current=null,e.type===`pointerup`&&n&&(ce(t.tool,n.pose),p(null))}else w.current.size===1?T.current={kind:`pan`}:w.current.size===0&&(T.current=null);F()},de=D?.transform,V;if(!E||!e.robotFrame.trim())V={text:`Set the TF frames in edit mode`,className:`error`};else if(de){let e=D.ageMs>Rl;V={text:`${Hl(de)}${e?` (stale)`:``}`,className:e?`stale`:``}}else V={text:D?.error??`Locating the robot…`,className:`error`};let fe=(e,t,n)=>(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":f===e,title:t,"aria-label":t,onClick:()=>p(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:f?`placing`:void 0,onPointerDown:B,onPointerMove:le,onPointerUp:ue,onPointerCancel:ue}),u.state!==`streaming`&&(0,J.jsxs)(`div`,{className:`nav-overlay ${u.state}`,children:[(0,J.jsx)(te,{width:28,height:28}),(0,J.jsx)(`span`,{children:u.message})]}),(0,J.jsxs)(`div`,{className:`overlay-toolbar`,children:[fe(`pose`,`Set the pose estimate`,v),fe(`goal`,`Send a navigation goal`,x),(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:()=>{h(!1),L()},children:(0,J.jsx)(ge,{width:17,height:17})}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":m,title:`Follow the robot`,"aria-label":`Follow the robot`,disabled:!de,onClick:()=>h(e=>!e),children:(0,J.jsx)(r,{width:17,height:17})})]}),f&&!t&&(0,J.jsx)(`div`,{className:`nav-hint`,children:f===`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 ${V.className}`,children:V.text})]})}var Ql=Ye({type:`navigation`,name:`Navigation`,description:`The map, the costmaps and the robot on them; set its pose and send it goals.`,icon:te,defaultSize:{w:8,h:6},minSize:{w:3,h:3},component:Zl,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`}]}),$l={open:`None (open)`,owe:`Enhanced Open (OWE)`,wep:`WEP`,"wpa-psk":`WPA/WPA2 Personal`,sae:`WPA3 Personal`,"wpa-eap":`WPA/WPA2 Enterprise`};function eu(e){return e!==`open`&&e!==`owe`}var tu=/^[\w.@-]{1,15}$/,nu=Array.from({length:14},(e,t)=>t+1),ru=[36,40,44,48,52,56,60,64,100,104,108,112,116,120,124,128,132,136,140,144,149,153,157,161,165,169,173,177];function iu(e){return tu.test(e)}function au(e){let t=e.split(`.`);return t.length===4&&t.every(e=>/^(0|[1-9]\d{0,2})$/.test(e)&&Number(e)<=255)}function ou(e){if(!/^[0-9a-f:.]+$/i.test(e)||!e.includes(`:`))return!1;let t=e.split(`::`);if(t.length>2)return!1;let n=t.flatMap(e=>e?e.split(`:`):[]),r=n.at(-1)??``,i=r.includes(`.`);if(i&&!au(r))return!1;let a=i?n.slice(0,-1):n;if(!a.every(e=>/^[0-9a-f]{1,4}$/i.test(e)))return!1;let o=a.length+(i?2:0);return t.length===2?o<8:o===8}function su(e){let[t,n,...r]=e.trim().split(`/`);return r.length>0||!au(t)?`“${e.trim()}” is not an IPv4 address`:n===void 0?`Give its network's size: ${t}/24`:!/^\d{1,2}$/.test(n)||Number(n)<1||Number(n)>32?`/${n} is not a network's size: /1 to /32 (/24: 255.255.255.0)`:null}function cu(e){return e.split(/[\s,;]+/).map(e=>e.trim()).filter(Boolean)}function lu(e){return new TextEncoder().encode(e).length}function uu(e,t,n=!1){switch(e){case`open`:case`owe`:return null;case`wpa-psk`:return/^[0-9a-f]{64}$/i.test(t)?null:/^[\x20-\x7e]*$/.test(t)?t.length<8||t.length>63?n?`8 to 63 characters`:`WPA passwords have 8 to 63 characters`:null:`Letters, digits and symbols of the keyboard only: no accents`;case`sae`:return t.length===0?`The network’s password`:t.length>128?`At most 128 characters`:null;case`wep`:return/^([\x20-\x7e]{5}|[\x20-\x7e]{13}|[0-9a-f]{10}|[0-9a-f]{26})$/i.test(t)?null:`WEP keys have 5 or 13 characters, or 10 or 26 hexadecimal digits`;case`wpa-eap`:return t.length===0?`Your password on the network`:null}}function du(e,t){let n={},{kind:r}=e,i=e.name.trim();if(i?(i.length>255||/[\x00-\x1f]/.test(i))&&(n.name=`At most 255 characters, on one line`):n.name=`A name for the connection`,e.interface&&!iu(e.interface)?n.interface=`“${e.interface}” is not an interface's name`:r===`hotspot`&&!e.interface&&(n.interface=`The Wi-Fi interface of the access point`),(!Number.isInteger(e.priority)||e.priority<-999||e.priority>999)&&(n.priority=`A whole number, from -999 to 999`),r!==`ethernet`){let i=lu(e.ssid);if(i===0?n.ssid=r===`hotspot`?`The name the access point shows`:`The network’s name`:i>32?n.ssid=`At most 32 bytes (fewer with accents and symbols)`:/[\x00-\x1f]/.test(e.ssid)&&(n.ssid=`No control characters`),r===`hotspot`&&e.security!==`open`&&e.security!==`wpa-psk`&&(n.security=`An access point is open, or secured by a WPA2 password`),e.security===`wpa-eap`&&(e.identity.trim()?/[\x00-\x1f]/.test(e.identity)&&(n.identity=`No control characters`):n.identity=`Your user name on the network`),e.password!==null){let t=uu(e.security,e.password,r===`hotspot`);t&&(n.password=t)}else t&&eu(e.security)&&(n.password=`The network’s password`);if(r===`hotspot`){let t=e.band===`a`?ru:e.band===`bg`?nu:[];e.channel!==0&&!t.includes(e.channel)&&(n.channel=e.band?`Not a channel of ${e.band===`a`?`5`:`2.4`} GHz`:`Choose the band of the channel`)}}(r===`hotspot`?[`shared`]:[`auto`,`manual`,`shared`,`disabled`]).includes(e.ipv4)||(n.ipv4=r===`hotspot`?`An access point gives the addresses (shared)`:`Not a way to get an address`);let a=e.addresses.map(su).find(e=>e!==null);a?n.addresses=a:e.ipv4===`manual`&&e.addresses.length===0?n.addresses=`The robot’s address on this network: 192.168.1.20/24`:e.ipv4===`shared`&&e.addresses.length>1&&(n.addresses=`One address: the robot’s, on the network it gives`),e.gateway&&!au(e.gateway)&&(n.gateway=`“${e.gateway}” is not an IPv4 address`);let o=e.dns.find(e=>!au(e)&&!ou(e));return o!==void 0&&(n.dns=`“${o}” is not an IP address`),n}function fu(e){let t=e.kind;return t!==`wifi`&&t!==`hotspot`&&t!==`ethernet`?null:{kind:t,name:e.name,interface:e.interface,autoconnect:e.autoconnect,priority:e.priority,ssid:e.ssid,hidden:e.hidden,security:e.security??`open`,password:null,identity:e.identity,band:e.band,channel:e.channel,ipv4:[`auto`,`manual`,`shared`,`disabled`].includes(e.ipv4Method)?e.ipv4Method:`auto`,addresses:e.addresses,gateway:e.gateway,dns:e.dns}}function pu(e){return{kind:e,name:``,interface:``,autoconnect:!0,priority:0,ssid:``,hidden:!1,security:e===`ethernet`?`open`:`wpa-psk`,password:e===`ethernet`?null:``,identity:``,band:``,channel:0,ipv4:e===`hotspot`?`shared`:`auto`,addresses:[],gateway:``,dns:[]}}function mu(e){return e>=70?4:e>=50?3:e>=30?2:1}function hu(e){return e<=0?``:e<3e3?`2.4 GHz`:e<5925?`5 GHz`:`6 GHz`}function gu(e){let t=e.split(/[\s,]+/).filter(Boolean).map(e=>RegExp(`^${e.replace(/[.+^${}()|[\]\\]/g,`\\$&`).replace(/\*/g,`.*`).replace(/\?/g,`.`)}$`));return t.length===0?()=>!0:e=>t.some(t=>t.test(e))}function _u(e,t,n){return e.filter(e=>t(e.name)&&(n||e.type!==`loopback`&&e.type!==`wifi-p2p`&&!e.external&&!(e.software&&e.state===10)))}var vu=[[/need auth/,`Waiting for the password…`],[/getting IP/i,`Getting an address…`],[/checking IP/i,`Checking the connection…`]];function yu(e,t){let{state:n}=e;if(n===100)return e.external?{text:`Configured by another program`,tone:`on`}:{text:e.connectionName?`Connected to ${e.connectionName}`:`Connected`,tone:`on`};if(n>30&&n<100){let t=vu.find(([t])=>t.test(e.stateText));return{text:t?t[1]:`Connecting…`,tone:`busy`}}return n===110?{text:`Disconnecting…`,tone:`busy`}:n===120?{text:e.reason?`Failed: ${e.reason}`:`Failed`,tone:`failed`}:n===20?e.carrier===!1?{text:`Cable unplugged`,tone:`off`}:e.type===`wifi`&&!t?{text:`Wi-Fi is off`,tone:`off`}:{text:`Unavailable`,tone:`off`}:n===10?{text:`Not managed by NetworkManager`,tone:`off`}:{text:`Disconnected`,tone:`off`}}function bu(e){switch(e.type){case`wifi`:return`Wi-Fi`;case`ethernet`:return`Ethernet`;case`gsm`:case`cdma`:return`Mobile broadband`;case`bt`:return`Bluetooth`;case`loopback`:return`Loopback`;default:return e.type.charAt(0).toUpperCase()+e.type.slice(1)}}var xu={openvpn:`OpenVPN`,vpnc:`Cisco VPN`,openconnect:`OpenConnect`,l2tp:`L2TP`,pptp:`PPTP`,strongswan:`IPsec`,libreswan:`IPsec`,fortisslvpn:`Fortinet`};function Su(e){switch(e.kind){case`wifi`:return`Wi-Fi network`;case`hotspot`:return`Access point`;case`ethernet`:return`Wired`;case`vpn`:return e.type===`wireguard`?`WireGuard`:`VPN${e.vpnService?` (${xu[e.vpnService]??e.vpnService})`:``}`;default:return e.type}}var Cu=[{kind:`wifi`,title:`Wi-Fi networks`},{kind:`hotspot`,title:`Access points`},{kind:`ethernet`,title:`Wired`},{kind:`vpn`,title:`VPN`},{kind:`other`,title:`Other`}];function wu(e,t){return Number(t.activeState!==null)-Number(e.activeState!==null)||(t.lastUsed??0)-(e.lastUsed??0)||e.name.localeCompare(t.name)}function Tu(e,t){let n=t.trim().toLowerCase();return!n||[e.name,e.ssid,e.interface,e.device??``].some(e=>e.toLowerCase().includes(n))}function Eu(e,t){if(e.device)return t.some(t=>t.name===e.device);if(e.interface)return t.some(t=>t.name===e.interface);let n=e.kind===`wifi`||e.kind===`hotspot`?`wifi`:e.kind===`ethernet`?`ethernet`:null;return n===null||t.some(e=>e.type===n)}function Du(e,t,n,r){let i=e.filter(e=>(r||!e.external)&&Eu(e,t)&&Tu(e,n));return Cu.map(({kind:e,title:t})=>({kind:e,title:t,connections:i.filter(t=>t.kind===e).sort(wu)})).filter(e=>e.connections.length>0)}function Ou(e,t,n){let r=e.filter(e=>e.kind===`wifi`&&e.ssid===t&&(!e.interface||e.interface===n)).sort(wu);return r.find(e=>e.device===n)??r.find(e=>e.device===null)??null}function ku(e,t,n){let r=n.trim().toLowerCase();return e.networks.filter(e=>e.device===t&&(!r||e.ssid.toLowerCase().includes(r))).map(n=>({network:n,saved:Ou(e.connections,n.ssid,t)})).sort((e,t)=>Number(t.network.active)-Number(e.network.active)||Number(t.saved!==null)-Number(e.saved!==null)||t.network.signal-e.network.signal)}function Au(e,t){return e.filter(e=>e.kind===`hotspot`&&(!e.interface||e.interface===t)).sort(wu)}function ju(e,t){return t.uuid&&e.uuid===t.uuid?!0:!!t.ssid&&e.ssid===t.ssid&&(!t.device||!e.device||e.device===t.device)}function Mu(e,t,n){let r=e.filter(e=>e.action!==`rescan`&&e.action!==`wifi`&&ju(e,t)),i=r.find(e=>e.finished===null)??null,a=r.find(e=>e.finished!==null);return{running:i,failed:!i&&a?.error&&n-(a.finished??0)<12e4?a:null}}function Nu(e,t,n,r){if(n||r)return n||r;let i=e.devices.find(t=>t.name===e.via),a=t===`wifi`||t===`hotspot`?`wifi`:t===`ethernet`?`ethernet`:null;return i&&i.type===a?i.name:null}function Pu(e,t){let{via:n}=e;if(!n)return null;let r=`This page reaches the robot through ${n}`,i=`uuid`in t?e.connections.find(e=>e.uuid===t.uuid):void 0,a=i?.device===n;switch(t.action){case`connect`:return!i||a||Nu(e,i.kind,t.device,i.interface)!==n?null:i.kind===`hotspot`?`${r}: starting the access point disconnects it from its network, and this page loses the robot. Join ${i.ssid||i.name} to reach it again.`:`${r}: connecting it to ${i.ssid||i.name} moves the robot to that network, and this page loses it unless it is on that network too.`;case`create`:{if(!t.connect)return null;let{settings:i}=t;return Nu(e,i.kind,t.device,i.interface)===n?i.kind===`hotspot`?`${r}: starting the access point disconnects it from its network, and this page loses the robot. Join ${i.ssid} to reach it again.`:`${r}: connecting it to ${i.ssid||i.name} moves the robot to that network, and this page loses it unless it is on that network too.`:null}case`disconnect`:return a?`${r}: disconnecting ${i.name} cuts this page off from the robot.`:null;case`delete`:return a?`${r}: forgetting ${i.name} disconnects it, and cuts this page off.`:null;case`modify`:return a?`${r}: saving reconnects ${i.name}, and if its address changes this page loses the robot.`:null;case`wifi`:{let i=e.devices.find(e=>e.name===n);return!t.enabled&&i?.type===`wifi`?`${r}, a Wi-Fi interface: turning Wi-Fi off cuts this page off from the robot.`:null}default:return null}}function Fu(e,t){if(e===null)return`Never used`;let n=Math.max(0,Math.round((t-e)/1e3));if(n<60)return`Used just now`;if(n<3600)return`Used ${Math.floor(n/60)} min ago`;if(n<86400)return`Used ${Math.floor(n/3600)} h ago`;let r=Math.floor(n/86400);return r<30?`Used ${r} day${r===1?``:`s`} ago`:`Used on ${new Date(e).toLocaleDateString()}`}function Iu(e,t){let n=new Set(t.map(e=>e.name));if(!n.has(e))return e;let r=2;for(;n.has(`${e} (${r})`);)r++;return`${e} (${r})`}function Lu(e,t,n,r,i,a){return{...pu(`wifi`),name:Iu(e.ssid,a),ssid:e.ssid,security:e.security,password:t,identity:n,autoconnect:r,hidden:i}}function Ru(e){let t=e.filter(e=>e.state===100&&!e.external);return t.find(e=>e.gateway)??t[0]??null}function zu(e,t){if(e.error)return{text:e.error,tone:`failed`};let n=e.activity.find(e=>e.finished===null);if(n)return{text:`${n.label}…`,tone:`busy`};let r=e.activity[0];if(r?.error&&t-(r.finished??0)<6e4)return{text:`${r.label}: ${r.error}`,tone:`failed`};let i=[],a;switch(e.connectivity){case`full`:i.push(`Online`),a=`on`;break;case`limited`:i.push(`No internet`),a=`warn`;break;case`portal`:i.push(`Behind a login page`),a=`warn`;break;default:i.push(e.state.startsWith(`connected`)?`Local network only`:`Disconnected`),a=e.state.startsWith(`connected`)?`warn`:`off`}let o=Ru(e.devices);if(o){let e=o.ipv4[0]?.split(`/`)[0];i.push(`${o.name}: ${o.connectionName}${e?` (${e})`:``}`)}return e.via&&i.push(`this page through ${e.via}`),{text:i.join(` · `),tone:a}}function Bu(e,t){return t?`This widget is read-only`:e.canChange?!e.permissions.control&&!e.permissions.modify?`The server’s user may not change the robot’s networks (see the README: a polkit rule)`:null:`The networks are changed from the dashboard’s own pages only`}var Vu=[[10,[16]],[16,[28]],[26,[44]],[18,[32,32]],[24,[43,43]],[16,[27,27,27,27]],[18,[31,31,31,31]],[22,[38,38,39,39]],[22,[36,36,36,37,37]],[26,[43,43,43,43,44]],[30,[50,51,51,51,51]],[22,[36,36,36,36,36,36,37,37]],[22,[37,37,37,37,37,37,37,37,38]]],Hu=[[],[6,18],[6,22],[6,26],[6,30],[6,34],[6,22,38],[6,24,42],[6,26,46],[6,28,50],[6,30,54],[6,32,58],[6,34,62]];function Uu(e,t){let n=0;for(let r=7;r>=0;r--)n=n<<1^(n>>>7)*285,n^=(t>>>r&1)*e;return n}function Wu(e){let t=Array(e).fill(0);t[e-1]=1;let n=1;for(let r=0;r<e;r++){for(let r=0;r<e;r++)t[r]=Uu(t[r],n),r+1<e&&(t[r]^=t[r+1]);n=Uu(n,2)}return t}function Gu(e,t){let n=t.map(()=>0);for(let r of e){let e=r^(n.shift()??0);n.push(0),t.forEach((t,r)=>{n[r]^=Uu(t,e)})}return n}var Ku=[(e,t)=>(e+t)%2==0,(e,t)=>t%2==0,e=>e%3==0,(e,t)=>(e+t)%3==0,(e,t)=>(Math.floor(e/3)+Math.floor(t/2))%2==0,(e,t)=>e*t%2+e*t%3==0,(e,t)=>(e*t%2+e*t%3)%2==0,(e,t)=>((e+t)%2+e*t%3)%2==0];function qu(e,t){let[n,r]=Vu[t-1],i=r.reduce((e,t)=>e+t,0)*8,a=[],o=(e,t)=>{for(let n=t-1;n>=0;n--)a.push(e>>>n&1)};o(4,4),o(e.length,t<10?8:16),e.forEach(e=>o(e,8)),o(0,Math.min(4,i-a.length)),o(0,(8-a.length%8)%8);for(let e=236;a.length<i;e^=253)o(e,8);let s=[];for(let e=0;e<a.length;e+=8)s.push(a.slice(e,e+8).reduce((e,t)=>e<<1|t,0));let c=Wu(n),l=[],u=0;for(let e of r){let t=s.slice(u,u+e);l.push({data:t,ec:Gu(t,c)}),u+=e}let d=[];for(let e=0;e<Math.max(...r);e++)l.forEach(t=>e<t.data.length&&d.push(t.data[e]));for(let e=0;e<n;e++)l.forEach(t=>d.push(t.ec[e]));return d}var Ju=class{size;dark;fixed;constructor(e){this.size=e,this.dark=Array.from({length:e},()=>Array(e).fill(!1)),this.fixed=Array.from({length:e},()=>Array(e).fill(!1))}set(e,t,n){this.dark[t][e]=n,this.fixed[t][e]=!0}};function Yu(e,t){let{size:n}=e;for(let t=0;t<n;t++)e.set(6,t,t%2==0),e.set(t,6,t%2==0);for(let[t,r]of[[3,3],[n-4,3],[3,n-4]])for(let i=-4;i<=4;i++)for(let a=-4;a<=4;a++){let o=t+a,s=r+i;if(o>=0&&o<n&&s>=0&&s<n){let t=Math.max(Math.abs(a),Math.abs(i));e.set(o,s,t!==2&&t!==4)}}let r=Hu[t-1],i=r.length-1;if(r.forEach((t,n)=>r.forEach((r,a)=>{if(!(n===0&&a===0||n===0&&a===i||n===i&&a===0))for(let n=-2;n<=2;n++)for(let i=-2;i<=2;i++)e.set(t+i,r+n,Math.max(Math.abs(i),Math.abs(n))!==1)})),Xu(e,0),t>=7){let r=t;for(let e=0;e<12;e++)r=r<<1^(r>>>11)*7973;let i=t<<12|r;for(let t=0;t<18;t++){let r=(i>>>t&1)==1,a=n-11+t%3,o=Math.floor(t/3);e.set(a,o,r),e.set(o,a,r)}}}function Xu(e,t){let{size:n}=e,r=0|t,i=r;for(let e=0;e<10;e++)i=i<<1^(i>>>9)*1335;let a=(r<<10|i)^21522,o=e=>(a>>>e&1)==1;for(let t=0;t<=5;t++)e.set(8,t,o(t));e.set(8,7,o(6)),e.set(8,8,o(7)),e.set(7,8,o(8));for(let t=9;t<15;t++)e.set(14-t,8,o(t));for(let t=0;t<8;t++)e.set(n-1-t,8,o(t));for(let t=8;t<15;t++)e.set(8,n-15+t,o(t));e.set(8,n-8,!0)}function Zu(e,t){let{size:n}=e,r=0;for(let i=n-1;i>=1;i-=2){i===6&&(i=5);for(let a=0;a<n;a++)for(let o=0;o<2;o++){let s=i-o,c=i+1&2?a:n-1-a;!e.fixed[c][s]&&r<t.length*8&&(e.dark[c][s]=(t[r>>>3]>>>7-(r&7)&1)==1,r++)}}}function Qu(e,t){let n=Ku[t];for(let t=0;t<e.size;t++)for(let r=0;r<e.size;r++)!e.fixed[t][r]&&n(r,t)&&(e.dark[t][r]=!e.dark[t][r])}function $u(e){let t=e.length,n=0,r=[...e,...Array.from({length:t},(t,n)=>e.map(e=>e[n]))];for(let e of r){let r=1;for(let i=1;i<=t;i++)i<t&&e[i]===e[i-1]?r++:(r>=5&&(n+=3+(r-5)),r=1);let i=n=>n>=0&&n<t&&e[n];for(let e=0;e+7<=t;e++){if(!(i(e)&&!i(e+1)&&i(e+2)&&i(e+3)&&i(e+4)&&!i(e+5)&&i(e+6)))continue;let t=[1,2,3,4].every(t=>!i(e-t)),r=[7,8,9,10].every(t=>!i(e+t));(t||r)&&(n+=40)}}for(let r=0;r+1<t;r++)for(let i=0;i+1<t;i++){let t=e[r][i];t===e[r][i+1]&&t===e[r+1][i]&&t===e[r+1][i+1]&&(n+=3)}let i=e.reduce((e,t)=>e+t.filter(Boolean).length,0),a=t*t;return n+=(Math.ceil(Math.abs(i*20-a*10)/a)-1)*10,n}function ed(e,t){let n=new TextEncoder().encode(e),r=0;for(let e=1;e<=Vu.length&&r===0;e++){let t=Vu[e-1][1].reduce((e,t)=>e+t,0)*8;4+(e<10?8:16)+n.length*8<=t&&(r=e)}if(r===0)return null;let i=qu(n,r),a=null;for(let e of t===void 0?[0,1,2,3,4,5,6,7]:[t]){let t=new Ju(17+4*r);Yu(t,r),Zu(t,i),Qu(t,e),Xu(t,e);let n=$u(t.dark);(!a||n<a.score)&&(a={score:n,dark:t.dark})}return a.dark}function td(e,t,n,r){let i=e=>e.replace(/([\\;,:"])/g,`\\$1`),a=n===`nopass`?``:`P:${i(t)};`;return`WIFI:T:${n};S:${i(e)};${a}${r?`H:true;`:``};`}function nd({signal:e,size:t=18}){let n=mu(e),r=e=>n>=e?void 0:.22;return(0,J.jsxs)(`svg`,{viewBox:`0 0 24 24`,width:t,height:t,fill:`none`,stroke:`currentColor`,strokeWidth:`2`,strokeLinecap:`round`,"aria-hidden":`true`,className:`net-signal`,children:[(0,J.jsx)(`path`,{d:`M2.5 9a14 14 0 0 1 19 0`,opacity:r(4)}),(0,J.jsx)(`path`,{d:`M5.5 12.5a9.5 9.5 0 0 1 13 0`,opacity:r(3)}),(0,J.jsx)(`path`,{d:`M8.6 15.9a5 5 0 0 1 6.8 0`,opacity:r(2)}),(0,J.jsx)(`circle`,{cx:`12`,cy:`19.3`,r:`1.3`,fill:`currentColor`,stroke:`none`})]})}function rd({kind:e,size:t=18}){let n={width:t,height:t};switch(e){case`wifi`:return(0,J.jsx)(O,{...n});case`hotspot`:return(0,J.jsx)(o,{...n});case`ethernet`:return(0,J.jsx)(c,{...n});case`vpn`:return(0,J.jsx)(He,{...n});default:return(0,J.jsx)(ue,{...n})}}function id({device:e,size:t=18}){return(0,J.jsx)(rd,{kind:e.type===`wifi`?`wifi`:e.type===`ethernet`?`ethernet`:e.type===`tun`||e.type===`wireguard`?`vpn`:`other`,size:t})}function ad({tone:e}){return(0,J.jsx)(`span`,{className:`net-dot ${e}`,"aria-hidden":`true`})}function od({label:e,help:t,error:n,children:r}){let i=(0,q.useId)();return(0,J.jsxs)(`div`,{className:`field`,children:[(0,J.jsx)(`label`,{className:`field-label`,htmlFor:i,children:e}),r(i),n?(0,J.jsx)(`p`,{className:`field-help error`,children:n}):t&&(0,J.jsx)(`p`,{className:`field-help`,children:t})]})}function sd({label:e,help:t,checked:n,onChange:r}){return(0,J.jsxs)(`div`,{className:`field`,children:[(0,J.jsxs)(`label`,{className:`toggle`,children:[(0,J.jsx)(`input`,{type:`checkbox`,checked:n,onChange:e=>r(e.target.checked)}),(0,J.jsx)(`span`,{className:`toggle-switch`,"aria-hidden":`true`}),(0,J.jsx)(`span`,{className:`field-label`,children:e})]}),t&&(0,J.jsx)(`p`,{className:`field-help`,children:t})]})}function cd({id:e,value:t,placeholder:n,autoFocus:r=!1,initiallyShown:i=!1,onChange:a}){let[o,s]=(0,q.useState)(i);return(0,J.jsxs)(`div`,{className:`net-password`,children:[(0,J.jsx)(`input`,{id:e,type:o?`text`:`password`,value:t,placeholder:n,autoComplete:`new-password`,autoCapitalize:`off`,spellCheck:!1,autoFocus:r,onChange:e=>a(e.target.value)}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:o?`Hide the password`:`Show the password`,"aria-label":o?`Hide the password`:`Show the password`,"aria-pressed":o,onClick:()=>s(e=>!e),children:o?(0,J.jsx)(P,{width:16,height:16}):(0,J.jsx)(Le,{width:16,height:16})})]})}function ld({text:e,label:t}){let n=(0,q.useMemo)(()=>{let t=ed(e);if(!t)return null;let n=``;return t.forEach((e,t)=>{for(let r=0;r<e.length;r++){if(!e[r])continue;let i=1;for(;r+i<e.length&&e[r+i];)i++;n+=`M${r+4} ${t+4}h${i}v1h-${i}z`,r+=i-1}}),{d:n,size:t.length+8}},[e]);return n?(0,J.jsxs)(`svg`,{className:`net-qr`,viewBox:`0 0 ${n.size} ${n.size}`,shapeRendering:`crispEdges`,role:`img`,"aria-label":t,children:[(0,J.jsx)(`rect`,{width:n.size,height:n.size,fill:`#fff`}),(0,J.jsx)(`path`,{d:n.d,fill:`#000`})]}):null}function ud(){let e=crypto.getRandomValues(new Uint32Array(12));return Array.from(e,e=>`abcdefghjkmnpqrstuvwxyzABCDEFGHJKLMNPQRSTUVWXYZ23456789`[e%55]).join(``)}function dd(e){return/Disconnected from the robot|No answer from the robot/.test(rs(e))}async function fd(e,t,n){try{let n=await b.networkAction(e);n.message?G(n.message,`error`):t&&G(t)}catch(e){if(n&&dd(e)){G(`This page lost the robot: it moved to another network, where it is to be reached now`);return}throw e}}function pd({risk:e,error:t}){return(0,J.jsxs)(J.Fragment,{children:[e&&(0,J.jsx)(`p`,{className:`net-warning`,children:e}),t&&(0,J.jsx)(`p`,{className:`net-error`,role:`alert`,children:t})]})}function md({state:e,request:t,onClose:n}){let r=t.kind===`password`?t.connection:null,i=t.kind===`join`?t.network:e.networks.find(e=>e.ssid===r.ssid&&(!t.device||e.device===t.device)),a=r?.ssid||r?.name||i?.ssid||``,o=r?.security??i?.security??`wpa-psk`,[s,c]=(0,q.useState)(``),[l,u]=(0,q.useState)(r?.identity??``),[d,f]=(0,q.useState)(!0),[p,m]=(0,q.useState)(!1),[h,g]=(0,q.useState)(!1),[_,v]=(0,q.useState)(t.kind===`password`?t.error:null),y=o===`wpa-eap`,b=uu(o,s)??(y&&!l.trim()?`Your user name on the network`:null),x=r?{action:`connect`,uuid:r.uuid,device:t.kind===`password`?t.device:null,password:s}:{action:`create`,settings:Lu(i,s,l.trim(),d,!1,e.connections),connect:!0,device:i.device},S=Pu(e,x),C=async e=>{if(e.preventDefault(),m(!0),!b){g(!0),v(null);try{await fd(x,`Connected to ${a}`,S!==null),n()}catch(e){v(rs(e)),g(!1)}}};return(0,J.jsx)($e,{title:r?`The password of ${a}`:`Join ${a}`,onClose:n,children:(0,J.jsxs)(`form`,{className:`modal-body`,onSubmit:e=>void C(e),children:[i&&(0,J.jsxs)(`p`,{className:`net-dialog-meta`,children:[(0,J.jsx)(nd,{signal:i.signal,size:16}),[$l[o],hu(i.frequency),`${i.signal}%`].filter(Boolean).join(` · `)]}),y&&(0,J.jsx)(od,{label:`User name`,error:p&&!l.trim()?`Your user name on the network`:null,children:e=>(0,J.jsx)(`input`,{id:e,value:l,autoComplete:`off`,autoCapitalize:`off`,spellCheck:!1,autoFocus:!0,onChange:e=>u(e.target.value)})}),(0,J.jsx)(od,{label:`Password`,error:p?uu(o,s):null,help:y?`PEAP with MSCHAPv2, the server’s certificate not checked`:void 0,children:e=>(0,J.jsx)(cd,{id:e,value:s,autoFocus:!y,onChange:c})}),!r&&(0,J.jsx)(sd,{label:`Connect automatically`,help:`Whenever the robot is in its range`,checked:d,onChange:f}),(0,J.jsx)(pd,{risk:S,error:_}),(0,J.jsxs)(`div`,{className:`modal-actions`,children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:n,children:`Cancel`}),(0,J.jsx)(`button`,{type:`submit`,className:`button ${S?`danger`:`primary`}`,disabled:h,children:h?`Connecting…`:r?`Connect`:`Join`})]})]})})}var hd={wifi:[{value:`auto`,label:`Automatic (DHCP)`},{value:`manual`,label:`Manual`},{value:`disabled`,label:`Disabled`}],hotspot:[{value:`shared`,label:`The robot gives them`}],ethernet:[{value:`auto`,label:`Automatic (DHCP)`},{value:`manual`,label:`Manual`},{value:`shared`,label:`Shared: the robot gives them, and its internet`},{value:`disabled`,label:`Disabled`}]},gd={bg:[1,2,3,4,5,6,7,8,9,10,11,12,13],a:[36,40,44,48,149,153,157,161,165]},_d=[`wpa-psk`,`sae`,`wpa-eap`,`open`,`owe`,`wep`];function vd(e,t){if(t.kind===`edit`)return fu(t.connection);let n=t.settings,r=pu(n);if(n===`hotspot`){let n=e.devices.filter(e=>e.type===`wifi`&&e.accessPoint),i=n.find(e=>e.name===t.device)??n.find(t=>t.name!==e.via)??n[0],a=(b.hostname||`robot`).slice(0,32);return{...r,interface:i?.name??``,ssid:a,name:Iu(a,e.connections),password:ud(),autoconnect:!1}}return n===`ethernet`?{...r,interface:t.device??``,name:Iu(`Wired connection`,e.connections)}:{...r,hidden:!0,interface:t.device??``}}function yd({state:e,request:t,onClose:n}){let r=t.kind===`edit`?t.connection:null,[i,a]=(0,q.useState)(()=>vd(e,t)),[o,s]=(0,q.useState)(i.addresses.join(`, `)),[c,l]=(0,q.useState)(i.dns.join(`, `)),[u,d]=(0,q.useState)(r!==null),[f,p]=(0,q.useState)(!0),[m,h]=(0,q.useState)(!1),[g,_]=(0,q.useState)(!1),[v,y]=(0,q.useState)(null),{kind:b}=i,x=b!==`ethernet`,S=t=>a(n=>{let i={...n,...t};return!u&&t.ssid!==void 0&&i.ssid&&(i.name=Iu(i.ssid,e.connections.filter(e=>e.uuid!==r?.uuid))),i}),C=du(i,!r);r&&x&&i.security!==(r.security??`open`)&&eu(i.security)&&i.password===null&&(C.password=`The network’s password, for its new security`);let w=e=>m?C[e]??null:null,T=r?{action:`modify`,uuid:r.uuid,settings:i}:{action:`create`,settings:i,connect:f,device:null},E=Pu(e,T),D=async e=>{if(e.preventDefault(),h(!0),Object.keys(C).length>0)return;_(!0),y(null);let t=`Saved ${i.name}`;!r&&f&&(t=b===`hotspot`?`The access point ${i.ssid} is on`:`Connected to ${i.ssid||i.name}`);try{await fd(T,t,E!==null),n()}catch(e){y(rs(e)),_(!1)}},O=e.devices.filter(e=>e.type===`wifi`&&(b!==`hotspot`||e.accessPoint)),k=e.devices.filter(e=>e.type===`ethernet`),A=e.devices.find(e=>e.name===i.interface),j;j=r?`Edit ${r.name}`:b===`hotspot`?`New access point`:b===`ethernet`?`New wired connection`:`Join a hidden network`;let M=`Save`;!r&&f&&(M=b===`hotspot`?`Start`:b===`wifi`?`Join`:`Connect`);let N=b===`ethernet`||O.length>1||i.interface||b===`hotspot`?(0,J.jsx)(od,{label:`Interface`,error:w(`interface`),help:b===`hotspot`?void 0:`Bound to it, the connection is not used by other interfaces: for a sensor’s cable, say`,children:t=>(0,J.jsxs)(`select`,{id:t,value:i.interface,onChange:e=>S({interface:e.target.value}),children:[b!==`hotspot`&&(0,J.jsx)(`option`,{value:``,children:x?`Any Wi-Fi interface`:`Any wired interface`}),b===`hotspot`&&!i.interface&&(0,J.jsx)(`option`,{value:``,children:`Choose one`}),(x?O:k).map(t=>(0,J.jsxs)(`option`,{value:t.name,children:[t.name,t.product||t.vendor?` (${t.product||t.vendor})`:``,t.name===e.via?` · this page`:``]},t.name)),i.interface&&!e.devices.some(e=>e.name===i.interface)&&(0,J.jsxs)(`option`,{value:i.interface,children:[i.interface,` (not here)`]})]})}):null,P=r&&i.password===null?`Unchanged: type a new one to change it`:void 0;return(0,J.jsx)($e,{title:j,onClose:n,wide:!0,children:(0,J.jsxs)(`form`,{className:`modal-body net-form`,onSubmit:e=>void D(e),children:[b===`hotspot`&&N,x&&(0,J.jsx)(od,{label:`Network name (SSID)`,error:w(`ssid`),help:b===`hotspot`?`What phones and laptops list`:void 0,children:e=>(0,J.jsx)(`input`,{id:e,value:i.ssid,autoComplete:`off`,autoCapitalize:`off`,spellCheck:!1,autoFocus:!r,onChange:e=>S({ssid:e.target.value})})}),x&&(0,J.jsxs)(`div`,{className:`net-form-row`,children:[(0,J.jsx)(od,{label:`Security`,error:w(`security`),children:e=>(0,J.jsx)(`select`,{id:e,value:i.security,onChange:e=>{let t=e.target.value;S({security:t,password:eu(t)?i.password??(r?null:``):null})},children:(b===`hotspot`?[`wpa-psk`,`open`]:_d).map(e=>(0,J.jsx)(`option`,{value:e,children:b===`hotspot`&&e===`wpa-psk`?`WPA2 Personal`:$l[e]},e))})}),i.security===`wpa-eap`&&(0,J.jsx)(od,{label:`User name`,error:w(`identity`),children:e=>(0,J.jsx)(`input`,{id:e,value:i.identity,autoComplete:`off`,autoCapitalize:`off`,spellCheck:!1,onChange:e=>S({identity:e.target.value})})})]}),x&&eu(i.security)&&(0,J.jsx)(od,{label:`Password`,error:w(`password`),help:P??(b===`hotspot`?`8 to 63 characters: give it to who joins, or share the access point’s QR code`:i.security===`wpa-eap`?`PEAP with MSCHAPv2, the server’s certificate not checked`:void 0),children:e=>(0,J.jsxs)(`div`,{className:`net-password-row`,children:[(0,J.jsx)(cd,{id:e,value:i.password??``,placeholder:r&&i.password===null?`Unchanged`:void 0,initiallyShown:b===`hotspot`&&!r,onChange:e=>S({password:e===``&&r?null:e})}),b===`hotspot`&&(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:()=>S({password:ud()}),children:`New one`})]})}),b===`hotspot`&&i.security===`open`&&(0,J.jsx)(`p`,{className:`net-warning`,children:`Open: anyone in range may join the robot’s network, and reach the dashboard.`}),b===`hotspot`&&(0,J.jsxs)(`div`,{className:`net-form-row`,children:[(0,J.jsx)(od,{label:`Band`,children:e=>(0,J.jsxs)(`select`,{id:e,value:i.band,onChange:e=>S({band:e.target.value,channel:0}),children:[(0,J.jsx)(`option`,{value:``,children:`Automatic`}),(0,J.jsx)(`option`,{value:`bg`,disabled:A&&!A.band24,children:`2.4 GHz: farther, every device`}),(0,J.jsx)(`option`,{value:`a`,disabled:A&&!A.band5,children:`5 GHz: faster`})]})}),(0,J.jsx)(od,{label:`Channel`,error:w(`channel`),children:e=>(0,J.jsxs)(`select`,{id:e,value:i.channel,disabled:!i.band,onChange:e=>S({channel:Number(e.target.value)}),children:[(0,J.jsx)(`option`,{value:0,children:`Automatic`}),(i.band?gd[i.band]:[]).map(e=>(0,J.jsx)(`option`,{value:e,children:e},e)),i.band&&i.channel!==0&&!gd[i.band].includes(i.channel)&&(0,J.jsx)(`option`,{value:i.channel,children:i.channel})]})})]}),b===`wifi`&&(0,J.jsx)(sd,{label:`Hidden network`,help:`It does not show its name: the robot looks for it by name`,checked:i.hidden,onChange:e=>S({hidden:e})}),b!==`hotspot`&&N,(0,J.jsx)(od,{label:`Connection name`,error:w(`name`),help:`How the robot’s lists name it`,children:e=>(0,J.jsx)(`input`,{id:e,value:i.name,autoComplete:`off`,onChange:e=>{d(!0),S({name:e.target.value})}})}),(0,J.jsx)(`h3`,{className:`net-form-heading`,children:`Addresses`}),b!==`hotspot`&&(0,J.jsx)(od,{label:`IPv4`,error:w(`ipv4`),children:e=>(0,J.jsx)(`select`,{id:e,value:i.ipv4,onChange:e=>S({ipv4:e.target.value}),children:hd[b].map(e=>(0,J.jsx)(`option`,{value:e.value,children:e.label},e.value))})}),(i.ipv4===`manual`||i.ipv4===`shared`)&&(0,J.jsx)(od,{label:i.ipv4===`manual`?`The robot’s address`:`The robot’s address on the network it gives`,error:w(`addresses`),help:i.ipv4===`manual`?`With its network’s size: 192.168.1.20/24. Several: separated by commas`:`Optional: 10.42.0.1/24 if empty. The others get addresses of its network`,children:e=>(0,J.jsx)(`input`,{id:e,value:o,placeholder:i.ipv4===`manual`?`192.168.1.20/24`:`10.42.0.1/24`,inputMode:`decimal`,autoComplete:`off`,spellCheck:!1,onChange:e=>{s(e.target.value),S({addresses:cu(e.target.value)})}})}),i.ipv4!==`disabled`&&b!==`hotspot`&&(0,J.jsxs)(`div`,{className:`net-form-row`,children:[i.ipv4===`manual`&&(0,J.jsx)(od,{label:`Gateway`,error:w(`gateway`),help:`Optional: the way to other networks`,children:e=>(0,J.jsx)(`input`,{id:e,value:i.gateway,placeholder:`192.168.1.1`,inputMode:`decimal`,autoComplete:`off`,spellCheck:!1,onChange:e=>S({gateway:e.target.value.trim()})})}),(0,J.jsx)(od,{label:`DNS servers`,error:w(`dns`),help:i.ipv4===`manual`?`Optional, separated by commas`:`Optional: besides the network’s`,children:e=>(0,J.jsx)(`input`,{id:e,value:c,placeholder:`1.1.1.1, 8.8.8.8`,inputMode:`decimal`,autoComplete:`off`,spellCheck:!1,onChange:e=>{l(e.target.value),S({dns:cu(e.target.value)})}})})]}),(0,J.jsx)(`h3`,{className:`net-form-heading`,children:`When`}),(0,J.jsx)(sd,{label:b===`hotspot`?`Start automatically`:`Connect automatically`,help:b===`hotspot`?`When the robot starts: it is then the robot’s network wherever it goes`:b===`wifi`?`Whenever the robot is in its range`:`Whenever a cable is plugged in`,checked:i.autoconnect,onChange:e=>S({autoconnect:e})}),i.autoconnect&&(0,J.jsx)(od,{label:`Priority`,error:w(`priority`),help:`Of the connections that connect automatically, the highest first`,children:e=>(0,J.jsx)(`input`,{id:e,type:`number`,min:-999,max:999,step:1,value:Number.isFinite(i.priority)?i.priority:``,onChange:e=>S({priority:e.target.value===``?0:Number(e.target.value)})})}),!r&&(0,J.jsx)(sd,{label:b===`hotspot`?`Start it now`:`Connect now`,checked:f,onChange:p}),(0,J.jsx)(pd,{risk:E,error:v}),(0,J.jsxs)(`div`,{className:`modal-actions`,children:[(0,J.jsx)(`button`,{type:`button`,className:`button`,onClick:n,children:`Cancel`}),(0,J.jsx)(`button`,{type:`submit`,className:`button ${E?`danger`:`primary`}`,disabled:g,children:g?f&&!r?`Connecting…`:`Saving…`:M})]})]})})}function bd({text:e,what:t}){return(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Copy the ${t}`,"aria-label":`Copy the ${t}`,onClick:()=>ts(e).then(()=>G(`Copied the ${t}`),e=>G(`Could not copy the ${t}: ${rs(e)}`,`error`)),children:(0,J.jsx)(z,{width:15,height:15})})}function xd({connection:e,onClose:t}){let[n,r]=(0,q.useState)(null),[i,a]=(0,q.useState)(null),[o,s]=(0,q.useState)(!1);(0,q.useEffect)(()=>{let t=!0;return b.networkAction({action:`secrets`,uuid:e.uuid}).then(e=>t&&r(e),e=>t&&a(rs(e))),()=>{t=!1}},[e.uuid]);let c=n?.ssid??e.ssid,l=n?.security??e.security??`open`,u=!eu(l),d=u||!!n?.password,f=n&&d&&l!==`wpa-eap`?td(c,n.password,u?`nopass`:l===`wep`?`WEP`:`WPA`,n.hidden):null,p;return p=i?(0,J.jsx)(`p`,{className:`net-error`,children:i}):n?(0,J.jsxs)(J.Fragment,{children:[f&&(0,J.jsxs)(`div`,{className:`net-share-code`,children:[(0,J.jsx)(ld,{text:f,label:`QR code to join ${c}`}),(0,J.jsxs)(`p`,{className:`net-muted`,children:[`Point a phone’s camera at it to join `,c]})]}),(0,J.jsxs)(`dl`,{className:`net-facts net-share-facts`,children:[(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:`Network`}),(0,J.jsxs)(`dd`,{children:[(0,J.jsx)(`span`,{children:c}),(0,J.jsx)(bd,{text:c,what:`network’s name`})]})]}),(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:`Security`}),(0,J.jsx)(`dd`,{children:$l[l]})]}),!u&&(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:`Password`}),(0,J.jsx)(`dd`,{children:d?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`span`,{className:`net-secret`,children:o?n.password:`•`.repeat(Math.min(16,n.password.length))}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:o?`Hide the password`:`Show the password`,"aria-label":o?`Hide the password`:`Show the password`,"aria-pressed":o,onClick:()=>s(e=>!e),children:o?`Hide`:`Show`}),(0,J.jsx)(bd,{text:n.password,what:`password`})]}):(0,J.jsx)(`span`,{className:`net-muted`,children:`Not readable: the server’s user may not read NetworkManager’s secrets, or they are kept by a desktop’s keyring`})})]})]})]}):(0,J.jsx)(`p`,{className:`net-muted`,children:`Reading the password…`}),(0,J.jsx)($e,{title:`Share ${c||e.name}`,onClose:t,children:(0,J.jsxs)(`div`,{className:`modal-body`,children:[p,(0,J.jsx)(`div`,{className:`modal-actions`,children:(0,J.jsx)(`button`,{type:`button`,className:`button primary`,onClick:t,autoFocus:!0,children:`Done`})})]})})}function Sd({request:e,state:t,onClose:n}){switch(e.kind){case`join`:case`password`:return(0,J.jsx)(md,{state:t,request:e,onClose:n});case`create`:case`edit`:return(0,J.jsx)(yd,{state:t,request:e,onClose:n});case`share`:return(0,J.jsx)(xd,{connection:e.connection,onClose:n})}}var Cd={auto:`Automatic (DHCP)`,manual:`Manual`,shared:`Shared: the robot gives the addresses`,disabled:`Disabled`,"link-local":`Link-local only`};function $({label:e,children:t}){return(0,J.jsxs)(`div`,{children:[(0,J.jsx)(`dt`,{children:e}),(0,J.jsx)(`dd`,{children:t})]})}function wd({icon:e,name:t,title:n,children:r,footer:i,onClose:a}){return(0,J.jsxs)(`section`,{className:`net-details`,"aria-label":`${t}: details`,children:[(0,J.jsxs)(`header`,{className:`net-details-header`,children:[(0,J.jsx)(`span`,{className:`net-details-icon`,children:e}),(0,J.jsx)(`strong`,{className:`net-details-name`,title:n??t,children:t}),(0,J.jsx)(`span`,{className:`net-spacer`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:`Close (Esc)`,"aria-label":`Close`,onClick:a,children:(0,J.jsx)(H,{width:16,height:16})})]}),(0,J.jsx)(`div`,{className:`net-details-body`,children:r}),i&&(0,J.jsx)(`footer`,{className:`net-details-actions`,children:i})]})}function Td({label:e,actions:t,danger:n=!1,primary:r=!1,disabled:i,onClick:a}){let o=t.blocked??i??null;return(0,J.jsx)(`button`,{type:`button`,className:`button${n?` danger`:r?` primary`:``}`,disabled:o!==null,title:o??void 0,onClick:a,children:e})}function Ed({list:e}){return e.length>0?(0,J.jsx)(J.Fragment,{children:e.map(e=>(0,J.jsx)(`span`,{className:`net-fact-line`,children:e},e))}):(0,J.jsx)(`span`,{className:`net-muted`,children:`None`})}function Dd(e){return/\/netplan-[^/]*$/.test(e)?`From netplan (/etc/netplan)`:e.startsWith(`/run/`)?`In memory: lost at reboot`:null}function Od({state:e,connection:t,now:n,signal:r=!0}){let i=e.devices.find(e=>e.name===t.device),a=t.kind===`wifi`||t.kind===`hotspot`,o=r&&t.kind===`wifi`?e.networks.find(e=>e.ssid===t.ssid):void 0,s=Dd(t.file),c=i?.state===100,l;return l=t.activeState===`activated`?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(ad,{tone:`on`}),` `,t.kind===`hotspot`?`On`:`Connected`,`, on `,t.device]}):t.activeState?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(ad,{tone:`busy`}),` `,i?yu(i,e.wifi).text:t.activeState]}):`Not connected`,(0,J.jsxs)(`dl`,{className:`net-facts`,children:[(0,J.jsx)($,{label:`Status`,children:l}),(0,J.jsx)($,{label:`Kind`,children:Su(t)}),a&&t.ssid&&t.ssid!==t.name&&(0,J.jsx)($,{label:`Network`,children:t.ssid}),a&&t.security&&(0,J.jsx)($,{label:`Security`,children:$l[t.security]}),t.security===`wpa-eap`&&t.identity&&(0,J.jsx)($,{label:`User name`,children:t.identity}),t.kind===`hotspot`&&(0,J.jsxs)($,{label:`Band`,children:[t.band?t.band===`a`?`5 GHz`:`2.4 GHz`:`Automatic`,t.channel>0&&`, channel ${t.channel}`]}),o&&(0,J.jsxs)($,{label:`Signal`,children:[o.signal,`% · `,hu(o.frequency),`, channel `,o.channel]}),t.hidden&&(0,J.jsx)($,{label:`Hidden`,children:`Its name is not shown: looked for by name`}),(t.kind===`wifi`||t.kind===`hotspot`||t.kind===`ethernet`)&&(0,J.jsx)($,{label:`Interface`,children:t.interface||`Any`}),t.ipv4Method&&(0,J.jsx)($,{label:`IPv4`,children:Cd[t.ipv4Method]??t.ipv4Method}),(c||t.addresses.length>0)&&(0,J.jsx)($,{label:`Address`,children:(0,J.jsx)(Ed,{list:c?i.ipv4:t.addresses})}),(c?i.gateway:t.gateway)&&(0,J.jsx)($,{label:`Gateway`,children:c?i.gateway:t.gateway}),(c?i.dns:t.dns).length>0&&(0,J.jsx)($,{label:`DNS`,children:(0,J.jsx)(Ed,{list:c?i.dns:t.dns})}),(0,J.jsx)($,{label:`Automatic`,children:t.autoconnect?`Yes${t.priority===0?``:`, priority ${t.priority}`}`:`No: only when asked`}),(0,J.jsx)($,{label:`Last used`,children:(0,J.jsx)(`span`,{title:t.lastUsed?new Date(t.lastUsed).toLocaleString():void 0,children:Fu(t.lastUsed,n).replace(/^Used (on )?/,``).replace(/^Never used$/,`Never`)})}),t.file&&(0,J.jsxs)($,{label:`File`,children:[(0,J.jsx)(`span`,{className:`net-fact-line`,children:t.file}),s&&(0,J.jsx)(`span`,{className:`net-fact-line net-muted`,children:s})]}),(0,J.jsx)($,{label:`UUID`,children:(0,J.jsx)(`span`,{className:`net-mono`,children:t.uuid})})]})}function kd({connection:e,actions:t}){if(t.readOnly||e.external)return null;let n=e.kind===`hotspot`,r=e.kind===`wifi`||n||e.kind===`ethernet`,i=e.readOnly?`NetworkManager has it read-only`:null;return(0,J.jsxs)(J.Fragment,{children:[e.activeState?(0,J.jsx)(Td,{label:n?`Stop`:`Disconnect`,actions:t,onClick:()=>t.disconnect(e)}):(0,J.jsx)(Td,{label:n?`Start`:`Connect`,primary:!0,actions:t,onClick:()=>t.connect(e,null)}),r&&(0,J.jsx)(Td,{label:`Edit…`,actions:t,disabled:i,onClick:()=>t.edit(e)}),(e.kind===`wifi`||n)&&(0,J.jsx)(Td,{label:`Share…`,actions:t,onClick:()=>t.share(e)}),(0,J.jsx)(Td,{label:`Forget…`,danger:!0,actions:t,disabled:i,onClick:()=>t.forget(e)})]})}function Ad({state:e,connection:t,actions:n,now:r,onClose:i}){let{failed:a}=Mu(e.activity,{uuid:t.uuid},r);return(0,J.jsxs)(wd,{icon:(0,J.jsx)(rd,{kind:t.kind,size:16}),name:t.name,onClose:i,footer:(0,J.jsx)(kd,{connection:t,actions:n}),children:[a&&(0,J.jsx)(`p`,{className:`net-error`,children:`${a.label}: ${a.error}`}),t.external&&(0,J.jsx)(`p`,{className:`net-muted`,children:`NetworkManager made it for an interface another program configures (docker, a VPN client…): it is not changed here.`}),(0,J.jsx)(Od,{state:e,connection:t,now:r})]})}function jd({state:e,network:t,actions:n,now:r,onClose:i}){let a=Ou(e.connections,t.ssid,t.device),{failed:o}=Mu(e.activity,{uuid:a?.uuid??null,ssid:t.ssid,device:t.device},r),s=a?(0,J.jsx)(kd,{connection:a,actions:n}):n.readOnly?null:(0,J.jsx)(Td,{label:`Join…`,primary:!0,actions:n,onClick:()=>n.join(t)});return(0,J.jsxs)(wd,{icon:(0,J.jsx)(nd,{signal:t.signal,size:16}),name:t.ssid,onClose:i,footer:s,children:[o&&(0,J.jsx)(`p`,{className:`net-error`,children:`${o.label}: ${o.error}`}),(0,J.jsxs)(`dl`,{className:`net-facts`,children:[(0,J.jsxs)($,{label:`Signal`,children:[t.signal,`%`]}),(0,J.jsxs)($,{label:`Security`,children:[$l[t.security],t.securityText&&` (${t.securityText})`]}),(0,J.jsxs)($,{label:`Band`,children:[hu(t.frequency),`, channel `,t.channel,` (`,t.frequency,` MHz)`]}),t.rate&&(0,J.jsx)($,{label:`Rate`,children:t.rate}),(0,J.jsxs)($,{label:`Access point`,children:[(0,J.jsx)(`span`,{className:`net-mono`,children:t.bssid}),t.points>1&&(0,J.jsxs)(`span`,{className:`net-fact-line net-muted`,children:[`The strongest of `,t.points]})]}),t.mode!==`Infra`&&(0,J.jsx)($,{label:`Mode`,children:t.mode}),(0,J.jsx)($,{label:`Seen by`,children:t.device})]}),a&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`h3`,{children:[`Saved as `,a.name]}),(0,J.jsx)(Od,{state:e,connection:a,now:r,signal:!1})]})]})}function Md({state:e,device:t,actions:n,onClose:r}){let i=yu(t,e.wifi),a=t.connection?e.connections.find(e=>e.uuid===t.connection):void 0,o=t.type===`wifi`?`wifi`:t.type===`ethernet`?`ethernet`:null,s=o?e.connections.filter(n=>!n.activeState&&(n.kind===o||o===`wifi`&&n.kind===`hotspot`)&&Eu(n,[t])&&(n.kind!==`wifi`||e.networks.some(e=>e.device===t.name&&e.ssid===n.ssid))):[],c=[t.band24&&`2.4 GHz`,t.band5&&`5 GHz`].filter(Boolean).join(` and `);return(0,J.jsxs)(wd,{icon:(0,J.jsx)(id,{device:t,size:16}),name:t.name,onClose:r,footer:a&&!t.external&&!n.readOnly?(0,J.jsx)(Td,{label:a.kind===`hotspot`?`Stop the access point`:`Disconnect`,actions:n,onClick:()=>n.disconnect(a)}):null,children:[(0,J.jsxs)(`dl`,{className:`net-facts`,children:[(0,J.jsxs)($,{label:`Status`,children:[(0,J.jsx)(ad,{tone:i.tone}),` `,i.text]}),t.reason&&t.state!==100&&(0,J.jsx)($,{label:`Why`,children:t.reason}),(0,J.jsx)($,{label:`Kind`,children:bu(t)}),(t.vendor||t.product)&&(0,J.jsx)($,{label:`Hardware`,children:[t.vendor,t.product].filter(Boolean).join(` `)}),t.driver&&(0,J.jsx)($,{label:`Driver`,children:t.driver}),t.hwaddr&&(0,J.jsx)($,{label:`MAC address`,children:(0,J.jsx)(`span`,{className:`net-mono`,children:t.hwaddr})}),t.speed&&(0,J.jsx)($,{label:`Speed`,children:t.speed}),t.mtu&&(0,J.jsx)($,{label:`MTU`,children:t.mtu}),t.type===`wifi`&&(0,J.jsx)($,{label:`Access point`,children:t.accessPoint?`It can be one${c?`, on ${c}`:``}`:`Not supported`}),(0,J.jsx)($,{label:`IPv4`,children:(0,J.jsx)(Ed,{list:t.ipv4})}),t.ipv6.length>0&&(0,J.jsx)($,{label:`IPv6`,children:(0,J.jsx)(Ed,{list:t.ipv6})}),t.gateway&&(0,J.jsx)($,{label:`Gateway`,children:t.gateway}),t.dns.length>0&&(0,J.jsx)($,{label:`DNS`,children:(0,J.jsx)(Ed,{list:t.dns})})]}),s.length>0&&!n.readOnly&&!t.external&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`h3`,{children:`Connect with`}),(0,J.jsx)(`ul`,{className:`net-choices`,children:s.map(e=>(0,J.jsxs)(`li`,{children:[(0,J.jsx)(rd,{kind:e.kind,size:15}),(0,J.jsx)(`span`,{className:`net-choice-name`,children:e.name}),(0,J.jsx)(Td,{label:e.kind===`hotspot`?`Start`:`Connect`,actions:n,onClick:()=>n.connect(e,t.name)})]},e.uuid))})]})]})}function Nd({selection:e,state:t,actions:n,now:r,onClose:i}){switch(e.type){case`network`:{let a=t.networks.find(t=>t.device===e.device&&t.ssid===e.ssid);return a?(0,J.jsx)(jd,{state:t,network:a,actions:n,now:r,onClose:i}):null}case`connection`:{let a=t.connections.find(t=>t.uuid===e.uuid);return a?(0,J.jsx)(Ad,{state:t,connection:a,actions:n,now:r,onClose:i}):null}case`device`:{let r=t.devices.find(t=>t.name===e.name);return r?(0,J.jsx)(Md,{state:t,device:r,actions:n,onClose:i}):null}}}function Pd(e,t){return JSON.stringify(e)===JSON.stringify(t)}function Fd({label:e,busy:t,primary:n=!1,actions:r,onClick:i}){return r.readOnly?null:(0,J.jsx)(`button`,{type:`button`,className:`net-action${n?` primary`:``}`,disabled:!!t||r.blocked!==null,title:r.blocked??void 0,onClick:i,children:t??e})}function Id({selected:e,icon:t,name:n,tags:r,sub:i,tone:a,action:o,onSelect:s}){return(0,J.jsxs)(`li`,{className:`net-row${e?` selected`:``}`,children:[(0,J.jsxs)(`button`,{type:`button`,className:`net-row-main`,"aria-pressed":e,onClick:s,children:[(0,J.jsx)(`span`,{className:`net-row-icon ${a}`,children:t}),(0,J.jsxs)(`span`,{className:`net-row-text`,children:[(0,J.jsxs)(`span`,{className:`net-row-name`,children:[(0,J.jsx)(`span`,{className:`net-row-label`,title:n,children:n}),r]}),(0,J.jsxs)(`span`,{className:`net-row-sub ${a}`,title:i,children:[(a===`busy`||a===`failed`)&&(0,J.jsx)(ad,{tone:a}),(0,J.jsx)(`span`,{className:`net-row-sub-text`,children:i})]})]})]}),o&&(0,J.jsx)(`div`,{className:`net-row-actions`,children:o})]})}function Ld({state:e,device:t}){return t&&t===e.via?(0,J.jsx)(`span`,{className:`net-tag accent`,title:`This page reaches the robot through it`,children:`this page`}):null}function Rd(e){return e?.ipv4[0]?.split(`/`)[0]??``}function zd({connection:e,...t}){let{state:n,actions:r,selection:i,onSelect:a,now:o}=t,s=n.devices.find(t=>t.name===e.device),{running:c,failed:l}=Mu(n.activity,{uuid:e.uuid,ssid:e.ssid||null,device:e.device},o),u=e.kind===`hotspot`,d,f=``;c?(d=`${c.label}…`,f=`busy`):e.activeState===`activated`?(d=[u?`On, on ${e.device}`:`Connected on ${e.device}`,Rd(s)].filter(Boolean).join(` · `),f=`on`):e.activeState===`activating`?(d=s?yu(s,n.wifi).text:`Connecting…`,f=`busy`):e.activeState===`deactivating`?(d=`Disconnecting…`,f=`busy`):l?(d=l.error??``,f=`failed`):d=[e.kind===`ethernet`&&e.ipv4Method===`manual`?e.addresses.join(`, `):u&&e.ssid!==e.name?e.ssid:``,Fu(e.lastUsed,o),e.autoconnect?``:`not automatic`].filter(Boolean).join(` · `);let p=e.activeState!==null,m={type:`connection`,uuid:e.uuid},h=n.devices.find(t=>t.name===e.interface),g=h&&n.devices.filter(e=>e.type===h.type).length>1;return(0,J.jsx)(Id,{selected:Pd(i,m),icon:(0,J.jsx)(rd,{kind:e.kind}),name:e.name,tags:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(Ld,{state:n,device:e.device}),g&&(0,J.jsx)(`span`,{className:`net-tag`,children:e.interface})]}),sub:d,tone:f,onSelect:()=>a(m),action:e.external?null:p?(0,J.jsx)(Fd,{label:u?`Stop`:`Disconnect`,busy:c?`…`:null,actions:r,onClick:()=>r.disconnect(e)}):(0,J.jsx)(Fd,{label:u?`Start`:`Connect`,busy:c?`…`:null,primary:!0,actions:r,onClick:()=>r.connect(e,null)})})}function Bd({network:e,saved:t,device:n,...r}){let{state:i,actions:a,selection:o,onSelect:s,now:c}=r,{running:l,failed:u}=Mu(i.activity,{uuid:t?.uuid??null,ssid:e.ssid,device:n.name},c),d=e.active&&n.connection!==null,f=d?i.connections.find(e=>e.uuid===n.connection):void 0,p=hu(e.frequency),m,h=``;if(l)m=`${l.label}…`,h=`busy`;else if(d){let e=yu(n,i.wifi);m=n.state===100?[`Connected`,Rd(n),p].filter(Boolean).join(` · `):e.text,h=e.tone}else u?(m=u.error??``,h=`failed`):m=[t?`Saved`:``,e.securityText||`Open`,p].filter(Boolean).join(` · `);let g={type:`network`,device:n.name,ssid:e.ssid},_;return d&&f?_=(0,J.jsx)(Fd,{label:`Disconnect`,actions:a,onClick:()=>a.disconnect(f)}):d||(_=(0,J.jsx)(Fd,{label:t?`Connect`:`Join`,busy:l?`…`:null,primary:!0,actions:a,onClick:()=>t?a.connect(t,n.name):a.join(e)})),(0,J.jsx)(Id,{selected:Pd(o,g),icon:(0,J.jsx)(nd,{signal:e.signal}),name:e.ssid,tags:(0,J.jsxs)(J.Fragment,{children:[e.security!==`open`&&e.security!==`owe`&&(0,J.jsx)(Oe,{className:`net-lock`,width:12,height:12}),d&&(0,J.jsx)(Ld,{state:i,device:n.name})]}),sub:m,tone:d&&h===``?`on`:h,action:_,onSelect:()=>s(g)})}function Vd({icon:e,label:t,disabled:n,onClick:r}){return(0,J.jsx)(`li`,{className:`net-row`,children:(0,J.jsxs)(`button`,{type:`button`,className:`net-row-main net-add`,disabled:n!==null,title:n??void 0,onClick:r,children:[(0,J.jsx)(`span`,{className:`net-row-icon`,children:e}),(0,J.jsx)(`span`,{className:`net-row-label`,children:t})]})})}function Hd({device:e,many:t,...n}){let{state:r,text:i,actions:a}=n,s=r.connections.find(t=>t.device===e.name&&(t.kind===`wifi`||t.kind===`hotspot`)),c=ku(r,e.name,i),l=s?.kind===`wifi`&&!c.some(e=>e.network.active)?s:null,u=e.accessPoint?Au(r.connections,e.name).filter(e=>e.uuid!==s?.uuid):[],d=null;c.length===0&&(d=i.trim()?`No network matches “${i.trim()}”`:s?.kind===`hotspot`?`An access point does not look for networks: stop it to join one`:r.scanning?`Looking for networks…`:`No network in range`);let f=a.blocked;return(0,J.jsxs)(`section`,{className:`net-section`,"aria-label":`Wi-Fi of ${e.name}`,children:[t&&(0,J.jsxs)(`h3`,{className:`net-heading`,children:[e.name,(e.product||e.vendor)&&(0,J.jsx)(`span`,{className:`net-heading-detail`,children:e.product||e.vendor})]}),(0,J.jsxs)(`ul`,{className:`net-list`,children:[s?.kind===`hotspot`&&(0,J.jsx)(zd,{...n,connection:s}),l&&(0,J.jsx)(zd,{...n,connection:l}),c.map(t=>(0,J.jsx)(Bd,{...n,network:t.network,saved:t.saved,device:e},t.network.ssid))]}),d&&(0,J.jsx)(`p`,{className:`net-note`,children:d}),!i.trim()&&(0,J.jsxs)(`ul`,{className:`net-list net-extra`,children:[u.map(e=>(0,J.jsx)(zd,{...n,connection:e},e.uuid)),!a.readOnly&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(Vd,{icon:(0,J.jsx)(ce,{width:16,height:16}),label:`Join a hidden network…`,disabled:f,onClick:()=>a.create(`wifi`,e.name)}),e.accessPoint&&(0,J.jsx)(Vd,{icon:(0,J.jsx)(o,{width:16,height:16}),label:`New access point…`,disabled:f,onClick:()=>a.create(`hotspot`,e.name)})]})]})]})}function Ud(e){let{state:t,devices:n,actions:r}=e,i=n.filter(e=>e.type===`wifi`);return t.wifi?i.length===0?(0,J.jsxs)(`div`,{className:`net-empty`,children:[(0,J.jsx)(f,{width:28,height:28}),(0,J.jsx)(`p`,{children:`No Wi-Fi interface`})]}):(0,J.jsx)(`div`,{className:`net-scroll`,children:i.map(t=>(0,J.jsx)(Hd,{...e,device:t,many:i.length>1},t.name))}):(0,J.jsxs)(`div`,{className:`net-empty`,children:[(0,J.jsx)(f,{width:28,height:28}),(0,J.jsx)(`p`,{children:t.wifiHardware?`Wi-Fi is off`:`Wi-Fi is off by its hardware switch`}),t.wifiHardware&&!r.readOnly&&(0,J.jsx)(`button`,{type:`button`,className:`button primary`,disabled:r.blocked!==null,title:r.blocked??void 0,onClick:()=>r.setWifi(!0),children:`Turn Wi-Fi on`})]})}function Wd(e){let{state:t,devices:n,text:r,all:i,actions:a}=e,o=Du(t.connections,n,r,i);return(0,J.jsxs)(`div`,{className:`net-scroll`,children:[o.length===0&&(0,J.jsx)(`p`,{className:`net-note`,children:r.trim()?`No connection matches “${r.trim()}”`:`No connection saved`}),o.map(t=>(0,J.jsxs)(`section`,{className:`net-section`,"aria-label":t.title,children:[(0,J.jsxs)(`h3`,{className:`net-heading`,children:[t.title,(0,J.jsx)(`span`,{className:`net-heading-detail`,children:t.connections.length})]}),(0,J.jsx)(`ul`,{className:`net-list`,children:t.connections.map(t=>(0,J.jsx)(zd,{...e,connection:t},t.uuid))})]},t.kind)),!r.trim()&&!a.readOnly&&(0,J.jsx)(`ul`,{className:`net-list net-extra`,children:(0,J.jsx)(Vd,{icon:(0,J.jsx)(ce,{width:16,height:16}),label:`New wired connection…`,disabled:a.blocked,onClick:()=>a.create(`ethernet`,null)})})]})}function Gd(e){let{state:t,devices:n,selection:r,onSelect:i,actions:a}=e;return n.length===0?(0,J.jsx)(`p`,{className:`net-note`,children:`No interface`}):(0,J.jsx)(`div`,{className:`net-scroll`,children:(0,J.jsx)(`ul`,{className:`net-list`,children:n.map(e=>{let n=yu(e,t.wifi),o=e.connection?t.connections.find(t=>t.uuid===e.connection):void 0,s={type:`device`,name:e.name};return(0,J.jsx)(Id,{selected:Pd(r,s),icon:(0,J.jsx)(id,{device:e}),name:e.name,tags:(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(Ld,{state:t,device:e.name}),(0,J.jsx)(`span`,{className:`net-row-detail`,children:e.product||e.vendor||bu(e)})]}),sub:[n.text,Rd(e)].filter(Boolean).join(` · `),tone:n.tone,onSelect:()=>i(s),action:o&&!e.external&&e.state===100?(0,J.jsx)(Fd,{label:o.kind===`hotspot`?`Stop`:`Disconnect`,actions:a,onClick:()=>a.disconnect(o)}):null},e.name)})})})}var Kd=620,qd=300,Jd=[{view:`wifi`,label:`Wi-Fi`,title:`The Wi-Fi networks in range`,Icon:O},{view:`saved`,label:`Saved`,title:`The connections saved`,Icon:B},{view:`devices`,label:`Interfaces`,title:`The interfaces, their addresses`,Icon:ue}];function Yd(e){let[t,n]=(0,q.useState)(()=>b.serverNow());return(0,q.useEffect)(()=>{let t=setInterval(()=>n(b.serverNow()),e);return()=>clearInterval(t)},[e]),t}function Xd({config:e}){let t=et(),[n,r]=(0,q.useState)(null),[i,a]=(0,q.useState)(e.view),[o,s]=(0,q.useState)(``),[c,l]=(0,q.useState)(null),[u,d]=(0,q.useState)(null),[p,m]=(0,q.useState)(null),[h,g]=(0,q.useState)({width:0,height:0}),_=(0,q.useRef)(null),v=Yd(5e3);(0,q.useEffect)(()=>a(e.view),[e.view]),(0,q.useEffect)(()=>b.subscribeNetwork(r),[]),(0,q.useEffect)(()=>{let e=_.current;if(!e)return;let t=new ResizeObserver(([e])=>g({width:e.contentRect.width,height:e.contentRect.height}));return t.observe(e),()=>t.disconnect()},[n!==null]);let y=(0,q.useMemo)(()=>gu(e.interfaces),[e.interfaces]),x=(0,q.useMemo)(()=>n?_u(n.devices,y,e.allInterfaces):[],[n,y,e.allInterfaces]),S=x.some(e=>e.type===`wifi`),C=i===`wifi`&&!S&&n&&x.length>0?`saved`:i,w=n?Bu(n,e.readOnly):null,T=(e,t)=>fd(e,t,n?Pu(n,e)!==null:!1).then(()=>null,e=>rs(e)),E=async(e,r)=>{let i=n?Pu(n,e):null;return!i&&!r.always||t.confirm({title:r.title,message:(0,J.jsxs)(J.Fragment,{children:[r.message,i&&(0,J.jsx)(`p`,{className:`net-warning`,children:i})]}),confirmLabel:r.confirmLabel,danger:i!==null||r.danger})},D=e=>e.kind===`wifi`&&e.ssid?e.ssid:e.name,k={blocked:w,readOnly:e.readOnly,connect:async(e,t)=>{let n={action:`connect`,uuid:e.uuid,device:t,password:null},r=e.kind===`hotspot`,i={title:r?`Start ${e.name}?`:`Switch to ${D(e)}?`,confirmLabel:r?`Start`:`Switch`,always:!1};if(!await E(n,i))return;let a=await T(n,r?`The access point ${D(e)} is on`:`Connected to ${D(e)}`);a&&(a===`Wrong password, or none given`&&e.security&&eu(e.security)?d({kind:`password`,connection:e,device:t,error:a}):G(`Could not ${r?`start`:`connect to`} ${D(e)}: ${a}`,`error`))},disconnect:async t=>{let n={action:`disconnect`,uuid:t.uuid},r=t.kind===`hotspot`,i={title:r?`Stop ${t.name}?`:`Disconnect from ${D(t)}?`,message:r?`Whoever joined the robot’s network loses it.`:t.autoconnect?`It does not connect by itself again until asked, or until the robot restarts.`:`It stays saved.`,confirmLabel:r?`Stop`:`Disconnect`,danger:!0,always:e.confirm};if(!await E(n,i))return;let a=await T(n,null);a&&G(`Could not ${r?`stop`:`disconnect from`} ${D(t)}: ${a}`,`error`)},forget:async e=>{let t={action:`delete`,uuid:e.uuid},n={title:`Forget ${e.name}?`,message:e.kind===`wifi`?`Its password is deleted with it: joining the network again asks for it.`:`Its settings are deleted with it.`,confirmLabel:`Forget`,danger:!0,always:!0};if(!await E(t,n))return;c?.type===`connection`&&c.uuid===e.uuid&&l(null);let r=await T(t,`Forgot ${e.name}`);r&&G(`Could not forget ${e.name}: ${r}`,`error`)},join:async e=>{if(eu(e.security)){d({kind:`join`,network:e});return}let t={action:`create`,settings:Lu(e,null,``,!0,!1,n?.connections??[]),connect:!0,device:e.device},r={title:`Join ${e.ssid}?`,message:e.security===`open`?`It is open: others on it may see what the robot sends.`:`It is open, its traffic encrypted (OWE).`,confirmLabel:`Join`,always:e.security===`open`};if(!await E(t,r))return;let i=await T(t,`Connected to ${e.ssid}`);i&&G(`Could not join ${e.ssid}: ${i}`,`error`)},create:(e,t)=>d({kind:`create`,settings:e,device:t}),edit:e=>d({kind:`edit`,connection:e}),share:e=>d({kind:`share`,connection:e}),setWifi:async t=>{let n={action:`wifi`,enabled:t},r={title:t?`Turn Wi-Fi on?`:`Turn Wi-Fi off?`,message:t?``:`Every Wi-Fi interface disconnects, access points stop.`,confirmLabel:t?`Turn on`:`Turn off`,danger:!t,always:!t&&e.confirm};if(!await E(n,r))return;let i=await T(n,null);i&&G(`Could not turn Wi-Fi ${t?`on`:`off`}: ${i}`,`error`)}},A=()=>void b.networkAction({action:`rescan`,device:null}).catch(e=>G(`Could not scan: ${rs(e)}`,`error`)),j=e=>{let t=e.currentTarget.getBoundingClientRect(),r=x.filter(e=>e.type===`wifi`),i=w;m({x:t.right-200,y:t.bottom+4,items:[{label:`Join a hidden network…`,disabled:i!==null||r.length===0||!n?.wifi,run:()=>k.create(`wifi`,null)},{label:`New access point…`,disabled:i!==null||!r.some(e=>e.accessPoint)||!n?.wifi,run:()=>k.create(`hotspot`,null)},{label:`New wired connection…`,disabled:i!==null,run:()=>k.create(`ethernet`,null)}]})};if((0,q.useEffect)(()=>{n&&c&&((c.type===`network`?n.networks.some(e=>e.device===c.device&&e.ssid===c.ssid):c.type===`connection`?n.connections.some(e=>e.uuid===c.uuid):n.devices.some(e=>e.name===c.name))||l(null))},[n,c]),!n)return(0,J.jsx)(`div`,{className:`widget-message`,children:`Reading the networks…`});let M={wifi:n.networks.filter(e=>x.some(t=>t.name===e.device)).length,saved:Du(n.connections,x,``,e.allInterfaces).reduce((e,t)=>e+t.connections.length,0),devices:x.length},N={state:n,devices:x,text:o,all:e.allInterfaces,selection:c,onSelect:e=>l(t=>JSON.stringify(t)===JSON.stringify(e)?null:e),actions:k,now:v},P=zu(n,v),{width:F,height:I}=h,L=F>=Kd,R=c&&(0,J.jsx)(Nd,{selection:c,state:n,actions:k,now:v,onClose:()=>l(null)}),ee;ee=n.error?(0,J.jsx)(`p`,{className:`net-note error`,children:n.error}):C===`wifi`?(0,J.jsx)(Ud,{...N}):C===`saved`?(0,J.jsx)(Wd,{...N}):(0,J.jsx)(Gd,{...N});let te=!e.readOnly&&!n.error&&w?(0,J.jsx)(`p`,{className:`net-banner`,role:`note`,children:w}):null;return(0,J.jsxs)(`div`,{ref:_,className:`net${R&&!L&&I>0&&I<qd?` cramped`:``}`,onKeyDown:e=>{e.key===`Escape`&&c&&l(null)},children:[(0,J.jsxs)(`div`,{className:`net-toolbar`,role:`toolbar`,"aria-label":`Networking`,children:[(0,J.jsx)(`div`,{className:`net-views`,role:`group`,"aria-label":`View`,children:Jd.filter(({view:e})=>e!==`wifi`||S).map(({view:e,label:t,title:n,Icon:r})=>(0,J.jsxs)(`button`,{type:`button`,className:`net-view`,"aria-pressed":C===e,title:n,onClick:()=>{a(e),l(null)},children:[(0,J.jsx)(r,{width:14,height:14}),(0,J.jsx)(`span`,{className:`net-view-name`,children:t}),(0,J.jsx)(`span`,{className:`net-view-count`,children:M[e]})]},e))}),C!==`devices`&&(0,J.jsxs)(`label`,{className:`net-search`,title:`Only those whose name contains`,children:[(0,J.jsx)(ne,{width:14,height:14}),(0,J.jsx)(`input`,{type:`search`,value:o,placeholder:`Filter…`,"aria-label":`Only those whose name contains`,spellCheck:!1,onChange:e=>s(e.target.value)})]}),(0,J.jsxs)(`div`,{className:`net-tools`,children:[C===`wifi`&&(0,J.jsx)(`button`,{type:`button`,className:`overlay-button${n.scanning?` net-spinning`:``}`,title:n.scanning?`Looking for networks…`:`Look for networks again`,"aria-label":`Look for networks again`,disabled:!n.wifi||n.scanning||n.error!==null,onClick:A,children:(0,J.jsx)(xe,{width:17,height:17})}),S&&!e.readOnly&&(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,"aria-pressed":n.wifi,title:n.wifiHardware?w??(n.wifi?`Wi-Fi is on: turn it off`:`Wi-Fi is off: turn it on`):`Wi-Fi is off by its hardware switch`,"aria-label":n.wifi?`Turn Wi-Fi off`:`Turn Wi-Fi on`,disabled:w!==null||!n.wifiHardware||n.error!==null,onClick:()=>k.setWifi(!n.wifi),children:n.wifi?(0,J.jsx)(O,{width:17,height:17}):(0,J.jsx)(f,{width:17,height:17})}),!e.readOnly&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`span`,{className:`overlay-separator`}),(0,J.jsx)(`button`,{type:`button`,className:`overlay-button`,title:w??`A new connection: a hidden network, an access point, a cable’s`,"aria-label":`New connection`,"aria-haspopup":`menu`,disabled:w!==null||n.error!==null,onClick:j,children:(0,J.jsx)(ce,{width:17,height:17})})]})]})]}),te,(0,J.jsxs)(`div`,{className:`net-body${L?` beside`:``}`,children:[(0,J.jsx)(`div`,{className:`net-main`,children:ee}),R]}),(0,J.jsxs)(`div`,{className:`net-status ${P.tone}`,title:P.text,children:[(0,J.jsx)(ad,{tone:P.tone}),(0,J.jsx)(`span`,{className:`net-status-text`,children:P.text})]}),u&&(0,J.jsx)(Sd,{request:u,state:n,onClose:()=>d(null)}),p&&(0,J.jsx)(os,{x:Math.max(4,p.x),y:p.y,items:p.items,onClose:()=>m(null)})]})}var Zd=Ye({type:`networking`,name:`Networking`,description:`The robot’s networks: join Wi-Fi networks, switch between those saved, set addresses, make it an access point.`,icon:ue,defaultSize:{w:6,h:7},minSize:{w:3,h:3},component:Xd,properties:[{key:`view`,label:`View`,kind:`select`,default:`wifi`,options:[{value:`wifi`,label:`Wi-Fi networks in range`},{value:`saved`,label:`Saved connections`},{value:`devices`,label:`Interfaces`}],help:`When the panel opens: its toolbar changes it`},{key:`interfaces`,label:`Interfaces`,kind:`string`,default:``,placeholder:`wlan0, eth*`,help:`Only these, and their connections: names or globs (*), separated by commas. All if empty`},{key:`allInterfaces`,label:`Show every interface`,kind:`boolean`,default:!1,help:`Also those other programs configure (docker’s bridges, VPN clients’ tunnels), the loopback, Wi-Fi P2P`},{key:`confirm`,label:`Ask before disconnecting`,kind:`boolean`,default:!0,help:`And before turning Wi-Fi off. A change that would cut this page off from the robot is always asked about`},{key:`readOnly`,label:`Read-only`,kind:`boolean`,default:!1,help:`The networks are shown, not changed: e.g. on a panel for operators`}]}),Qd=`modulepreload`,$d=function(e){return`/`+e},ef={},tf=function(e){return e.pathname.endsWith(`.css`)},nf=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},rf=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=$d(t,n);let r=s(t),i=tf(r);return nf(ef,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`:Qd,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)})},af=(0,q.lazy)(()=>rf(()=>import(`./RobotModelView.js`),__vite__mapDeps([0,1,2,3,4])));function of({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)(af,{config:e})})}var sf=Ye({type:`robot-model`,name:`Robot Model`,description:`The robot in 3D, its moving joints highlighted, and its TF frames.`,icon:Fe,defaultSize:{w:6,h:5},minSize:{w:3,h:3},component:of,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`}]}),cf={x:0,y:0,z:0};function lf(e){return e.x===0&&e.y===0&&e.z===0}function uf(e,t){b.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 df({config:e,editing:t}){let n=We()===`open`,[r,i]=(0,q.useState)(cf),a=(0,q.useRef)(cf),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),!lf(t)&&!s.current?(s.current=!0,uf(o.current,t)):lf(t)&&s.current&&(s.current=!1,uf(o.current,cf))},[]);(0,q.useEffect)(()=>{let t=setInterval(()=>s.current&&uf(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,uf({...o.current,topic:l,stamped:u},cf))},[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)(Ze,{axes:`xy`,label:`x · y`,disabled:d,onMove:(e,t)=>c({x:t,y:-e})}),(0,J.jsx)(Ze,{axes:`x`,label:`z`,disabled:d,onMove:e=>c({z:-e})})]}):(0,J.jsx)(Ze,{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 ff=Ye({type:`teleop`,name:`Teleop`,description:`Drive the robot with on-screen pads, publishing velocity commands.`,icon:h,defaultSize:{w:6,h:4},minSize:{w:3,h:3},component:df,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`}]}),pf=(0,q.lazy)(()=>rf(()=>import(`./TerminalView.js`),__vite__mapDeps([5,1,2,3,4,6,7,8])));function mf({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)(pf,{config:e,panelId:n,widgetId:t.id,editing:r})})}var hf=Ye({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:Ie,defaultSize:{w:8,h:6},minSize:{w:3,h:3},component:mf,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:nt,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 gf(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 _f=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||!gf(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)&&gf(e,t.get(e.key))?{...e,default:t.get(e.key)}:e)}:e}};function vf(e,t){let n={};for(let r of e.properties){let e=t[r.key];n[r.key]=gf(r,e)?e:r.default}return n}var yf=new _f([ff,Ql,sf,vt,Wi,pl,zi,lt,Ni,Si,Al,eo,dl,hf,Zd]);function bf(e,t){return yf.registerPlugin(e,t)}function xf(){return yf.entries()}function Sf(e){return yf.definition(e)}function Cf(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 wf(e,t,n){return e.x>=0&&e.y>=0&&!t.some(t=>t.id!==n&&Cf(e,t))}function Tf(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 Ef(e,t,n){let{rows:r}=Tf(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(wf(n,e))return n}return{x:0,y:r,...t}}function Df(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 Of={desktop:{label:`Desktop`,columns:null,previewWidth:null},tablet:{label:`Tablet`,columns:12,previewWidth:820},phone:{label:`Phone`,columns:6,previewWidth:390}};function kf(e){return e<640?`phone`:e<1100?`tablet`:`desktop`}function Af(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 jf(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&&Af(e,i))return!1;return!0}function Mf(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=>Af(r,e)))return r}}function Nf(e,t,n){let r=Of[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=Mf(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 Pf(e,t,n){return{...e,layouts:{...e.layouts,[t]:n}}}function Ff(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,Pf(e,t,{rects:a,hidden:n.hidden})}function If(e,t,n,r,i){return Pf(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 Lf(e,t){let{[t]:n,...r}=e.layouts??{},{layouts:i,...a}=e;return Object.keys(r).length>0?{...a,layouts:r}:a}var Rf=4,zf=4,Bf=100,Vf=32;function Hf(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 Uf({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=Hf(d),[p,m]=(0,q.useState)(null),h=Of[t].columns,g=(r??f.width)-32,_=h===null?64:Math.max(Vf,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=Tf(p?[...b,p.rect]:b),S=h??(i?Math.max(x.cols+Rf,v):x.cols),C=i?Math.max(x.rows+Rf,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=Sf(e.widgets.find(e=>e.id===p.id)?.type??``)?.minSize,n=h===null?Bf: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(Bf,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)>zf})},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&&jf(r,n,h,t)&&s(t,r)},O=!p||jf(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${O?``:` invalid`}`,style:Df(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=Df(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=Sf(r.type),f=d?.icon??Pe;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:D,onPointerCancel:D,children:[(0,J.jsx)(Wf,{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 ${Of[t].label.toLowerCase()}s`,"aria-label":`Hide on ${Of[t].label.toLowerCase()}s`,onPointerDown:e=>e.stopPropagation(),onClick:()=>l(r.id),children:(0,J.jsx)(P,{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)(E,{width:14,height:14})})]}),(0,J.jsx)(`div`,{className:`resize-handle`,title:`Resize`,onPointerDown:e=>w(e,r,`resize`)})]})]},r.id)})]})})}var Wf=(0,q.memo)(function({instance:e,panelId:t,editing:n}){let r=Sf(e.type),i=(0,q.useMemo)(()=>r?vf(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)(Gf,{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?`]})})]})}),Gf=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 Kf({widget:e,onChange:t,onDuplicate:n,onRemove:r,onClose:i}){let a=Sf(e.type),o=a?vf(a,e.config):e.config,s=a?.icon??Pe,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)(H,{})})]}),(0,J.jsxs)(`div`,{className:`properties-body`,children:[(0,J.jsx)(qf,{label:`Title`,help:`Shown above the widget, if set`,children:n=>(0,J.jsx)(Yf,{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)(Jf,{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)(z,{}),` Duplicate`]}),(0,J.jsxs)(`button`,{type:`button`,className:`button danger`,onClick:r,children:[(0,J.jsx)(E,{}),` Remove`]})]})]})}function qf({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 Jf({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)(qf,{label:e.label,help:e.help,children:r=>{switch(e.kind){case`number`:return(0,J.jsx)(Yf,{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)(Yf,{id:r,multiline:!0,value:String(t),placeholder:e.placeholder,onCommit:n});case`image`:case`behavior-tree`:return(0,J.jsx)(Mt,{id:r,kind:e.kind,value:String(t),placeholder:e.placeholder,onCommit:n,children:e=>(0,J.jsx)(Yf,{...e})});case`topic`:return(0,J.jsx)(Xf,{id:r,value:String(t),types:e.topicTypes,placeholder:e.placeholder,onCommit:n});default:return(0,J.jsx)(Yf,{id:r,value:String(t),placeholder:e.placeholder,onCommit:n})}}})}function Yf({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 Xf({id:e,value:t,types:n,placeholder:r,onCommit:i}){let[a,o]=(0,q.useState)([]),s=`${e}-topics`,c=()=>Xe.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)(Yf,{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 Zf(){let e=new Map;for(let t of xf())e.set(t.plugin,[...e.get(t.plugin)??[],t]);return[...e].map(([e,t])=>({plugin:e,entries:t}))}function Qf({onAdd:e,onClose:t}){let n=Zf();return(0,J.jsx)($e,{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 $f=500,ep=18,tp={desktop:Ve,tablet:l,phone:ie},np=e=>Sf(e)?.minSize??{w:1,h:1};function rp(){let[e,t]=(0,q.useState)(()=>kf(window.innerWidth));return(0,q.useEffect)(()=>{let e=()=>t(kf(window.innerWidth));return window.addEventListener(`resize`,e),()=>window.removeEventListener(`resize`,e)},[]),e}function ip(){return decodeURIComponent(location.hash.replace(/^#\/?/,``))}function ap(e,t=!1){let n=`#/${encodeURIComponent(e)}`;t?(history.replaceState(null,``,n),window.dispatchEvent(new HashChangeEvent(`hashchange`))):location.hash=n}function op(e){return`${e.replace(/[^A-Za-z0-9_-]+/g,`-`).slice(-48)}-${Math.random().toString(36).slice(2,8)}`}function sp(e){return e instanceof Error?e.message:String(e)}function cp(){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(()=>Xe.savePanel(e).then(()=>{n.current||t(`saved`)},n=>{t(`failed`),G(`Could not save “${e.name}”: ${sp(n)}`,`error`)}))),i.current},[]),o=(0,q.useCallback)(e=>{n.current=e,t(`saving`),r.current&&clearTimeout(r.current),r.current=setTimeout(a,$f)},[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 lp(){let e=We(),t=et(),[n,r]=cp(),[i,a]=(0,q.useState)(null),[o,s]=(0,q.useState)(ip),c=(0,q.useRef)(o);c.current=o;let[l,u]=(0,q.useState)(null),d=(0,q.useRef)(null),[f,p]=(0,q.useState)(null),[m,h]=(0,q.useState)(`view`),[g,_]=(0,q.useState)(null),[v,y]=(0,q.useState)(!1),[x,S]=(0,q.useState)(!1),C=(0,q.useRef)([]),[w,T]=(0,q.useState)(!1),E=(0,q.useRef)(12),D=(0,q.useCallback)(e=>{E.current=e},[]),O=m===`edit`,A=rp(),[j,M]=(0,q.useState)(null),N=O?j??A:A,P=(0,q.useRef)(N);P.current=N;let F=(0,q.useMemo)(()=>l?Nf(l,N,np):null,[l,N]),I=(0,q.useCallback)(e=>{d.current=e,u(e)},[]),L=(0,q.useCallback)(async()=>{try{a(await Xe.listPanels())}catch(e){G(`Could not list the panels: ${sp(e)}`,`error`)}},[]),R=(0,q.useCallback)(e=>{let t=d.current;if(!t)return;let n=e(t);C.current=[...C.current.slice(-49),t],T(!0),I(n),r.schedule(n)},[r,I]),ee=(0,q.useCallback)(()=>{let e=C.current.pop();T(C.current.length>0),e&&(I(e),r.schedule(e),_(t=>t&&e.widgets.some(e=>e.id===t)?t:null))},[r,I]);(0,q.useEffect)(()=>{let e=()=>s(ip());return window.addEventListener(`hashchange`,e),()=>window.removeEventListener(`hashchange`,e)},[]),(0,q.useEffect)(()=>{e!==`closed`&&L()},[L,e]),(0,q.useEffect)(()=>{i&&i.length>0&&!i.some(e=>e.id===o)&&ap(i[0].id,!0)},[i,o]);let te=(0,q.useCallback)(async e=>{try{let t=await Xe.getPanel(e);e===c.current&&(I(t),p(null))}catch(t){e===c.current&&p(sp(t))}},[I]),z=i?.some(e=>e.id===o)??!1;(0,q.useEffect)(()=>{if(!z)return;let e=!0;return r.flush().then(()=>{e&&(C.current=[],T(!1),_(null),te(o))}),()=>{e=!1}},[o,z,te,r]),(0,q.useEffect)(()=>b.onServerMessage(e=>{e.type===`error`&&G(e.message,`error`),e.type===`panels.changed`&&e.origin!==b.clientId&&(L(),e.id===d.current?.id&&!e.deleted&&!r.isPending()&&te(e.id))}),[L,te,r]);let ne=async e=>{e===`view`&&(_(null),M(null),await r.flush()),h(e),S(!1)},re=e=>{y(!1);let t=d.current;if(!t)return;let n=P.current===`desktop`?E.current:ep,r=Ef(t.widgets,e.defaultSize,n),i={id:op(e.type),type:e.type,title:``,...r,config:{}};R(e=>({...e,widgets:[...e.widgets,i]})),_(i.id)},ie=(0,q.useCallback)((e,t)=>R(n=>Ff(n,P.current,Nf(n,P.current,np),e,t)),[R]),ae=(0,q.useCallback)((e,t=!0)=>{let n=P.current;n!==`desktop`&&(R(r=>If(r,n,Nf(r,n,np),e,t)),_(t=>t===e?null:t))},[R]),oe=(0,q.useCallback)(e=>{let t=d.current?.widgets.find(t=>t.id===e);if(R(t=>({...t,widgets:t.widgets.filter(t=>t.id!==e)})),_(t=>t===e?null:t),t){let e=t.title||Sf(t.type)?.name||t.type;G(`Removed “${e}”`,`info`,{label:`Undo`,run:ee})}},[R,ee]),se=e=>{let t=d.current,n=t?.widgets.find(t=>t.id===e);if(!t||!n)return;let r=P.current===`desktop`?E.current:ep,i=Ef(t.widgets,{w:n.w,h:n.h},r),a={...n,...i,id:op(n.type),config:structuredClone(n.config)};R(e=>({...e,widgets:[...e.widgets,a]})),_(a.id)},B=async()=>{S(!1);let e=await t.prompt({title:`New panel`,label:`Name`,confirmLabel:`Create`});if(e)try{let t=await Xe.createPanel({name:e,widgets:[]});await L(),ap(t.id),h(`edit`)}catch(e){G(`Could not create the panel: ${sp(e)}`,`error`)}},le=async()=>{S(!1);let e=d.current;if(!e)return;let n=await t.prompt({title:`Rename panel`,label:`Name`,initial:e.name,confirmLabel:`Rename`});n&&n!==e.name&&(R(e=>({...e,name:n})),await r.flush(),await L())},ue=async()=>{S(!1);let e=d.current;if(e)try{await r.flush();let t=await Xe.createPanel({name:`${e.name} (copy)`,widgets:e.widgets});await L(),ap(t.id)}catch(e){G(`Could not duplicate the panel: ${sp(e)}`,`error`)}},de=async()=>{S(!1);let e=d.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 Xe.deletePanel(e.id),I(null),await L()}catch(e){G(`Could not delete the panel: ${sp(e)}`,`error`)}};(0,q.useEffect)(()=>{if(!O)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(),ee();return}let t=d.current?.widgets.find(e=>e.id===g);if(!t)return;if(e.key===`Delete`||e.key===`Backspace`){e.preventDefault(),oe(t.id);return}let n={ArrowLeft:[-1,0],ArrowRight:[1,0],ArrowUp:[0,-1],ArrowDown:[0,1]}[e.key],r=Nf(d.current,P.current,np),i=r.rects.get(t.id);if(n&&i){e.preventDefault();let a={...i,x:i.x+n[0],y:i.y+n[1]};jf(a,r,Of[P.current].columns,t.id)&&ie(t.id,a)}};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[O,g,ee,oe,ie]);let V=O?l?.widgets.find(e=>e.id===g):void 0,fe={connecting:`Connecting…`,open:`Connected to ${b.hostname}`,closed:`Disconnected, reconnecting…`}[e];return(0,J.jsxs)(`div`,{className:`app${O?` editing`:``}`,children:[(0,J.jsxs)(`header`,{className:`topbar`,children:[(0,J.jsxs)(`div`,{className:`brand`,title:fe,children:[(0,J.jsx)(Re,{width:22,height:22}),(0,J.jsx)(`span`,{className:`brand-name`,children:b.hostname||`Tassello`}),(0,J.jsx)(`span`,{className:`connection-dot ${e}`,"aria-label":fe})]}),i&&i.length>0&&(0,J.jsx)(`select`,{className:`panel-select`,"aria-label":`Panel`,value:o,onChange:e=>ap(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`}),O&&l&&(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:!w,onClick:ee,children:(0,J.jsx)(_e,{})}),(0,J.jsxs)(`button`,{type:`button`,className:`button primary`,"aria-label":`Add widget`,onClick:()=>y(!0),children:[(0,J.jsx)(ce,{}),` `,(0,J.jsx)(`span`,{className:`hide-narrow`,children:`Add widget`})]})]}),O&&(0,J.jsx)(`div`,{className:`mode-switch device-switch`,role:`group`,"aria-label":`Layout of`,children:Object.keys(Of).map(e=>{let t=tp[e];return(0,J.jsx)(`button`,{type:`button`,"aria-pressed":N===e,title:`The ${Of[e].label.toLowerCase()} layout`,"aria-label":`${Of[e].label} layout`,onClick:()=>{M(e),_(null)},children:(0,J.jsx)(t,{})},e)})}),O&&(0,J.jsxs)(`div`,{className:`menu`,children:[(0,J.jsx)(`button`,{type:`button`,className:`icon-button`,"aria-label":`Panel actions`,"aria-expanded":x,onClick:()=>S(e=>!e),children:(0,J.jsx)(k,{})}),x&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`div`,{className:`menu-backdrop`,onPointerDown:()=>S(!1)}),(0,J.jsxs)(`div`,{className:`menu-list`,role:`menu`,children:[(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:B,children:`New panel…`}),l&&(0,J.jsxs)(J.Fragment,{children:[(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:le,children:`Rename panel…`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,onClick:ue,children:`Duplicate panel`}),(0,J.jsx)(`button`,{type:`button`,role:`menuitem`,className:`danger`,onClick:de,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":!O,onClick:()=>ne(`view`),children:[(0,J.jsx)(Le,{}),` `,(0,J.jsx)(`span`,{className:`hide-narrow`,children:`View`})]}),(0,J.jsxs)(`button`,{type:`button`,"aria-label":`Edit`,title:`Edit`,"aria-pressed":O,onClick:()=>ne(`edit`),children:[(0,J.jsx)(he,{}),` `,(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:B,children:[(0,J.jsx)(ce,{}),` Create a panel`]})]}):f?(0,J.jsxs)(`div`,{className:`empty-state`,children:[(0,J.jsx)(`h1`,{children:`Cannot open this panel`}),(0,J.jsx)(`p`,{children:f})]}):l?(0,J.jsxs)(J.Fragment,{children:[(0,J.jsxs)(`div`,{className:`board-column`,children:[O&&N!==`desktop`&&F&&(0,J.jsxs)(`div`,{className:`layout-bar`,children:[(0,J.jsxs)(`span`,{children:[(0,J.jsxs)(`strong`,{children:[Of[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=l.widgets.find(t=>t.id===e);return(0,J.jsxs)(`button`,{type:`button`,className:`layout-chip`,title:`Show it again`,onClick:()=>ae(e,!1),children:[t?.title||Sf(t?.type??``)?.name||e,` +`]},e)})]}),(F.custom||F.hidden.length>0)&&(0,J.jsx)(`button`,{type:`button`,className:`link-button`,onClick:()=>R(e=>Lf(e,N)),children:`Back to automatic`})]}),F&&(0,J.jsx)(Uf,{panel:l,device:N,layout:F,previewWidth:N===A?null:Of[N].previewWidth,editing:O,selectedId:g,onSelect:_,onPlace:ie,onRemove:oe,onHide:N===`desktop`?void 0:ae,onVisibleColumns:D},N)]}),l.widgets.length===0&&(0,J.jsx)(`div`,{className:`board-hint`,children:O?(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.`]})}),V&&(0,J.jsx)(Kf,{widget:V,onChange:e=>R(t=>({...t,widgets:t.widgets.map(t=>t.id===e.id?e:t)})),onDuplicate:()=>se(V.id),onRemove:()=>oe(V.id),onClose:()=>_(null)},V.id)]}):null}),v&&(0,J.jsx)(Qf,{onAdd:re,onClose:()=>y(!1)}),(0,J.jsx)(Ke,{})]})}var up=[];function dp(e){return e instanceof Error?e.message:String(e)}async function fp(){try{up=await Xe.listPlugins()}catch(e){return[`The plugins could not be listed: ${dp(e)}`]}let e=up.flatMap(e=>e.error?[`Plugin ${e.name}: its server side did not start: ${e.error}`]:[]);for(let e of up)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(up.map(e=>e.client?rf(()=>import(e.client),[]):Promise.resolve(null)))).forEach((t,n)=>{let{name:r}=up[n];if(t.status===`rejected`){e.push(`Plugin ${r} did not load: ${dp(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 bf(r,i))e.push(`Plugin ${r}: ${t}`)}),e}b.connect();var pp=await fp();(0,K.createRoot)(document.getElementById(`root`)).render((0,J.jsx)(q.StrictMode,{children:(0,J.jsx)(tt,{children:(0,J.jsx)(lp,{})})}));for(let e of pp)console.error(e),G(e,`error`);
|