boxglow 0.5.1 → 0.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -153,7 +153,7 @@ The server finds `boxglow.json` like the CLI does (current directory upwards, or
153
153
 
154
154
  ## VS Code extension
155
155
 
156
- Install **Boxglow** from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=sukima.boxglow-vscode): search for "Boxglow" in the Extensions view, or run `code --install-extension sukima.boxglow-vscode`. Keep the extension and the CLI on matching releases (extension 0.4.1 goes with boxglow 0.5.1).
156
+ Install **Boxglow** from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=sukima.boxglow-vscode): search for "Boxglow" in the Extensions view, or run `code --install-extension sukima.boxglow-vscode`. Keep the extension and the CLI on matching releases (extension 0.4.1 goes with boxglow 0.5.2).
157
157
 
158
158
  `vscode/` holds the extension's source. It opens `boxglow.json` as the same diagram inside the editor (custom editor "Boxglow"; right-click the file or use the editor title button / command *Boxglow: Open boxglow.json as a diagram*). The diagram follows the file when the CLI or an agent writes it, edits in the diagram are written back, and light / dark follow the VS Code theme. To build it yourself: `npm run build:vscode` (bundles the web app into `vscode/media/`), then `cd vscode && npm run package` (`.vsix`, install via *Extensions: Install from VSIX...*).
159
159
 
package/bin/boxglow.js CHANGED
@@ -1040,7 +1040,7 @@ function t(ja, vars) {
1040
1040
  if (typeof document !== "undefined") document.documentElement.lang = current;
1041
1041
 
1042
1042
  // package.json
1043
- var version = "0.5.1";
1043
+ var version = "0.5.2";
1044
1044
 
1045
1045
  // src/model/version.ts
1046
1046
  var APP_VERSION = version;
@@ -3462,4 +3462,4 @@ Set the \`cycles\` parameter to \`"ref"\` to resolve cyclical schemas with defs.
3462
3462
  `)}function iD(e){let t=Up(e,Wf);return[`# ${e.name}`,``,e.description,``,q(`全体の進捗: {white}/{total} ブロックが完了 (BlackBox {black} / GrayBox {gray} / WhiteBox {white})`,{white:t.white,total:t.total,black:t.black,gray:t.gray}),``,q(`ブロックは「入力から出力を作るタスク」。BlackBox は出力だけ決まっていて中身が未定、GrayBox は分解中・着手中、WhiteBox は完了。`),``].join(`
3463
3463
  `)+rD(e,Wf,2,!0)}function aD(e,t,n){let r=e.blocks[t];if(!r)return``;let i=[...mp(e,t)].reverse().map(t=>t.id===`root`?e.name:t.title),a=[];a.push(`# ${q(`依頼: {title}`,{title:r.title})}`),a.push(``),a.push(q(`このタスクは「{chain}」の中の 1 ブロックです。ブロックは「入力から出力を作る作業」で、出力の成果物が確定したら完了 (WhiteBox) になります。`,{chain:i.join(` > `)})),a.push(``);for(let n of[...mp(e,t)].reverse()){let e=Pf(n.scope);e.length&&a.push(`## `+n.title,...e.map(e=>e.label+`: `+e.text),``)}a.push(rD(e,t,2,!1));let o=fp(e,r.parentId??`root`).filter(e=>e.id!==t);if(o.length>0){a.push(`## `+q(`同じ階層の他のブロック`)),a.push(``);for(let e of o)a.push(`- ${e.title} (${q($E[e.status])})`);a.push(``)}let s=fp(e,t);if(s.length>0){a.push(`## `+q(`現在の下の階層`)),a.push(``);for(let e of s)a.push(`- ${e.title} (${q($E[e.status])})`);a.push(``)}if(a.push(`## `+q(`お願い`)),a.push(``),n===`plan`)a.push(q(`上の入力から出力を得るための手順を提案してください。前提が足りなければ、追加で必要な入力を挙げてください。`));else if(n===`decompose`){a.push(q(`このブロックを、入力と出力を持つ小さなブロックに分解してください。次の JSON 形式で答えてください。`)),a.push(``),a.push("```json");let e=q(`ブロック名`);a.push(JSON.stringify({blocks:[{title:e,description:q(`やること`),inputs:[q(`入力名`)],outputs:[q(`出力名`)]}],connections:[{from:`${e}.${q(`出力名`)}`,to:`${e}.${q(`入力名`)}`}]},null,2)),a.push("```")}else a.push(q(`入力と出力の定義に抜けや曖昧さがないか指摘してください。出力が「確定した」と言える条件も提案してください。`));return a.push(``),a.join(`
3464
3464
  `)}function oD(e,t){let n=fp(e,t),r=[`flowchart LR`],i=e=>e.replace(/"/g,`'`);r.push(` IN(["${q(`入力`)}"])`),r.push(` OUT(["${q(`出力`)}"])`);for(let e of n){let t=e.status===`white`?`["${i(e.title)}"]`:e.status===`gray`?`[["${i(e.title)}"]]`:`{{"${i(e.title)}"}}`;r.push(` ${e.id}${t}`)}for(let a of Object.values(e.edges)){let o=e.ports[a.from.portId],s=e.ports[a.to.portId];if(!o||!s)continue;let c=o.blockId===t?`IN`:n.some(e=>e.id===o.blockId)?o.blockId:null,l=s.blockId===t?`OUT`:n.some(e=>e.id===s.blockId)?s.blockId:null;if(!c||!l)continue;let u=o.direction===`out`?o.name:s.name;r.push(` ${c} ${a.auto?`-.->`:`-->`}|${i(u)}| ${l}`)}r.push(` classDef white fill:#fbfbfb,stroke:#3a3f46,color:#2f343a`),r.push(` classDef gray fill:#d9dde1,stroke:#3a3f46,color:#2f343a`),r.push(` classDef black fill:#3a3f46,stroke:#3a3f46,color:#e8eaed`);for(let e of n)r.push(` class ${e.id} ${e.status}`);return r.join(`
3465
- `)}var sD=[`#0d8080`,`#e8875e`,`#3aa85a`,`#6b7075`,`#2f6fb3`,`#a0522d`],cD={black:`?`,gray:`~`,white:`✓`},lD={statuses:new Set([`black`,`gray`,`white`]),memberId:null,unassigned:!1,category:null};function uD(e,t,n){let r=e.blocks[t];return!(!r||!n.statuses.has(r.status)||n.memberId&&!r.assigneeIds.includes(n.memberId)||n.unassigned&&(r.assigneeIds.length>0||cp(r)===`project`)||n.category&&r.category!==n.category)}var dD=e=>e.statuses.size===3&&e.memberId===null&&!e.unassigned&&e.category===null;function fD({project:e,parentId:t,depth:n,selectedId:r,onSelect:i,closed:a,onToggle:o}){Nw();let s=fp(e,t).sort((e,t)=>e.position.y-t.position.y||e.position.x-t.position.x);return(0,x.jsx)(x.Fragment,{children:s.map(t=>{let s=fp(e,t.id).length>0,c=a.has(t.id);return(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`div`,{className:`tree-row`,"data-selected":r===t.id,style:{paddingLeft:8+n*14},onClick:()=>i(t.id),title:t.title,children:[s?(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,style:{padding:`0 4px`},onClick:e=>{e.stopPropagation(),o(t.id)},title:q(c?`開く`:`閉じる`),children:c?`▸`:`▾`}):(0,x.jsx)(`span`,{style:{width:20,display:`inline-block`}}),(0,x.jsx)(`span`,{className:`tree-glyph ${t.status}`,children:cD[t.status]}),(0,x.jsx)(`span`,{className:`truncate`,children:t.title})]}),s&&!c&&(0,x.jsx)(fD,{project:e,parentId:t.id,depth:n+1,selectedId:r,onSelect:i,closed:a,onToggle:o})]},t.id)})})}function pD({project:e,filter:t,onFilter:n,onClose:r,width:i}){Nw();let a=$(e=>e.readonly),o=$(e=>e.selection),s=$(e=>e.select),c=$(e=>e.apply),[l,u]=(0,y.useState)(()=>new Set),d=e=>u(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n}),[f,p]=(0,y.useState)(``),[m,h]=(0,y.useState)(sD[0]),g=$(e=>e.focusBlock),_=$(e=>e.setToast),v=$(e=>e.meId),b=$(e=>e.setMe),[S,C]=(0,y.useState)([]);(0,y.useEffect)(()=>{WE().then(C)},[]);let w=()=>void WE().then(C),T=t=>{let n=oT(e,o,$.getState().viewScope);c(e=>{let r=_m(e,n,t,`human`);return setTimeout(()=>{s({blockId:r.blockId}),g(r.blockId)},0),r.project})},E=async()=>{let e=await RE(`.json,application/json`);if(e)try{await GE(vm(e)),w(),_(q(`テンプレートをライブラリに追加しました`))}catch(e){_(e instanceof Error?e.message:String(e))}},D=e=>{let r=new Set(t.statuses);r.has(e)?r.delete(e):r.add(e),r.size!==0&&n({...t,statuses:r})},O=()=>{f.trim()&&(c(e=>zp(e,f.trim(),m).project),p(``),h(sD[(sD.indexOf(m)+1)%sD.length]))},[k,A]=(0,y.useState)(`tree`),j=[{id:`tree`,label:`Tree`,hint:q(`ボックスの一覧 (押すと選ぶ)`)},{id:`filter`,label:`Filter`,hint:q(`状態や担当でボックスを絞る`)},{id:`members`,label:`Members`,hint:q(`担当にする人を登録。自分を決める`)},{id:`parts`,label:`Parts`,hint:q(`他のプロジェクトでも使い回すボックス`)}];return(0,x.jsxs)(`div`,{className:`drawer card`,style:{width:i},children:[(0,x.jsxs)(`div`,{className:`flex items-center gap-1 mb-2`,children:[(0,x.jsx)(`div`,{className:`seg flex-1`,style:{gridTemplateColumns:`repeat(4, 1fr)`},children:j.map(e=>(0,x.jsx)(`button`,{className:`seg__btn`,"data-on":k===e.id,onClick:()=>A(e.id),title:e.hint,style:{padding:`6px 2px`,fontSize:12},children:e.label},e.id))}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:r,title:`Close`,children:`×`})]}),(0,x.jsx)(`div`,{className:`text-[11px] mb-2`,style:{color:`var(--text-muted)`},children:j.find(e=>e.id===k)?.hint}),k===`tree`&&(fp(e,`root`).length===0?(0,x.jsx)(`div`,{className:`text-[12px] px-2`,style:{color:`var(--text-muted)`},children:`No blocks yet`}):(0,x.jsx)(fD,{project:e,parentId:`root`,depth:0,selectedId:o.blockId,onSelect:e=>{s({blockId:e}),g(e)},closed:l,onToggle:d})),k===`filter`&&(0,x.jsxs)(`div`,{className:`flex flex-wrap gap-1`,children:[[`black`,`gray`,`white`].map(e=>(0,x.jsxs)(`button`,{className:`chip`,"data-on":t.statuses.has(e),onClick:()=>D(e),children:[(0,x.jsx)(`span`,{className:`tree-glyph ${e}`,style:{width:12,height:12,fontSize:8,lineHeight:`8px`},children:cD[e]}),MT[e]]},e)),v&&(0,x.jsx)(`button`,{className:`chip`,"data-on":t.memberId===v,onClick:()=>n({...t,memberId:t.memberId===v?null:v,unassigned:!1}),title:q(`自分の担当だけ`),children:`Mine`}),(0,x.jsx)(`button`,{className:`chip`,"data-on":t.unassigned,onClick:()=>n({...t,unassigned:!t.unassigned,memberId:null}),title:q(`担当がいないボックスだけ`),children:q(`未担当`)}),e.members.filter(e=>e.id!==v).map(e=>(0,x.jsxs)(`button`,{className:`chip`,"data-on":t.memberId===e.id,onClick:()=>n({...t,memberId:t.memberId===e.id?null:e.id,unassigned:!1}),title:q(`{name} の担当だけ`,{name:e.name}),children:[(0,x.jsx)(`span`,{className:`avatar`,style:{background:e.color,width:16,height:16,fontSize:9},children:e.name.slice(0,1)}),e.name]},e.id)),(0,x.jsx)(`div`,{className:`label mt-3`,children:`Category`}),(0,x.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:Bf.map(e=>(0,x.jsxs)(`button`,{className:`chip cat-chip${e.neutral?` neutral`:``}`,"data-on":t.category===e.key,style:{"--cat":e.color},onClick:()=>n({...t,category:t.category===e.key?null:e.key}),title:q(`{label} のボックスだけ`,{label:q(e.label)}),children:[(0,x.jsx)(`span`,{className:`cat-chip__dot`}),q(e.label)]},e.key))}),!dD(t)&&(0,x.jsx)(`button`,{className:`chip mt-3`,onClick:()=>n({...lD,statuses:new Set(lD.statuses)}),children:`Clear`})]}),k===`parts`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`text-[11px] mb-1`,style:{color:`var(--text-muted)`},children:q(`挿入先: {target}`,{target:(()=>{let t=oT(e,o,$.getState().viewScope),n=e.blocks[t];return n?cp(n)===`project`?n.title:q(`{title} の隣`,{title:n.title}):q(`最上位`)})()})}),(0,x.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[S.length===0&&(0,x.jsx)(`div`,{className:`text-[12px] px-1`,style:{color:`var(--text-muted)`},children:q(`ボックスを選び、右の「⋯」から「Save as Part」すると、ここに並びます。`)}),S.map(e=>(0,x.jsxs)(`div`,{className:`flex items-center gap-1 text-[13px] px-1`,children:[(0,x.jsx)(`span`,{className:`truncate`,title:`${e.description||e.name} (v${e.version}${e.tags.length?`, `+e.tags.join(`, `):``})`,children:e.name}),(0,x.jsxs)(`span`,{className:`text-[10px]`,style:{color:`var(--text-muted)`},children:[`v`,e.version]}),(0,x.jsxs)(`span`,{className:`ml-auto flex gap-0.5`,children:[!a&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,title:q(`挿入`),onClick:()=>T(e),children:`Insert`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,title:q(`JSON で保存 (他のリポジトリや人と共有)`),onClick:()=>IE(`${zE(e.name)}.boxglow-block.json`,JSON.stringify(e,null,2),`application/json`),children:`↓`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,title:q(`ライブラリから消す`),onClick:()=>{confirm(q(`テンプレート「{name}」を消しますか?`,{name:e.name}))&&KE(e.id).then(w)},children:`×`})]})]},e.id)),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm self-start`,onClick:E,children:`Import`})]})]}),k===`members`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`flex flex-col gap-1`,children:e.members.map(e=>(0,x.jsxs)(`div`,{className:`flex items-center gap-2 text-[13px] px-1`,children:[(0,x.jsx)(`span`,{className:`avatar`,style:{background:e.color},children:e.name.slice(0,1)}),(0,x.jsx)(`span`,{className:`truncate`,children:e.name}),(0,x.jsx)(`button`,{className:`chip ml-auto`,"data-on":v===e.id,onClick:()=>b(v===e.id?null:e.id),title:q(`このブラウザでは自分として扱う (自分の担当のボックスに帯が付く)`),children:v===e.id?`Me`:`Set as me`}),!a&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,title:q(`外す`),onClick:()=>c(t=>Bp(t,e.id)),children:`×`})]},e.id))}),!a&&(0,x.jsxs)(`div`,{className:`flex items-center gap-1 mt-2`,children:[(0,x.jsx)(`span`,{className:`avatar flex-none`,style:{background:m,cursor:`pointer`},title:q(`色を変える`),onClick:()=>h(sD[(sD.indexOf(m)+1)%sD.length]),children:f.slice(0,1)||`+`}),(0,x.jsx)(`input`,{className:`input`,placeholder:`Name`,value:f,onChange:e=>p(e.target.value),onKeyDown:e=>e.key===`Enter`&&O()}),(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:O,disabled:!f.trim(),children:`Add`})]})]})]})}function mD({title:e,children:t}){Nw();let n=$(e=>e.select);return(0,x.jsxs)(`div`,{className:`flex items-center gap-1 mb-2`,children:[(0,x.jsx)(`span`,{className:`label truncate flex-1`,title:e,children:e}),t,(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>n({}),title:q(`閉じる (Esc)`),children:`×`})]})}function hD({project:e,onOpenDrawer:t}){let n=$(e=>e.selection);return n.edgeId&&e.edges[n.edgeId]?(0,x.jsx)(bD,{project:e,edgeId:n.edgeId}):n.blockId&&e.blocks[n.blockId]?(0,x.jsx)(vD,{project:e,blockId:n.blockId,onOpenDrawer:t}):n.terminal?(0,x.jsx)(_D,{project:e,which:n.terminal,groupId:n.terminalGroup}):n.project?(0,x.jsx)(gD,{project:e}):n.timeline?(0,x.jsx)(XE,{project:e}):null}function gD({project:e}){Nw();let t=$(e=>e.readonly),n=$(e=>e.apply),r=Up(e,Wf);return(0,x.jsxs)(`div`,{className:`flex flex-col gap-4 p-3`,children:[(0,x.jsx)(mD,{title:`Project`}),(0,x.jsx)(HE,{project:e}),(0,x.jsx)(`input`,{className:`input font-head text-[16px]`,value:e.name,disabled:t,onChange:e=>n(t=>({...structuredClone(t),name:e.target.value}))}),(0,x.jsx)(AE,{multiline:!0,className:`input`,placeholder:q(`ゴール (何を達成したいか)`),value:e.description,disabled:t,onCommit:e=>n(t=>({...structuredClone(t),description:e}))}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{className:`progress-bar`,children:(0,x.jsx)(`span`,{style:{width:`${Math.round(r.ratio*100)}%`}})}),(0,x.jsx)(`div`,{className:`text-[12px] mt-1`,style:{color:`var(--text-muted)`},children:q(`完了 {white} / {total}`,{white:r.white,total:r.total})})]})]})}function _D({project:e,which:t,groupId:n}){Nw();let r=$(e=>e.readonly),i=$(e=>e.apply),a=$(e=>e.select),o=$(e=>e.setToast),s=n?Im(e).find(e=>e.id===n)??null:null,c=Im(e),l=t===`out`?`Project Outputs`:s?`Input Group`:`Project Inputs`;return(0,x.jsxs)(`div`,{className:`flex flex-col gap-3 p-3`,children:[(0,x.jsx)(mD,{title:l}),s&&(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsxs)(`div`,{className:`sec__head`,children:[(0,x.jsx)(`span`,{className:`label`,children:`Group`}),(0,x.jsxs)(`span`,{className:`flex gap-1`,children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,title:q(`このグループを JSON に書き出す (他のプロジェクトで読み込める)`),onClick:()=>IE(`${zE(s.name)}.boxglow-inputs.json`,Um(e,s.id),`application/json`),children:`Export`}),!r&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm btn-danger`,title:q(`グループを消す (入力は Inputs に戻る)`),onClick:()=>{confirm(q(`グループ「{name}」を消しますか? (入力は Inputs に戻ります)`,{name:s.name}))&&(a({terminal:`in`}),i(e=>Bm(e,s.id)))},children:`Delete`})]})]}),(0,x.jsx)(`input`,{className:`input font-head text-[15px]`,value:s.name,disabled:r,placeholder:`Group name`,onChange:e=>i(t=>zm(t,s.id,{name:e.target.value}))}),(0,x.jsx)(`input`,{className:`input`,value:s.description,disabled:r,placeholder:q(`説明 (任意。例: PCI-SIG の仕様書一式)`),onChange:e=>i(t=>zm(t,s.id,{description:e.target.value}))})]}),(0,x.jsx)(OE,{project:e,blockId:Wf,direction:t,readonly:r,title:t===`in`?`Inputs`:`Outputs`,allowAdd:t===`out`||!!s,groupId:t===`in`?s?s.id:null:void 0}),t===`in`&&!s&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:`var(--text-muted)`},children:q(`ここには、下の階層で供給元が決まっていない入力が自動で上がります。各入力はグループに移せます。`)}),(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsxs)(`div`,{className:`sec__head`,children:[(0,x.jsx)(`span`,{className:`label`,children:`Groups`}),!r&&(0,x.jsxs)(`span`,{className:`flex gap-1`,children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>{let e=prompt(q(`グループの名前 (例: PCIe 仕様書)`));e?.trim()&&i(t=>{let n=Rm(t,e.trim());return setTimeout(()=>a({terminal:`in`,terminalGroup:n.groupId}),0),n.project})},children:`+ Group`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:async()=>{let e=await RE(`.json,application/json`);if(e)try{i(t=>{let n=Wm(t,e);return setTimeout(()=>a({terminal:`in`,terminalGroup:n.groupId}),0),n.project})}catch(e){o(e instanceof Error?e.message:String(e))}},title:q(`他のプロジェクトで書き出したグループを読み込む`),children:`Import`})]})]}),c.length===0&&(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:`var(--text-muted)`},children:q(`仕様書などを種類ごとに分けるときは、グループを作って入力を入れます (例: PCIe 仕様書、DDR 仕様書)。`)}),c.map(t=>(0,x.jsxs)(`button`,{className:`tree-row text-left`,onClick:()=>a({terminal:`in`,terminalGroup:t.id}),children:[(0,x.jsx)(`span`,{className:`truncate`,children:t.name}),(0,x.jsx)(`span`,{className:`ml-auto text-[11px]`,style:{color:`var(--text-muted)`},children:Lm(e,t.id).length})]},t.id))]})]})]})}function vD({project:e,blockId:t}){Nw();let n=$(e=>e.readonly),r=$(e=>e.apply),i=$(e=>e.select),a=$(e=>e.setToast),o=$(e=>e.meId),[s,c]=(0,y.useState)(!1),[l,u]=(0,y.useState)(!1),[d,f]=(0,y.useState)(null),[p,m]=(0,y.useState)(!0),[h,g]=(0,y.useState)(!1),[_,v]=(0,y.useState)(``),[b,S]=(0,y.useState)(`status`),C=e.blocks[t],w=_.trim()?e.members.filter(e=>e.name.toLowerCase().includes(_.trim().toLowerCase())&&!C.assigneeIds.includes(e.id)).slice(0,8):[],T=fp(e,t),E=[...mp(e,t)].reverse(),D=Xp(e,t),O=Up(e,t),k=C.decisions.filter(e=>e.answer===void 0),A=C.decisions.filter(n=>n.answer!==void 0&&!fm(e,t,n)),j=Hp(e,t),M=cp(C)===`project`;(0,y.useEffect)(()=>{c(!1),u(!1),f(null),m(!0),g(!1),v(``)},[t]);let N=e=>r(n=>wp(n,t,{status:e})),P=e=>r(n=>{let r=n.blocks[t].assigneeIds;return wp(n,t,{assigneeIds:r.includes(e)?r.filter(t=>t!==e):[...r,e]})}),F=()=>{T.length>0&&!confirm(q(`「{title}」と下の階層のブロックを削除します。よろしいですか?`,{title:C.title}))||(i({}),r(e=>Dp(e,t)))},ee=async n=>{c(!1),await LE(aD(e,t,n))?a(q(`AI に渡すテキストをコピーしました`)):f(n)},I=async()=>{g(!1);let n=hm(e,t,{tags:(prompt(q(`部品の札 (例: 画像処理, 認証。カンマ区切り。省略可)`))??``).split(/[,、]/).map(e=>e.trim()).filter(Boolean)});await GE(n),a(q(`「{name}」を部品として保存しました (☰ の「部品」から挿入)`,{name:n.name}))},te={status:q(`状態・進捗・活動・判断`),io:q(`入力と出力 (成果物)`),owner:q(`担当`),dates:q(`開始日・期日・時間`),more:q(`AI に渡す・メモ・資料`)};return(0,x.jsxs)(`div`,{className:`flex flex-col gap-4 p-3`,children:[(0,x.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,x.jsx)(`span`,{className:`label truncate flex-1`,title:E.map(e=>e.id===`root`?``:e.title).filter(Boolean).join(` › `),children:M?`Project`:E.map(e=>e.id===`root`?``:e.title).filter(Boolean).join(` › `)||`Top`}),(0,x.jsx)(`button`,{className:`chip`,style:{fontFamily:`ui-monospace, monospace`},title:q(`短い ID (押すとコピー。検索や CLI で使えます)`),onClick:async()=>{await LE(C.key??``)&&a(q(`ID {key} をコピーしました`,{key:C.key??``}))},children:C.key}),!n&&(0,x.jsxs)(`div`,{className:`relative`,children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>g(!h),title:q(`その他`),children:`⋯`}),h&&(0,x.jsxs)(`div`,{className:`card absolute right-0 mt-1 p-1 flex flex-col z-30`,style:{minWidth:200},children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>{g(!1),u(!0)},children:q(`作業範囲を編集`)}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>{g(!1),r(e=>({...e,focusBlockId:e.focusBlockId===t?void 0:t}))},children:e.focusBlockId===t?q(`今回の範囲の優先を解除`):q(`このボックスを今回の範囲にする`)}),!M&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:I,children:`Save as Part`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>{g(!1),f(`plan`),S(`more`)},children:`Show AI text`}),(0,x.jsx)(`div`,{style:{borderTop:`1px solid var(--line-soft)`,margin:`4px 0`}}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start btn-danger`,onClick:F,children:`Delete`})]})]}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>i({}),title:q(`閉じる (Esc)`),children:`×`})]}),(0,x.jsx)(AE,{className:`input font-head text-[16px]`,value:C.title,disabled:n,placeholder:q(`Title (何を作るか)`),onCommit:e=>r(n=>wp(n,t,{title:e}))}),(0,x.jsx)(VE,{project:e,blockId:t,editing:l,onClose:()=>u(!1)}),zf(C)&&(0,x.jsx)(`p`,{className:`text-[12px] description-reminder`,style:{color:`var(--accent)`},children:zf(C)}),(0,x.jsx)(`div`,{className:`seg`,style:{gridTemplateColumns:`repeat(5, 1fr)`},children:[[`status`,q(`状態`)],[`io`,q(`入出力`)],[`owner`,q(`担当`)],[`dates`,q(`日程`)],[`more`,q(`その他`)]].map(([n,r])=>(0,x.jsxs)(`button`,{className:`seg__btn`,"data-on":b===n,onClick:()=>S(n),style:{padding:`6px 2px`,fontSize:12},title:te[n],children:[r,n===`status`&&(k.length>0||A.length>0)&&(0,x.jsx)(`span`,{className:`dot decision`,style:{marginLeft:4,display:`inline-block`,width:6,height:6,borderRadius:999,background:`var(--accent)`}}),n===`io`&&(0,x.jsxs)(`span`,{style:{marginLeft:4,fontSize:10,opacity:.7},children:[Y(e,t,`in`).length,`/`,Y(e,t,`out`).length]})]},n))}),b!==`status`&&(k.length>0||A.length>0)&&(0,x.jsxs)(`button`,{className:`btn btn-sm inspector-attention`,onClick:()=>S(`status`),title:q(`Status で確認`),"aria-label":[k.length>0?q(`回答待ち {n}`,{n:k.length}):``,A.length>0?q(`AI未確認 {n}`,{n:A.length}):``,q(`Status で確認`)].filter(Boolean).join(` `),children:[[k.length>0?q(`回答待ち {n}`,{n:k.length}):``,A.length>0?q(`AI未確認 {n}`,{n:A.length}):``].filter(Boolean).join(`・`),(0,x.jsx)(`span`,{"aria-hidden":`true`,style:{marginLeft:8},children:`→`})]}),b===`status`&&(0,x.jsxs)(`section`,{className:`sec`,children:[k.length>0&&(0,x.jsxs)(`div`,{className:`attention-section`,children:[(0,x.jsx)(`h3`,{className:`label`,children:q(`回答が必要です`)}),k.map(n=>(0,x.jsx)(JE,{project:e,blockId:t,decisionId:n.id},n.id))]}),A.length>0&&(0,x.jsxs)(`div`,{className:`attention-section`,children:[(0,x.jsx)(`h3`,{className:`label`,children:q(`AI未確認の回答`)}),A.map(n=>(0,x.jsx)(JE,{project:e,blockId:t,decisionId:n.id},n.id))]}),(0,x.jsx)(`div`,{className:`sec__head`,children:(0,x.jsx)(`span`,{className:`label`,children:`Status`})}),(0,x.jsx)(`div`,{className:`seg`,children:[`black`,`gray`,`white`].map(e=>(0,x.jsxs)(`button`,{className:`seg__btn`,"data-on":C.status===e,disabled:n,onClick:()=>N(e),title:q(NT[e]),children:[(0,x.jsx)(`span`,{className:`tree-glyph ${e}`,children:cD[e]}),(0,x.jsx)(`span`,{children:MT[e]})]},e))}),D&&!n&&(0,x.jsx)(`button`,{className:`btn btn-primary btn-sm w-full`,onClick:()=>N(`white`),title:q(`下の階層が全部完了し、出力に成果物が付いています`),children:q(`完了にできます → Done`)}),C.status!==`white`&&cp(C)!==`project`&&Y(e,t,`in`).length>0&&(()=>{let n=Yp(e,t);return n.length===0?(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:`var(--primary-strong)`},children:q(`必須の入力はそろっています (着手できます)`)}):(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:`var(--text-muted)`},children:q(`必須の入力待ち: {names}`,{names:n.map(e=>e.name).join(`, `)})})})(),M&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`sec__head mt-2`,children:(0,x.jsx)(`span`,{className:`label`,children:`Repository`})}),(0,x.jsx)(`input`,{className:`input`,placeholder:q(`パスや URL (例: ../mg-core、github.com/you/repo)`),value:C.repo??``,disabled:n,onChange:e=>r(n=>wp(n,t,{repo:e.target.value}),{history:!1}),onBlur:e=>r(n=>wp(n,t,{repo:e.target.value.trim()||void 0}))}),(0,x.jsx)(`div`,{className:`text-[11px]`,style:{color:`var(--text-muted)`},children:q(`複数のリポジトリをまたぐときは、boxglow.json を上のフォルダに 1 つ置き、各リポジトリの AI には環境変数 BOXGLOW_FILE でその場所を教えます`)})]}),(0,x.jsxs)(`label`,{className:`category-field`,children:[(0,x.jsx)(`span`,{className:`label`,children:`Category`}),(0,x.jsxs)(`select`,{className:`input`,"aria-label":`Category`,value:C.category??``,disabled:n,onChange:e=>r(n=>ym(n,t,e.target.value||null)),children:[(0,x.jsx)(`option`,{value:``,children:q(`カテゴリなし`)}),Bf.map(e=>(0,x.jsx)(`option`,{value:e.key,children:q(e.label)},e.key))]})]}),C.status!==`white`&&(0,x.jsxs)(`div`,{className:`flex items-center gap-2 text-[12px]`,style:{color:`var(--text-muted)`},children:[(0,x.jsx)(`input`,{type:`range`,min:0,max:100,step:5,value:j,disabled:n,className:`flex-1`,title:q(`進捗 (ドラッグで入力)`),onChange:e=>r(n=>Wp(n,t,Number(e.target.value),`human`),{history:!1}),onMouseUp:e=>r(n=>Wp(n,t,Number(e.target.value),`human`))}),(0,x.jsxs)(`span`,{style:{minWidth:36,textAlign:`right`},children:[j,`%`]}),typeof C.progress==`number`?(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,title:q(`手入力をやめて、下の階層から自動で計算する`),onClick:()=>r(e=>Wp(e,t,null,`human`)),children:`Auto`}):T.length>0?(0,x.jsxs)(`span`,{title:q(`下の階層の完了数`),children:[O.white,`/`,O.total]}):null]}),C.activity&&(0,x.jsxs)(`div`,{className:`flex flex-col gap-1 pl-2`,style:{borderLeft:`3px solid ${C.activity.state===`needs_decision`?`var(--accent)`:`var(--primary)`}`},children:[(0,x.jsxs)(`div`,{className:`flex items-center gap-2 text-[12px]`,children:[(0,x.jsx)(`span`,{className:`tl-actor`,children:ET(C.activity.actor)}),(0,x.jsx)(`b`,{children:q(OT[C.activity.state])}),(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`},children:AT(C.activity.since)}),!n&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm ml-auto`,title:q(`活動の印を消す`),onClick:()=>r(e=>rm(e,t)),children:`×`})]}),C.activity.note&&C.activity.state!==`needs_decision`&&(0,x.jsx)(`div`,{className:`text-[13px]`,children:C.activity.note})]}),(0,x.jsxs)(`details`,{className:`text-[12px]`,open:!!e.handoffs?.[t]&&C.status!==`white`,children:[(0,x.jsx)(`summary`,{children:q(`AI への引き継ぎ`)}),e.handoffs?.[t]?.note&&Rf(C,e.handoffs[t].at,`older`)&&(0,x.jsx)(`p`,{className:`my-2 text-[11px]`,children:Rf(C,e.handoffs[t].at,`older`)}),(0,x.jsx)(`p`,{className:`my-2`,children:q(`セッションを越えて残す発見・次の手順・未解決事項。AI は context コマンドで判断と合わせて読み直します。`)}),(0,x.jsx)(AE,{multiline:!0,className:`input`,value:e.handoffs?.[t]?.note??``,disabled:n,placeholder:q(`発見 / 次の手順 / 未解決事項`),onCommit:e=>r(n=>({...n,handoffs:{...n.handoffs,[t]:{note:e,actor:`human`,at:new Date().toISOString()}}}))}),(0,x.jsx)(`button`,{className:`btn btn-sm mt-2`,onClick:async()=>{let n=await LE(JSON.stringify(QE(e,t),null,2));a(q(n?`引き継ぎ情報をコピーしました`:`コピーできませんでした`))},children:q(`判断・入出力も含めてコピー`)})]}),C.decisions.filter(n=>n.answer!==void 0&&fm(e,t,n)).length>0&&(0,x.jsxs)(`details`,{className:`text-[12px]`,children:[(0,x.jsx)(`summary`,{style:{cursor:`pointer`,color:`var(--text-muted)`},children:q(`判断の記録 ({n})`,{n:C.decisions.filter(n=>n.answer!==void 0&&fm(e,t,n)).length})}),(0,x.jsx)(`div`,{className:`flex flex-col gap-3 mt-2`,children:C.decisions.filter(n=>n.answer!==void 0&&fm(e,t,n)).map(n=>(0,x.jsx)(JE,{project:e,blockId:t,decisionId:n.id},n.id))})]})]}),b===`owner`&&(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsx)(`div`,{className:`sec__head`,children:(0,x.jsx)(`span`,{className:`label`,children:q(`担当`)})}),(0,x.jsxs)(`div`,{className:`flex items-center gap-1 flex-wrap`,children:[C.assigneeIds.map(t=>{let r=e.members.find(e=>e.id===t);return r?(0,x.jsxs)(`span`,{className:`chip`,"data-on":r.id===o,style:{cursor:`default`},title:r.id===o?q(`{name} (自分)`,{name:r.name}):r.name,children:[(0,x.jsx)(`span`,{className:`avatar`,style:{background:r.color,width:16,height:16,fontSize:9},children:r.name.slice(0,1)}),r.name,!n&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,style:{padding:`0 2px`},title:q(`外す`),onClick:()=>P(r.id),children:`×`})]},t):null}),C.assigneeIds.length===0&&(0,x.jsx)(`span`,{className:`text-[12px]`,style:{color:`var(--text-muted)`},children:q(`未担当`)}),!n&&o&&!C.assigneeIds.includes(o)&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>P(o),title:q(`自分を担当にする`),children:`Me`})]}),!n&&(0,x.jsxs)(`div`,{className:`relative`,children:[(0,x.jsx)(`input`,{className:`input`,placeholder:e.members.length===0?q(`名前を打って Enter で登録`):q(`名前で検索して Enter で割り当て`),value:_,onChange:e=>v(e.target.value),onKeyDown:e=>{if(e.key===`Escape`){v(``);return}if(e.key!==`Enter`)return;let n=w[0];if(n){C.assigneeIds.includes(n.id)||P(n.id),v(``);return}let i=_.trim();i&&(r(e=>{let n=zp(e,i,sD[e.members.length%sD.length]);return wp(n.project,t,{assigneeIds:[...n.project.blocks[t].assigneeIds,n.memberId]})}),v(``))}}),_.trim()&&(0,x.jsxs)(`div`,{className:`card absolute left-0 right-0 mt-1 p-1 flex flex-col z-30`,style:{maxHeight:220,overflow:`auto`},children:[w.map(e=>(0,x.jsxs)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onMouseDown:e=>e.preventDefault(),onClick:()=>{C.assigneeIds.includes(e.id)||P(e.id),v(``)},children:[(0,x.jsx)(`span`,{className:`avatar`,style:{background:e.color,width:16,height:16,fontSize:9,marginRight:6},children:e.name.slice(0,1)}),e.name]},e.id)),w.length===0&&(0,x.jsx)(`div`,{className:`text-[12px] p-1`,style:{color:`var(--text-muted)`},children:q(`見つかりません。Enter で「{name}」を登録して割り当て`,{name:_.trim()})})]})]})]}),b===`dates`&&(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsx)(`div`,{className:`sec__head`,children:(0,x.jsx)(`span`,{className:`label`,children:`Schedule`})}),(0,x.jsxs)(`div`,{className:`grid grid-cols-2 gap-x-3 gap-y-1 text-[12px]`,children:[(0,x.jsxs)(`label`,{className:`flex items-center gap-2 col-span-2`,children:[(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`,minWidth:32},children:q(`開始`)}),(0,x.jsx)(jE,{value:C.startDate??``,disabled:n,onChange:e=>r(n=>bm(n,t,{startDate:e||null},`human`))})]}),(0,x.jsxs)(`label`,{className:`flex items-center gap-2 col-span-2`,children:[(0,x.jsx)(`span`,{style:{color:xm(C)?`var(--danger)`:`var(--text-muted)`,minWidth:32},children:q(`期日`)}),(0,x.jsx)(jE,{value:C.dueDate??``,disabled:n,danger:xm(C),onChange:e=>r(n=>bm(n,t,{dueDate:e||null},`human`))})]}),(0,x.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`,minWidth:32},children:q(`見積`)}),(0,x.jsx)(`input`,{type:`number`,min:0,step:.5,className:`input input-plain`,placeholder:`h`,value:C.estimateHours??``,disabled:n,onChange:e=>r(n=>bm(n,t,{estimateHours:e.target.value===``?null:Number(e.target.value)},`human`))}),(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`},children:`h`})]}),(0,x.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`,minWidth:32},children:q(`実績`)}),(0,x.jsx)(`input`,{type:`number`,min:0,step:.5,className:`input input-plain`,placeholder:`h`,value:C.actualHours??``,disabled:n,onChange:e=>r(n=>bm(n,t,{actualHours:e.target.value===``?null:Number(e.target.value)},`human`))}),(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`},children:`h`})]})]}),C.dueDate&&C.status!==`white`&&(()=>{let e=Sm(C);return e===null?null:(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:e<0?`var(--danger)`:`var(--text-muted)`},children:e<0?q(`期日を {d} 日過ぎています`,{d:-e}):e===0?q(`期日は今日です`):q(`期日まであと {d} 日`,{d:e})})})()]}),b===`io`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(OE,{project:e,blockId:t,direction:`in`,readonly:n,title:`Inputs`}),(0,x.jsx)(OE,{project:e,blockId:t,direction:`out`,readonly:n,title:`Outputs`,allowAdd:jp(e,t)})]}),b===`more`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsx)(`div`,{className:`sec__head`,children:(0,x.jsx)(`span`,{className:`label`,children:`Issue`})}),(0,x.jsx)(`input`,{className:`input`,placeholder:q(`JIRA / Redmine / GitHub Issue の URL`),value:C.issue??``,disabled:n,onChange:e=>r(n=>wp(n,t,{issue:e.target.value}),{history:!1}),onBlur:e=>r(n=>wp(n,t,{issue:e.target.value.trim()||void 0}))}),C.issue&&(0,x.jsx)(`a`,{className:`text-[12px] underline`,href:C.issue,target:`_blank`,rel:`noreferrer`,style:{color:`var(--primary-strong)`},children:q(`開く: {key}`,{key:Gm(C.issue)})})]}),(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsxs)(`div`,{className:`sec__head`,children:[(0,x.jsx)(`span`,{className:`label`,children:`AI`}),(0,x.jsxs)(`button`,{className:`btn btn-sm`,"data-on":s,onClick:()=>c(!s),title:q(`このボックスの入出力と位置づけを Markdown にしてコピーして AI に渡す`),children:[`Copy for AI `,s?`▴`:`▾`]})]}),s&&(0,x.jsxs)(`div`,{className:`flex flex-col pl-2`,style:{borderLeft:`3px solid var(--line-soft)`},children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>ee(`plan`),children:q(`手順を提案してもらう (コピー)`)}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>ee(`decompose`),children:q(`分解案を JSON でもらう (コピー)`)}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>ee(`review`),children:q(`入出力の抜けを指摘してもらう (コピー)`)})]}),d&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`textarea`,{className:`input`,style:{minHeight:180,fontSize:12},readOnly:!0,value:aD(e,t,d)}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>f(null),children:`Close`})]})]}),(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsxs)(`div`,{className:`sec__head`,children:[(0,x.jsxs)(`span`,{className:`label`,children:[`Notes`,C.description||C.artifacts.length>0?` *`:``]}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>m(!p),children:p?`▴`:`▾`})]}),p&&(0,x.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[C.description&&Rf(C,C.descriptionUpdatedAt,`older`)&&(0,x.jsx)(`p`,{className:`text-[11px]`,children:Rf(C,C.descriptionUpdatedAt,`older`)}),(0,x.jsx)(AE,{multiline:!0,className:`input`,placeholder:q(`メモ (入力から出力をどう作るか)`),value:C.description,disabled:n,onCommit:e=>r(n=>wp(n,t,{description:e}))}),(0,x.jsx)(DE,{artifacts:C.artifacts,readonly:n,addLabel:`Link`,onChange:e=>r(n=>wp(n,t,{artifacts:e}))})]})]})]})]})}function yD({project:e,edgeId:t}){Nw();let n=$(e=>e.viewScope),r=$(e=>e.setViewScope),i=(0,y.useMemo)(()=>Km(e,t),[e,t]);return i.length<2?null:(0,x.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,x.jsx)(`div`,{className:`text-[11px] font-bold`,style:{color:`var(--text-muted)`},children:`Tabs`}),(0,x.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:i.map(t=>(0,x.jsx)(`button`,{className:`chip`,"data-on":n===t,onClick:()=>r(t),title:t?q(`{title} のタブでこの線の続きを見る`,{title:e.blocks[t]?.title??``}):q(`All でこの線を見る`),children:t?e.blocks[t]?.title??`?`:`All`},t??`all`))})]})}function bD({project:e,edgeId:t}){Nw();let n=$(e=>e.readonly),r=$(e=>e.apply),i=$(e=>e.select),a=e.edges[t],o=e.ports[a.from.portId],s=e.ports[a.to.portId],c=t=>t===`root`?q(`プロジェクト`):e.blocks[t]?.title??`?`;return(0,x.jsxs)(`div`,{className:`flex flex-col gap-3 p-3`,children:[(0,x.jsx)(mD,{title:q(`配線`)}),(0,x.jsx)(`div`,{className:`wire-state`,"data-ready":qp(e,a),children:qp(e,a)?q(`確定済み`):q(`入力待ち`)}),(0,x.jsx)(`p`,{className:`wire-reason`,children:qp(e,a)?q(`供給元の完了・成果物、または上流の入力を確認できています。`):q(`供給元が未完了で成果物がない、または上流の入力がまだ確定していません。`)}),(0,x.jsxs)(`div`,{className:`text-[13px]`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`b`,{children:c(o.blockId)}),q(`「{name}」`,{name:o.name})]}),(0,x.jsx)(`div`,{className:`my-1`,style:{color:`var(--text-muted)`},children:`↓`}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`b`,{children:c(s.blockId)}),q(`「{name}」`,{name:s.name})]})]}),(0,x.jsx)(yD,{project:e,edgeId:t}),a.auto?(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:`var(--text-muted)`},children:q(`自動の線。手動でつなぐと置き換わります。`)}):!n&&(0,x.jsx)(`button`,{className:`btn btn-sm self-start`,onClick:()=>{i({}),r(e=>Rp(e,t))},children:q(`接続を外す`)})]})}var xD=e=>e===void 0?q(`削除済み`):typeof e==`string`?e||q(`空欄`):e&&typeof e==`object`&&`note`in e&&`actor`in e&&`at`in e?`${e.note}\n\n${e.actor} · ${e.at}`:JSON.stringify(e,null,2);function SD({onClose:e}){let{project:t,conflict:n,previewConflict:r,resolveConflict:i,saveError:a}=$(),[o,s]=(0,y.useState)({}),c=(0,y.useRef)(null),l=r();(0,y.useEffect)(()=>{let e=c.current,t=document.activeElement;return e.showModal(),()=>{e.close(),t?.focus()}},[]),(0,y.useEffect)(()=>{s({})},[n?.revision,n?.text]);let u=l?.conflicts??[],d=u.filter(e=>!e.automatic&&!o[e.id]).length,f=e=>{let[n,r,i]=e.segments,a=n===`blocks`||n===`handoffs`?t?.blocks[r]:void 0,o={title:q(`題名`),name:q(`名前`),description:q(`説明`),note:q(`引き継ぎメモ`),decisions:q(`判断と回答`),status:`Status`,artifacts:q(`成果物`),position:q(`位置`),category:`Category`,progress:q(`進捗`)};return a?`${a.key} ${a.title} · ${n===`handoffs`?q(`引き継ぎメモ`):i?o[i]??i:q(`タスク全体`)}`:o[e.path]??e.path};return(0,x.jsxs)(`dialog`,{ref:c,className:`conflict-dialog`,"aria-labelledby":`conflict-title`,onCancel:e,children:[(0,x.jsxs)(`div`,{className:`conflict-dialog__head`,children:[(0,x.jsx)(`h2`,{id:`conflict-title`,className:`font-head`,children:q(`競合する変更を比較`)}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:e,"aria-label":q(`閉じる (Esc)`),children:`×`})]}),(0,x.jsxs)(`div`,{className:`conflict-dialog__body`,children:[(0,x.jsx)(`p`,{children:q(`別の項目の変更は両方残ります。同じ項目を変更した箇所だけ、残す内容を選んでください。`)}),u.length===0&&(0,x.jsx)(`p`,{children:q(`別の項目の変更です。統合できます。`)}),u.map(e=>(0,x.jsxs)(`fieldset`,{className:`conflict-item`,children:[(0,x.jsx)(`legend`,{children:f(e)}),e.automatic?(0,x.jsxs)(`p`,{children:[q(`番号の重複は自動で解消します。`),`: `,xD(e.theirs)]}):(0,x.jsx)(`div`,{className:`conflict-columns`,children:[`ours`,`theirs`].map(t=>(0,x.jsxs)(`label`,{className:`conflict-choice`,"data-selected":o[e.id]===t,children:[(0,x.jsxs)(`span`,{children:[(0,x.jsx)(`input`,{type:`radio`,name:e.id,checked:o[e.id]===t,onChange:()=>s(n=>({...n,[e.id]:t}))}),` `,q(t===`ours`?`手元の編集`:`最新のファイル`)]}),(0,x.jsx)(`pre`,{children:xD(e[t])})]},t))})]},e.id)),a&&(0,x.jsx)(`p`,{className:`text-[12px]`,role:`status`,children:a})]}),(0,x.jsxs)(`div`,{className:`conflict-dialog__foot`,children:[(0,x.jsx)(`span`,{"aria-live":`polite`,children:q(`未選択: {n}`,{n:d})}),(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:e,children:q(`あとで選ぶ`)}),(0,x.jsx)(`button`,{className:`btn btn-primary btn-sm`,disabled:d>0||!n,onClick:()=>{i(`merge`,o,n?.revision)&&e()},children:q(`選択した内容で統合`)})]})]})}function CD(){let{project:e,source:t,saveError:n,conflict:r,resolveConflict:i,previewConflict:a,saveNow:o,readonlyReason:s}=$(),[c,l]=(0,y.useState)(!1);if(!e||!n&&t!==`file`&&!s)return null;let u=a()?.conflicts.filter(e=>!e.automatic).length??0;return(0,x.jsxs)(`div`,{className:`save-notice`,role:n?`alert`:`status`,children:[(0,x.jsx)(`span`,{children:n??s??q(`このファイルは閲覧専用です。共同編集は npx boxglow serve --open または VS Code 拡張で開いてください。`)}),n&&(0,x.jsxs)(`div`,{className:`flex flex-wrap gap-2 mt-2`,children:[(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:()=>IE(`boxglow-unsaved.json`,Zp(e),`application/json`),children:q(`手元の編集を JSON で退避`)}),r?(0,x.jsxs)(x.Fragment,{children:[u>0?(0,x.jsxs)(`button`,{className:`btn btn-primary btn-sm`,onClick:()=>l(!0),children:[q(`変更を比較して選ぶ`),` (`,u,`)`]}):(0,x.jsx)(`button`,{className:`btn btn-primary btn-sm`,onClick:()=>i(`merge`),children:q(`両方の変更を統合`)}),(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:()=>{IE(`boxglow-unsaved.json`,Zp(e),`application/json`),i(`remote`)},children:q(`手元を退避して最新のファイルを開く`)})]}):(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:o,children:q(`保存を再試行`)})]}),c&&r&&(0,x.jsx)(SD,{onClose:()=>l(!1)})]})}var wD=`0.5.1`;function TD(){let e=$(e=>e.peerVersion),t=$(e=>e.source);return(0,x.jsxs)(`details`,{className:`version-info`,children:[(0,x.jsxs)(`summary`,{title:q(`バージョンと接続先`),children:[`v`,wD]}),(0,x.jsxs)(`div`,{className:`card version-info__content`,children:[(0,x.jsx)(`b`,{children:q(`バージョンと接続先`)}),(0,x.jsxs)(`dl`,{children:[(0,x.jsx)(`dt`,{children:`GUI`}),(0,x.jsx)(`dd`,{children:wD}),(0,x.jsx)(`dt`,{children:q(`保存先`)}),(0,x.jsx)(`dd`,{children:t===`serve`?`CLI server`:t===`vscode`?`VS Code`:q(t===`file`?`閲覧専用ファイル`:`ブラウザ内`)}),e&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`dt`,{children:t===`vscode`?`Extension`:`CLI`}),(0,x.jsx)(`dd`,{children:e.extension??e.app??q(`取得できません`)}),(0,x.jsx)(`dt`,{children:q(`接続先のアプリ`)}),(0,x.jsx)(`dd`,{children:e.app??q(`取得できません`)}),(0,x.jsx)(`dt`,{children:q(`保存方式`)}),(0,x.jsxs)(`dd`,{children:[`GUI `,1,` / `,q(`接続先`),` `,e.protocol??`?`]})]}),(0,x.jsx)(`dt`,{children:`Build (JST)`}),(0,x.jsx)(`dd`,{children:`2026-10-05 22:57`})]}),e&&(e.protocol!==1||e.app!==wD)&&(0,x.jsx)(`p`,{role:`status`,children:q(`接続先と画面のバージョンが異なるか、確認できません。CLI・拡張を更新し、画面を再読み込みしてください。`)})]})]})}function ED({project:e,onToggleDrawer:t,onHelp:n}){let r=Nw(),i=$(e=>e.readonly),a=$(e=>e.ephemeral),o=$(e=>e.saveState),s=$(e=>e.apply),c=$(e=>e.undo),l=$(e=>e.redo),u=$(e=>e.past.length),d=$(e=>e.future.length),f=$(e=>e.select),p=$(e=>e.focusBlock),m=$(e=>e.selection),h=$(e=>e.closeProject),g=$(e=>e.importJSON),_=$(e=>e.copyToMine),v=$(e=>e.setToast),[b,S]=(0,y.useState)(()=>document.documentElement.dataset.theme||NE());(0,y.useEffect)(()=>{let e=new MutationObserver(()=>S(document.documentElement.dataset.theme||NE()));return e.observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]}),()=>e.disconnect()},[]);let[C,w]=(0,y.useState)(!1),[T,E]=(0,y.useState)(``),[D,O]=(0,y.useState)(!1),k=(0,y.useRef)(null),A=T.trim()?Cm(e,T,12):[],j=e=>{f({blockId:e}),p(e),E(``),O(!1)};(0,y.useEffect)(()=>{let e=e=>{if(document.querySelector(`dialog[open]`))return;let t=e.target;(!t||t.tagName!==`INPUT`&&t.tagName!==`TEXTAREA`)&&e.key===`/`&&!e.isComposing&&!t?.isContentEditable&&t?.tagName!==`SELECT`&&(e.preventDefault(),O(!0),setTimeout(()=>k.current?.focus(),0))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[]),(0,y.useEffect)(()=>{let e=()=>w(!1);return C&&window.addEventListener(`click`,e),()=>window.removeEventListener(`click`,e)},[C]);let M=()=>{let e=b===`dark`?`light`:`dark`;PE(e),S(e)},N=()=>{let e=prompt(q(`追加するプロジェクトの名前 (リポジトリごとに 1 つなど)`));e?.trim()&&s(t=>{let n=$f(t,e.trim());return setTimeout(()=>{f({blockId:n.blockId}),p(n.blockId)},0),n.project})},P=()=>s(e=>ih(ap(e))),F=()=>{let t=oT(e,m,$.getState().viewScope);s(e=>{let n=Cp(e,{parentId:t,title:q(`新しいブロック`)}),r=structuredClone(n.project);return r.blocks[t]&&(r.blocks[t].collapsed=!1),setTimeout(()=>{f({blockId:n.blockId}),p(n.blockId)},0),r})},ee=()=>IE(`${zE(e.name)}.boxglow.json`,Zp(e),`application/json`),I=()=>IE(`${zE(e.name)}.md`,iD(e),`text/markdown`),te=async()=>{v(await LE(oD(e,m.blockId??`root`))?q(`Mermaid をコピーしました`):q(`コピーできませんでした`))},ne=async()=>{let e=await RE(`.json,application/json`);if(e)try{await g(e)}catch(e){v(e instanceof Error?e.message:String(e))}},L=$(e=>e.fileName),re=$(e=>e.editMode),ie=$(e=>e.setEditMode),ae=$(e=>e.saveNow),oe=$(e=>e.source),se=$(e=>e.reload),ce=$(e=>e.reloading),le=i?`Read only`:a?`Sample (not saved)`:o===`saving`?`Saving…`:o===`unsaved`?`Unsaved`:`Saved`,ue=i?q(`閲覧専用`):a?q(`サンプルは保存されません。Save で自分のプロジェクトとして保存`):L?q(`{file} に自動で保存します (変更後)。Save で今すぐ書きます`,{file:L}):q(`このブラウザに自動で保存します`),de=pm(e),fe=de.working.length;return(0,x.jsxs)(`header`,{className:`topbar`,"data-editing":re,children:[(0,x.jsxs)(`div`,{className:`topbar-identity`,children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:t,title:q(`階層 / 絞り込み / メンバー / 部品`),children:`☰`}),oe!==`vscode`&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:h,title:q(`Home (プロジェクト一覧へ)`),"aria-label":`Home`,children:(0,x.jsxs)(`svg`,{width:`18`,height:`18`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2.2`,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":`true`,children:[(0,x.jsx)(`path`,{d:`M3 11.5 12 4l9 7.5`}),(0,x.jsx)(`path`,{d:`M5.5 10.5V20h13v-9.5`}),(0,x.jsx)(`path`,{d:`M10 20v-5h4v5`})]})}),(0,x.jsx)(`button`,{className:`project-name`,onClick:()=>f({project:!0}),title:e.name,children:e.name}),(0,x.jsxs)(`span`,{className:`save-chip ${o===`unsaved`?`unsaved`:``}`,title:ue,children:[!a&&(0,x.jsx)(`span`,{className:`save-chip__file`,children:L??q(`ブラウザ内`)}),(0,x.jsx)(`span`,{children:le})]}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>void se(),disabled:ce,title:q(oe===`idb`?`最新の内容を読み込む`:`最新の内容を読み込む (ファイルを今すぐ読み直す)`),"aria-label":`Reload`,children:(0,x.jsxs)(`svg`,{className:ce?`spin`:void 0,width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2.2`,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":`true`,children:[(0,x.jsx)(`path`,{d:`M20 12a8 8 0 1 1-2.6-5.9`}),(0,x.jsx)(`path`,{d:`M20 4v5h-5`})]})}),a&&!i&&(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:_,title:q(`自分のプロジェクトとして保存`),children:`Save`}),!a&&!i&&(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:ae,disabled:o===`saved`||o===`saving`,title:ue,children:`Save`})]}),(0,x.jsxs)(`div`,{className:`topbar-tools`,children:[(0,x.jsxs)(`button`,{className:`summary-chip`,"data-on":m.timeline,onClick:()=>f({timeline:!m.timeline}),title:q(`今の状況 (作業中・判断待ち・ログ)`),children:[fe>0&&(0,x.jsx)(`span`,{className:`dot`}),fe>0&&(0,x.jsxs)(`span`,{children:[(0,x.jsxs)(`span`,{className:`summary-chip__txt`,children:[q(`作業中`),` `]}),fe]}),de.blocked.length>0&&(0,x.jsxs)(`span`,{children:[(0,x.jsxs)(`span`,{className:`summary-chip__txt`,children:[q(`詰まり・確認待ち`),` `]}),de.blocked.length]}),de.decisions.length>0&&(0,x.jsxs)(`span`,{className:`summary-decision`,children:[(0,x.jsxs)(`span`,{className:`summary-chip__txt`,children:[q(`判断待ち`),` `]}),de.decisions.length]}),de.answered.length>0&&(0,x.jsxs)(`span`,{children:[(0,x.jsxs)(`span`,{className:`summary-chip__txt`,children:[q(`回答済み`),` `]}),de.answered.length]}),fe===0&&de.blocked.length===0&&de.decisions.length===0&&de.answered.length===0&&(0,x.jsx)(`span`,{children:`Activity`})]}),!i&&(0,x.jsxs)(`button`,{className:`mode-toggle`,"data-on":re,onClick:()=>ie(!re),title:q(re?`Edit モード: ドラッグで移動・結線・階層移動ができます。押すと View (閲覧) に`:`View モード: ドラッグでの編集は効きません。押すと Edit に`),children:[(0,x.jsx)(`span`,{className:`mode-toggle__knob`}),(0,x.jsx)(`span`,{children:re?`Edit`:`View`})]}),(0,x.jsxs)(`div`,{className:`relative topbar-search`,children:[(0,x.jsx)(`input`,{"aria-label":q(`ブロックを検索`),ref:k,className:`input search-box`,placeholder:q(`Search ID / 題名`),value:T,onChange:e=>{E(e.target.value),O(!0)},onFocus:()=>O(!0),onKeyDown:e=>{e.key===`Enter`&&!e.nativeEvent.isComposing&&A[0]&&j(A[0].id),e.key===`Escape`&&(O(!1),E(``),e.target.blur())},onBlur:()=>setTimeout(()=>O(!1),150)}),D&&T.trim()&&A.length>0&&(0,x.jsx)(`div`,{className:`card absolute right-0 mt-1 p-1 flex flex-col z-30`,style:{width:`min(320px, calc(100vw - 32px))`,maxHeight:320,overflow:`auto`},children:A.map(e=>(0,x.jsxs)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onMouseDown:e=>e.preventDefault(),onClick:()=>j(e.id),children:[(0,x.jsx)(`span`,{className:`chip`,style:{fontFamily:`ui-monospace, monospace`,marginRight:6},children:e.key}),(0,x.jsx)(`span`,{className:`truncate`,children:e.title})]},e.id))}),D&&T.trim()&&A.length===0&&(0,x.jsx)(`div`,{className:`card absolute right-0 mt-1 p-2 text-[12px] z-30`,style:{minWidth:200,color:`var(--text-muted)`},children:q(`見つかりません`)})]}),!i&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{className:`btn btn-primary btn-sm desktop-action`,onClick:F,title:q(`ブロックを追加 (N)。ボックスを選んでいればその中に、選んでいなければプロジェクトの中に`),children:`+ Block`}),(0,x.jsx)(`button`,{className:`btn btn-sm desktop-action layout-action`,onClick:P,title:q(`Auto Layout: 依存関係で並べ直す (大項目は畳んだ前提)`),children:`Auto Layout`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm desktop-action`,onClick:c,disabled:u===0,title:q(`元に戻す (Ctrl+Z)`),"aria-label":`Undo`,children:`↶`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm desktop-action`,onClick:l,disabled:d===0,title:q(`やり直す (Ctrl+Y)`),"aria-label":`Redo`,children:`↷`})]}),(0,x.jsxs)(`div`,{className:`relative`,children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:e=>{e.stopPropagation(),w(!C)},title:`Menu`,"aria-expanded":C,onKeyDown:e=>{e.key===`Escape`&&w(!1)},children:`⋯`}),C&&(0,x.jsxs)(`div`,{className:`card absolute right-0 mt-1 p-1 flex flex-col z-30`,style:{minWidth:220,maxHeight:`min(480px, 65dvh)`,overflowY:`auto`},children:[!i&&(0,x.jsxs)(`div`,{className:`menu-actions`,children:[(0,x.jsx)(`button`,{className:`btn btn-primary btn-sm`,onClick:F,children:`+ Block`}),(0,x.jsx)(`button`,{className:`btn btn-sm layout-action`,onClick:P,children:`Auto Layout`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:c,disabled:u===0,children:`Undo`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:l,disabled:d===0,children:`Redo`})]}),!i&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:N,title:q(`同じファイルにプロジェクトのボックスを足す`),children:`New Project`}),!i&&(0,x.jsx)(`div`,{style:{borderTop:`1px solid var(--line-soft)`,margin:`4px 0`}}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:ee,children:`Export JSON`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:I,children:`Export Markdown`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:te,children:`Copy Mermaid`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:ne,children:`Import JSON`}),(0,x.jsx)(`div`,{style:{borderTop:`1px solid var(--line-soft)`,margin:`4px 0`}}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:n,children:`Help`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:h,children:`Home`}),(0,x.jsx)(`div`,{style:{borderTop:`1px solid var(--line-soft)`,margin:`4px 0`}}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>jf(r===`en`?`ja`:`en`),title:q(`画面の文言の言語を切り替える`),children:r===`en`?`日本語`:`English`})]})]}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:M,title:b===`dark`?`Light mode`:`Dark mode`,children:b===`dark`?`☀`:`☾`})]})]})}var DD=240;function OD({project:e,majors:t,scope:n,onSelect:r,marked:i}){Nw();let a=(0,y.useRef)(null),[o,s]=(0,y.useState)(!1),[c,l]=(0,y.useState)(!1),[u,d]=(0,y.useState)(!1),f=()=>{let e=a.current;e&&(s(e.scrollLeft>1),l(e.scrollLeft+e.clientWidth<e.scrollWidth-1))};(0,y.useEffect)(()=>{f();let e=a.current;if(!e)return;let t=new ResizeObserver(f);return t.observe(e),()=>t.disconnect()},[t.length]),(0,y.useEffect)(()=>{(a.current?.querySelector(`.canvas-tab[data-on="true"]`))?.scrollIntoView({inline:`nearest`,block:`nearest`}),setTimeout(f,0)},[n]),(0,y.useEffect)(()=>{if(!u)return;let e=e=>{e.target.closest?.(`.tab-list, .tab-list-btn`)||d(!1)},t=e=>{e.key===`Escape`&&d(!1)};return window.addEventListener(`mousedown`,e),window.addEventListener(`keydown`,t),()=>{window.removeEventListener(`mousedown`,e),window.removeEventListener(`keydown`,t)}},[u]);let p=e=>a.current?.scrollBy({left:e,behavior:`smooth`}),m=e=>{r(e),d(!1)};return(0,x.jsxs)(`div`,{className:`canvas-tabs`,role:`tablist`,children:[(0,x.jsxs)(`div`,{className:`tab-nav`,children:[(0,x.jsx)(`button`,{className:`tab-nav-btn tab-list-btn`,"data-on":u,onClick:()=>d(e=>!e),title:q(`タブの一覧 (押して選ぶ)`),children:`≡`}),(0,x.jsx)(`button`,{className:`tab-nav-btn`,disabled:!o,onClick:()=>p(-240),title:q(`左へ`),children:`◀`}),(0,x.jsx)(`button`,{className:`tab-nav-btn`,disabled:!c,onClick:()=>p(DD),title:q(`右へ`),children:`▶`})]}),(0,x.jsxs)(`div`,{className:`tab-strip`,ref:a,onScroll:f,children:[(0,x.jsx)(`button`,{className:`canvas-tab`,role:`tab`,"data-on":n===null,"data-marked":i?.has(null)||void 0,onClick:()=>m(null),title:q(`大項目の一覧を俯瞰する (中はそれぞれのタブで)`),children:`All`}),t.map(e=>(0,x.jsxs)(`button`,{className:`canvas-tab`,role:`tab`,"data-on":n===e.id,"data-marked":i?.has(e.id)||void 0,onClick:()=>m(e.id),title:i?.has(e.id)?q(`{title} (選んだ線の続きがある)`,{title:e.title}):q(`{title} の中を見る`,{title:e.title}),children:[(0,x.jsx)(PT,{status:e.status}),(0,x.jsx)(`span`,{className:`truncate`,children:e.title})]},e.id))]}),u&&(0,x.jsxs)(`div`,{className:`tab-list card`,role:`menu`,children:[(0,x.jsxs)(`button`,{className:`tab-list-row`,"data-on":n===null,onClick:()=>m(null),children:[(0,x.jsx)(`span`,{className:`tab-list-icon`,children:`⊞`}),(0,x.jsx)(`span`,{className:`truncate`,children:`All`})]}),t.map(t=>{let r=Up(e,t.id);return(0,x.jsxs)(`button`,{className:`tab-list-row`,"data-on":n===t.id,onClick:()=>m(t.id),title:t.title,children:[(0,x.jsx)(PT,{status:t.status}),(0,x.jsx)(`span`,{className:`truncate`,children:t.title}),(0,x.jsx)(`span`,{className:`tab-list-prog`,children:r.total>0?`${r.percent}%`:``})]},t.id)})]})]})}function kD(e,t,n,r){try{let i=Number(localStorage.getItem(e));return Number.isFinite(i)&&i>=n&&i<=r?i:t}catch{return t}}function AD(e,t){try{localStorage.setItem(e,String(t))}catch{}}var jD={min:260,max:760,def:320},MD={min:220,max:640,def:280};function ND(){Nw();let e=$(e=>e.project),t=cT(),n=$(e=>e.embed),r=$(e=>e.readonly),i=$(e=>e.toast),a=$(e=>e.setToast),o=$(e=>e.selection),s=$(e=>e.select),c=$(e=>e.focusBlock),l=$(e=>e.apply),u=$(e=>e.undo),d=$(e=>e.redo),f=$(e=>e.setMode),p=$(e=>e.openSample),m=$(e=>e.openExample),h=$(e=>e.openProject),g=$(e=>e.openFromServer),_=$(e=>e.openFromVsCode),v=$(e=>e.viewScope),b=$(e=>e.setViewScope),[S,C]=(0,y.useState)(!1),[w,T]=(0,y.useState)(()=>kD(`boxglow:rightW`,jD.def,jD.min,jD.max)),[E,D]=(0,y.useState)(()=>kD(`boxglow:drawerW`,MD.def,MD.min,MD.max)),O=(0,y.useCallback)(e=>{T(e),AD(`boxglow:rightW`,e)},[]),k=(0,y.useCallback)(e=>{D(e),AD(`boxglow:drawerW`,e)},[]),[A,j]=(0,y.useState)(!1),[M,N]=(0,y.useState)({...lD,statuses:new Set(lD.statuses)});(0,y.useEffect)(()=>{let e=new URLSearchParams(window.location.search),t=e.get(`view`)===`article`,n=t||e.get(`embed`)===`1`;f({embed:n,readonly:t||e.get(`readonly`)===`1`});let r=e.get(`theme`);(r===`dark`||r===`light`)&&PE(r,!1);let i=null;if(n&&window.parent!==window)try{let e=window.parent.document.documentElement,t=()=>{let t=e.dataset.theme;(t===`dark`||t===`light`)&&PE(t,!1)};t(),i=new MutationObserver(t),i.observe(e,{attributes:!0,attributeFilter:[`data-theme`]})}catch{}if(window.acquireVsCodeApi){let e=()=>PE(document.body.classList.contains(`vscode-dark`)||document.body.classList.contains(`vscode-high-contrast`)?`dark`:`light`,!1);e(),i=new MutationObserver(e),i.observe(document.body,{attributes:!0,attributeFilter:[`class`]}),_()}else if(e.get(`demo`)===`daw`)m();else if(t||e.get(`demo`)===`1`){if(p(),t){let e=$.getState(),t=Object.values(e.project?.blocks??{}),n=t.find(e=>e.kind===`task`&&t.some(t=>t.parentId===e.id));n&&e.setViewScope(n.id)}}else if(e.get(`serve`)===`1`)g();else{let e=window.location.hash.match(/p=([\w-]+)/);e&&h(e[1])}return()=>i?.disconnect()},[f,p,m,h,g,_]),(0,y.useEffect)(()=>{let e=e=>{let t=$.getState();!t.ephemeral&&[`saving`,`unsaved`].includes(t.saveState)&&(e.preventDefault(),e.returnValue=``)};return window.addEventListener(`beforeunload`,e),()=>window.removeEventListener(`beforeunload`,e)},[]),(0,y.useEffect)(()=>{if(!i)return;let e=setTimeout(()=>a(null),3200);return()=>clearTimeout(e)},[i,a]),(0,y.useEffect)(()=>{let e=e=>{if(document.querySelector(`dialog[open]`)||e.isComposing)return;let t=e.target;if(t&&(t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.tagName===`SELECT`||t.isContentEditable))return;let n=$.getState().project;if(!n)return;let i=$.getState().selection;if((e.ctrlKey||e.metaKey)&&e.key.toLowerCase()===`z`)e.preventDefault(),e.shiftKey?d():u();else if((e.ctrlKey||e.metaKey)&&e.key.toLowerCase()===`y`)e.preventDefault(),d();else if(e.key===`Delete`||e.key===`Backspace`){if(r||!$.getState().editMode)return;if(i.edgeId){let e=n.edges[i.edgeId];e&&!e.auto&&(s({}),l(e=>Rp(e,i.edgeId)))}else if(i.blockId){let e=n.blocks[i.blockId],t=Object.values(n.blocks).filter(e=>e.parentId===i.blockId).length;e&&(t===0||confirm(q(`「{title}」と下の階層のブロックを削除します。よろしいですか?`,{title:e.title})))&&(s({}),l(e=>Dp(e,i.blockId)))}}else if(e.key.toLowerCase()===`n`&&!e.ctrlKey&&!e.metaKey){if(r)return;let e=oT(n,i,$.getState().viewScope);l(t=>{let n=Cp(t,{parentId:e,title:q(`新しいブロック`)}),r=structuredClone(n.project);return r.blocks[e]&&(r.blocks[e].collapsed=!1),setTimeout(()=>{s({blockId:n.blockId}),c(n.blockId)},0),r})}else e.key===`Escape`&&(s({}),j(!1))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[l,u,d,s,r,c]);let P=(0,y.useMemo)(()=>!e||dD(M)?null:t=>uD(e,t,M),[e,M]),F=(0,y.useCallback)(()=>C(e=>!e),[]),ee=(0,y.useCallback)(()=>C(!0),[]),I=e?Up(e,Wf):null,te=(0,y.useMemo)(()=>{let e=new URL(window.location.href);return e.searchParams.delete(`embed`),e.searchParams.delete(`readonly`),e.searchParams.delete(`view`),e.searchParams.set(`demo`,e.searchParams.get(`demo`)===`daw`?`daw`:`1`),e.toString()},[]),ne=!!e&&!n&&(o.blockId!==null||o.edgeId!==null||o.terminal!==null||o.project||o.timeline),L=[`app-grid`,n?`embed`:``,ne?``:`no-right`].filter(Boolean).join(` `),re=(0,y.useMemo)(()=>e?np(e):[],[e]),ie=(0,y.useMemo)(()=>e&&o.edgeId&&e.edges[o.edgeId]?new Set(Km(e,o.edgeId)):void 0,[e,o.edgeId]),ae=!!e&&re.length>0,oe=v&&e?.blocks[v]?v:null,se=(0,y.useMemo)(()=>e&&oe?sp(e,oe):[],[e,oe]),ce=se[0]?.id??null;return(0,x.jsxs)(`div`,{className:L,style:{"--right-w":`${w}px`},children:[(0,x.jsxs)(`div`,{className:`app-top`,children:[e&&!n&&(0,x.jsx)(ED,{project:e,onToggleDrawer:F,onHelp:()=>j(!0)}),e&&!n&&(0,x.jsx)(CD,{})]}),(0,x.jsxs)(`main`,{className:`app-main relative min-w-0 min-h-0`,children:[(0,x.jsxs)(`div`,{className:`canvas-wrap`,children:[e&&(0,x.jsx)(yd,{children:(0,x.jsx)(EE,{project:t??e,matcher:P})}),e&&S&&!n&&(0,x.jsx)(pD,{project:t??e,filter:M,onFilter:N,onClose:()=>C(!1),width:E}),e&&S&&!n&&(0,x.jsx)(kE,{side:`right`,width:E,min:MD.min,max:MD.max,onWidth:k,style:{left:8+E-5,top:8,bottom:8}}),e&&(se.length>0||!n&&!dD(M))&&(0,x.jsxs)(`div`,{className:`scope-path`,style:{left:S&&!n?8+E+8:8},children:[se.length>0&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{className:`scope-crumb`,onClick:()=>b(null),title:q(`大項目の一覧へ`),children:`All`}),se.map((e,t)=>(0,x.jsxs)(`span`,{className:`contents`,children:[(0,x.jsx)(`span`,{className:`scope-sep`,children:`›`}),t===se.length-1?(0,x.jsx)(`span`,{className:`scope-crumb current`,title:e.title,children:e.title}):(0,x.jsx)(`button`,{className:`scope-crumb`,onClick:()=>b(e.id),title:q(`{title} へ戻る`,{title:e.title}),children:e.title})]},e.id))]}),!n&&!dD(M)&&(0,x.jsx)(`button`,{className:`chip`,"data-on":`true`,onClick:()=>N({...lD,statuses:new Set(lD.statuses)}),title:q(`絞り込みを解除`),children:`Filtered ×`})]}),n&&(0,x.jsx)(`a`,{className:`btn btn-accent absolute top-2 right-2 z-10`,href:te,target:`_blank`,rel:`noopener noreferrer`,children:`Open full ↗`}),n&&se.length===0&&(0,x.jsx)(`span`,{className:`absolute top-2 left-2 z-10 font-head text-[14px] px-2 py-1 rounded-lg`,style:{background:`var(--bg-card)`,border:`2px solid var(--line)`},children:`Boxglow`})]}),ae&&(0,x.jsx)(OD,{project:e,majors:re,scope:ce,onSelect:b,marked:ie}),!e&&!n&&(0,x.jsx)(BE,{}),A&&(0,x.jsx)(`div`,{className:`modal-backdrop`,onClick:()=>j(!1),children:(0,x.jsxs)(`div`,{className:`card modal p-5 flex flex-col gap-2`,style:{width:420},onClick:e=>e.stopPropagation(),children:[(0,x.jsx)(`div`,{className:`font-head text-[16px]`,children:`Help`}),(0,x.jsx)(`table`,{className:`help-table`,children:(0,x.jsxs)(`tbody`,{children:[(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`ブロックを置く`)}),(0,x.jsxs)(`td`,{children:[(0,x.jsx)(`span`,{className:`kbd`,children:`N`}),` `,q(`または「+ Block」(選んだボックスの中に)`)]})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:`Edit / View`}),(0,x.jsx)(`td`,{children:q(`上の切替。Edit のときだけドラッグで移動・結線・階層移動と Del が効く`)})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`結線`)}),(0,x.jsx)(`td`,{children:q(`丸から相手の丸、または相手のボックスへドラッグ (近くで離せばつながる)`)})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`階層を移す`)}),(0,x.jsx)(`td`,{children:q(`ボックスをドラッグして別のボックスの中に落とす`)})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`下の階層を畳む / 展開`)}),(0,x.jsx)(`td`,{children:q(`ブロックをダブルクリック`)})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`削除`)}),(0,x.jsx)(`td`,{children:(0,x.jsx)(`span`,{className:`kbd`,children:`Del`})})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`元に戻す / やり直す`)}),(0,x.jsxs)(`td`,{children:[(0,x.jsx)(`span`,{className:`kbd`,children:`Ctrl+Z`}),` / `,(0,x.jsx)(`span`,{className:`kbd`,children:`Ctrl+Y`})]})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`選択を解除`)}),(0,x.jsx)(`td`,{children:(0,x.jsx)(`span`,{className:`kbd`,children:`Esc`})})]})]})}),(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:`var(--text-muted)`},children:q(`ボックスは「入力から出力を作るタスク」。出力を先に決め、大きなボックスは「分解する」で中にボックスを置く。供給元の無い入力は左端の入力まで自動で点線が伸びる。`)}),(0,x.jsx)(`button`,{className:`btn btn-sm self-end`,onClick:()=>j(!1),children:`Close`})]})})]}),(0,x.jsxs)(`aside`,{className:`panel right ${ne?``:`hidden-panel`}`,children:[e&&ne&&(0,x.jsx)(kE,{side:`left`,width:w,min:jD.min,max:jD.max,onWidth:O}),e&&ne&&(0,x.jsx)(hD,{project:e,onOpenDrawer:ee})]}),(0,x.jsxs)(`footer`,{className:`app-footer flex items-center gap-3 px-3 text-[12px]`,style:{borderTop:`2px solid var(--line)`,background:`var(--bg-card)`},children:[e&&I&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`span`,{className:`font-head`,children:[`Done `,I.white,` / `,I.total,` · `,I.percent,`%`]}),(0,x.jsx)(`div`,{className:`progress-bar`,style:{width:160},children:(0,x.jsx)(`span`,{style:{width:`${I.percent}%`}})}),n&&(0,x.jsx)(`a`,{className:`underline`,href:te,target:`_blank`,rel:`noopener noreferrer`,style:{color:`var(--primary-strong)`},children:q(`Boxglow で開く`)})]}),!e&&(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`},children:`Boxglow`}),(0,x.jsx)(TD,{}),(0,x.jsxs)(`span`,{className:`build-stamp text-[10px]`,style:{color:`var(--text-muted)`},title:q(`ビルド日時 (日本時間)。古い場合は再読み込み (Ctrl+F5) してください`),children:[`build `,`2026-10-05 22:57`]})]}),i&&(0,x.jsx)(`div`,{className:`toast`,role:`status`,children:i})]})}FE(),window.boxglow={store:$},b.createRoot(document.getElementById(`root`)).render((0,x.jsx)(y.StrictMode,{children:(0,x.jsx)(ND,{})}));
3465
+ `)}var sD=[`#0d8080`,`#e8875e`,`#3aa85a`,`#6b7075`,`#2f6fb3`,`#a0522d`],cD={black:`?`,gray:`~`,white:`✓`},lD={statuses:new Set([`black`,`gray`,`white`]),memberId:null,unassigned:!1,category:null};function uD(e,t,n){let r=e.blocks[t];return!(!r||!n.statuses.has(r.status)||n.memberId&&!r.assigneeIds.includes(n.memberId)||n.unassigned&&(r.assigneeIds.length>0||cp(r)===`project`)||n.category&&r.category!==n.category)}var dD=e=>e.statuses.size===3&&e.memberId===null&&!e.unassigned&&e.category===null;function fD({project:e,parentId:t,depth:n,selectedId:r,onSelect:i,closed:a,onToggle:o}){Nw();let s=fp(e,t).sort((e,t)=>e.position.y-t.position.y||e.position.x-t.position.x);return(0,x.jsx)(x.Fragment,{children:s.map(t=>{let s=fp(e,t.id).length>0,c=a.has(t.id);return(0,x.jsxs)(`div`,{children:[(0,x.jsxs)(`div`,{className:`tree-row`,"data-selected":r===t.id,style:{paddingLeft:8+n*14},onClick:()=>i(t.id),title:t.title,children:[s?(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,style:{padding:`0 4px`},onClick:e=>{e.stopPropagation(),o(t.id)},title:q(c?`開く`:`閉じる`),children:c?`▸`:`▾`}):(0,x.jsx)(`span`,{style:{width:20,display:`inline-block`}}),(0,x.jsx)(`span`,{className:`tree-glyph ${t.status}`,children:cD[t.status]}),(0,x.jsx)(`span`,{className:`truncate`,children:t.title})]}),s&&!c&&(0,x.jsx)(fD,{project:e,parentId:t.id,depth:n+1,selectedId:r,onSelect:i,closed:a,onToggle:o})]},t.id)})})}function pD({project:e,filter:t,onFilter:n,onClose:r,width:i}){Nw();let a=$(e=>e.readonly),o=$(e=>e.selection),s=$(e=>e.select),c=$(e=>e.apply),[l,u]=(0,y.useState)(()=>new Set),d=e=>u(t=>{let n=new Set(t);return n.has(e)?n.delete(e):n.add(e),n}),[f,p]=(0,y.useState)(``),[m,h]=(0,y.useState)(sD[0]),g=$(e=>e.focusBlock),_=$(e=>e.setToast),v=$(e=>e.meId),b=$(e=>e.setMe),[S,C]=(0,y.useState)([]);(0,y.useEffect)(()=>{WE().then(C)},[]);let w=()=>void WE().then(C),T=t=>{let n=oT(e,o,$.getState().viewScope);c(e=>{let r=_m(e,n,t,`human`);return setTimeout(()=>{s({blockId:r.blockId}),g(r.blockId)},0),r.project})},E=async()=>{let e=await RE(`.json,application/json`);if(e)try{await GE(vm(e)),w(),_(q(`テンプレートをライブラリに追加しました`))}catch(e){_(e instanceof Error?e.message:String(e))}},D=e=>{let r=new Set(t.statuses);r.has(e)?r.delete(e):r.add(e),r.size!==0&&n({...t,statuses:r})},O=()=>{f.trim()&&(c(e=>zp(e,f.trim(),m).project),p(``),h(sD[(sD.indexOf(m)+1)%sD.length]))},[k,A]=(0,y.useState)(`tree`),j=[{id:`tree`,label:`Tree`,hint:q(`ボックスの一覧 (押すと選ぶ)`)},{id:`filter`,label:`Filter`,hint:q(`状態や担当でボックスを絞る`)},{id:`members`,label:`Members`,hint:q(`担当にする人を登録。自分を決める`)},{id:`parts`,label:`Parts`,hint:q(`他のプロジェクトでも使い回すボックス`)}];return(0,x.jsxs)(`div`,{className:`drawer card`,style:{width:i},children:[(0,x.jsxs)(`div`,{className:`flex items-center gap-1 mb-2`,children:[(0,x.jsx)(`div`,{className:`seg flex-1`,style:{gridTemplateColumns:`repeat(4, 1fr)`},children:j.map(e=>(0,x.jsx)(`button`,{className:`seg__btn`,"data-on":k===e.id,onClick:()=>A(e.id),title:e.hint,style:{padding:`6px 2px`,fontSize:12},children:e.label},e.id))}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:r,title:`Close`,children:`×`})]}),(0,x.jsx)(`div`,{className:`text-[11px] mb-2`,style:{color:`var(--text-muted)`},children:j.find(e=>e.id===k)?.hint}),k===`tree`&&(fp(e,`root`).length===0?(0,x.jsx)(`div`,{className:`text-[12px] px-2`,style:{color:`var(--text-muted)`},children:`No blocks yet`}):(0,x.jsx)(fD,{project:e,parentId:`root`,depth:0,selectedId:o.blockId,onSelect:e=>{s({blockId:e}),g(e)},closed:l,onToggle:d})),k===`filter`&&(0,x.jsxs)(`div`,{className:`flex flex-wrap gap-1`,children:[[`black`,`gray`,`white`].map(e=>(0,x.jsxs)(`button`,{className:`chip`,"data-on":t.statuses.has(e),onClick:()=>D(e),children:[(0,x.jsx)(`span`,{className:`tree-glyph ${e}`,style:{width:12,height:12,fontSize:8,lineHeight:`8px`},children:cD[e]}),MT[e]]},e)),v&&(0,x.jsx)(`button`,{className:`chip`,"data-on":t.memberId===v,onClick:()=>n({...t,memberId:t.memberId===v?null:v,unassigned:!1}),title:q(`自分の担当だけ`),children:`Mine`}),(0,x.jsx)(`button`,{className:`chip`,"data-on":t.unassigned,onClick:()=>n({...t,unassigned:!t.unassigned,memberId:null}),title:q(`担当がいないボックスだけ`),children:q(`未担当`)}),e.members.filter(e=>e.id!==v).map(e=>(0,x.jsxs)(`button`,{className:`chip`,"data-on":t.memberId===e.id,onClick:()=>n({...t,memberId:t.memberId===e.id?null:e.id,unassigned:!1}),title:q(`{name} の担当だけ`,{name:e.name}),children:[(0,x.jsx)(`span`,{className:`avatar`,style:{background:e.color,width:16,height:16,fontSize:9},children:e.name.slice(0,1)}),e.name]},e.id)),(0,x.jsx)(`div`,{className:`label mt-3`,children:`Category`}),(0,x.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:Bf.map(e=>(0,x.jsxs)(`button`,{className:`chip cat-chip${e.neutral?` neutral`:``}`,"data-on":t.category===e.key,style:{"--cat":e.color},onClick:()=>n({...t,category:t.category===e.key?null:e.key}),title:q(`{label} のボックスだけ`,{label:q(e.label)}),children:[(0,x.jsx)(`span`,{className:`cat-chip__dot`}),q(e.label)]},e.key))}),!dD(t)&&(0,x.jsx)(`button`,{className:`chip mt-3`,onClick:()=>n({...lD,statuses:new Set(lD.statuses)}),children:`Clear`})]}),k===`parts`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`text-[11px] mb-1`,style:{color:`var(--text-muted)`},children:q(`挿入先: {target}`,{target:(()=>{let t=oT(e,o,$.getState().viewScope),n=e.blocks[t];return n?cp(n)===`project`?n.title:q(`{title} の隣`,{title:n.title}):q(`最上位`)})()})}),(0,x.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[S.length===0&&(0,x.jsx)(`div`,{className:`text-[12px] px-1`,style:{color:`var(--text-muted)`},children:q(`ボックスを選び、右の「⋯」から「Save as Part」すると、ここに並びます。`)}),S.map(e=>(0,x.jsxs)(`div`,{className:`flex items-center gap-1 text-[13px] px-1`,children:[(0,x.jsx)(`span`,{className:`truncate`,title:`${e.description||e.name} (v${e.version}${e.tags.length?`, `+e.tags.join(`, `):``})`,children:e.name}),(0,x.jsxs)(`span`,{className:`text-[10px]`,style:{color:`var(--text-muted)`},children:[`v`,e.version]}),(0,x.jsxs)(`span`,{className:`ml-auto flex gap-0.5`,children:[!a&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,title:q(`挿入`),onClick:()=>T(e),children:`Insert`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,title:q(`JSON で保存 (他のリポジトリや人と共有)`),onClick:()=>IE(`${zE(e.name)}.boxglow-block.json`,JSON.stringify(e,null,2),`application/json`),children:`↓`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,title:q(`ライブラリから消す`),onClick:()=>{confirm(q(`テンプレート「{name}」を消しますか?`,{name:e.name}))&&KE(e.id).then(w)},children:`×`})]})]},e.id)),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm self-start`,onClick:E,children:`Import`})]})]}),k===`members`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`flex flex-col gap-1`,children:e.members.map(e=>(0,x.jsxs)(`div`,{className:`flex items-center gap-2 text-[13px] px-1`,children:[(0,x.jsx)(`span`,{className:`avatar`,style:{background:e.color},children:e.name.slice(0,1)}),(0,x.jsx)(`span`,{className:`truncate`,children:e.name}),(0,x.jsx)(`button`,{className:`chip ml-auto`,"data-on":v===e.id,onClick:()=>b(v===e.id?null:e.id),title:q(`このブラウザでは自分として扱う (自分の担当のボックスに帯が付く)`),children:v===e.id?`Me`:`Set as me`}),!a&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,title:q(`外す`),onClick:()=>c(t=>Bp(t,e.id)),children:`×`})]},e.id))}),!a&&(0,x.jsxs)(`div`,{className:`flex items-center gap-1 mt-2`,children:[(0,x.jsx)(`span`,{className:`avatar flex-none`,style:{background:m,cursor:`pointer`},title:q(`色を変える`),onClick:()=>h(sD[(sD.indexOf(m)+1)%sD.length]),children:f.slice(0,1)||`+`}),(0,x.jsx)(`input`,{className:`input`,placeholder:`Name`,value:f,onChange:e=>p(e.target.value),onKeyDown:e=>e.key===`Enter`&&O()}),(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:O,disabled:!f.trim(),children:`Add`})]})]})]})}function mD({title:e,children:t}){Nw();let n=$(e=>e.select);return(0,x.jsxs)(`div`,{className:`flex items-center gap-1 mb-2`,children:[(0,x.jsx)(`span`,{className:`label truncate flex-1`,title:e,children:e}),t,(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>n({}),title:q(`閉じる (Esc)`),children:`×`})]})}function hD({project:e,onOpenDrawer:t}){let n=$(e=>e.selection);return n.edgeId&&e.edges[n.edgeId]?(0,x.jsx)(bD,{project:e,edgeId:n.edgeId}):n.blockId&&e.blocks[n.blockId]?(0,x.jsx)(vD,{project:e,blockId:n.blockId,onOpenDrawer:t}):n.terminal?(0,x.jsx)(_D,{project:e,which:n.terminal,groupId:n.terminalGroup}):n.project?(0,x.jsx)(gD,{project:e}):n.timeline?(0,x.jsx)(XE,{project:e}):null}function gD({project:e}){Nw();let t=$(e=>e.readonly),n=$(e=>e.apply),r=Up(e,Wf);return(0,x.jsxs)(`div`,{className:`flex flex-col gap-4 p-3`,children:[(0,x.jsx)(mD,{title:`Project`}),(0,x.jsx)(HE,{project:e}),(0,x.jsx)(`input`,{className:`input font-head text-[16px]`,value:e.name,disabled:t,onChange:e=>n(t=>({...structuredClone(t),name:e.target.value}))}),(0,x.jsx)(AE,{multiline:!0,className:`input`,placeholder:q(`ゴール (何を達成したいか)`),value:e.description,disabled:t,onCommit:e=>n(t=>({...structuredClone(t),description:e}))}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`div`,{className:`progress-bar`,children:(0,x.jsx)(`span`,{style:{width:`${Math.round(r.ratio*100)}%`}})}),(0,x.jsx)(`div`,{className:`text-[12px] mt-1`,style:{color:`var(--text-muted)`},children:q(`完了 {white} / {total}`,{white:r.white,total:r.total})})]})]})}function _D({project:e,which:t,groupId:n}){Nw();let r=$(e=>e.readonly),i=$(e=>e.apply),a=$(e=>e.select),o=$(e=>e.setToast),s=n?Im(e).find(e=>e.id===n)??null:null,c=Im(e),l=t===`out`?`Project Outputs`:s?`Input Group`:`Project Inputs`;return(0,x.jsxs)(`div`,{className:`flex flex-col gap-3 p-3`,children:[(0,x.jsx)(mD,{title:l}),s&&(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsxs)(`div`,{className:`sec__head`,children:[(0,x.jsx)(`span`,{className:`label`,children:`Group`}),(0,x.jsxs)(`span`,{className:`flex gap-1`,children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,title:q(`このグループを JSON に書き出す (他のプロジェクトで読み込める)`),onClick:()=>IE(`${zE(s.name)}.boxglow-inputs.json`,Um(e,s.id),`application/json`),children:`Export`}),!r&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm btn-danger`,title:q(`グループを消す (入力は Inputs に戻る)`),onClick:()=>{confirm(q(`グループ「{name}」を消しますか? (入力は Inputs に戻ります)`,{name:s.name}))&&(a({terminal:`in`}),i(e=>Bm(e,s.id)))},children:`Delete`})]})]}),(0,x.jsx)(`input`,{className:`input font-head text-[15px]`,value:s.name,disabled:r,placeholder:`Group name`,onChange:e=>i(t=>zm(t,s.id,{name:e.target.value}))}),(0,x.jsx)(`input`,{className:`input`,value:s.description,disabled:r,placeholder:q(`説明 (任意。例: PCI-SIG の仕様書一式)`),onChange:e=>i(t=>zm(t,s.id,{description:e.target.value}))})]}),(0,x.jsx)(OE,{project:e,blockId:Wf,direction:t,readonly:r,title:t===`in`?`Inputs`:`Outputs`,allowAdd:t===`out`||!!s,groupId:t===`in`?s?s.id:null:void 0}),t===`in`&&!s&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:`var(--text-muted)`},children:q(`ここには、下の階層で供給元が決まっていない入力が自動で上がります。各入力はグループに移せます。`)}),(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsxs)(`div`,{className:`sec__head`,children:[(0,x.jsx)(`span`,{className:`label`,children:`Groups`}),!r&&(0,x.jsxs)(`span`,{className:`flex gap-1`,children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>{let e=prompt(q(`グループの名前 (例: PCIe 仕様書)`));e?.trim()&&i(t=>{let n=Rm(t,e.trim());return setTimeout(()=>a({terminal:`in`,terminalGroup:n.groupId}),0),n.project})},children:`+ Group`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:async()=>{let e=await RE(`.json,application/json`);if(e)try{i(t=>{let n=Wm(t,e);return setTimeout(()=>a({terminal:`in`,terminalGroup:n.groupId}),0),n.project})}catch(e){o(e instanceof Error?e.message:String(e))}},title:q(`他のプロジェクトで書き出したグループを読み込む`),children:`Import`})]})]}),c.length===0&&(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:`var(--text-muted)`},children:q(`仕様書などを種類ごとに分けるときは、グループを作って入力を入れます (例: PCIe 仕様書、DDR 仕様書)。`)}),c.map(t=>(0,x.jsxs)(`button`,{className:`tree-row text-left`,onClick:()=>a({terminal:`in`,terminalGroup:t.id}),children:[(0,x.jsx)(`span`,{className:`truncate`,children:t.name}),(0,x.jsx)(`span`,{className:`ml-auto text-[11px]`,style:{color:`var(--text-muted)`},children:Lm(e,t.id).length})]},t.id))]})]})]})}function vD({project:e,blockId:t}){Nw();let n=$(e=>e.readonly),r=$(e=>e.apply),i=$(e=>e.select),a=$(e=>e.setToast),o=$(e=>e.meId),[s,c]=(0,y.useState)(!1),[l,u]=(0,y.useState)(!1),[d,f]=(0,y.useState)(null),[p,m]=(0,y.useState)(!0),[h,g]=(0,y.useState)(!1),[_,v]=(0,y.useState)(``),[b,S]=(0,y.useState)(`status`),C=e.blocks[t],w=_.trim()?e.members.filter(e=>e.name.toLowerCase().includes(_.trim().toLowerCase())&&!C.assigneeIds.includes(e.id)).slice(0,8):[],T=fp(e,t),E=[...mp(e,t)].reverse(),D=Xp(e,t),O=Up(e,t),k=C.decisions.filter(e=>e.answer===void 0),A=C.decisions.filter(n=>n.answer!==void 0&&!fm(e,t,n)),j=Hp(e,t),M=cp(C)===`project`;(0,y.useEffect)(()=>{c(!1),u(!1),f(null),m(!0),g(!1),v(``)},[t]);let N=e=>r(n=>wp(n,t,{status:e})),P=e=>r(n=>{let r=n.blocks[t].assigneeIds;return wp(n,t,{assigneeIds:r.includes(e)?r.filter(t=>t!==e):[...r,e]})}),F=()=>{T.length>0&&!confirm(q(`「{title}」と下の階層のブロックを削除します。よろしいですか?`,{title:C.title}))||(i({}),r(e=>Dp(e,t)))},ee=async n=>{c(!1),await LE(aD(e,t,n))?a(q(`AI に渡すテキストをコピーしました`)):f(n)},I=async()=>{g(!1);let n=hm(e,t,{tags:(prompt(q(`部品の札 (例: 画像処理, 認証。カンマ区切り。省略可)`))??``).split(/[,、]/).map(e=>e.trim()).filter(Boolean)});await GE(n),a(q(`「{name}」を部品として保存しました (☰ の「部品」から挿入)`,{name:n.name}))},te={status:q(`状態・進捗・活動・判断`),io:q(`入力と出力 (成果物)`),owner:q(`担当`),dates:q(`開始日・期日・時間`),more:q(`AI に渡す・メモ・資料`)};return(0,x.jsxs)(`div`,{className:`flex flex-col gap-4 p-3`,children:[(0,x.jsxs)(`div`,{className:`flex items-center gap-1`,children:[(0,x.jsx)(`span`,{className:`label truncate flex-1`,title:E.map(e=>e.id===`root`?``:e.title).filter(Boolean).join(` › `),children:M?`Project`:E.map(e=>e.id===`root`?``:e.title).filter(Boolean).join(` › `)||`Top`}),(0,x.jsx)(`button`,{className:`chip`,style:{fontFamily:`ui-monospace, monospace`},title:q(`短い ID (押すとコピー。検索や CLI で使えます)`),onClick:async()=>{await LE(C.key??``)&&a(q(`ID {key} をコピーしました`,{key:C.key??``}))},children:C.key}),!n&&(0,x.jsxs)(`div`,{className:`relative`,children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>g(!h),title:q(`その他`),children:`⋯`}),h&&(0,x.jsxs)(`div`,{className:`card absolute right-0 mt-1 p-1 flex flex-col z-30`,style:{minWidth:200},children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>{g(!1),u(!0)},children:q(`作業範囲を編集`)}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>{g(!1),r(e=>({...e,focusBlockId:e.focusBlockId===t?void 0:t}))},children:e.focusBlockId===t?q(`今回の範囲の優先を解除`):q(`このボックスを今回の範囲にする`)}),!M&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:I,children:`Save as Part`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>{g(!1),f(`plan`),S(`more`)},children:`Show AI text`}),(0,x.jsx)(`div`,{style:{borderTop:`1px solid var(--line-soft)`,margin:`4px 0`}}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start btn-danger`,onClick:F,children:`Delete`})]})]}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>i({}),title:q(`閉じる (Esc)`),children:`×`})]}),(0,x.jsx)(AE,{className:`input font-head text-[16px]`,value:C.title,disabled:n,placeholder:q(`Title (何を作るか)`),onCommit:e=>r(n=>wp(n,t,{title:e}))}),(0,x.jsx)(VE,{project:e,blockId:t,editing:l,onClose:()=>u(!1)}),zf(C)&&(0,x.jsx)(`p`,{className:`text-[12px] description-reminder`,style:{color:`var(--accent)`},children:zf(C)}),(0,x.jsx)(`div`,{className:`seg`,style:{gridTemplateColumns:`repeat(5, 1fr)`},children:[[`status`,q(`状態`)],[`io`,q(`入出力`)],[`owner`,q(`担当`)],[`dates`,q(`日程`)],[`more`,q(`その他`)]].map(([n,r])=>(0,x.jsxs)(`button`,{className:`seg__btn`,"data-on":b===n,onClick:()=>S(n),style:{padding:`6px 2px`,fontSize:12},title:te[n],children:[r,n===`status`&&(k.length>0||A.length>0)&&(0,x.jsx)(`span`,{className:`dot decision`,style:{marginLeft:4,display:`inline-block`,width:6,height:6,borderRadius:999,background:`var(--accent)`}}),n===`io`&&(0,x.jsxs)(`span`,{style:{marginLeft:4,fontSize:10,opacity:.7},children:[Y(e,t,`in`).length,`/`,Y(e,t,`out`).length]})]},n))}),b!==`status`&&(k.length>0||A.length>0)&&(0,x.jsxs)(`button`,{className:`btn btn-sm inspector-attention`,onClick:()=>S(`status`),title:q(`Status で確認`),"aria-label":[k.length>0?q(`回答待ち {n}`,{n:k.length}):``,A.length>0?q(`AI未確認 {n}`,{n:A.length}):``,q(`Status で確認`)].filter(Boolean).join(` `),children:[[k.length>0?q(`回答待ち {n}`,{n:k.length}):``,A.length>0?q(`AI未確認 {n}`,{n:A.length}):``].filter(Boolean).join(`・`),(0,x.jsx)(`span`,{"aria-hidden":`true`,style:{marginLeft:8},children:`→`})]}),b===`status`&&(0,x.jsxs)(`section`,{className:`sec`,children:[k.length>0&&(0,x.jsxs)(`div`,{className:`attention-section`,children:[(0,x.jsx)(`h3`,{className:`label`,children:q(`回答が必要です`)}),k.map(n=>(0,x.jsx)(JE,{project:e,blockId:t,decisionId:n.id},n.id))]}),A.length>0&&(0,x.jsxs)(`div`,{className:`attention-section`,children:[(0,x.jsx)(`h3`,{className:`label`,children:q(`AI未確認の回答`)}),A.map(n=>(0,x.jsx)(JE,{project:e,blockId:t,decisionId:n.id},n.id))]}),(0,x.jsx)(`div`,{className:`sec__head`,children:(0,x.jsx)(`span`,{className:`label`,children:`Status`})}),(0,x.jsx)(`div`,{className:`seg`,children:[`black`,`gray`,`white`].map(e=>(0,x.jsxs)(`button`,{className:`seg__btn`,"data-on":C.status===e,disabled:n,onClick:()=>N(e),title:q(NT[e]),children:[(0,x.jsx)(`span`,{className:`tree-glyph ${e}`,children:cD[e]}),(0,x.jsx)(`span`,{children:MT[e]})]},e))}),D&&!n&&(0,x.jsx)(`button`,{className:`btn btn-primary btn-sm w-full`,onClick:()=>N(`white`),title:q(`下の階層が全部完了し、出力に成果物が付いています`),children:q(`完了にできます → Done`)}),C.status!==`white`&&cp(C)!==`project`&&Y(e,t,`in`).length>0&&(()=>{let n=Yp(e,t);return n.length===0?(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:`var(--primary-strong)`},children:q(`必須の入力はそろっています (着手できます)`)}):(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:`var(--text-muted)`},children:q(`必須の入力待ち: {names}`,{names:n.map(e=>e.name).join(`, `)})})})(),M&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`div`,{className:`sec__head mt-2`,children:(0,x.jsx)(`span`,{className:`label`,children:`Repository`})}),(0,x.jsx)(`input`,{className:`input`,placeholder:q(`パスや URL (例: ../mg-core、github.com/you/repo)`),value:C.repo??``,disabled:n,onChange:e=>r(n=>wp(n,t,{repo:e.target.value}),{history:!1}),onBlur:e=>r(n=>wp(n,t,{repo:e.target.value.trim()||void 0}))}),(0,x.jsx)(`div`,{className:`text-[11px]`,style:{color:`var(--text-muted)`},children:q(`複数のリポジトリをまたぐときは、boxglow.json を上のフォルダに 1 つ置き、各リポジトリの AI には環境変数 BOXGLOW_FILE でその場所を教えます`)})]}),(0,x.jsxs)(`label`,{className:`category-field`,children:[(0,x.jsx)(`span`,{className:`label`,children:`Category`}),(0,x.jsxs)(`select`,{className:`input`,"aria-label":`Category`,value:C.category??``,disabled:n,onChange:e=>r(n=>ym(n,t,e.target.value||null)),children:[(0,x.jsx)(`option`,{value:``,children:q(`カテゴリなし`)}),Bf.map(e=>(0,x.jsx)(`option`,{value:e.key,children:q(e.label)},e.key))]})]}),C.status!==`white`&&(0,x.jsxs)(`div`,{className:`flex items-center gap-2 text-[12px]`,style:{color:`var(--text-muted)`},children:[(0,x.jsx)(`input`,{type:`range`,min:0,max:100,step:5,value:j,disabled:n,className:`flex-1`,title:q(`進捗 (ドラッグで入力)`),onChange:e=>r(n=>Wp(n,t,Number(e.target.value),`human`),{history:!1}),onMouseUp:e=>r(n=>Wp(n,t,Number(e.target.value),`human`))}),(0,x.jsxs)(`span`,{style:{minWidth:36,textAlign:`right`},children:[j,`%`]}),typeof C.progress==`number`?(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,title:q(`手入力をやめて、下の階層から自動で計算する`),onClick:()=>r(e=>Wp(e,t,null,`human`)),children:`Auto`}):T.length>0?(0,x.jsxs)(`span`,{title:q(`下の階層の完了数`),children:[O.white,`/`,O.total]}):null]}),C.activity&&(0,x.jsxs)(`div`,{className:`flex flex-col gap-1 pl-2`,style:{borderLeft:`3px solid ${C.activity.state===`needs_decision`?`var(--accent)`:`var(--primary)`}`},children:[(0,x.jsxs)(`div`,{className:`flex items-center gap-2 text-[12px]`,children:[(0,x.jsx)(`span`,{className:`tl-actor`,children:ET(C.activity.actor)}),(0,x.jsx)(`b`,{children:q(OT[C.activity.state])}),(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`},children:AT(C.activity.since)}),!n&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm ml-auto`,title:q(`活動の印を消す`),onClick:()=>r(e=>rm(e,t)),children:`×`})]}),C.activity.note&&C.activity.state!==`needs_decision`&&(0,x.jsx)(`div`,{className:`text-[13px]`,children:C.activity.note})]}),(0,x.jsxs)(`details`,{className:`text-[12px]`,open:!!e.handoffs?.[t]&&C.status!==`white`,children:[(0,x.jsx)(`summary`,{children:q(`AI への引き継ぎ`)}),e.handoffs?.[t]?.note&&Rf(C,e.handoffs[t].at,`older`)&&(0,x.jsx)(`p`,{className:`my-2 text-[11px]`,children:Rf(C,e.handoffs[t].at,`older`)}),(0,x.jsx)(`p`,{className:`my-2`,children:q(`セッションを越えて残す発見・次の手順・未解決事項。AI は context コマンドで判断と合わせて読み直します。`)}),(0,x.jsx)(AE,{multiline:!0,className:`input`,value:e.handoffs?.[t]?.note??``,disabled:n,placeholder:q(`発見 / 次の手順 / 未解決事項`),onCommit:e=>r(n=>({...n,handoffs:{...n.handoffs,[t]:{note:e,actor:`human`,at:new Date().toISOString()}}}))}),(0,x.jsx)(`button`,{className:`btn btn-sm mt-2`,onClick:async()=>{let n=await LE(JSON.stringify(QE(e,t),null,2));a(q(n?`引き継ぎ情報をコピーしました`:`コピーできませんでした`))},children:q(`判断・入出力も含めてコピー`)})]}),C.decisions.filter(n=>n.answer!==void 0&&fm(e,t,n)).length>0&&(0,x.jsxs)(`details`,{className:`text-[12px]`,children:[(0,x.jsx)(`summary`,{style:{cursor:`pointer`,color:`var(--text-muted)`},children:q(`判断の記録 ({n})`,{n:C.decisions.filter(n=>n.answer!==void 0&&fm(e,t,n)).length})}),(0,x.jsx)(`div`,{className:`flex flex-col gap-3 mt-2`,children:C.decisions.filter(n=>n.answer!==void 0&&fm(e,t,n)).map(n=>(0,x.jsx)(JE,{project:e,blockId:t,decisionId:n.id},n.id))})]})]}),b===`owner`&&(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsx)(`div`,{className:`sec__head`,children:(0,x.jsx)(`span`,{className:`label`,children:q(`担当`)})}),(0,x.jsxs)(`div`,{className:`flex items-center gap-1 flex-wrap`,children:[C.assigneeIds.map(t=>{let r=e.members.find(e=>e.id===t);return r?(0,x.jsxs)(`span`,{className:`chip`,"data-on":r.id===o,style:{cursor:`default`},title:r.id===o?q(`{name} (自分)`,{name:r.name}):r.name,children:[(0,x.jsx)(`span`,{className:`avatar`,style:{background:r.color,width:16,height:16,fontSize:9},children:r.name.slice(0,1)}),r.name,!n&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,style:{padding:`0 2px`},title:q(`外す`),onClick:()=>P(r.id),children:`×`})]},t):null}),C.assigneeIds.length===0&&(0,x.jsx)(`span`,{className:`text-[12px]`,style:{color:`var(--text-muted)`},children:q(`未担当`)}),!n&&o&&!C.assigneeIds.includes(o)&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>P(o),title:q(`自分を担当にする`),children:`Me`})]}),!n&&(0,x.jsxs)(`div`,{className:`relative`,children:[(0,x.jsx)(`input`,{className:`input`,placeholder:e.members.length===0?q(`名前を打って Enter で登録`):q(`名前で検索して Enter で割り当て`),value:_,onChange:e=>v(e.target.value),onKeyDown:e=>{if(e.key===`Escape`){v(``);return}if(e.key!==`Enter`)return;let n=w[0];if(n){C.assigneeIds.includes(n.id)||P(n.id),v(``);return}let i=_.trim();i&&(r(e=>{let n=zp(e,i,sD[e.members.length%sD.length]);return wp(n.project,t,{assigneeIds:[...n.project.blocks[t].assigneeIds,n.memberId]})}),v(``))}}),_.trim()&&(0,x.jsxs)(`div`,{className:`card absolute left-0 right-0 mt-1 p-1 flex flex-col z-30`,style:{maxHeight:220,overflow:`auto`},children:[w.map(e=>(0,x.jsxs)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onMouseDown:e=>e.preventDefault(),onClick:()=>{C.assigneeIds.includes(e.id)||P(e.id),v(``)},children:[(0,x.jsx)(`span`,{className:`avatar`,style:{background:e.color,width:16,height:16,fontSize:9,marginRight:6},children:e.name.slice(0,1)}),e.name]},e.id)),w.length===0&&(0,x.jsx)(`div`,{className:`text-[12px] p-1`,style:{color:`var(--text-muted)`},children:q(`見つかりません。Enter で「{name}」を登録して割り当て`,{name:_.trim()})})]})]})]}),b===`dates`&&(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsx)(`div`,{className:`sec__head`,children:(0,x.jsx)(`span`,{className:`label`,children:`Schedule`})}),(0,x.jsxs)(`div`,{className:`grid grid-cols-2 gap-x-3 gap-y-1 text-[12px]`,children:[(0,x.jsxs)(`label`,{className:`flex items-center gap-2 col-span-2`,children:[(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`,minWidth:32},children:q(`開始`)}),(0,x.jsx)(jE,{value:C.startDate??``,disabled:n,onChange:e=>r(n=>bm(n,t,{startDate:e||null},`human`))})]}),(0,x.jsxs)(`label`,{className:`flex items-center gap-2 col-span-2`,children:[(0,x.jsx)(`span`,{style:{color:xm(C)?`var(--danger)`:`var(--text-muted)`,minWidth:32},children:q(`期日`)}),(0,x.jsx)(jE,{value:C.dueDate??``,disabled:n,danger:xm(C),onChange:e=>r(n=>bm(n,t,{dueDate:e||null},`human`))})]}),(0,x.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`,minWidth:32},children:q(`見積`)}),(0,x.jsx)(`input`,{type:`number`,min:0,step:.5,className:`input input-plain`,placeholder:`h`,value:C.estimateHours??``,disabled:n,onChange:e=>r(n=>bm(n,t,{estimateHours:e.target.value===``?null:Number(e.target.value)},`human`))}),(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`},children:`h`})]}),(0,x.jsxs)(`label`,{className:`flex items-center gap-2`,children:[(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`,minWidth:32},children:q(`実績`)}),(0,x.jsx)(`input`,{type:`number`,min:0,step:.5,className:`input input-plain`,placeholder:`h`,value:C.actualHours??``,disabled:n,onChange:e=>r(n=>bm(n,t,{actualHours:e.target.value===``?null:Number(e.target.value)},`human`))}),(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`},children:`h`})]})]}),C.dueDate&&C.status!==`white`&&(()=>{let e=Sm(C);return e===null?null:(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:e<0?`var(--danger)`:`var(--text-muted)`},children:e<0?q(`期日を {d} 日過ぎています`,{d:-e}):e===0?q(`期日は今日です`):q(`期日まであと {d} 日`,{d:e})})})()]}),b===`io`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(OE,{project:e,blockId:t,direction:`in`,readonly:n,title:`Inputs`}),(0,x.jsx)(OE,{project:e,blockId:t,direction:`out`,readonly:n,title:`Outputs`,allowAdd:jp(e,t)})]}),b===`more`&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsx)(`div`,{className:`sec__head`,children:(0,x.jsx)(`span`,{className:`label`,children:`Issue`})}),(0,x.jsx)(`input`,{className:`input`,placeholder:q(`JIRA / Redmine / GitHub Issue の URL`),value:C.issue??``,disabled:n,onChange:e=>r(n=>wp(n,t,{issue:e.target.value}),{history:!1}),onBlur:e=>r(n=>wp(n,t,{issue:e.target.value.trim()||void 0}))}),C.issue&&(0,x.jsx)(`a`,{className:`text-[12px] underline`,href:C.issue,target:`_blank`,rel:`noreferrer`,style:{color:`var(--primary-strong)`},children:q(`開く: {key}`,{key:Gm(C.issue)})})]}),(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsxs)(`div`,{className:`sec__head`,children:[(0,x.jsx)(`span`,{className:`label`,children:`AI`}),(0,x.jsxs)(`button`,{className:`btn btn-sm`,"data-on":s,onClick:()=>c(!s),title:q(`このボックスの入出力と位置づけを Markdown にしてコピーして AI に渡す`),children:[`Copy for AI `,s?`▴`:`▾`]})]}),s&&(0,x.jsxs)(`div`,{className:`flex flex-col pl-2`,style:{borderLeft:`3px solid var(--line-soft)`},children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>ee(`plan`),children:q(`手順を提案してもらう (コピー)`)}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>ee(`decompose`),children:q(`分解案を JSON でもらう (コピー)`)}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>ee(`review`),children:q(`入出力の抜けを指摘してもらう (コピー)`)})]}),d&&(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`textarea`,{className:`input`,style:{minHeight:180,fontSize:12},readOnly:!0,value:aD(e,t,d)}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>f(null),children:`Close`})]})]}),(0,x.jsxs)(`section`,{className:`sec`,children:[(0,x.jsxs)(`div`,{className:`sec__head`,children:[(0,x.jsxs)(`span`,{className:`label`,children:[`Notes`,C.description||C.artifacts.length>0?` *`:``]}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>m(!p),children:p?`▴`:`▾`})]}),p&&(0,x.jsxs)(`div`,{className:`flex flex-col gap-2`,children:[C.description&&Rf(C,C.descriptionUpdatedAt,`older`)&&(0,x.jsx)(`p`,{className:`text-[11px]`,children:Rf(C,C.descriptionUpdatedAt,`older`)}),(0,x.jsx)(AE,{multiline:!0,className:`input`,placeholder:q(`メモ (入力から出力をどう作るか)`),value:C.description,disabled:n,onCommit:e=>r(n=>wp(n,t,{description:e}))}),(0,x.jsx)(DE,{artifacts:C.artifacts,readonly:n,addLabel:`Link`,onChange:e=>r(n=>wp(n,t,{artifacts:e}))})]})]})]})]})}function yD({project:e,edgeId:t}){Nw();let n=$(e=>e.viewScope),r=$(e=>e.setViewScope),i=(0,y.useMemo)(()=>Km(e,t),[e,t]);return i.length<2?null:(0,x.jsxs)(`div`,{className:`flex flex-col gap-1`,children:[(0,x.jsx)(`div`,{className:`text-[11px] font-bold`,style:{color:`var(--text-muted)`},children:`Tabs`}),(0,x.jsx)(`div`,{className:`flex flex-wrap gap-1`,children:i.map(t=>(0,x.jsx)(`button`,{className:`chip`,"data-on":n===t,onClick:()=>r(t),title:t?q(`{title} のタブでこの線の続きを見る`,{title:e.blocks[t]?.title??``}):q(`All でこの線を見る`),children:t?e.blocks[t]?.title??`?`:`All`},t??`all`))})]})}function bD({project:e,edgeId:t}){Nw();let n=$(e=>e.readonly),r=$(e=>e.apply),i=$(e=>e.select),a=e.edges[t],o=e.ports[a.from.portId],s=e.ports[a.to.portId],c=t=>t===`root`?q(`プロジェクト`):e.blocks[t]?.title??`?`;return(0,x.jsxs)(`div`,{className:`flex flex-col gap-3 p-3`,children:[(0,x.jsx)(mD,{title:q(`配線`)}),(0,x.jsx)(`div`,{className:`wire-state`,"data-ready":qp(e,a),children:qp(e,a)?q(`確定済み`):q(`入力待ち`)}),(0,x.jsx)(`p`,{className:`wire-reason`,children:qp(e,a)?q(`供給元の完了・成果物、または上流の入力を確認できています。`):q(`供給元が未完了で成果物がない、または上流の入力がまだ確定していません。`)}),(0,x.jsxs)(`div`,{className:`text-[13px]`,children:[(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`b`,{children:c(o.blockId)}),q(`「{name}」`,{name:o.name})]}),(0,x.jsx)(`div`,{className:`my-1`,style:{color:`var(--text-muted)`},children:`↓`}),(0,x.jsxs)(`div`,{children:[(0,x.jsx)(`b`,{children:c(s.blockId)}),q(`「{name}」`,{name:s.name})]})]}),(0,x.jsx)(yD,{project:e,edgeId:t}),a.auto?(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:`var(--text-muted)`},children:q(`自動の線。手動でつなぐと置き換わります。`)}):!n&&(0,x.jsx)(`button`,{className:`btn btn-sm self-start`,onClick:()=>{i({}),r(e=>Rp(e,t))},children:q(`接続を外す`)})]})}var xD=e=>e===void 0?q(`削除済み`):typeof e==`string`?e||q(`空欄`):e&&typeof e==`object`&&`note`in e&&`actor`in e&&`at`in e?`${e.note}\n\n${e.actor} · ${e.at}`:JSON.stringify(e,null,2);function SD({onClose:e}){let{project:t,conflict:n,previewConflict:r,resolveConflict:i,saveError:a}=$(),[o,s]=(0,y.useState)({}),c=(0,y.useRef)(null),l=r();(0,y.useEffect)(()=>{let e=c.current,t=document.activeElement;return e.showModal(),()=>{e.close(),t?.focus()}},[]),(0,y.useEffect)(()=>{s({})},[n?.revision,n?.text]);let u=l?.conflicts??[],d=u.filter(e=>!e.automatic&&!o[e.id]).length,f=e=>{let[n,r,i]=e.segments,a=n===`blocks`||n===`handoffs`?t?.blocks[r]:void 0,o={title:q(`題名`),name:q(`名前`),description:q(`説明`),note:q(`引き継ぎメモ`),decisions:q(`判断と回答`),status:`Status`,artifacts:q(`成果物`),position:q(`位置`),category:`Category`,progress:q(`進捗`)};return a?`${a.key} ${a.title} · ${n===`handoffs`?q(`引き継ぎメモ`):i?o[i]??i:q(`タスク全体`)}`:o[e.path]??e.path};return(0,x.jsxs)(`dialog`,{ref:c,className:`conflict-dialog`,"aria-labelledby":`conflict-title`,onCancel:e,children:[(0,x.jsxs)(`div`,{className:`conflict-dialog__head`,children:[(0,x.jsx)(`h2`,{id:`conflict-title`,className:`font-head`,children:q(`競合する変更を比較`)}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:e,"aria-label":q(`閉じる (Esc)`),children:`×`})]}),(0,x.jsxs)(`div`,{className:`conflict-dialog__body`,children:[(0,x.jsx)(`p`,{children:q(`別の項目の変更は両方残ります。同じ項目を変更した箇所だけ、残す内容を選んでください。`)}),u.length===0&&(0,x.jsx)(`p`,{children:q(`別の項目の変更です。統合できます。`)}),u.map(e=>(0,x.jsxs)(`fieldset`,{className:`conflict-item`,children:[(0,x.jsx)(`legend`,{children:f(e)}),e.automatic?(0,x.jsxs)(`p`,{children:[q(`番号の重複は自動で解消します。`),`: `,xD(e.theirs)]}):(0,x.jsx)(`div`,{className:`conflict-columns`,children:[`ours`,`theirs`].map(t=>(0,x.jsxs)(`label`,{className:`conflict-choice`,"data-selected":o[e.id]===t,children:[(0,x.jsxs)(`span`,{children:[(0,x.jsx)(`input`,{type:`radio`,name:e.id,checked:o[e.id]===t,onChange:()=>s(n=>({...n,[e.id]:t}))}),` `,q(t===`ours`?`手元の編集`:`最新のファイル`)]}),(0,x.jsx)(`pre`,{children:xD(e[t])})]},t))})]},e.id)),a&&(0,x.jsx)(`p`,{className:`text-[12px]`,role:`status`,children:a})]}),(0,x.jsxs)(`div`,{className:`conflict-dialog__foot`,children:[(0,x.jsx)(`span`,{"aria-live":`polite`,children:q(`未選択: {n}`,{n:d})}),(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:e,children:q(`あとで選ぶ`)}),(0,x.jsx)(`button`,{className:`btn btn-primary btn-sm`,disabled:d>0||!n,onClick:()=>{i(`merge`,o,n?.revision)&&e()},children:q(`選択した内容で統合`)})]})]})}function CD(){let{project:e,source:t,saveError:n,conflict:r,resolveConflict:i,previewConflict:a,saveNow:o,readonlyReason:s}=$(),[c,l]=(0,y.useState)(!1);if(!e||!n&&t!==`file`&&!s)return null;let u=a()?.conflicts.filter(e=>!e.automatic).length??0;return(0,x.jsxs)(`div`,{className:`save-notice`,role:n?`alert`:`status`,children:[(0,x.jsx)(`span`,{children:n??s??q(`このファイルは閲覧専用です。共同編集は npx boxglow serve --open または VS Code 拡張で開いてください。`)}),n&&(0,x.jsxs)(`div`,{className:`flex flex-wrap gap-2 mt-2`,children:[(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:()=>IE(`boxglow-unsaved.json`,Zp(e),`application/json`),children:q(`手元の編集を JSON で退避`)}),r?(0,x.jsxs)(x.Fragment,{children:[u>0?(0,x.jsxs)(`button`,{className:`btn btn-primary btn-sm`,onClick:()=>l(!0),children:[q(`変更を比較して選ぶ`),` (`,u,`)`]}):(0,x.jsx)(`button`,{className:`btn btn-primary btn-sm`,onClick:()=>i(`merge`),children:q(`両方の変更を統合`)}),(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:()=>{IE(`boxglow-unsaved.json`,Zp(e),`application/json`),i(`remote`)},children:q(`手元を退避して最新のファイルを開く`)})]}):(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:o,children:q(`保存を再試行`)})]}),c&&r&&(0,x.jsx)(SD,{onClose:()=>l(!1)})]})}var wD=`0.5.2`;function TD(){let e=$(e=>e.peerVersion),t=$(e=>e.source);return(0,x.jsxs)(`details`,{className:`version-info`,children:[(0,x.jsxs)(`summary`,{title:q(`バージョンと接続先`),children:[`v`,wD]}),(0,x.jsxs)(`div`,{className:`card version-info__content`,children:[(0,x.jsx)(`b`,{children:q(`バージョンと接続先`)}),(0,x.jsxs)(`dl`,{children:[(0,x.jsx)(`dt`,{children:`GUI`}),(0,x.jsx)(`dd`,{children:wD}),(0,x.jsx)(`dt`,{children:q(`保存先`)}),(0,x.jsx)(`dd`,{children:t===`serve`?`CLI server`:t===`vscode`?`VS Code`:q(t===`file`?`閲覧専用ファイル`:`ブラウザ内`)}),e&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`dt`,{children:t===`vscode`?`Extension`:`CLI`}),(0,x.jsx)(`dd`,{children:e.extension??e.app??q(`取得できません`)}),(0,x.jsx)(`dt`,{children:q(`接続先のアプリ`)}),(0,x.jsx)(`dd`,{children:e.app??q(`取得できません`)}),(0,x.jsx)(`dt`,{children:q(`保存方式`)}),(0,x.jsxs)(`dd`,{children:[`GUI `,1,` / `,q(`接続先`),` `,e.protocol??`?`]})]}),(0,x.jsx)(`dt`,{children:`Build (JST)`}),(0,x.jsx)(`dd`,{children:`2026-10-05 23:04`})]}),e&&(e.protocol!==1||e.app!==wD)&&(0,x.jsx)(`p`,{role:`status`,children:q(`接続先と画面のバージョンが異なるか、確認できません。CLI・拡張を更新し、画面を再読み込みしてください。`)})]})]})}function ED({project:e,onToggleDrawer:t,onHelp:n}){let r=Nw(),i=$(e=>e.readonly),a=$(e=>e.ephemeral),o=$(e=>e.saveState),s=$(e=>e.apply),c=$(e=>e.undo),l=$(e=>e.redo),u=$(e=>e.past.length),d=$(e=>e.future.length),f=$(e=>e.select),p=$(e=>e.focusBlock),m=$(e=>e.selection),h=$(e=>e.closeProject),g=$(e=>e.importJSON),_=$(e=>e.copyToMine),v=$(e=>e.setToast),[b,S]=(0,y.useState)(()=>document.documentElement.dataset.theme||NE());(0,y.useEffect)(()=>{let e=new MutationObserver(()=>S(document.documentElement.dataset.theme||NE()));return e.observe(document.documentElement,{attributes:!0,attributeFilter:[`data-theme`]}),()=>e.disconnect()},[]);let[C,w]=(0,y.useState)(!1),[T,E]=(0,y.useState)(``),[D,O]=(0,y.useState)(!1),k=(0,y.useRef)(null),A=T.trim()?Cm(e,T,12):[],j=e=>{f({blockId:e}),p(e),E(``),O(!1)};(0,y.useEffect)(()=>{let e=e=>{if(document.querySelector(`dialog[open]`))return;let t=e.target;(!t||t.tagName!==`INPUT`&&t.tagName!==`TEXTAREA`)&&e.key===`/`&&!e.isComposing&&!t?.isContentEditable&&t?.tagName!==`SELECT`&&(e.preventDefault(),O(!0),setTimeout(()=>k.current?.focus(),0))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[]),(0,y.useEffect)(()=>{let e=()=>w(!1);return C&&window.addEventListener(`click`,e),()=>window.removeEventListener(`click`,e)},[C]);let M=()=>{let e=b===`dark`?`light`:`dark`;PE(e),S(e)},N=()=>{let e=prompt(q(`追加するプロジェクトの名前 (リポジトリごとに 1 つなど)`));e?.trim()&&s(t=>{let n=$f(t,e.trim());return setTimeout(()=>{f({blockId:n.blockId}),p(n.blockId)},0),n.project})},P=()=>s(e=>ih(ap(e))),F=()=>{let t=oT(e,m,$.getState().viewScope);s(e=>{let n=Cp(e,{parentId:t,title:q(`新しいブロック`)}),r=structuredClone(n.project);return r.blocks[t]&&(r.blocks[t].collapsed=!1),setTimeout(()=>{f({blockId:n.blockId}),p(n.blockId)},0),r})},ee=()=>IE(`${zE(e.name)}.boxglow.json`,Zp(e),`application/json`),I=()=>IE(`${zE(e.name)}.md`,iD(e),`text/markdown`),te=async()=>{v(await LE(oD(e,m.blockId??`root`))?q(`Mermaid をコピーしました`):q(`コピーできませんでした`))},ne=async()=>{let e=await RE(`.json,application/json`);if(e)try{await g(e)}catch(e){v(e instanceof Error?e.message:String(e))}},L=$(e=>e.fileName),re=$(e=>e.editMode),ie=$(e=>e.setEditMode),ae=$(e=>e.saveNow),oe=$(e=>e.source),se=$(e=>e.reload),ce=$(e=>e.reloading),le=i?`Read only`:a?`Sample (not saved)`:o===`saving`?`Saving…`:o===`unsaved`?`Unsaved`:`Saved`,ue=i?q(`閲覧専用`):a?q(`サンプルは保存されません。Save で自分のプロジェクトとして保存`):L?q(`{file} に自動で保存します (変更後)。Save で今すぐ書きます`,{file:L}):q(`このブラウザに自動で保存します`),de=pm(e),fe=de.working.length;return(0,x.jsxs)(`header`,{className:`topbar`,"data-editing":re,children:[(0,x.jsxs)(`div`,{className:`topbar-identity`,children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:t,title:q(`階層 / 絞り込み / メンバー / 部品`),children:`☰`}),oe!==`vscode`&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:h,title:q(`Home (プロジェクト一覧へ)`),"aria-label":`Home`,children:(0,x.jsxs)(`svg`,{width:`18`,height:`18`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2.2`,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":`true`,children:[(0,x.jsx)(`path`,{d:`M3 11.5 12 4l9 7.5`}),(0,x.jsx)(`path`,{d:`M5.5 10.5V20h13v-9.5`}),(0,x.jsx)(`path`,{d:`M10 20v-5h4v5`})]})}),(0,x.jsx)(`button`,{className:`project-name`,onClick:()=>f({project:!0}),title:e.name,children:e.name}),(0,x.jsxs)(`span`,{className:`save-chip ${o===`unsaved`?`unsaved`:``}`,title:ue,children:[!a&&(0,x.jsx)(`span`,{className:`save-chip__file`,children:L??q(`ブラウザ内`)}),(0,x.jsx)(`span`,{children:le})]}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:()=>void se(),disabled:ce,title:q(oe===`idb`?`最新の内容を読み込む`:`最新の内容を読み込む (ファイルを今すぐ読み直す)`),"aria-label":`Reload`,children:(0,x.jsxs)(`svg`,{className:ce?`spin`:void 0,width:`16`,height:`16`,viewBox:`0 0 24 24`,fill:`none`,stroke:`currentColor`,strokeWidth:`2.2`,strokeLinecap:`round`,strokeLinejoin:`round`,"aria-hidden":`true`,children:[(0,x.jsx)(`path`,{d:`M20 12a8 8 0 1 1-2.6-5.9`}),(0,x.jsx)(`path`,{d:`M20 4v5h-5`})]})}),a&&!i&&(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:_,title:q(`自分のプロジェクトとして保存`),children:`Save`}),!a&&!i&&(0,x.jsx)(`button`,{className:`btn btn-sm`,onClick:ae,disabled:o===`saved`||o===`saving`,title:ue,children:`Save`})]}),(0,x.jsxs)(`div`,{className:`topbar-tools`,children:[(0,x.jsxs)(`button`,{className:`summary-chip`,"data-on":m.timeline,onClick:()=>f({timeline:!m.timeline}),title:q(`今の状況 (作業中・判断待ち・ログ)`),children:[fe>0&&(0,x.jsx)(`span`,{className:`dot`}),fe>0&&(0,x.jsxs)(`span`,{children:[(0,x.jsxs)(`span`,{className:`summary-chip__txt`,children:[q(`作業中`),` `]}),fe]}),de.blocked.length>0&&(0,x.jsxs)(`span`,{children:[(0,x.jsxs)(`span`,{className:`summary-chip__txt`,children:[q(`詰まり・確認待ち`),` `]}),de.blocked.length]}),de.decisions.length>0&&(0,x.jsxs)(`span`,{className:`summary-decision`,children:[(0,x.jsxs)(`span`,{className:`summary-chip__txt`,children:[q(`判断待ち`),` `]}),de.decisions.length]}),de.answered.length>0&&(0,x.jsxs)(`span`,{children:[(0,x.jsxs)(`span`,{className:`summary-chip__txt`,children:[q(`回答済み`),` `]}),de.answered.length]}),fe===0&&de.blocked.length===0&&de.decisions.length===0&&de.answered.length===0&&(0,x.jsx)(`span`,{children:`Activity`})]}),!i&&(0,x.jsxs)(`button`,{className:`mode-toggle`,"data-on":re,onClick:()=>ie(!re),title:q(re?`Edit モード: ドラッグで移動・結線・階層移動ができます。押すと View (閲覧) に`:`View モード: ドラッグでの編集は効きません。押すと Edit に`),children:[(0,x.jsx)(`span`,{className:`mode-toggle__knob`}),(0,x.jsx)(`span`,{children:re?`Edit`:`View`})]}),(0,x.jsxs)(`div`,{className:`relative topbar-search`,children:[(0,x.jsx)(`input`,{"aria-label":q(`ブロックを検索`),ref:k,className:`input search-box`,placeholder:q(`Search ID / 題名`),value:T,onChange:e=>{E(e.target.value),O(!0)},onFocus:()=>O(!0),onKeyDown:e=>{e.key===`Enter`&&!e.nativeEvent.isComposing&&A[0]&&j(A[0].id),e.key===`Escape`&&(O(!1),E(``),e.target.blur())},onBlur:()=>setTimeout(()=>O(!1),150)}),D&&T.trim()&&A.length>0&&(0,x.jsx)(`div`,{className:`card absolute right-0 mt-1 p-1 flex flex-col z-30`,style:{width:`min(320px, calc(100vw - 32px))`,maxHeight:320,overflow:`auto`},children:A.map(e=>(0,x.jsxs)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onMouseDown:e=>e.preventDefault(),onClick:()=>j(e.id),children:[(0,x.jsx)(`span`,{className:`chip`,style:{fontFamily:`ui-monospace, monospace`,marginRight:6},children:e.key}),(0,x.jsx)(`span`,{className:`truncate`,children:e.title})]},e.id))}),D&&T.trim()&&A.length===0&&(0,x.jsx)(`div`,{className:`card absolute right-0 mt-1 p-2 text-[12px] z-30`,style:{minWidth:200,color:`var(--text-muted)`},children:q(`見つかりません`)})]}),!i&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{className:`btn btn-primary btn-sm desktop-action`,onClick:F,title:q(`ブロックを追加 (N)。ボックスを選んでいればその中に、選んでいなければプロジェクトの中に`),children:`+ Block`}),(0,x.jsx)(`button`,{className:`btn btn-sm desktop-action layout-action`,onClick:P,title:q(`Auto Layout: 依存関係で並べ直す (大項目は畳んだ前提)`),children:`Auto Layout`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm desktop-action`,onClick:c,disabled:u===0,title:q(`元に戻す (Ctrl+Z)`),"aria-label":`Undo`,children:`↶`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm desktop-action`,onClick:l,disabled:d===0,title:q(`やり直す (Ctrl+Y)`),"aria-label":`Redo`,children:`↷`})]}),(0,x.jsxs)(`div`,{className:`relative`,children:[(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:e=>{e.stopPropagation(),w(!C)},title:`Menu`,"aria-expanded":C,onKeyDown:e=>{e.key===`Escape`&&w(!1)},children:`⋯`}),C&&(0,x.jsxs)(`div`,{className:`card absolute right-0 mt-1 p-1 flex flex-col z-30`,style:{minWidth:220,maxHeight:`min(480px, 65dvh)`,overflowY:`auto`},children:[!i&&(0,x.jsxs)(`div`,{className:`menu-actions`,children:[(0,x.jsx)(`button`,{className:`btn btn-primary btn-sm`,onClick:F,children:`+ Block`}),(0,x.jsx)(`button`,{className:`btn btn-sm layout-action`,onClick:P,children:`Auto Layout`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:c,disabled:u===0,children:`Undo`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:l,disabled:d===0,children:`Redo`})]}),!i&&(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:N,title:q(`同じファイルにプロジェクトのボックスを足す`),children:`New Project`}),!i&&(0,x.jsx)(`div`,{style:{borderTop:`1px solid var(--line-soft)`,margin:`4px 0`}}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:ee,children:`Export JSON`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:I,children:`Export Markdown`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:te,children:`Copy Mermaid`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:ne,children:`Import JSON`}),(0,x.jsx)(`div`,{style:{borderTop:`1px solid var(--line-soft)`,margin:`4px 0`}}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:n,children:`Help`}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:h,children:`Home`}),(0,x.jsx)(`div`,{style:{borderTop:`1px solid var(--line-soft)`,margin:`4px 0`}}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm justify-start`,onClick:()=>jf(r===`en`?`ja`:`en`),title:q(`画面の文言の言語を切り替える`),children:r===`en`?`日本語`:`English`})]})]}),(0,x.jsx)(`button`,{className:`btn btn-ghost btn-sm`,onClick:M,title:b===`dark`?`Light mode`:`Dark mode`,children:b===`dark`?`☀`:`☾`})]})]})}var DD=240;function OD({project:e,majors:t,scope:n,onSelect:r,marked:i}){Nw();let a=(0,y.useRef)(null),[o,s]=(0,y.useState)(!1),[c,l]=(0,y.useState)(!1),[u,d]=(0,y.useState)(!1),f=()=>{let e=a.current;e&&(s(e.scrollLeft>1),l(e.scrollLeft+e.clientWidth<e.scrollWidth-1))};(0,y.useEffect)(()=>{f();let e=a.current;if(!e)return;let t=new ResizeObserver(f);return t.observe(e),()=>t.disconnect()},[t.length]),(0,y.useEffect)(()=>{(a.current?.querySelector(`.canvas-tab[data-on="true"]`))?.scrollIntoView({inline:`nearest`,block:`nearest`}),setTimeout(f,0)},[n]),(0,y.useEffect)(()=>{if(!u)return;let e=e=>{e.target.closest?.(`.tab-list, .tab-list-btn`)||d(!1)},t=e=>{e.key===`Escape`&&d(!1)};return window.addEventListener(`mousedown`,e),window.addEventListener(`keydown`,t),()=>{window.removeEventListener(`mousedown`,e),window.removeEventListener(`keydown`,t)}},[u]);let p=e=>a.current?.scrollBy({left:e,behavior:`smooth`}),m=e=>{r(e),d(!1)};return(0,x.jsxs)(`div`,{className:`canvas-tabs`,role:`tablist`,children:[(0,x.jsxs)(`div`,{className:`tab-nav`,children:[(0,x.jsx)(`button`,{className:`tab-nav-btn tab-list-btn`,"data-on":u,onClick:()=>d(e=>!e),title:q(`タブの一覧 (押して選ぶ)`),children:`≡`}),(0,x.jsx)(`button`,{className:`tab-nav-btn`,disabled:!o,onClick:()=>p(-240),title:q(`左へ`),children:`◀`}),(0,x.jsx)(`button`,{className:`tab-nav-btn`,disabled:!c,onClick:()=>p(DD),title:q(`右へ`),children:`▶`})]}),(0,x.jsxs)(`div`,{className:`tab-strip`,ref:a,onScroll:f,children:[(0,x.jsx)(`button`,{className:`canvas-tab`,role:`tab`,"data-on":n===null,"data-marked":i?.has(null)||void 0,onClick:()=>m(null),title:q(`大項目の一覧を俯瞰する (中はそれぞれのタブで)`),children:`All`}),t.map(e=>(0,x.jsxs)(`button`,{className:`canvas-tab`,role:`tab`,"data-on":n===e.id,"data-marked":i?.has(e.id)||void 0,onClick:()=>m(e.id),title:i?.has(e.id)?q(`{title} (選んだ線の続きがある)`,{title:e.title}):q(`{title} の中を見る`,{title:e.title}),children:[(0,x.jsx)(PT,{status:e.status}),(0,x.jsx)(`span`,{className:`truncate`,children:e.title})]},e.id))]}),u&&(0,x.jsxs)(`div`,{className:`tab-list card`,role:`menu`,children:[(0,x.jsxs)(`button`,{className:`tab-list-row`,"data-on":n===null,onClick:()=>m(null),children:[(0,x.jsx)(`span`,{className:`tab-list-icon`,children:`⊞`}),(0,x.jsx)(`span`,{className:`truncate`,children:`All`})]}),t.map(t=>{let r=Up(e,t.id);return(0,x.jsxs)(`button`,{className:`tab-list-row`,"data-on":n===t.id,onClick:()=>m(t.id),title:t.title,children:[(0,x.jsx)(PT,{status:t.status}),(0,x.jsx)(`span`,{className:`truncate`,children:t.title}),(0,x.jsx)(`span`,{className:`tab-list-prog`,children:r.total>0?`${r.percent}%`:``})]},t.id)})]})]})}function kD(e,t,n,r){try{let i=Number(localStorage.getItem(e));return Number.isFinite(i)&&i>=n&&i<=r?i:t}catch{return t}}function AD(e,t){try{localStorage.setItem(e,String(t))}catch{}}var jD={min:260,max:760,def:320},MD={min:220,max:640,def:280};function ND(){Nw();let e=$(e=>e.project),t=cT(),n=$(e=>e.embed),r=$(e=>e.readonly),i=$(e=>e.toast),a=$(e=>e.setToast),o=$(e=>e.selection),s=$(e=>e.select),c=$(e=>e.focusBlock),l=$(e=>e.apply),u=$(e=>e.undo),d=$(e=>e.redo),f=$(e=>e.setMode),p=$(e=>e.openSample),m=$(e=>e.openExample),h=$(e=>e.openProject),g=$(e=>e.openFromServer),_=$(e=>e.openFromVsCode),v=$(e=>e.viewScope),b=$(e=>e.setViewScope),[S,C]=(0,y.useState)(!1),[w,T]=(0,y.useState)(()=>kD(`boxglow:rightW`,jD.def,jD.min,jD.max)),[E,D]=(0,y.useState)(()=>kD(`boxglow:drawerW`,MD.def,MD.min,MD.max)),O=(0,y.useCallback)(e=>{T(e),AD(`boxglow:rightW`,e)},[]),k=(0,y.useCallback)(e=>{D(e),AD(`boxglow:drawerW`,e)},[]),[A,j]=(0,y.useState)(!1),[M,N]=(0,y.useState)({...lD,statuses:new Set(lD.statuses)});(0,y.useEffect)(()=>{let e=new URLSearchParams(window.location.search),t=e.get(`view`)===`article`,n=t||e.get(`embed`)===`1`;f({embed:n,readonly:t||e.get(`readonly`)===`1`});let r=e.get(`theme`);(r===`dark`||r===`light`)&&PE(r,!1);let i=null;if(n&&window.parent!==window)try{let e=window.parent.document.documentElement,t=()=>{let t=e.dataset.theme;(t===`dark`||t===`light`)&&PE(t,!1)};t(),i=new MutationObserver(t),i.observe(e,{attributes:!0,attributeFilter:[`data-theme`]})}catch{}if(window.acquireVsCodeApi){let e=()=>PE(document.body.classList.contains(`vscode-dark`)||document.body.classList.contains(`vscode-high-contrast`)?`dark`:`light`,!1);e(),i=new MutationObserver(e),i.observe(document.body,{attributes:!0,attributeFilter:[`class`]}),_()}else if(e.get(`demo`)===`daw`)m();else if(t||e.get(`demo`)===`1`){if(p(),t){let e=$.getState(),t=Object.values(e.project?.blocks??{}),n=t.find(e=>e.kind===`task`&&t.some(t=>t.parentId===e.id));n&&e.setViewScope(n.id)}}else if(e.get(`serve`)===`1`)g();else{let e=window.location.hash.match(/p=([\w-]+)/);e&&h(e[1])}return()=>i?.disconnect()},[f,p,m,h,g,_]),(0,y.useEffect)(()=>{let e=e=>{let t=$.getState();!t.ephemeral&&[`saving`,`unsaved`].includes(t.saveState)&&(e.preventDefault(),e.returnValue=``)};return window.addEventListener(`beforeunload`,e),()=>window.removeEventListener(`beforeunload`,e)},[]),(0,y.useEffect)(()=>{if(!i)return;let e=setTimeout(()=>a(null),3200);return()=>clearTimeout(e)},[i,a]),(0,y.useEffect)(()=>{let e=e=>{if(document.querySelector(`dialog[open]`)||e.isComposing)return;let t=e.target;if(t&&(t.tagName===`INPUT`||t.tagName===`TEXTAREA`||t.tagName===`SELECT`||t.isContentEditable))return;let n=$.getState().project;if(!n)return;let i=$.getState().selection;if((e.ctrlKey||e.metaKey)&&e.key.toLowerCase()===`z`)e.preventDefault(),e.shiftKey?d():u();else if((e.ctrlKey||e.metaKey)&&e.key.toLowerCase()===`y`)e.preventDefault(),d();else if(e.key===`Delete`||e.key===`Backspace`){if(r||!$.getState().editMode)return;if(i.edgeId){let e=n.edges[i.edgeId];e&&!e.auto&&(s({}),l(e=>Rp(e,i.edgeId)))}else if(i.blockId){let e=n.blocks[i.blockId],t=Object.values(n.blocks).filter(e=>e.parentId===i.blockId).length;e&&(t===0||confirm(q(`「{title}」と下の階層のブロックを削除します。よろしいですか?`,{title:e.title})))&&(s({}),l(e=>Dp(e,i.blockId)))}}else if(e.key.toLowerCase()===`n`&&!e.ctrlKey&&!e.metaKey){if(r)return;let e=oT(n,i,$.getState().viewScope);l(t=>{let n=Cp(t,{parentId:e,title:q(`新しいブロック`)}),r=structuredClone(n.project);return r.blocks[e]&&(r.blocks[e].collapsed=!1),setTimeout(()=>{s({blockId:n.blockId}),c(n.blockId)},0),r})}else e.key===`Escape`&&(s({}),j(!1))};return window.addEventListener(`keydown`,e),()=>window.removeEventListener(`keydown`,e)},[l,u,d,s,r,c]);let P=(0,y.useMemo)(()=>!e||dD(M)?null:t=>uD(e,t,M),[e,M]),F=(0,y.useCallback)(()=>C(e=>!e),[]),ee=(0,y.useCallback)(()=>C(!0),[]),I=e?Up(e,Wf):null,te=(0,y.useMemo)(()=>{let e=new URL(window.location.href);return e.searchParams.delete(`embed`),e.searchParams.delete(`readonly`),e.searchParams.delete(`view`),e.searchParams.set(`demo`,e.searchParams.get(`demo`)===`daw`?`daw`:`1`),e.toString()},[]),ne=!!e&&!n&&(o.blockId!==null||o.edgeId!==null||o.terminal!==null||o.project||o.timeline),L=[`app-grid`,n?`embed`:``,ne?``:`no-right`].filter(Boolean).join(` `),re=(0,y.useMemo)(()=>e?np(e):[],[e]),ie=(0,y.useMemo)(()=>e&&o.edgeId&&e.edges[o.edgeId]?new Set(Km(e,o.edgeId)):void 0,[e,o.edgeId]),ae=!!e&&re.length>0,oe=v&&e?.blocks[v]?v:null,se=(0,y.useMemo)(()=>e&&oe?sp(e,oe):[],[e,oe]),ce=se[0]?.id??null;return(0,x.jsxs)(`div`,{className:L,style:{"--right-w":`${w}px`},children:[(0,x.jsxs)(`div`,{className:`app-top`,children:[e&&!n&&(0,x.jsx)(ED,{project:e,onToggleDrawer:F,onHelp:()=>j(!0)}),e&&!n&&(0,x.jsx)(CD,{})]}),(0,x.jsxs)(`main`,{className:`app-main relative min-w-0 min-h-0`,children:[(0,x.jsxs)(`div`,{className:`canvas-wrap`,children:[e&&(0,x.jsx)(yd,{children:(0,x.jsx)(EE,{project:t??e,matcher:P})}),e&&S&&!n&&(0,x.jsx)(pD,{project:t??e,filter:M,onFilter:N,onClose:()=>C(!1),width:E}),e&&S&&!n&&(0,x.jsx)(kE,{side:`right`,width:E,min:MD.min,max:MD.max,onWidth:k,style:{left:8+E-5,top:8,bottom:8}}),e&&(se.length>0||!n&&!dD(M))&&(0,x.jsxs)(`div`,{className:`scope-path`,style:{left:S&&!n?8+E+8:8},children:[se.length>0&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsx)(`button`,{className:`scope-crumb`,onClick:()=>b(null),title:q(`大項目の一覧へ`),children:`All`}),se.map((e,t)=>(0,x.jsxs)(`span`,{className:`contents`,children:[(0,x.jsx)(`span`,{className:`scope-sep`,children:`›`}),t===se.length-1?(0,x.jsx)(`span`,{className:`scope-crumb current`,title:e.title,children:e.title}):(0,x.jsx)(`button`,{className:`scope-crumb`,onClick:()=>b(e.id),title:q(`{title} へ戻る`,{title:e.title}),children:e.title})]},e.id))]}),!n&&!dD(M)&&(0,x.jsx)(`button`,{className:`chip`,"data-on":`true`,onClick:()=>N({...lD,statuses:new Set(lD.statuses)}),title:q(`絞り込みを解除`),children:`Filtered ×`})]}),n&&(0,x.jsx)(`a`,{className:`btn btn-accent absolute top-2 right-2 z-10`,href:te,target:`_blank`,rel:`noopener noreferrer`,children:`Open full ↗`}),n&&se.length===0&&(0,x.jsx)(`span`,{className:`absolute top-2 left-2 z-10 font-head text-[14px] px-2 py-1 rounded-lg`,style:{background:`var(--bg-card)`,border:`2px solid var(--line)`},children:`Boxglow`})]}),ae&&(0,x.jsx)(OD,{project:e,majors:re,scope:ce,onSelect:b,marked:ie}),!e&&!n&&(0,x.jsx)(BE,{}),A&&(0,x.jsx)(`div`,{className:`modal-backdrop`,onClick:()=>j(!1),children:(0,x.jsxs)(`div`,{className:`card modal p-5 flex flex-col gap-2`,style:{width:420},onClick:e=>e.stopPropagation(),children:[(0,x.jsx)(`div`,{className:`font-head text-[16px]`,children:`Help`}),(0,x.jsx)(`table`,{className:`help-table`,children:(0,x.jsxs)(`tbody`,{children:[(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`ブロックを置く`)}),(0,x.jsxs)(`td`,{children:[(0,x.jsx)(`span`,{className:`kbd`,children:`N`}),` `,q(`または「+ Block」(選んだボックスの中に)`)]})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:`Edit / View`}),(0,x.jsx)(`td`,{children:q(`上の切替。Edit のときだけドラッグで移動・結線・階層移動と Del が効く`)})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`結線`)}),(0,x.jsx)(`td`,{children:q(`丸から相手の丸、または相手のボックスへドラッグ (近くで離せばつながる)`)})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`階層を移す`)}),(0,x.jsx)(`td`,{children:q(`ボックスをドラッグして別のボックスの中に落とす`)})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`下の階層を畳む / 展開`)}),(0,x.jsx)(`td`,{children:q(`ブロックをダブルクリック`)})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`削除`)}),(0,x.jsx)(`td`,{children:(0,x.jsx)(`span`,{className:`kbd`,children:`Del`})})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`元に戻す / やり直す`)}),(0,x.jsxs)(`td`,{children:[(0,x.jsx)(`span`,{className:`kbd`,children:`Ctrl+Z`}),` / `,(0,x.jsx)(`span`,{className:`kbd`,children:`Ctrl+Y`})]})]}),(0,x.jsxs)(`tr`,{children:[(0,x.jsx)(`td`,{children:q(`選択を解除`)}),(0,x.jsx)(`td`,{children:(0,x.jsx)(`span`,{className:`kbd`,children:`Esc`})})]})]})}),(0,x.jsx)(`div`,{className:`text-[12px]`,style:{color:`var(--text-muted)`},children:q(`ボックスは「入力から出力を作るタスク」。出力を先に決め、大きなボックスは「分解する」で中にボックスを置く。供給元の無い入力は左端の入力まで自動で点線が伸びる。`)}),(0,x.jsx)(`button`,{className:`btn btn-sm self-end`,onClick:()=>j(!1),children:`Close`})]})})]}),(0,x.jsxs)(`aside`,{className:`panel right ${ne?``:`hidden-panel`}`,children:[e&&ne&&(0,x.jsx)(kE,{side:`left`,width:w,min:jD.min,max:jD.max,onWidth:O}),e&&ne&&(0,x.jsx)(hD,{project:e,onOpenDrawer:ee})]}),(0,x.jsxs)(`footer`,{className:`app-footer flex items-center gap-3 px-3 text-[12px]`,style:{borderTop:`2px solid var(--line)`,background:`var(--bg-card)`},children:[e&&I&&(0,x.jsxs)(x.Fragment,{children:[(0,x.jsxs)(`span`,{className:`font-head`,children:[`Done `,I.white,` / `,I.total,` · `,I.percent,`%`]}),(0,x.jsx)(`div`,{className:`progress-bar`,style:{width:160},children:(0,x.jsx)(`span`,{style:{width:`${I.percent}%`}})}),n&&(0,x.jsx)(`a`,{className:`underline`,href:te,target:`_blank`,rel:`noopener noreferrer`,style:{color:`var(--primary-strong)`},children:q(`Boxglow で開く`)})]}),!e&&(0,x.jsx)(`span`,{style:{color:`var(--text-muted)`},children:`Boxglow`}),(0,x.jsx)(TD,{}),(0,x.jsxs)(`span`,{className:`build-stamp text-[10px]`,style:{color:`var(--text-muted)`},title:q(`ビルド日時 (日本時間)。古い場合は再読み込み (Ctrl+F5) してください`),children:[`build `,`2026-10-05 23:04`]})]}),i&&(0,x.jsx)(`div`,{className:`toast`,role:`status`,children:i})]})}FE(),window.boxglow={store:$},b.createRoot(document.getElementById(`root`)).render((0,x.jsx)(y.StrictMode,{children:(0,x.jsx)(ND,{})}));
package/dist/index.html CHANGED
@@ -27,7 +27,7 @@
27
27
  } catch (e) {}
28
28
  })();
29
29
  </script>
30
- <script type="module" crossorigin src="./assets/index-wmf5YkIk.js"></script>
30
+ <script type="module" crossorigin src="./assets/index-qzdNjZOL.js"></script>
31
31
  <link rel="stylesheet" crossorigin href="./assets/index-B0rLWujQ.css">
32
32
  </head>
33
33
  <body>
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "boxglow",
3
3
  "private": false,
4
- "version": "0.5.1",
4
+ "version": "0.5.2",
5
5
  "type": "module",
6
6
  "description": "See at a glance what your AI agents and your team are working on: tasks as input/output boxes that go from BlackBox to WhiteBox. Web app + CLI, one boxglow.json in your repo.",
7
7
  "scripts": {