@ehfuse/outliner 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,14 +1,14 @@
1
1
  /**
2
- * Formatting toolbar — font size · bold · underline · strike · text color · background, plus undo / redo.
3
- * Shared by the outline and the mind map; it edits the style of the selected node(s).
2
+ * Formatting toolbar — font size · bold · underline · strike · text color · background · clear format, plus undo / redo.
3
+ * Shared by the outline and the mind map; it edits the style of the selected node.
4
+ * Looks like the @ehfuse/editor toolbar on purpose: same icons (@ehfuse/toolbar-icons), same 32px buttons,
5
+ * same black tooltip and the same color picker (@ehfuse/mui-color-picker).
4
6
  * `start` / `end` / `children` let the host add its own controls (view switch, map tools, …).
5
7
  */
6
- import { type ReactNode } from "react";
8
+ import { type MouseEvent, type ReactNode } from "react";
7
9
  import { type TreeNodeStyle } from "./tree";
8
10
  import type { OutlinerStrings } from "./i18n";
9
11
  export declare const FONT_SIZES: number[];
10
- export declare const TEXT_COLORS: string[];
11
- export declare const BACKGROUND_COLORS: string[];
12
12
  export interface FormatToolbarProps {
13
13
  strings: OutlinerStrings;
14
14
  /** Style of the node being edited (undefined → nothing selected; format buttons are disabled). */
@@ -23,11 +23,17 @@ export interface FormatToolbarProps {
23
23
  end?: ReactNode;
24
24
  readOnly?: boolean;
25
25
  }
26
+ /** Same tooltip as the editor toolbar — black, 14px, arrow, below. */
27
+ export declare function ToolTip({ title, children }: {
28
+ title: string;
29
+ children: ReactNode;
30
+ }): import("react").JSX.Element;
31
+ /** Same button as the editor toolbar — 32px, 4px radius, light grey when on. */
26
32
  export declare function ToolButton({ label, active, disabled, onClick, children }: {
27
33
  label: string;
28
34
  active?: boolean;
29
35
  disabled?: boolean;
30
- onClick: () => void;
36
+ onClick: (event: MouseEvent<HTMLElement>) => void;
31
37
  children: ReactNode;
32
38
  }): import("react").JSX.Element;
33
39
  export declare const ToolDivider: () => import("react").JSX.Element;
package/dist/i18n.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /** UI strings (ko · en · ja · zh · de · fr · it · vi). Unknown locale → English. */
2
2
  declare const STRINGS: {
3
3
  readonly ko: {
4
+ readonly clearFormat: "서식 지우기";
4
5
  readonly fontSize: "글자 크기";
5
6
  readonly sizeDefault: "기본";
6
7
  readonly bold: "진하게";
@@ -18,6 +19,7 @@ declare const STRINGS: {
18
19
  readonly hint: "Enter: 새 줄 · Tab / Shift+Tab: 들여쓰기 / 내어쓰기 · Alt+↑↓: 순서 · 줄 앞 손잡이 끌기: 옮기기 · 빈 줄 Backspace: 지우기";
19
20
  };
20
21
  readonly en: {
22
+ readonly clearFormat: "Clear format";
21
23
  readonly fontSize: "Font size";
22
24
  readonly sizeDefault: "Default";
23
25
  readonly bold: "Bold";
@@ -35,6 +37,7 @@ declare const STRINGS: {
35
37
  readonly hint: "Enter: new line · Tab / Shift+Tab: indent / outdent · Alt+↑↓: reorder · Drag the row handle: move · Backspace on empty: delete";
36
38
  };
37
39
  readonly ja: {
40
+ readonly clearFormat: "書式をクリア";
38
41
  readonly fontSize: "文字サイズ";
39
42
  readonly sizeDefault: "標準";
40
43
  readonly bold: "太字";
@@ -52,6 +55,7 @@ declare const STRINGS: {
52
55
  readonly hint: "Enter: 新しい行 · Tab / Shift+Tab: 字下げ / 字上げ · Alt+↑↓: 並べ替え · 行頭のハンドルをドラッグ: 移動 · 空行で Backspace: 削除";
53
56
  };
54
57
  readonly zh: {
58
+ readonly clearFormat: "清除格式";
55
59
  readonly fontSize: "字号";
56
60
  readonly sizeDefault: "默认";
57
61
  readonly bold: "加粗";
@@ -69,6 +73,7 @@ declare const STRINGS: {
69
73
  readonly hint: "Enter: 新行 · Tab / Shift+Tab: 缩进 / 取消缩进 · Alt+↑↓: 顺序 · 拖动行首手柄: 移动 · 空行 Backspace: 删除";
70
74
  };
71
75
  readonly de: {
76
+ readonly clearFormat: "Formatierung löschen";
72
77
  readonly fontSize: "Schriftgröße";
73
78
  readonly sizeDefault: "Standard";
74
79
  readonly bold: "Fett";
@@ -86,6 +91,7 @@ declare const STRINGS: {
86
91
  readonly hint: "Enter: neue Zeile · Tab / Shift+Tab: ein- / ausrücken · Alt+↑↓: Reihenfolge · Griff ziehen: verschieben · Backspace leer: löschen";
87
92
  };
88
93
  readonly fr: {
94
+ readonly clearFormat: "Effacer la mise en forme";
89
95
  readonly fontSize: "Taille";
90
96
  readonly sizeDefault: "Par défaut";
91
97
  readonly bold: "Gras";
@@ -103,6 +109,7 @@ declare const STRINGS: {
103
109
  readonly hint: "Entrée : nouvelle ligne · Tab / Maj+Tab : indenter / désindenter · Alt+↑↓ : ordre · Glisser la poignée : déplacer · Retour arrière vide : supprimer";
104
110
  };
105
111
  readonly it: {
112
+ readonly clearFormat: "Cancella formattazione";
106
113
  readonly fontSize: "Dimensione";
107
114
  readonly sizeDefault: "Predefinita";
108
115
  readonly bold: "Grassetto";
@@ -120,6 +127,7 @@ declare const STRINGS: {
120
127
  readonly hint: "Invio: nuova riga · Tab / Maiusc+Tab: rientro / riduci · Alt+↑↓: ordine · Trascina la maniglia: sposta · Backspace su vuota: elimina";
121
128
  };
122
129
  readonly vi: {
130
+ readonly clearFormat: "Xóa định dạng";
123
131
  readonly fontSize: "Cỡ chữ";
124
132
  readonly sizeDefault: "Mặc định";
125
133
  readonly bold: "Đậm";
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  export { Outliner, type OutlinerProps } from "./Outliner";
2
2
  export { OutlineList, outlineTextStyle, type OutlineListProps } from "./OutlineList";
3
- export { FormatToolbar, ToolButton, ToolDivider, FONT_SIZES, TEXT_COLORS, BACKGROUND_COLORS, type FormatToolbarProps } from "./FormatToolbar";
3
+ export { FormatToolbar, ToolButton, ToolDivider, ToolTip, FONT_SIZES, type FormatToolbarProps } from "./FormatToolbar";
4
4
  export { useTreeHistory, type TreeHistory } from "./history";
5
5
  export { outlinerStrings, type OutlinerStrings } from "./i18n";
6
6
  export { measureText, DEFAULT_FONT_FAMILY } from "./measure";
package/dist/index.esm.js CHANGED
@@ -1,2 +1,2 @@
1
- import{useState as Je}from"react";import{Box as De}from"@mui/material";import{useState as pe}from"react";import{Box as P,ButtonBase as G,Divider as Ee,IconButton as ge,Menu as Oe,MenuItem as ue,Popover as Me,Tooltip as W}from"@mui/material";import we from"@mui/icons-material/FormatBold";import Ae from"@mui/icons-material/FormatUnderlined";import Fe from"@mui/icons-material/StrikethroughS";import Pe from"@mui/icons-material/FormatColorText";import Le from"@mui/icons-material/FormatColorFill";import He from"@mui/icons-material/Undo";import Ue from"@mui/icons-material/Redo";import Ke from"@mui/icons-material/ArrowDropDown";import Ge from"@mui/icons-material/FormatColorReset";var ee=()=>Math.random().toString(16).slice(2,18),oo=e=>({id:"root",topic:e,children:[]}),Re=e=>structuredClone(e);function b(e,n){if(e.id===n)return{node:e,parent:null,index:0};let t=[e];for(;t.length;){let i=t.pop(),r=i.children??[];for(let l=0;l<r.length;l++){if(r[l].id===n)return{node:r[l],parent:i,index:l};t.push(r[l])}}return null}var A=(e,n)=>e.id===n||(e.children??[]).some(t=>A(t,n)),no=e=>e.expanded===!1&&(e.children?.length??0)>0;function oe(e){let n=[],t=(i,r,l)=>{if(n.push({node:i,depth:r,parentId:l}),i.expanded!==!1)for(let d of i.children??[])t(d,r+1,i.id)};return t(e,0,null),n}function B(e,n){let t=Re(e),i=n(t);return i===!1?null:{root:t,focusId:i||void 0}}var Ie=(e,n,t="",i=!1)=>B(e,r=>{let l=b(r,n);if(!l)return!1;let d={id:ee(),topic:t};return l.node.children=i?[d,...l.node.children??[]]:[...l.node.children??[],d],l.node.expanded=!0,d.id}),ve=(e,n,t="")=>B(e,i=>{let r=b(i,n);if(!r)return!1;let l={id:ee(),topic:t};return r.parent?r.parent.children.splice(r.index+1,0,l):(r.node.children=[l,...r.node.children??[]],r.node.expanded=!0),l.id}),ne=(e,n)=>{let t=b(e,n);return t&&(!t.parent||(t.node.children?.length??0)>0&&t.node.expanded!==!1)?Ie(e,n,"",!0):ve(e,n)},te=(e,n)=>B(e,t=>{let i=b(t,n);return i?.parent?(i.parent.children.splice(i.index,1),i.parent.children[i.index-1]?.id??i.parent.id):!1}),re=(e,n)=>B(e,t=>{let i=b(t,n);if(!i?.parent||i.index===0)return!1;let r=i.parent.children[i.index-1];return i.parent.children.splice(i.index,1),r.children=[...r.children??[],i.node],r.expanded=!0,n}),ie=(e,n)=>B(e,t=>{let i=b(t,n);if(!i?.parent)return!1;let r=b(t,i.parent.id);return r?.parent?(i.parent.children.splice(i.index,1),r.parent.children.splice(r.index+1,0,i.node),n):!1}),le=(e,n,t)=>B(e,i=>{let r=b(i,n);if(!r?.parent)return!1;let l=r.parent.children,d=r.index+t;return d<0||d>=l.length?!1:([l[r.index],l[d]]=[l[d],l[r.index]],n)}),de=(e,n,t,i)=>B(e,r=>{let l=b(r,n);if(!l?.parent||A(l.node,t))return!1;l.parent.children.splice(l.index,1);let d=b(r,t);return d?(i==="child"||!d.parent?(d.node.children=[...d.node.children??[],l.node],d.node.expanded=!0):d.parent.children.splice(d.index+(i==="after"?1:0),0,l.node),n):!1}),ae=(e,n,t)=>B(e,i=>{let r=b(i,n);if(!r||r.node.topic===t)return!1;r.node.topic=t}),se=(e,n,t)=>B(e,i=>{let r=b(i,n);if(!r||!(r.node.children?.length??0))return!1;r.node.expanded=t??r.node.expanded===!1}),ce=(e,n,t)=>B(e,i=>{let r=!1;for(let l of n){let d=b(i,l);if(!d)continue;let u={...d.node.style??{}};for(let[g,s]of Object.entries(t))s===void 0||s===""?delete u[g]:u[g]=s;d.node.style=Object.keys(u).length?u:void 0,d.node.style||delete d.node.style,r=!0}return r?void 0:!1});function U(e,n){return(e?.textDecoration??"").split(/\s+/).includes(n)}function K(e,n){let t=new Set((e?.textDecoration??"").split(/\s+/).filter(Boolean));return t.has(n)?t.delete(n):t.add(n),t.size?[...t].join(" "):void 0}import{Fragment as Te,jsx as a,jsxs as v}from"react/jsx-runtime";var he=[12,14,16,18,20,24,28],xe=["#1f2328","#5f6368","#d93025","#e8710a","#f9ab00","#188038","#1a73e8","#9334e6","#c2185b","#ffffff"],be=["#fde2e1","#feefc3","#fff8c5","#ceead6","#d2e3fc","#e9d7fe","#fad2e1","#e8eaed","#3c4043","#1a73e8"],me=(e=!1)=>({width:30,height:30,borderRadius:1,color:e?"primary.main":"text.secondary",bgcolor:e?"rgba(25,118,210,0.10)":"transparent","&:hover":{bgcolor:e?"rgba(25,118,210,0.16)":"rgba(0,0,0,0.06)"}});function O({label:e,active:n,disabled:t,onClick:i,children:r}){return a(W,{title:e,disableInteractive:!0,children:a("span",{children:a(ge,{size:"small","aria-label":e,"aria-pressed":n,disabled:t,onMouseDown:l=>l.preventDefault(),onClick:i,sx:me(n),children:r})})})}var F=()=>a(Ee,{orientation:"vertical",flexItem:!0,sx:{mx:.5,my:.75}});function fe({label:e,icon:n,value:t,colors:i,noneLabel:r,disabled:l,onPick:d}){let[u,g]=pe(null);return v(Te,{children:[a(W,{title:e,disableInteractive:!0,children:a("span",{children:v(ge,{size:"small","aria-label":e,disabled:l,onMouseDown:s=>s.preventDefault(),onClick:s=>g(s.currentTarget),sx:{...me(!1),flexDirection:"column",gap:0},children:[n,a(P,{sx:{width:16,height:3,mt:"-3px",borderRadius:.5,bgcolor:t??"transparent",border:t?0:"1px solid #c4c7cc"}})]})})}),a(Me,{open:!!u,anchorEl:u,onClose:()=>g(null),transitionDuration:0,anchorOrigin:{vertical:"bottom",horizontal:"left"},disableRestoreFocus:!0,children:v(P,{sx:{p:1,display:"grid",gridTemplateColumns:"repeat(5, 24px)",gap:.75},children:[i.map(s=>a(G,{"aria-label":s,onMouseDown:h=>h.preventDefault(),onClick:()=>{d(s),g(null)},sx:{width:24,height:24,borderRadius:.75,bgcolor:s,border:"1px solid rgba(0,0,0,0.12)",outline:t?.toLowerCase()===s?"2px solid #1a73e8":"none",outlineOffset:1}},s)),v(G,{onMouseDown:s=>s.preventDefault(),onClick:()=>{d(void 0),g(null)},sx:{gridColumn:"1 / -1",height:26,borderRadius:.75,fontSize:13,color:"text.secondary",gap:.5,"&:hover":{bgcolor:"rgba(0,0,0,0.05)"}},children:[a(Ge,{sx:{fontSize:16}}),r]})]})})]})}function $({strings:e,style:n,onStyle:t,canUndo:i,canRedo:r,onUndo:l,onRedo:d,start:u,children:g,end:s,readOnly:h}){let[p,f]=pe(null),x=h||!n,m=n?.fontSize?parseFloat(n.fontSize):null,I=n?.fontWeight==="bold"||Number(n?.fontWeight)>=600;return v(P,{sx:{display:"flex",alignItems:"center",flexWrap:"wrap",gap:.25,minHeight:40,px:1,borderBottom:"1px solid #e0e0e0",bgcolor:"#fff",flexShrink:0},children:[u,u?a(F,{}):null,l?v(Te,{children:[a(O,{label:e.undo,disabled:h||!i,onClick:l,children:a(He,{sx:{fontSize:18}})}),a(O,{label:e.redo,disabled:h||!r,onClick:()=>d?.(),children:a(Ue,{sx:{fontSize:18}})}),a(F,{})]}):null,a(W,{title:e.fontSize,disableInteractive:!0,children:a("span",{children:v(G,{disabled:x,onMouseDown:c=>c.preventDefault(),onClick:c=>f(c.currentTarget),sx:{height:30,px:.75,borderRadius:1,fontSize:13,color:x?"text.disabled":"text.primary",minWidth:52,justifyContent:"space-between","&:hover":{bgcolor:"rgba(0,0,0,0.06)"}},children:[m??e.sizeDefault,a(Ke,{sx:{fontSize:18,color:"text.secondary"}})]})})}),v(Oe,{open:!!p,anchorEl:p,onClose:()=>f(null),transitionDuration:0,disableRestoreFocus:!0,children:[a(ue,{dense:!0,selected:m===null,onClick:()=>{t({fontSize:void 0}),f(null)},children:e.sizeDefault}),he.map(c=>a(ue,{dense:!0,selected:m===c,onClick:()=>{t({fontSize:`${c}px`}),f(null)},children:c},c))]}),a(O,{label:e.bold,active:I,disabled:x,onClick:()=>t({fontWeight:I?void 0:"bold"}),children:a(we,{sx:{fontSize:19}})}),a(O,{label:e.underline,active:U(n,"underline"),disabled:x,onClick:()=>t({textDecoration:K(n,"underline")}),children:a(Ae,{sx:{fontSize:19}})}),a(O,{label:e.strike,active:U(n,"line-through"),disabled:x,onClick:()=>t({textDecoration:K(n,"line-through")}),children:a(Fe,{sx:{fontSize:19}})}),a(fe,{label:e.textColor,icon:a(Pe,{sx:{fontSize:17}}),value:n?.color,colors:xe,noneLabel:e.noColor,disabled:x,onPick:c=>t({color:c})}),a(fe,{label:e.background,icon:a(Le,{sx:{fontSize:17}}),value:n?.background,colors:be,noneLabel:e.noColor,disabled:x,onPick:c=>t({background:c})}),g?a(F,{}):null,g,a(P,{sx:{flex:1}}),s]})}import{useEffect as We,useRef as Ne,useState as Y}from"react";import{Box as M,IconButton as $e}from"@mui/material";import _e from"@mui/icons-material/ArrowRight";import Ye from"@mui/icons-material/ArrowDropDown";import je from"@mui/icons-material/DragIndicator";var w=null,L=new Map,Se="-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif";function _(e,n,t=400,i=Se){let r=`${t} ${n}px ${i}`,l=`${r}|${e}`,d=L.get(l);if(d!==void 0)return d;!w&&typeof document<"u"&&(w=document.createElement("canvas").getContext("2d"));let u=0;if(w)w.font=r,u=w.measureText(e).width;else for(let g of e)u+=(/[ᄀ-ᅵ]/.test(g)?1:.55)*n;return L.size>5e3&&L.clear(),L.set(l,u),u}import{jsx as R,jsxs as Ve}from"react/jsx-runtime";var Ze=22,Xe=15;function ye(e,n){return{fontSize:e?.fontSize?Math.min(28,Math.max(12,parseFloat(e.fontSize))):Xe,fontWeight:e?.fontWeight??(n===0?700:400),color:e?.color,textDecoration:e?.textDecoration,background:e?.background}}function j({root:e,onEdit:n,selectedId:t,onSelect:i,strings:r,readOnly:l,onUndo:d,onRedo:u,paddingTop:g=8,paddingBottom:s=40}){let h=Ne(new Map),p=Ne(new Map),[f,x]=Y(null),[m,I]=Y(null),[c,k]=Y(null),D=oe(e);We(()=>{if(!f)return;let o=h.current.get(f);o&&(o.focus(),o.setSelectionRange(o.value.length,o.value.length),x(null))},[f,e]);let E=(o,S)=>{o&&(n(o.root,S),o.focusId&&(x(o.focusId),i?.(o.focusId)))},Ce=(o,S)=>{if(o.nativeEvent.isComposing)return;let C=D[S],y=C.node.id,z=o.ctrlKey||o.metaKey;if(z&&(o.key==="z"||o.key==="Z")){o.preventDefault(),o.shiftKey?u?.():d?.();return}if(z&&(o.key==="y"||o.key==="Y")){o.preventDefault(),u?.();return}if(!l){if(o.key==="Enter")o.preventDefault(),E(ne(e,y));else if(o.key==="Tab")o.preventDefault(),E(o.shiftKey?ie(e,y):re(e,y));else if(o.altKey&&(o.key==="ArrowUp"||o.key==="ArrowDown"))o.preventDefault(),E(le(e,y,o.key==="ArrowUp"?-1:1));else if(o.key==="ArrowUp"||o.key==="ArrowDown"){let T=D[S+(o.key==="ArrowUp"?-1:1)];T&&(o.preventDefault(),x(T.node.id),i?.(T.node.id))}else if(o.key==="Backspace"&&o.currentTarget.value===""&&C.depth>0&&!(C.node.children?.length??0)){o.preventDefault();let T=te(e,y);T&&E({root:T.root,focusId:D[S-1]?.node.id})}}},J=c?b(e,c)?.node??null:null,ze=(o,S)=>{o.button!==0||l||(o.preventDefault(),o.currentTarget.setPointerCapture(o.pointerId),k(S),I(null))},Be=o=>{if(!c||!J)return;let S=null;for(let C of D){let y=p.current.get(C.node.id);if(!y)continue;let z=y.getBoundingClientRect();if(!(o.clientY<z.top||o.clientY>=z.bottom)){A(J,C.node.id)||(S={id:C.node.id,place:o.clientY<z.top+z.height/2?"before":"after"});break}}(S?.id!==m?.id||S?.place!==m?.place)&&I(S)},Q=o=>{o.currentTarget.hasPointerCapture(o.pointerId)&&o.currentTarget.releasePointerCapture(o.pointerId),c&&m&&E(de(e,c,m.id,m.place)),k(null),I(null)};return R(M,{sx:{position:"relative",height:"100%",overflowY:"auto",bgcolor:"#fff",pt:`${g}px`,pb:`${s}px`,px:1.5},children:D.map((o,S)=>{let C=(o.node.children?.length??0)>0,y=o.node.expanded===!1,z=m?.id===o.node.id?m.place:null,T=ye(o.node.style,o.depth);return Ve(M,{ref:N=>{N?p.current.set(o.node.id,N):p.current.delete(o.node.id)},sx:{display:"flex",alignItems:"center",minHeight:26,pl:`${o.depth*Ze}px`,borderRadius:.75,bgcolor:t===o.node.id?"rgba(26,115,232,0.06)":"transparent",boxShadow:N=>z==="before"?`inset 0 2px 0 ${N.palette.primary.main}`:z==="after"?`inset 0 -2px 0 ${N.palette.primary.main}`:"none",opacity:c===o.node.id?.4:1,"&:hover .ol-handle":{visibility:"visible"}},children:[R(M,{className:"ol-handle",title:r.drag,onPointerDown:o.depth>0?N=>ze(N,o.node.id):void 0,onPointerMove:Be,onPointerUp:Q,onPointerCancel:Q,sx:{display:"flex",color:"#b0b4ba",cursor:o.depth>0&&!l?c?"grabbing":"grab":"default",visibility:c===o.node.id?"visible":"hidden",width:18,flexShrink:0,touchAction:"none"},children:o.depth>0&&!l?R(je,{sx:{fontSize:16}}):null}),C?R($e,{size:"small","aria-label":y?r.unfold:r.fold,title:y?r.unfold:r.fold,onClick:()=>E(se(e,o.node.id)),sx:{width:22,height:22,p:0,color:"text.secondary"},children:y?R(_e,{sx:{fontSize:20}}):R(Ye,{sx:{fontSize:20}})}):R(M,{sx:{width:22,display:"flex",justifyContent:"center",flexShrink:0},children:R(M,{sx:{width:5,height:5,borderRadius:"50%",bgcolor:"#9aa0a6"}})}),R(M,{sx:{flex:1,minWidth:0,display:"flex",ml:.5},children:R("input",{ref:N=>{N?h.current.set(o.node.id,N):h.current.delete(o.node.id)},value:o.node.topic,readOnly:l,placeholder:o.depth===0?r.root:"",spellCheck:!1,autoComplete:"off",onFocus:()=>i?.(o.node.id),onChange:N=>E(ae(e,o.node.id,N.target.value),`topic:${o.node.id}`),onKeyDown:N=>Ce(N,S),style:{width:T.background?Math.ceil(_(o.node.topic||" ",Number(T.fontSize),T.fontWeight))+16:"100%",maxWidth:"100%",border:0,outline:0,font:"inherit",padding:T.background?"2px 6px":"2px 0",borderRadius:4,background:T.background??"transparent",color:T.color??"inherit",fontSize:T.fontSize,fontWeight:T.fontWeight,textDecoration:[T.textDecoration,y&&C?"underline dotted #9aa0a6":""].filter(Boolean).join(" ")||void 0}})})]},o.node.id)})})}import{useCallback as H,useRef as Z,useState as qe}from"react";function X(e=100,n=1200){let t=Z([]),i=Z([]),r=Z(null),[,l]=qe(0),d=()=>l(p=>p+1),u=H((p,f)=>{let x=Date.now(),m=f&&r.current?.key===f&&x-r.current.at<n;r.current=f?{key:f,at:x}:null,i.current=[],m||(t.current.push(p),t.current.length>e&&t.current.shift()),d()},[e,n]),g=H(p=>{let f=t.current.pop();return f?(i.current.push(p),r.current=null,d(),f):null},[]),s=H(p=>{let f=i.current.pop();return f?(t.current.push(p),r.current=null,d(),f):null},[]),h=H(()=>{t.current=[],i.current=[],r.current=null,d()},[]);return{canUndo:t.current.length>0,canRedo:i.current.length>0,record:u,undo:g,redo:s,clear:h}}var ke={ko:{fontSize:"\uAE00\uC790 \uD06C\uAE30",sizeDefault:"\uAE30\uBCF8",bold:"\uC9C4\uD558\uAC8C",underline:"\uBC11\uC904",strike:"\uCDE8\uC18C\uC120",textColor:"\uAE00\uC790\uC0C9",background:"\uBC30\uACBD\uC0C9",noColor:"\uC5C6\uC74C",undo:"\uB418\uB3CC\uB9AC\uAE30",redo:"\uB2E4\uC2DC \uD558\uAE30",fold:"\uC811\uAE30",unfold:"\uD3BC\uCE58\uAE30",drag:"\uB04C\uC5B4\uC11C \uC62E\uAE30\uAE30",root:"\uC8FC\uC81C",hint:"Enter: \uC0C8 \uC904 \xB7 Tab / Shift+Tab: \uB4E4\uC5EC\uC4F0\uAE30 / \uB0B4\uC5B4\uC4F0\uAE30 \xB7 Alt+\u2191\u2193: \uC21C\uC11C \xB7 \uC904 \uC55E \uC190\uC7A1\uC774 \uB04C\uAE30: \uC62E\uAE30\uAE30 \xB7 \uBE48 \uC904 Backspace: \uC9C0\uC6B0\uAE30"},en:{fontSize:"Font size",sizeDefault:"Default",bold:"Bold",underline:"Underline",strike:"Strikethrough",textColor:"Text color",background:"Background",noColor:"None",undo:"Undo",redo:"Redo",fold:"Collapse",unfold:"Expand",drag:"Drag to move",root:"Topic",hint:"Enter: new line \xB7 Tab / Shift+Tab: indent / outdent \xB7 Alt+\u2191\u2193: reorder \xB7 Drag the row handle: move \xB7 Backspace on empty: delete"},ja:{fontSize:"\u6587\u5B57\u30B5\u30A4\u30BA",sizeDefault:"\u6A19\u6E96",bold:"\u592A\u5B57",underline:"\u4E0B\u7DDA",strike:"\u53D6\u308A\u6D88\u3057\u7DDA",textColor:"\u6587\u5B57\u8272",background:"\u80CC\u666F\u8272",noColor:"\u306A\u3057",undo:"\u5143\u306B\u623B\u3059",redo:"\u3084\u308A\u76F4\u3059",fold:"\u6298\u308A\u305F\u305F\u3080",unfold:"\u5C55\u958B",drag:"\u30C9\u30E9\u30C3\u30B0\u3067\u79FB\u52D5",root:"\u30C6\u30FC\u30DE",hint:"Enter: \u65B0\u3057\u3044\u884C \xB7 Tab / Shift+Tab: \u5B57\u4E0B\u3052 / \u5B57\u4E0A\u3052 \xB7 Alt+\u2191\u2193: \u4E26\u3079\u66FF\u3048 \xB7 \u884C\u982D\u306E\u30CF\u30F3\u30C9\u30EB\u3092\u30C9\u30E9\u30C3\u30B0: \u79FB\u52D5 \xB7 \u7A7A\u884C\u3067 Backspace: \u524A\u9664"},zh:{fontSize:"\u5B57\u53F7",sizeDefault:"\u9ED8\u8BA4",bold:"\u52A0\u7C97",underline:"\u4E0B\u5212\u7EBF",strike:"\u5220\u9664\u7EBF",textColor:"\u6587\u5B57\u989C\u8272",background:"\u80CC\u666F\u8272",noColor:"\u65E0",undo:"\u64A4\u9500",redo:"\u91CD\u505A",fold:"\u6298\u53E0",unfold:"\u5C55\u5F00",drag:"\u62D6\u52A8\u4EE5\u79FB\u52A8",root:"\u4E3B\u9898",hint:"Enter: \u65B0\u884C \xB7 Tab / Shift+Tab: \u7F29\u8FDB / \u53D6\u6D88\u7F29\u8FDB \xB7 Alt+\u2191\u2193: \u987A\u5E8F \xB7 \u62D6\u52A8\u884C\u9996\u624B\u67C4: \u79FB\u52A8 \xB7 \u7A7A\u884C Backspace: \u5220\u9664"},de:{fontSize:"Schriftgr\xF6\xDFe",sizeDefault:"Standard",bold:"Fett",underline:"Unterstrichen",strike:"Durchgestrichen",textColor:"Textfarbe",background:"Hintergrund",noColor:"Keine",undo:"R\xFCckg\xE4ngig",redo:"Wiederholen",fold:"Einklappen",unfold:"Ausklappen",drag:"Zum Verschieben ziehen",root:"Thema",hint:"Enter: neue Zeile \xB7 Tab / Shift+Tab: ein- / ausr\xFCcken \xB7 Alt+\u2191\u2193: Reihenfolge \xB7 Griff ziehen: verschieben \xB7 Backspace leer: l\xF6schen"},fr:{fontSize:"Taille",sizeDefault:"Par d\xE9faut",bold:"Gras",underline:"Soulign\xE9",strike:"Barr\xE9",textColor:"Couleur du texte",background:"Arri\xE8re-plan",noColor:"Aucune",undo:"Annuler",redo:"R\xE9tablir",fold:"Replier",unfold:"D\xE9plier",drag:"Glisser pour d\xE9placer",root:"Sujet",hint:"Entr\xE9e : nouvelle ligne \xB7 Tab / Maj+Tab : indenter / d\xE9sindenter \xB7 Alt+\u2191\u2193 : ordre \xB7 Glisser la poign\xE9e : d\xE9placer \xB7 Retour arri\xE8re vide : supprimer"},it:{fontSize:"Dimensione",sizeDefault:"Predefinita",bold:"Grassetto",underline:"Sottolineato",strike:"Barrato",textColor:"Colore testo",background:"Sfondo",noColor:"Nessuno",undo:"Annulla",redo:"Ripeti",fold:"Comprimi",unfold:"Espandi",drag:"Trascina per spostare",root:"Argomento",hint:"Invio: nuova riga \xB7 Tab / Maiusc+Tab: rientro / riduci \xB7 Alt+\u2191\u2193: ordine \xB7 Trascina la maniglia: sposta \xB7 Backspace su vuota: elimina"},vi:{fontSize:"C\u1EE1 ch\u1EEF",sizeDefault:"M\u1EB7c \u0111\u1ECBnh",bold:"\u0110\u1EADm",underline:"G\u1EA1ch ch\xE2n",strike:"G\u1EA1ch ngang",textColor:"M\xE0u ch\u1EEF",background:"M\xE0u n\u1EC1n",noColor:"Kh\xF4ng",undo:"Ho\xE0n t\xE1c",redo:"L\xE0m l\u1EA1i",fold:"Thu g\u1ECDn",unfold:"M\u1EDF r\u1ED9ng",drag:"K\xE9o \u0111\u1EC3 di chuy\u1EC3n",root:"Ch\u1EE7 \u0111\u1EC1",hint:"Enter: d\xF2ng m\u1EDBi \xB7 Tab / Shift+Tab: th\u1EE5t v\xE0o / ra \xB7 Alt+\u2191\u2193: th\u1EE9 t\u1EF1 \xB7 K\xE9o tay c\u1EA7m: di chuy\u1EC3n \xB7 Backspace d\xF2ng tr\u1ED1ng: x\xF3a"}};function V(e,n){let t=(e??"en").slice(0,2).toLowerCase();return{...ke[t]??ke.en,...n}}import{jsx as q,jsxs as eo}from"react/jsx-runtime";function Qe({value:e,onChange:n,locale:t,strings:i,readOnly:r,toolbar:l=!0,toolbarStart:d,toolbarEnd:u,height:g="100%"}){let s=V(t,i),h=X(),[p,f]=Je(null),x=(k,D)=>{h.record(e,D),n(k)},m=()=>{let k=h.undo(e);k&&n(k)},I=()=>{let k=h.redo(e);k&&n(k)},c=p?b(e,p)?.node:void 0;return eo(De,{sx:{display:"flex",flexDirection:"column",height:g,minHeight:0,bgcolor:"#fff"},children:[l?q($,{strings:s,style:c?c.style??{}:void 0,onStyle:k=>{if(!p)return;let D=ce(e,[p],k);D&&x(D.root)},canUndo:h.canUndo,canRedo:h.canRedo,onUndo:m,onRedo:I,start:d,end:u,readOnly:r}):null,q(De,{sx:{flex:1,minHeight:0},children:q(j,{root:e,onEdit:x,selectedId:p,onSelect:f,strings:s,readOnly:r,onUndo:m,onRedo:I})})]})}export{be as BACKGROUND_COLORS,Se as DEFAULT_FONT_FAMILY,he as FONT_SIZES,$ as FormatToolbar,j as OutlineList,Qe as Outliner,xe as TEXT_COLORS,O as ToolButton,F as ToolDivider,ne as addBelow,Ie as addChild,ve as addSibling,A as containsNode,oo as createTree,U as hasDecoration,re as indentNode,no as isFolded,b as locateNode,_ as measureText,de as moveNode,ee as newNodeId,ie as outdentNode,ye as outlineTextStyle,V as outlinerStrings,te as removeNode,ce as setNodeStyle,ae as setTopic,le as shiftNode,K as toggleDecoration,se as toggleFold,X as useTreeHistory,oe as visibleRows};
1
+ import{useState as _e}from"react";import{Box as Te}from"@mui/material";import{useState as fe}from"react";import{Box as w,ButtonBase as ve,Menu as Be,MenuItem as ce,Tooltip as Ee}from"@mui/material";import{ColorPicker as ze}from"@ehfuse/mui-color-picker";import{BoldIcon as Fe,FontColorIcon as Ie,FontFillIcon as Re,RedoIcon as Me,RemoveFormatIcon as we,StrikeIcon as Pe,UnderlineIcon as Ae,UndoIcon as He}from"@ehfuse/toolbar-icons";var Q=()=>Math.random().toString(16).slice(2,18),Ve=e=>({id:"root",topic:e,children:[]}),ke=e=>structuredClone(e);function h(e,o){if(e.id===o)return{node:e,parent:null,index:0};let t=[e];for(;t.length;){let i=t.pop(),r=i.children??[];for(let l=0;l<r.length;l++){if(r[l].id===o)return{node:r[l],parent:i,index:l};t.push(r[l])}}return null}var A=(e,o)=>e.id===o||(e.children??[]).some(t=>A(t,o)),Xe=e=>e.expanded===!1&&(e.children?.length??0)>0;function ee(e){let o=[],t=(i,r,l)=>{if(o.push({node:i,depth:r,parentId:l}),i.expanded!==!1)for(let d of i.children??[])t(d,r+1,i.id)};return t(e,0,null),o}function B(e,o){let t=ke(e),i=o(t);return i===!1?null:{root:t,focusId:i||void 0}}var De=(e,o,t="",i=!1)=>B(e,r=>{let l=h(r,o);if(!l)return!1;let d={id:Q(),topic:t};return l.node.children=i?[d,...l.node.children??[]]:[...l.node.children??[],d],l.node.expanded=!0,d.id}),Ce=(e,o,t="")=>B(e,i=>{let r=h(i,o);if(!r)return!1;let l={id:Q(),topic:t};return r.parent?r.parent.children.splice(r.index+1,0,l):(r.node.children=[l,...r.node.children??[]],r.node.expanded=!0),l.id}),oe=(e,o)=>{let t=h(e,o);return t&&(!t.parent||(t.node.children?.length??0)>0&&t.node.expanded!==!1)?De(e,o,"",!0):Ce(e,o)},ne=(e,o)=>B(e,t=>{let i=h(t,o);return i?.parent?(i.parent.children.splice(i.index,1),i.parent.children[i.index-1]?.id??i.parent.id):!1}),te=(e,o)=>B(e,t=>{let i=h(t,o);if(!i?.parent||i.index===0)return!1;let r=i.parent.children[i.index-1];return i.parent.children.splice(i.index,1),r.children=[...r.children??[],i.node],r.expanded=!0,o}),re=(e,o)=>B(e,t=>{let i=h(t,o);if(!i?.parent)return!1;let r=h(t,i.parent.id);return r?.parent?(i.parent.children.splice(i.index,1),r.parent.children.splice(r.index+1,0,i.node),o):!1}),ie=(e,o,t)=>B(e,i=>{let r=h(i,o);if(!r?.parent)return!1;let l=r.parent.children,d=r.index+t;return d<0||d>=l.length?!1:([l[r.index],l[d]]=[l[d],l[r.index]],o)}),le=(e,o,t,i)=>B(e,r=>{let l=h(r,o);if(!l?.parent||A(l.node,t))return!1;l.parent.children.splice(l.index,1);let d=h(r,t);return d?(i==="child"||!d.parent?(d.node.children=[...d.node.children??[],l.node],d.node.expanded=!0):d.parent.children.splice(d.index+(i==="after"?1:0),0,l.node),o):!1}),de=(e,o,t)=>B(e,i=>{let r=h(i,o);if(!r||r.node.topic===t)return!1;r.node.topic=t}),ae=(e,o,t)=>B(e,i=>{let r=h(i,o);if(!r||!(r.node.children?.length??0))return!1;r.node.expanded=t??r.node.expanded===!1}),se=(e,o,t)=>B(e,i=>{let r=!1;for(let l of o){let d=h(i,l);if(!d)continue;let c={...d.node.style??{}};for(let[g,k]of Object.entries(t))k===void 0||k===""?delete c[g]:c[g]=k;d.node.style=Object.keys(c).length?c:void 0,d.node.style||delete d.node.style,r=!0}return r?void 0:!1});function U(e,o){return(e?.textDecoration??"").split(/\s+/).includes(o)}function W(e,o){let t=new Set((e?.textDecoration??"").split(/\s+/).filter(Boolean));return t.has(o)?t.delete(o):t.add(o),t.size?[...t].join(" "):void 0}import{Fragment as ge,jsx as a,jsxs as M}from"react/jsx-runtime";var pe=[12,14,16,18,20,24,28,32];function K({title:e,children:o}){return a(Ee,{title:e,placement:"bottom",arrow:!0,disableInteractive:!0,leaveDelay:0,slotProps:{tooltip:{sx:{bgcolor:"#000000",color:"#ffffff",fontSize:"14px",fontWeight:"normal","& .MuiTooltip-arrow":{color:"#000000"}}}},children:a("span",{style:{display:"inline-flex"},children:o})})}function F({label:e,active:o=!1,disabled:t=!1,onClick:i,children:r}){return a(K,{title:e,children:a(w,{component:"button",type:"button","aria-label":e,"aria-pressed":o,disabled:t,onMouseDown:l=>l.preventDefault(),onClick:l=>{l.preventDefault(),t||i(l)},sx:{display:"inline-flex",alignItems:"center",justifyContent:"center",width:32,height:32,p:"6px",border:"none",borderRadius:"4px",bgcolor:o?"rgba(0, 0, 0, 0.08)":"transparent",color:t?"rgba(0, 0, 0, 0.26)":"inherit",cursor:t?"not-allowed":"pointer",transition:"background-color 150ms cubic-bezier(0.4, 0, 0.2, 1)","&:hover:not(:disabled)":{bgcolor:o?"rgba(0, 0, 0, 0.08)":"rgba(0, 0, 0, 0.04)"},"&:focus":{outline:"none"},"& svg":{width:20,height:20}},children:r})})}var H=()=>a(w,{sx:{width:"1px",alignSelf:"stretch",my:"8px",mx:"4px",bgcolor:"#e0e0e0"}});function ue({label:e,type:o,value:t,disabled:i,onPick:r}){let[l,d]=fe(null),c=t??(o==="color"?"#000000":"#FFFFFF");return M(ge,{children:[a(F,{label:e,disabled:i,onClick:g=>d(g.currentTarget),children:o==="color"?a(Ie,{width:"20px",height:"20px",barColor:c}):a(Re,{width:"20px",fillColor:c})}),l?a(ze,{value:c,onChange:g=>{r(g),d(null)},anchor:l,anchorMode:"auto",onClose:()=>d(null),position:"bottomCenter",advanced:{position:"bottom"},shape:"square",colorSize:16,gap:4,padding:5,popover:{disableEnforceFocus:!0,disableAutoFocus:!0,disableRestoreFocus:!0,sx:{zIndex:10001}}}):null]})}function G({strings:e,style:o,onStyle:t,canUndo:i,canRedo:r,onUndo:l,onRedo:d,start:c,children:g,end:k,readOnly:m}){let[f,u]=fe(null),p=!!m||!o,x=o?.fontSize?parseFloat(o.fontSize):null,z=o?.fontWeight==="bold"||Number(o?.fontWeight)>=600,y=!!(o&&Object.keys(o).length>0);return M(w,{sx:{display:"flex",alignItems:"center",flexWrap:"wrap",gap:"2px",minHeight:44,px:1,py:"4px",borderBottom:"1px solid #e0e0e0",bgcolor:"#fff",color:"#333",flexShrink:0},children:[c,c?a(H,{}):null,l?M(ge,{children:[a(F,{label:e.undo,disabled:m||!i,onClick:l,children:a(He,{})}),a(F,{label:e.redo,disabled:m||!r,onClick:()=>d?.(),children:a(Me,{})}),a(H,{})]}):null,a(K,{title:e.fontSize,children:M(ve,{disabled:p,onMouseDown:s=>s.preventDefault(),onClick:s=>u(s.currentTarget),sx:{height:32,minWidth:64,px:1,gap:.5,justifyContent:"space-between",border:"1px solid #d0d0d0",borderRadius:"4px",fontSize:14,color:p?"rgba(0,0,0,0.26)":"#333",bgcolor:"#fff","&:hover":{borderColor:"#999"}},children:[x??e.sizeDefault,a(w,{component:"span",sx:{fontSize:10,color:"#888"},children:"\u25BC"})]})}),M(Be,{open:!!f,anchorEl:f,onClose:()=>u(null),transitionDuration:0,disableRestoreFocus:!0,slotProps:{paper:{sx:{maxHeight:320}}},children:[a(ce,{dense:!0,selected:x===null,onClick:()=>{t({fontSize:void 0}),u(null)},children:e.sizeDefault}),pe.map(s=>a(ce,{dense:!0,selected:x===s,onClick:()=>{t({fontSize:`${s}px`}),u(null)},children:s},s))]}),a(F,{label:e.bold,active:z,disabled:p,onClick:()=>t({fontWeight:z?void 0:"bold"}),children:a(Fe,{})}),a(F,{label:e.underline,active:U(o,"underline"),disabled:p,onClick:()=>t({textDecoration:W(o,"underline")}),children:a(Ae,{})}),a(F,{label:e.strike,active:U(o,"line-through"),disabled:p,onClick:()=>t({textDecoration:W(o,"line-through")}),children:a(Pe,{})}),a(ue,{label:e.textColor,type:"color",value:o?.color,disabled:p,onPick:s=>t({color:s})}),a(ue,{label:e.background,type:"background",value:o?.background,disabled:p,onPick:s=>t({background:s.toLowerCase()==="#ffffff"?void 0:s})}),a(F,{label:e.clearFormat,disabled:p||!y,onClick:()=>t({fontSize:void 0,color:void 0,background:void 0,fontWeight:void 0,textDecoration:void 0}),children:a(we,{})}),g?a(H,{}):null,g,a(w,{sx:{flex:1}}),k]})}import{useEffect as Oe,useRef as xe,useState as j}from"react";import{Box as R,IconButton as Le}from"@mui/material";import Ue from"@mui/icons-material/ArrowRight";import We from"@mui/icons-material/ArrowDropDown";import Ke from"@mui/icons-material/DragIndicator";var P=null,O=new Map,he="-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif";function $(e,o,t=400,i=he){let r=`${t} ${o}px ${i}`,l=`${r}|${e}`,d=O.get(l);if(d!==void 0)return d;!P&&typeof document<"u"&&(P=document.createElement("canvas").getContext("2d"));let c=0;if(P)P.font=r,c=P.measureText(e).width;else for(let g of e)c+=(/[ᄀ-ᅵ]/.test(g)?1:.55)*o;return O.size>5e3&&O.clear(),O.set(l,c),c}import{jsx as E,jsxs as je}from"react/jsx-runtime";var Ge=22,$e=15;function be(e,o){return{fontSize:e?.fontSize?Math.min(28,Math.max(12,parseFloat(e.fontSize))):$e,fontWeight:e?.fontWeight??(o===0?700:400),color:e?.color,textDecoration:e?.textDecoration,background:e?.background}}function Y({root:e,onEdit:o,selectedId:t,onSelect:i,strings:r,readOnly:l,onUndo:d,onRedo:c,paddingTop:g=8,paddingBottom:k=40}){let m=xe(new Map),f=xe(new Map),[u,p]=j(null),[x,z]=j(null),[y,s]=j(null),D=ee(e);Oe(()=>{if(!u)return;let n=m.current.get(u);n&&(n.focus(),n.setSelectionRange(n.value.length,n.value.length),p(null))},[u,e]);let I=(n,T)=>{n&&(o(n.root,T),n.focusId&&(p(n.focusId),i?.(n.focusId)))},Ne=(n,T)=>{if(n.nativeEvent.isComposing)return;let C=D[T],S=C.node.id,v=n.ctrlKey||n.metaKey;if(v&&(n.key==="z"||n.key==="Z")){n.preventDefault(),n.shiftKey?c?.():d?.();return}if(v&&(n.key==="y"||n.key==="Y")){n.preventDefault(),c?.();return}if(!l){if(n.key==="Enter")n.preventDefault(),I(oe(e,S));else if(n.key==="Tab")n.preventDefault(),I(n.shiftKey?re(e,S):te(e,S));else if(n.altKey&&(n.key==="ArrowUp"||n.key==="ArrowDown"))n.preventDefault(),I(ie(e,S,n.key==="ArrowUp"?-1:1));else if(n.key==="ArrowUp"||n.key==="ArrowDown"){let b=D[T+(n.key==="ArrowUp"?-1:1)];b&&(n.preventDefault(),p(b.node.id),i?.(b.node.id))}else if(n.key==="Backspace"&&n.currentTarget.value===""&&C.depth>0&&!(C.node.children?.length??0)){n.preventDefault();let b=ne(e,S);b&&I({root:b.root,focusId:D[T-1]?.node.id})}}},X=y?h(e,y)?.node??null:null,ye=(n,T)=>{n.button!==0||l||(n.preventDefault(),n.currentTarget.setPointerCapture(n.pointerId),s(T),z(null))},Se=n=>{if(!y||!X)return;let T=null;for(let C of D){let S=f.current.get(C.node.id);if(!S)continue;let v=S.getBoundingClientRect();if(!(n.clientY<v.top||n.clientY>=v.bottom)){A(X,C.node.id)||(T={id:C.node.id,place:n.clientY<v.top+v.height/2?"before":"after"});break}}(T?.id!==x?.id||T?.place!==x?.place)&&z(T)},J=n=>{n.currentTarget.hasPointerCapture(n.pointerId)&&n.currentTarget.releasePointerCapture(n.pointerId),y&&x&&I(le(e,y,x.id,x.place)),s(null),z(null)};return E(R,{sx:{position:"relative",height:"100%",overflowY:"auto",bgcolor:"#fff",pt:`${g}px`,pb:`${k}px`,px:1.5},children:D.map((n,T)=>{let C=(n.node.children?.length??0)>0,S=n.node.expanded===!1,v=x?.id===n.node.id?x.place:null,b=be(n.node.style,n.depth);return je(R,{ref:N=>{N?f.current.set(n.node.id,N):f.current.delete(n.node.id)},sx:{display:"flex",alignItems:"center",minHeight:26,pl:`${n.depth*Ge}px`,borderRadius:.75,bgcolor:t===n.node.id?"rgba(26,115,232,0.06)":"transparent",boxShadow:N=>v==="before"?`inset 0 2px 0 ${N.palette.primary.main}`:v==="after"?`inset 0 -2px 0 ${N.palette.primary.main}`:"none",opacity:y===n.node.id?.4:1,"&:hover .ol-handle":{visibility:"visible"}},children:[E(R,{className:"ol-handle",title:r.drag,onPointerDown:n.depth>0?N=>ye(N,n.node.id):void 0,onPointerMove:Se,onPointerUp:J,onPointerCancel:J,sx:{display:"flex",color:"#b0b4ba",cursor:n.depth>0&&!l?y?"grabbing":"grab":"default",visibility:y===n.node.id?"visible":"hidden",width:18,flexShrink:0,touchAction:"none"},children:n.depth>0&&!l?E(Ke,{sx:{fontSize:16}}):null}),C?E(Le,{size:"small","aria-label":S?r.unfold:r.fold,title:S?r.unfold:r.fold,onClick:()=>I(ae(e,n.node.id)),sx:{width:22,height:22,p:0,color:"text.secondary"},children:S?E(Ue,{sx:{fontSize:20}}):E(We,{sx:{fontSize:20}})}):E(R,{sx:{width:22,display:"flex",justifyContent:"center",flexShrink:0},children:E(R,{sx:{width:5,height:5,borderRadius:"50%",bgcolor:"#9aa0a6"}})}),E(R,{sx:{flex:1,minWidth:0,display:"flex",ml:.5},children:E("input",{ref:N=>{N?m.current.set(n.node.id,N):m.current.delete(n.node.id)},value:n.node.topic,readOnly:l,placeholder:n.depth===0?r.root:"",spellCheck:!1,autoComplete:"off",onFocus:()=>i?.(n.node.id),onChange:N=>I(de(e,n.node.id,N.target.value),`topic:${n.node.id}`),onKeyDown:N=>Ne(N,T),style:{width:b.background?Math.ceil($(n.node.topic||" ",Number(b.fontSize),b.fontWeight))+16:"100%",maxWidth:"100%",border:0,outline:0,font:"inherit",padding:b.background?"2px 6px":"2px 0",borderRadius:4,background:b.background??"transparent",color:b.color??"inherit",fontSize:b.fontSize,fontWeight:b.fontWeight,textDecoration:[b.textDecoration,S&&C?"underline dotted #9aa0a6":""].filter(Boolean).join(" ")||void 0}})})]},n.node.id)})})}import{useCallback as L,useRef as _,useState as Ye}from"react";function Z(e=100,o=1200){let t=_([]),i=_([]),r=_(null),[,l]=Ye(0),d=()=>l(f=>f+1),c=L((f,u)=>{let p=Date.now(),x=u&&r.current?.key===u&&p-r.current.at<o;r.current=u?{key:u,at:p}:null,i.current=[],x||(t.current.push(f),t.current.length>e&&t.current.shift()),d()},[e,o]),g=L(f=>{let u=t.current.pop();return u?(i.current.push(f),r.current=null,d(),u):null},[]),k=L(f=>{let u=i.current.pop();return u?(t.current.push(f),r.current=null,d(),u):null},[]),m=L(()=>{t.current=[],i.current=[],r.current=null,d()},[]);return{canUndo:t.current.length>0,canRedo:i.current.length>0,record:c,undo:g,redo:k,clear:m}}var me={ko:{clearFormat:"\uC11C\uC2DD \uC9C0\uC6B0\uAE30",fontSize:"\uAE00\uC790 \uD06C\uAE30",sizeDefault:"\uAE30\uBCF8",bold:"\uC9C4\uD558\uAC8C",underline:"\uBC11\uC904",strike:"\uCDE8\uC18C\uC120",textColor:"\uAE00\uC790\uC0C9",background:"\uBC30\uACBD\uC0C9",noColor:"\uC5C6\uC74C",undo:"\uB418\uB3CC\uB9AC\uAE30",redo:"\uB2E4\uC2DC \uD558\uAE30",fold:"\uC811\uAE30",unfold:"\uD3BC\uCE58\uAE30",drag:"\uB04C\uC5B4\uC11C \uC62E\uAE30\uAE30",root:"\uC8FC\uC81C",hint:"Enter: \uC0C8 \uC904 \xB7 Tab / Shift+Tab: \uB4E4\uC5EC\uC4F0\uAE30 / \uB0B4\uC5B4\uC4F0\uAE30 \xB7 Alt+\u2191\u2193: \uC21C\uC11C \xB7 \uC904 \uC55E \uC190\uC7A1\uC774 \uB04C\uAE30: \uC62E\uAE30\uAE30 \xB7 \uBE48 \uC904 Backspace: \uC9C0\uC6B0\uAE30"},en:{clearFormat:"Clear format",fontSize:"Font size",sizeDefault:"Default",bold:"Bold",underline:"Underline",strike:"Strikethrough",textColor:"Text color",background:"Background",noColor:"None",undo:"Undo",redo:"Redo",fold:"Collapse",unfold:"Expand",drag:"Drag to move",root:"Topic",hint:"Enter: new line \xB7 Tab / Shift+Tab: indent / outdent \xB7 Alt+\u2191\u2193: reorder \xB7 Drag the row handle: move \xB7 Backspace on empty: delete"},ja:{clearFormat:"\u66F8\u5F0F\u3092\u30AF\u30EA\u30A2",fontSize:"\u6587\u5B57\u30B5\u30A4\u30BA",sizeDefault:"\u6A19\u6E96",bold:"\u592A\u5B57",underline:"\u4E0B\u7DDA",strike:"\u53D6\u308A\u6D88\u3057\u7DDA",textColor:"\u6587\u5B57\u8272",background:"\u80CC\u666F\u8272",noColor:"\u306A\u3057",undo:"\u5143\u306B\u623B\u3059",redo:"\u3084\u308A\u76F4\u3059",fold:"\u6298\u308A\u305F\u305F\u3080",unfold:"\u5C55\u958B",drag:"\u30C9\u30E9\u30C3\u30B0\u3067\u79FB\u52D5",root:"\u30C6\u30FC\u30DE",hint:"Enter: \u65B0\u3057\u3044\u884C \xB7 Tab / Shift+Tab: \u5B57\u4E0B\u3052 / \u5B57\u4E0A\u3052 \xB7 Alt+\u2191\u2193: \u4E26\u3079\u66FF\u3048 \xB7 \u884C\u982D\u306E\u30CF\u30F3\u30C9\u30EB\u3092\u30C9\u30E9\u30C3\u30B0: \u79FB\u52D5 \xB7 \u7A7A\u884C\u3067 Backspace: \u524A\u9664"},zh:{clearFormat:"\u6E05\u9664\u683C\u5F0F",fontSize:"\u5B57\u53F7",sizeDefault:"\u9ED8\u8BA4",bold:"\u52A0\u7C97",underline:"\u4E0B\u5212\u7EBF",strike:"\u5220\u9664\u7EBF",textColor:"\u6587\u5B57\u989C\u8272",background:"\u80CC\u666F\u8272",noColor:"\u65E0",undo:"\u64A4\u9500",redo:"\u91CD\u505A",fold:"\u6298\u53E0",unfold:"\u5C55\u5F00",drag:"\u62D6\u52A8\u4EE5\u79FB\u52A8",root:"\u4E3B\u9898",hint:"Enter: \u65B0\u884C \xB7 Tab / Shift+Tab: \u7F29\u8FDB / \u53D6\u6D88\u7F29\u8FDB \xB7 Alt+\u2191\u2193: \u987A\u5E8F \xB7 \u62D6\u52A8\u884C\u9996\u624B\u67C4: \u79FB\u52A8 \xB7 \u7A7A\u884C Backspace: \u5220\u9664"},de:{clearFormat:"Formatierung l\xF6schen",fontSize:"Schriftgr\xF6\xDFe",sizeDefault:"Standard",bold:"Fett",underline:"Unterstrichen",strike:"Durchgestrichen",textColor:"Textfarbe",background:"Hintergrund",noColor:"Keine",undo:"R\xFCckg\xE4ngig",redo:"Wiederholen",fold:"Einklappen",unfold:"Ausklappen",drag:"Zum Verschieben ziehen",root:"Thema",hint:"Enter: neue Zeile \xB7 Tab / Shift+Tab: ein- / ausr\xFCcken \xB7 Alt+\u2191\u2193: Reihenfolge \xB7 Griff ziehen: verschieben \xB7 Backspace leer: l\xF6schen"},fr:{clearFormat:"Effacer la mise en forme",fontSize:"Taille",sizeDefault:"Par d\xE9faut",bold:"Gras",underline:"Soulign\xE9",strike:"Barr\xE9",textColor:"Couleur du texte",background:"Arri\xE8re-plan",noColor:"Aucune",undo:"Annuler",redo:"R\xE9tablir",fold:"Replier",unfold:"D\xE9plier",drag:"Glisser pour d\xE9placer",root:"Sujet",hint:"Entr\xE9e : nouvelle ligne \xB7 Tab / Maj+Tab : indenter / d\xE9sindenter \xB7 Alt+\u2191\u2193 : ordre \xB7 Glisser la poign\xE9e : d\xE9placer \xB7 Retour arri\xE8re vide : supprimer"},it:{clearFormat:"Cancella formattazione",fontSize:"Dimensione",sizeDefault:"Predefinita",bold:"Grassetto",underline:"Sottolineato",strike:"Barrato",textColor:"Colore testo",background:"Sfondo",noColor:"Nessuno",undo:"Annulla",redo:"Ripeti",fold:"Comprimi",unfold:"Espandi",drag:"Trascina per spostare",root:"Argomento",hint:"Invio: nuova riga \xB7 Tab / Maiusc+Tab: rientro / riduci \xB7 Alt+\u2191\u2193: ordine \xB7 Trascina la maniglia: sposta \xB7 Backspace su vuota: elimina"},vi:{clearFormat:"X\xF3a \u0111\u1ECBnh d\u1EA1ng",fontSize:"C\u1EE1 ch\u1EEF",sizeDefault:"M\u1EB7c \u0111\u1ECBnh",bold:"\u0110\u1EADm",underline:"G\u1EA1ch ch\xE2n",strike:"G\u1EA1ch ngang",textColor:"M\xE0u ch\u1EEF",background:"M\xE0u n\u1EC1n",noColor:"Kh\xF4ng",undo:"Ho\xE0n t\xE1c",redo:"L\xE0m l\u1EA1i",fold:"Thu g\u1ECDn",unfold:"M\u1EDF r\u1ED9ng",drag:"K\xE9o \u0111\u1EC3 di chuy\u1EC3n",root:"Ch\u1EE7 \u0111\u1EC1",hint:"Enter: d\xF2ng m\u1EDBi \xB7 Tab / Shift+Tab: th\u1EE5t v\xE0o / ra \xB7 Alt+\u2191\u2193: th\u1EE9 t\u1EF1 \xB7 K\xE9o tay c\u1EA7m: di chuy\u1EC3n \xB7 Backspace d\xF2ng tr\u1ED1ng: x\xF3a"}};function q(e,o){let t=(e??"en").slice(0,2).toLowerCase();return{...me[t]??me.en,...o}}import{jsx as V,jsxs as qe}from"react/jsx-runtime";function Ze({value:e,onChange:o,locale:t,strings:i,readOnly:r,toolbar:l=!0,toolbarStart:d,toolbarEnd:c,height:g="100%"}){let k=q(t,i),m=Z(),[f,u]=_e(null),p=(s,D)=>{m.record(e,D),o(s)},x=()=>{let s=m.undo(e);s&&o(s)},z=()=>{let s=m.redo(e);s&&o(s)},y=f?h(e,f)?.node:void 0;return qe(Te,{sx:{display:"flex",flexDirection:"column",height:g,minHeight:0,bgcolor:"#fff"},children:[l?V(G,{strings:k,style:y?y.style??{}:void 0,onStyle:s=>{if(!f)return;let D=se(e,[f],s);D&&p(D.root)},canUndo:m.canUndo,canRedo:m.canRedo,onUndo:x,onRedo:z,start:d,end:c,readOnly:r}):null,V(Te,{sx:{flex:1,minHeight:0},children:V(Y,{root:e,onEdit:p,selectedId:f,onSelect:u,strings:k,readOnly:r,onUndo:x,onRedo:z})})]})}export{he as DEFAULT_FONT_FAMILY,pe as FONT_SIZES,G as FormatToolbar,Y as OutlineList,Ze as Outliner,F as ToolButton,H as ToolDivider,K as ToolTip,oe as addBelow,De as addChild,Ce as addSibling,A as containsNode,Ve as createTree,U as hasDecoration,te as indentNode,Xe as isFolded,h as locateNode,$ as measureText,le as moveNode,Q as newNodeId,re as outdentNode,be as outlineTextStyle,q as outlinerStrings,ne as removeNode,se as setNodeStyle,de as setTopic,ie as shiftNode,W as toggleDecoration,ae as toggleFold,Z as useTreeHistory,ee as visibleRows};
2
2
  //# sourceMappingURL=index.esm.js.map
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/Outliner.tsx", "../src/FormatToolbar.tsx", "../src/tree.ts", "../src/OutlineList.tsx", "../src/measure.ts", "../src/history.ts", "../src/i18n.ts"],
4
- "sourcesContent": ["/**\n * Outliner \u2014 toolbar + rows, with its own undo history. Controlled: pass `value` and `onChange`.\n * For a custom layout use `OutlineList` + `FormatToolbar` + `useTreeHistory` directly (the mind map does).\n */\nimport { useState, type ReactNode } from \"react\";\nimport { Box } from \"@mui/material\";\nimport { FormatToolbar } from \"./FormatToolbar\";\nimport { OutlineList } from \"./OutlineList\";\nimport { useTreeHistory } from \"./history\";\nimport { outlinerStrings, type OutlinerStrings } from \"./i18n\";\nimport { locateNode, setNodeStyle, type TreeNode } from \"./tree\";\n\nexport interface OutlinerProps {\n value: TreeNode;\n onChange: (value: TreeNode) => void;\n locale?: string;\n strings?: Partial<OutlinerStrings>;\n readOnly?: boolean;\n /** Show the formatting toolbar (default true). */\n toolbar?: boolean;\n toolbarStart?: ReactNode;\n toolbarEnd?: ReactNode;\n height?: number | string;\n}\n\nexport function Outliner({ value, onChange, locale, strings: overrides, readOnly, toolbar = true, toolbarStart, toolbarEnd, height = \"100%\" }: OutlinerProps) {\n const strings = outlinerStrings(locale, overrides);\n const history = useTreeHistory();\n const [selected, setSelected] = useState<string | null>(null);\n const commit = (next: TreeNode, mergeKey?: string) => {\n history.record(value, mergeKey);\n onChange(next);\n };\n const undo = () => {\n const prev = history.undo(value);\n if (prev) onChange(prev);\n };\n const redo = () => {\n const next = history.redo(value);\n if (next) onChange(next);\n };\n const selectedNode = selected ? locateNode(value, selected)?.node : undefined;\n return (\n <Box sx={{ display: \"flex\", flexDirection: \"column\", height, minHeight: 0, bgcolor: \"#fff\" }}>\n {toolbar ? (\n <FormatToolbar\n strings={strings}\n style={selectedNode ? (selectedNode.style ?? {}) : undefined}\n onStyle={(patch) => {\n if (!selected) return;\n const result = setNodeStyle(value, [selected], patch);\n if (result) commit(result.root);\n }}\n canUndo={history.canUndo}\n canRedo={history.canRedo}\n onUndo={undo}\n onRedo={redo}\n start={toolbarStart}\n end={toolbarEnd}\n readOnly={readOnly}\n />\n ) : null}\n <Box sx={{ flex: 1, minHeight: 0 }}>\n <OutlineList root={value} onEdit={commit} selectedId={selected} onSelect={setSelected} strings={strings} readOnly={readOnly} onUndo={undo} onRedo={redo} />\n </Box>\n </Box>\n );\n}\n", "/**\n * Formatting toolbar \u2014 font size \u00B7 bold \u00B7 underline \u00B7 strike \u00B7 text color \u00B7 background, plus undo / redo.\n * Shared by the outline and the mind map; it edits the style of the selected node(s).\n * `start` / `end` / `children` let the host add its own controls (view switch, map tools, \u2026).\n */\nimport { useState, type ReactNode } from \"react\";\nimport { Box, ButtonBase, Divider, IconButton, Menu, MenuItem, Popover, Tooltip } from \"@mui/material\";\nimport FormatBoldIcon from \"@mui/icons-material/FormatBold\";\nimport FormatUnderlinedIcon from \"@mui/icons-material/FormatUnderlined\";\nimport StrikethroughSIcon from \"@mui/icons-material/StrikethroughS\";\nimport FormatColorTextIcon from \"@mui/icons-material/FormatColorText\";\nimport FormatColorFillIcon from \"@mui/icons-material/FormatColorFill\";\nimport UndoIcon from \"@mui/icons-material/Undo\";\nimport RedoIcon from \"@mui/icons-material/Redo\";\nimport ArrowDropDownIcon from \"@mui/icons-material/ArrowDropDown\";\nimport FormatColorResetIcon from \"@mui/icons-material/FormatColorReset\";\nimport { hasDecoration, toggleDecoration, type TreeNodeStyle } from \"./tree\";\nimport type { OutlinerStrings } from \"./i18n\";\n\nexport const FONT_SIZES = [12, 14, 16, 18, 20, 24, 28];\nexport const TEXT_COLORS = [\"#1f2328\", \"#5f6368\", \"#d93025\", \"#e8710a\", \"#f9ab00\", \"#188038\", \"#1a73e8\", \"#9334e6\", \"#c2185b\", \"#ffffff\"];\nexport const BACKGROUND_COLORS = [\"#fde2e1\", \"#feefc3\", \"#fff8c5\", \"#ceead6\", \"#d2e3fc\", \"#e9d7fe\", \"#fad2e1\", \"#e8eaed\", \"#3c4043\", \"#1a73e8\"];\n\nexport interface FormatToolbarProps {\n strings: OutlinerStrings;\n /** Style of the node being edited (undefined \u2192 nothing selected; format buttons are disabled). */\n style: TreeNodeStyle | undefined;\n onStyle: (patch: Partial<TreeNodeStyle>) => void;\n canUndo?: boolean;\n canRedo?: boolean;\n onUndo?: () => void;\n onRedo?: () => void;\n start?: ReactNode;\n children?: ReactNode;\n end?: ReactNode;\n readOnly?: boolean;\n}\n\nconst btnSx = (active = false) => ({\n width: 30,\n height: 30,\n borderRadius: 1,\n color: active ? \"primary.main\" : \"text.secondary\",\n bgcolor: active ? \"rgba(25,118,210,0.10)\" : \"transparent\",\n \"&:hover\": { bgcolor: active ? \"rgba(25,118,210,0.16)\" : \"rgba(0,0,0,0.06)\" },\n});\n\nexport function ToolButton({ label, active, disabled, onClick, children }: { label: string; active?: boolean; disabled?: boolean; onClick: () => void; children: ReactNode }) {\n return (\n <Tooltip title={label} disableInteractive>\n <span>\n <IconButton size=\"small\" aria-label={label} aria-pressed={active} disabled={disabled} onMouseDown={(event) => event.preventDefault()} onClick={onClick} sx={btnSx(active)}>\n {children}\n </IconButton>\n </span>\n </Tooltip>\n );\n}\n\nexport const ToolDivider = () => <Divider orientation=\"vertical\" flexItem sx={{ mx: 0.5, my: 0.75 }} />;\n\nfunction ColorButton({ label, icon, value, colors, noneLabel, disabled, onPick }: { label: string; icon: ReactNode; value?: string; colors: string[]; noneLabel: string; disabled: boolean; onPick: (color: string | undefined) => void }) {\n const [anchor, setAnchor] = useState<HTMLElement | null>(null);\n return (\n <>\n <Tooltip title={label} disableInteractive>\n <span>\n <IconButton size=\"small\" aria-label={label} disabled={disabled} onMouseDown={(event) => event.preventDefault()} onClick={(event) => setAnchor(event.currentTarget)} sx={{ ...btnSx(false), flexDirection: \"column\", gap: 0 }}>\n {icon}\n <Box sx={{ width: 16, height: 3, mt: \"-3px\", borderRadius: 0.5, bgcolor: value ?? \"transparent\", border: value ? 0 : \"1px solid #c4c7cc\" }} />\n </IconButton>\n </span>\n </Tooltip>\n <Popover open={Boolean(anchor)} anchorEl={anchor} onClose={() => setAnchor(null)} transitionDuration={0} anchorOrigin={{ vertical: \"bottom\", horizontal: \"left\" }} disableRestoreFocus>\n <Box sx={{ p: 1, display: \"grid\", gridTemplateColumns: \"repeat(5, 24px)\", gap: 0.75 }}>\n {colors.map((color) => (\n <ButtonBase\n key={color}\n aria-label={color}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n onPick(color);\n setAnchor(null);\n }}\n sx={{ width: 24, height: 24, borderRadius: 0.75, bgcolor: color, border: \"1px solid rgba(0,0,0,0.12)\", outline: value?.toLowerCase() === color ? \"2px solid #1a73e8\" : \"none\", outlineOffset: 1 }}\n />\n ))}\n <ButtonBase\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n onPick(undefined);\n setAnchor(null);\n }}\n sx={{ gridColumn: \"1 / -1\", height: 26, borderRadius: 0.75, fontSize: 13, color: \"text.secondary\", gap: 0.5, \"&:hover\": { bgcolor: \"rgba(0,0,0,0.05)\" } }}\n >\n <FormatColorResetIcon sx={{ fontSize: 16 }} />\n {noneLabel}\n </ButtonBase>\n </Box>\n </Popover>\n </>\n );\n}\n\nexport function FormatToolbar({ strings, style, onStyle, canUndo, canRedo, onUndo, onRedo, start, children, end, readOnly }: FormatToolbarProps) {\n const [sizeAnchor, setSizeAnchor] = useState<HTMLElement | null>(null);\n const disabled = readOnly || !style;\n const size = style?.fontSize ? parseFloat(style.fontSize) : null;\n const bold = style?.fontWeight === \"bold\" || Number(style?.fontWeight) >= 600;\n return (\n <Box\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n flexWrap: \"wrap\",\n gap: 0.25,\n minHeight: 40,\n px: 1,\n borderBottom: \"1px solid #e0e0e0\",\n bgcolor: \"#fff\",\n flexShrink: 0,\n }}\n >\n {start}\n {start ? <ToolDivider /> : null}\n {onUndo ? (\n <>\n <ToolButton label={strings.undo} disabled={readOnly || !canUndo} onClick={onUndo}>\n <UndoIcon sx={{ fontSize: 18 }} />\n </ToolButton>\n <ToolButton label={strings.redo} disabled={readOnly || !canRedo} onClick={() => onRedo?.()}>\n <RedoIcon sx={{ fontSize: 18 }} />\n </ToolButton>\n <ToolDivider />\n </>\n ) : null}\n <Tooltip title={strings.fontSize} disableInteractive>\n <span>\n <ButtonBase\n disabled={disabled}\n onMouseDown={(event) => event.preventDefault()}\n onClick={(event) => setSizeAnchor(event.currentTarget)}\n sx={{ height: 30, px: 0.75, borderRadius: 1, fontSize: 13, color: disabled ? \"text.disabled\" : \"text.primary\", minWidth: 52, justifyContent: \"space-between\", \"&:hover\": { bgcolor: \"rgba(0,0,0,0.06)\" } }}\n >\n {size ?? strings.sizeDefault}\n <ArrowDropDownIcon sx={{ fontSize: 18, color: \"text.secondary\" }} />\n </ButtonBase>\n </span>\n </Tooltip>\n <Menu open={Boolean(sizeAnchor)} anchorEl={sizeAnchor} onClose={() => setSizeAnchor(null)} transitionDuration={0} disableRestoreFocus>\n <MenuItem\n dense\n selected={size === null}\n onClick={() => {\n onStyle({ fontSize: undefined });\n setSizeAnchor(null);\n }}\n >\n {strings.sizeDefault}\n </MenuItem>\n {FONT_SIZES.map((value) => (\n <MenuItem\n key={value}\n dense\n selected={size === value}\n onClick={() => {\n onStyle({ fontSize: `${value}px` });\n setSizeAnchor(null);\n }}\n >\n {value}\n </MenuItem>\n ))}\n </Menu>\n <ToolButton label={strings.bold} active={bold} disabled={disabled} onClick={() => onStyle({ fontWeight: bold ? undefined : \"bold\" })}>\n <FormatBoldIcon sx={{ fontSize: 19 }} />\n </ToolButton>\n <ToolButton label={strings.underline} active={hasDecoration(style, \"underline\")} disabled={disabled} onClick={() => onStyle({ textDecoration: toggleDecoration(style, \"underline\") })}>\n <FormatUnderlinedIcon sx={{ fontSize: 19 }} />\n </ToolButton>\n <ToolButton label={strings.strike} active={hasDecoration(style, \"line-through\")} disabled={disabled} onClick={() => onStyle({ textDecoration: toggleDecoration(style, \"line-through\") })}>\n <StrikethroughSIcon sx={{ fontSize: 19 }} />\n </ToolButton>\n <ColorButton label={strings.textColor} icon={<FormatColorTextIcon sx={{ fontSize: 17 }} />} value={style?.color} colors={TEXT_COLORS} noneLabel={strings.noColor} disabled={disabled} onPick={(color) => onStyle({ color })} />\n <ColorButton label={strings.background} icon={<FormatColorFillIcon sx={{ fontSize: 17 }} />} value={style?.background} colors={BACKGROUND_COLORS} noneLabel={strings.noColor} disabled={disabled} onPick={(color) => onStyle({ background: color })} />\n {children ? <ToolDivider /> : null}\n {children}\n <Box sx={{ flex: 1 }} />\n {end}\n </Box>\n );\n}\n", "/**\n * Tree data and edit operations shared by the outline and the mind map.\n *\n * The shape follows Mind Elixir's `nodeData` so data saved by it opens unchanged:\n * `{ id, topic, children?, expanded?, style? }` \u2014 unknown keys are carried along untouched.\n * Every operation is pure: it returns a new root (structural copy) and, when useful,\n * the id that should be focused next.\n */\n\n/** Text style of one node (same keys as Mind Elixir `style`). */\nexport interface TreeNodeStyle {\n fontSize?: string;\n color?: string;\n background?: string;\n fontWeight?: string;\n textDecoration?: string;\n}\n\nexport interface TreeNode {\n id: string;\n topic: string;\n children?: TreeNode[];\n /** `false` = folded. Missing means expanded. */\n expanded?: boolean;\n style?: TreeNodeStyle;\n [key: string]: unknown;\n}\n\nexport interface TreeEdit {\n root: TreeNode;\n /** Node to select / focus after the edit. */\n focusId?: string;\n}\n\nexport interface TreeRow {\n node: TreeNode;\n depth: number;\n parentId: string | null;\n}\n\n/** Short random id (hex, like Mind Elixir). */\nexport const newNodeId = () => Math.random().toString(16).slice(2, 18);\n\nexport const createTree = (topic: string): TreeNode => ({ id: \"root\", topic, children: [] });\n\nconst clone = (root: TreeNode): TreeNode => structuredClone(root) as TreeNode;\n\n/** Finds a node with its parent and index (in the given tree). */\nexport function locateNode(root: TreeNode, id: string): { node: TreeNode; parent: TreeNode | null; index: number } | null {\n if (root.id === id) return { node: root, parent: null, index: 0 };\n const stack: TreeNode[] = [root];\n while (stack.length) {\n const parent = stack.pop()!;\n const list = parent.children ?? [];\n for (let i = 0; i < list.length; i++) {\n if (list[i].id === id) return { node: list[i], parent, index: i };\n stack.push(list[i]);\n }\n }\n return null;\n}\n\n/** True when `id` is `node` itself or one of its descendants. */\nexport const containsNode = (node: TreeNode, id: string): boolean => node.id === id || (node.children ?? []).some((child) => containsNode(child, id));\n\nexport const isFolded = (node: TreeNode) => node.expanded === false && (node.children?.length ?? 0) > 0;\n\n/** Rows that are visible (folded subtrees hidden), in reading order. */\nexport function visibleRows(root: TreeNode): TreeRow[] {\n const rows: TreeRow[] = [];\n const walk = (node: TreeNode, depth: number, parentId: string | null) => {\n rows.push({ node, depth, parentId });\n if (node.expanded !== false) for (const child of node.children ?? []) walk(child, depth + 1, node.id);\n };\n walk(root, 0, null);\n return rows;\n}\n\n/** Runs `run` on a copy; returns null when nothing changed (run returned false). */\nfunction edit(root: TreeNode, run: (copy: TreeNode) => string | void | false): TreeEdit | null {\n const copy = clone(root);\n const focusId = run(copy);\n if (focusId === false) return null;\n return { root: copy, focusId: focusId || undefined };\n}\n\n/** New child at the end (or `first`). */\nexport const addChild = (root: TreeNode, id: string, topic = \"\", first = false) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at) return false;\n const fresh: TreeNode = { id: newNodeId(), topic };\n at.node.children = first ? [fresh, ...(at.node.children ?? [])] : [...(at.node.children ?? []), fresh];\n at.node.expanded = true;\n return fresh.id;\n });\n\n/** New sibling right after (root \u2192 first child). */\nexport const addSibling = (root: TreeNode, id: string, topic = \"\") =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at) return false;\n const fresh: TreeNode = { id: newNodeId(), topic };\n if (!at.parent) {\n at.node.children = [fresh, ...(at.node.children ?? [])];\n at.node.expanded = true;\n } else at.parent.children!.splice(at.index + 1, 0, fresh);\n return fresh.id;\n });\n\n/** Outline \"Enter\": first child when the row is an open parent, otherwise next sibling. */\nexport const addBelow = (root: TreeNode, id: string) => {\n const at = locateNode(root, id);\n if (at && (!at.parent || ((at.node.children?.length ?? 0) > 0 && at.node.expanded !== false))) return addChild(root, id, \"\", true);\n return addSibling(root, id);\n};\n\n/** Removes the node (not the root). Focus goes to the previous sibling, else the parent. */\nexport const removeNode = (root: TreeNode, id: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent) return false;\n at.parent.children!.splice(at.index, 1);\n return at.parent.children![at.index - 1]?.id ?? at.parent.id;\n });\n\n/** Becomes the last child of the previous sibling. */\nexport const indentNode = (root: TreeNode, id: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent || at.index === 0) return false;\n const prev = at.parent.children![at.index - 1];\n at.parent.children!.splice(at.index, 1);\n prev.children = [...(prev.children ?? []), at.node];\n prev.expanded = true;\n return id;\n });\n\n/** Becomes the sibling right after its parent. */\nexport const outdentNode = (root: TreeNode, id: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent) return false;\n const up = locateNode(copy, at.parent.id);\n if (!up?.parent) return false;\n at.parent.children!.splice(at.index, 1);\n up.parent.children!.splice(up.index + 1, 0, at.node);\n return id;\n });\n\n/** Moves one step among its siblings. */\nexport const shiftNode = (root: TreeNode, id: string, step: -1 | 1) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent) return false;\n const list = at.parent.children!;\n const to = at.index + step;\n if (to < 0 || to >= list.length) return false;\n [list[at.index], list[to]] = [list[to], list[at.index]];\n return id;\n });\n\n/** Moves `from` before / after `to`, or into `to` as its last child. */\nexport const moveNode = (root: TreeNode, from: string, to: string, place: \"before\" | \"after\" | \"child\") =>\n edit(root, (copy) => {\n const src = locateNode(copy, from);\n if (!src?.parent || containsNode(src.node, to)) return false;\n src.parent.children!.splice(src.index, 1);\n const dst = locateNode(copy, to);\n if (!dst) return false;\n if (place === \"child\" || !dst.parent) {\n dst.node.children = [...(dst.node.children ?? []), src.node];\n dst.node.expanded = true;\n } else dst.parent.children!.splice(dst.index + (place === \"after\" ? 1 : 0), 0, src.node);\n return from;\n });\n\nexport const setTopic = (root: TreeNode, id: string, topic: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at || at.node.topic === topic) return false;\n at.node.topic = topic;\n });\n\nexport const toggleFold = (root: TreeNode, id: string, expanded?: boolean) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at || !(at.node.children?.length ?? 0)) return false;\n at.node.expanded = expanded ?? at.node.expanded === false;\n });\n\n/** Merges a style patch; `undefined` values remove the key. */\nexport const setNodeStyle = (root: TreeNode, ids: string[], patch: Partial<TreeNodeStyle>) =>\n edit(root, (copy) => {\n let changed = false;\n for (const id of ids) {\n const at = locateNode(copy, id);\n if (!at) continue;\n const next: TreeNodeStyle = { ...(at.node.style ?? {}) };\n for (const [key, value] of Object.entries(patch) as [keyof TreeNodeStyle, string | undefined][]) {\n if (value === undefined || value === \"\") delete next[key];\n else next[key] = value;\n }\n at.node.style = Object.keys(next).length ? next : undefined;\n if (!at.node.style) delete at.node.style;\n changed = true;\n }\n return changed ? undefined : false;\n });\n\n/** `textDecoration` holds both underline and line-through. */\nexport function hasDecoration(style: TreeNodeStyle | undefined, kind: \"underline\" | \"line-through\") {\n return (style?.textDecoration ?? \"\").split(/\\s+/).includes(kind);\n}\nexport function toggleDecoration(style: TreeNodeStyle | undefined, kind: \"underline\" | \"line-through\"): string | undefined {\n const set = new Set((style?.textDecoration ?? \"\").split(/\\s+/).filter(Boolean));\n if (set.has(kind)) set.delete(kind);\n else set.add(kind);\n return set.size ? [...set].join(\" \") : undefined;\n}\n", "/**\n * Outline rows \u2014 one node per line, fold / unfold, indent / outdent, reorder, drag to move, per-node style.\n *\n * Keys: Enter new line \u00B7 Tab indent \u00B7 Shift+Tab outdent \u00B7 Alt+\u2191/\u2193 reorder \u00B7 \u2191/\u2193 previous / next row \u00B7\n * Backspace on an empty row deletes it \u00B7 Ctrl/\u2318+Z undo \u00B7 Ctrl/\u2318+Shift+Z or Ctrl+Y redo.\n * Dragging follows the pointer directly (native drag & drop doesn't fire drops reliably inside drawers / modals).\n */\nimport { useEffect, useRef, useState, type CSSProperties, type KeyboardEvent, type PointerEvent } from \"react\";\nimport { Box, IconButton } from \"@mui/material\";\nimport ArrowRightIcon from \"@mui/icons-material/ArrowRight\";\nimport ArrowDropDownIcon from \"@mui/icons-material/ArrowDropDown\";\nimport DragIndicatorIcon from \"@mui/icons-material/DragIndicator\";\nimport {\n addBelow,\n containsNode,\n indentNode,\n locateNode,\n moveNode,\n outdentNode,\n removeNode,\n setTopic,\n shiftNode,\n toggleFold,\n visibleRows,\n type TreeEdit,\n type TreeNode,\n type TreeNodeStyle,\n} from \"./tree\";\nimport type { OutlinerStrings } from \"./i18n\";\nimport { measureText } from \"./measure\";\n\nconst INDENT = 22;\nconst BASE_FONT = 15;\n\nexport interface OutlineListProps {\n root: TreeNode;\n /** A change; `mergeKey` is set for typing so history can merge it. */\n onEdit: (root: TreeNode, mergeKey?: string) => void;\n selectedId?: string | null;\n onSelect?: (id: string) => void;\n strings: OutlinerStrings;\n readOnly?: boolean;\n onUndo?: () => void;\n onRedo?: () => void;\n /** Extra space above the first row / below the last row (px). */\n paddingTop?: number;\n paddingBottom?: number;\n}\n\n/** Node style \u2192 input style (font size is clamped so the list stays a list). */\nexport function outlineTextStyle(style: TreeNodeStyle | undefined, depth: number): CSSProperties {\n const size = style?.fontSize ? Math.min(28, Math.max(12, parseFloat(style.fontSize))) : BASE_FONT;\n return {\n fontSize: size,\n fontWeight: style?.fontWeight ?? (depth === 0 ? 700 : 400),\n color: style?.color,\n textDecoration: style?.textDecoration,\n background: style?.background,\n };\n}\n\nexport function OutlineList({ root, onEdit, selectedId, onSelect, strings, readOnly, onUndo, onRedo, paddingTop = 8, paddingBottom = 40 }: OutlineListProps) {\n const inputs = useRef(new Map<string, HTMLInputElement>());\n const rowEls = useRef(new Map<string, HTMLDivElement>());\n const [focus, setFocus] = useState<string | null>(null);\n const [drop, setDrop] = useState<{ id: string; place: \"before\" | \"after\" } | null>(null);\n const [dragging, setDragging] = useState<string | null>(null);\n const rows = visibleRows(root);\n\n useEffect(() => {\n if (!focus) return;\n const el = inputs.current.get(focus);\n if (!el) return;\n el.focus();\n el.setSelectionRange(el.value.length, el.value.length);\n setFocus(null);\n }, [focus, root]);\n\n const apply = (result: TreeEdit | null, mergeKey?: string) => {\n if (!result) return;\n onEdit(result.root, mergeKey);\n if (result.focusId) {\n setFocus(result.focusId);\n onSelect?.(result.focusId);\n }\n };\n\n const onKey = (event: KeyboardEvent<HTMLInputElement>, index: number) => {\n if (event.nativeEvent.isComposing) return;\n const row = rows[index];\n const id = row.node.id;\n const mod = event.ctrlKey || event.metaKey;\n if (mod && (event.key === \"z\" || event.key === \"Z\")) {\n event.preventDefault();\n if (event.shiftKey) onRedo?.();\n else onUndo?.();\n return;\n }\n if (mod && (event.key === \"y\" || event.key === \"Y\")) {\n event.preventDefault();\n onRedo?.();\n return;\n }\n if (readOnly) return;\n if (event.key === \"Enter\") {\n event.preventDefault();\n apply(addBelow(root, id));\n } else if (event.key === \"Tab\") {\n event.preventDefault();\n apply(event.shiftKey ? outdentNode(root, id) : indentNode(root, id));\n } else if (event.altKey && (event.key === \"ArrowUp\" || event.key === \"ArrowDown\")) {\n event.preventDefault();\n apply(shiftNode(root, id, event.key === \"ArrowUp\" ? -1 : 1));\n } else if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\n const next = rows[index + (event.key === \"ArrowUp\" ? -1 : 1)];\n if (next) {\n event.preventDefault();\n setFocus(next.node.id);\n onSelect?.(next.node.id);\n }\n } else if (event.key === \"Backspace\" && event.currentTarget.value === \"\" && row.depth > 0 && !(row.node.children?.length ?? 0)) {\n event.preventDefault();\n const result = removeNode(root, id);\n if (result) apply({ root: result.root, focusId: rows[index - 1]?.node.id });\n }\n };\n\n // Drag \u2014 follow the pointer on the handle; drop before / after the row under it (never into itself).\n const dragNode = dragging ? locateNode(root, dragging)?.node ?? null : null;\n const onHandleDown = (event: PointerEvent<HTMLDivElement>, id: string) => {\n if (event.button !== 0 || readOnly) return;\n event.preventDefault();\n event.currentTarget.setPointerCapture(event.pointerId);\n setDragging(id);\n setDrop(null);\n };\n const onHandleMove = (event: PointerEvent<HTMLDivElement>) => {\n if (!dragging || !dragNode) return;\n let next: { id: string; place: \"before\" | \"after\" } | null = null;\n for (const row of rows) {\n const el = rowEls.current.get(row.node.id);\n if (!el) continue;\n const r = el.getBoundingClientRect();\n if (event.clientY < r.top || event.clientY >= r.bottom) continue;\n if (!containsNode(dragNode, row.node.id)) next = { id: row.node.id, place: event.clientY < r.top + r.height / 2 ? \"before\" : \"after\" };\n break;\n }\n if (next?.id !== drop?.id || next?.place !== drop?.place) setDrop(next);\n };\n const onHandleUp = (event: PointerEvent<HTMLDivElement>) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);\n if (dragging && drop) apply(moveNode(root, dragging, drop.id, drop.place));\n setDragging(null);\n setDrop(null);\n };\n\n return (\n <Box sx={{ position: \"relative\", height: \"100%\", overflowY: \"auto\", bgcolor: \"#fff\", pt: `${paddingTop}px`, pb: `${paddingBottom}px`, px: 1.5 }}>\n {rows.map((row, index) => {\n const hasKids = (row.node.children?.length ?? 0) > 0;\n const folded = row.node.expanded === false;\n const line = drop?.id === row.node.id ? drop.place : null;\n const text = outlineTextStyle(row.node.style, row.depth);\n return (\n <Box\n key={row.node.id}\n ref={(el: HTMLDivElement | null) => {\n if (el) rowEls.current.set(row.node.id, el);\n else rowEls.current.delete(row.node.id);\n }}\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n minHeight: 26,\n pl: `${row.depth * INDENT}px`,\n borderRadius: 0.75,\n bgcolor: selectedId === row.node.id ? \"rgba(26,115,232,0.06)\" : \"transparent\",\n // Drop line \u2014 inset shadow so it takes no height.\n boxShadow: (theme) =>\n line === \"before\" ? `inset 0 2px 0 ${theme.palette.primary.main}` : line === \"after\" ? `inset 0 -2px 0 ${theme.palette.primary.main}` : \"none\",\n opacity: dragging === row.node.id ? 0.4 : 1,\n \"&:hover .ol-handle\": { visibility: \"visible\" },\n }}\n >\n <Box\n className=\"ol-handle\"\n title={strings.drag}\n onPointerDown={row.depth > 0 ? (event: PointerEvent<HTMLDivElement>) => onHandleDown(event, row.node.id) : undefined}\n onPointerMove={onHandleMove}\n onPointerUp={onHandleUp}\n onPointerCancel={onHandleUp}\n sx={{\n display: \"flex\",\n color: \"#b0b4ba\",\n cursor: row.depth > 0 && !readOnly ? (dragging ? \"grabbing\" : \"grab\") : \"default\",\n visibility: dragging === row.node.id ? \"visible\" : \"hidden\",\n width: 18,\n flexShrink: 0,\n touchAction: \"none\",\n }}\n >\n {row.depth > 0 && !readOnly ? <DragIndicatorIcon sx={{ fontSize: 16 }} /> : null}\n </Box>\n {hasKids ? (\n <IconButton\n size=\"small\"\n aria-label={folded ? strings.unfold : strings.fold}\n title={folded ? strings.unfold : strings.fold}\n onClick={() => apply(toggleFold(root, row.node.id))}\n sx={{ width: 22, height: 22, p: 0, color: \"text.secondary\" }}\n >\n {folded ? <ArrowRightIcon sx={{ fontSize: 20 }} /> : <ArrowDropDownIcon sx={{ fontSize: 20 }} />}\n </IconButton>\n ) : (\n <Box sx={{ width: 22, display: \"flex\", justifyContent: \"center\", flexShrink: 0 }}>\n <Box sx={{ width: 5, height: 5, borderRadius: \"50%\", bgcolor: \"#9aa0a6\" }} />\n </Box>\n )}\n <Box sx={{ flex: 1, minWidth: 0, display: \"flex\", ml: 0.5 }}>\n <input\n ref={(el) => {\n if (el) inputs.current.set(row.node.id, el);\n else inputs.current.delete(row.node.id);\n }}\n value={row.node.topic}\n readOnly={readOnly}\n placeholder={row.depth === 0 ? strings.root : \"\"}\n spellCheck={false}\n autoComplete=\"off\"\n onFocus={() => onSelect?.(row.node.id)}\n onChange={(event) => apply(setTopic(root, row.node.id, event.target.value), `topic:${row.node.id}`)}\n onKeyDown={(event) => onKey(event, index)}\n style={{\n // Background hugs the text like a highlighter; the input keeps full width for clicks.\n width: text.background ? Math.ceil(measureText(row.node.topic || \" \", Number(text.fontSize), text.fontWeight as string)) + 16 : \"100%\",\n maxWidth: \"100%\",\n border: 0,\n outline: 0,\n font: \"inherit\",\n padding: text.background ? \"2px 6px\" : \"2px 0\",\n borderRadius: 4,\n background: text.background ?? \"transparent\",\n color: text.color ?? \"inherit\",\n fontSize: text.fontSize,\n fontWeight: text.fontWeight,\n textDecoration: [text.textDecoration, folded && hasKids ? \"underline dotted #9aa0a6\" : \"\"].filter(Boolean).join(\" \") || undefined,\n }}\n />\n </Box>\n </Box>\n );\n })}\n </Box>\n );\n}\n", "/** Text width with a cached canvas (used for highlight width in the outline and node sizes in the map). */\nlet ctx: CanvasRenderingContext2D | null = null;\nconst cache = new Map<string, number>();\n\nexport const DEFAULT_FONT_FAMILY = \"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif\";\n\nexport function measureText(text: string, fontSize: number, fontWeight: string | number = 400, fontFamily = DEFAULT_FONT_FAMILY): number {\n const font = `${fontWeight} ${fontSize}px ${fontFamily}`;\n const key = `${font}|${text}`;\n const hit = cache.get(key);\n if (hit !== undefined) return hit;\n if (!ctx && typeof document !== \"undefined\") ctx = document.createElement(\"canvas\").getContext(\"2d\");\n // No canvas (SSR / tests) \u2014 rough guess: wide glyphs 1em, others 0.55em.\n let width = 0;\n if (ctx) {\n ctx.font = font;\n width = ctx.measureText(text).width;\n } else for (const ch of text) width += (/[\u1100-\uFFDC]/.test(ch) ? 1 : 0.55) * fontSize;\n if (cache.size > 5000) cache.clear();\n cache.set(key, width);\n return width;\n}\n", "/**\n * Undo / redo for a controlled tree.\n * Typing into one node within `mergeMs` is merged into one step, so undo doesn't go back one letter at a time.\n */\nimport { useCallback, useRef, useState } from \"react\";\nimport type { TreeNode } from \"./tree\";\n\nexport interface TreeHistory {\n canUndo: boolean;\n canRedo: boolean;\n /** Records the tree before a change. `mergeKey` merges consecutive changes with the same key (e.g. typing in one node). */\n record: (before: TreeNode, mergeKey?: string) => void;\n undo: (current: TreeNode) => TreeNode | null;\n redo: (current: TreeNode) => TreeNode | null;\n clear: () => void;\n}\n\nexport function useTreeHistory(limit = 100, mergeMs = 1200): TreeHistory {\n const past = useRef<TreeNode[]>([]);\n const future = useRef<TreeNode[]>([]);\n const last = useRef<{ key: string; at: number } | null>(null);\n const [, bump] = useState(0);\n const refresh = () => bump((n) => n + 1);\n\n const record = useCallback(\n (before: TreeNode, mergeKey?: string) => {\n const now = Date.now();\n const merge = mergeKey && last.current?.key === mergeKey && now - last.current.at < mergeMs;\n last.current = mergeKey ? { key: mergeKey, at: now } : null;\n future.current = [];\n if (!merge) {\n past.current.push(before);\n if (past.current.length > limit) past.current.shift();\n }\n refresh();\n },\n [limit, mergeMs]\n );\n const undo = useCallback((current: TreeNode) => {\n const prev = past.current.pop();\n if (!prev) return null;\n future.current.push(current);\n last.current = null;\n refresh();\n return prev;\n }, []);\n const redo = useCallback((current: TreeNode) => {\n const next = future.current.pop();\n if (!next) return null;\n past.current.push(current);\n last.current = null;\n refresh();\n return next;\n }, []);\n const clear = useCallback(() => {\n past.current = [];\n future.current = [];\n last.current = null;\n refresh();\n }, []);\n return { canUndo: past.current.length > 0, canRedo: future.current.length > 0, record, undo, redo, clear };\n}\n", "/** UI strings (ko \u00B7 en \u00B7 ja \u00B7 zh \u00B7 de \u00B7 fr \u00B7 it \u00B7 vi). Unknown locale \u2192 English. */\nconst STRINGS = {\n ko: {\n fontSize: \"\uAE00\uC790 \uD06C\uAE30\",\n sizeDefault: \"\uAE30\uBCF8\",\n bold: \"\uC9C4\uD558\uAC8C\",\n underline: \"\uBC11\uC904\",\n strike: \"\uCDE8\uC18C\uC120\",\n textColor: \"\uAE00\uC790\uC0C9\",\n background: \"\uBC30\uACBD\uC0C9\",\n noColor: \"\uC5C6\uC74C\",\n undo: \"\uB418\uB3CC\uB9AC\uAE30\",\n redo: \"\uB2E4\uC2DC \uD558\uAE30\",\n fold: \"\uC811\uAE30\",\n unfold: \"\uD3BC\uCE58\uAE30\",\n drag: \"\uB04C\uC5B4\uC11C \uC62E\uAE30\uAE30\",\n root: \"\uC8FC\uC81C\",\n hint: \"Enter: \uC0C8 \uC904 \u00B7 Tab / Shift+Tab: \uB4E4\uC5EC\uC4F0\uAE30 / \uB0B4\uC5B4\uC4F0\uAE30 \u00B7 Alt+\u2191\u2193: \uC21C\uC11C \u00B7 \uC904 \uC55E \uC190\uC7A1\uC774 \uB04C\uAE30: \uC62E\uAE30\uAE30 \u00B7 \uBE48 \uC904 Backspace: \uC9C0\uC6B0\uAE30\",\n },\n en: {\n fontSize: \"Font size\",\n sizeDefault: \"Default\",\n bold: \"Bold\",\n underline: \"Underline\",\n strike: \"Strikethrough\",\n textColor: \"Text color\",\n background: \"Background\",\n noColor: \"None\",\n undo: \"Undo\",\n redo: \"Redo\",\n fold: \"Collapse\",\n unfold: \"Expand\",\n drag: \"Drag to move\",\n root: \"Topic\",\n hint: \"Enter: new line \u00B7 Tab / Shift+Tab: indent / outdent \u00B7 Alt+\u2191\u2193: reorder \u00B7 Drag the row handle: move \u00B7 Backspace on empty: delete\",\n },\n ja: {\n fontSize: \"\u6587\u5B57\u30B5\u30A4\u30BA\",\n sizeDefault: \"\u6A19\u6E96\",\n bold: \"\u592A\u5B57\",\n underline: \"\u4E0B\u7DDA\",\n strike: \"\u53D6\u308A\u6D88\u3057\u7DDA\",\n textColor: \"\u6587\u5B57\u8272\",\n background: \"\u80CC\u666F\u8272\",\n noColor: \"\u306A\u3057\",\n undo: \"\u5143\u306B\u623B\u3059\",\n redo: \"\u3084\u308A\u76F4\u3059\",\n fold: \"\u6298\u308A\u305F\u305F\u3080\",\n unfold: \"\u5C55\u958B\",\n drag: \"\u30C9\u30E9\u30C3\u30B0\u3067\u79FB\u52D5\",\n root: \"\u30C6\u30FC\u30DE\",\n hint: \"Enter: \u65B0\u3057\u3044\u884C \u00B7 Tab / Shift+Tab: \u5B57\u4E0B\u3052 / \u5B57\u4E0A\u3052 \u00B7 Alt+\u2191\u2193: \u4E26\u3079\u66FF\u3048 \u00B7 \u884C\u982D\u306E\u30CF\u30F3\u30C9\u30EB\u3092\u30C9\u30E9\u30C3\u30B0: \u79FB\u52D5 \u00B7 \u7A7A\u884C\u3067 Backspace: \u524A\u9664\",\n },\n zh: {\n fontSize: \"\u5B57\u53F7\",\n sizeDefault: \"\u9ED8\u8BA4\",\n bold: \"\u52A0\u7C97\",\n underline: \"\u4E0B\u5212\u7EBF\",\n strike: \"\u5220\u9664\u7EBF\",\n textColor: \"\u6587\u5B57\u989C\u8272\",\n background: \"\u80CC\u666F\u8272\",\n noColor: \"\u65E0\",\n undo: \"\u64A4\u9500\",\n redo: \"\u91CD\u505A\",\n fold: \"\u6298\u53E0\",\n unfold: \"\u5C55\u5F00\",\n drag: \"\u62D6\u52A8\u4EE5\u79FB\u52A8\",\n root: \"\u4E3B\u9898\",\n hint: \"Enter: \u65B0\u884C \u00B7 Tab / Shift+Tab: \u7F29\u8FDB / \u53D6\u6D88\u7F29\u8FDB \u00B7 Alt+\u2191\u2193: \u987A\u5E8F \u00B7 \u62D6\u52A8\u884C\u9996\u624B\u67C4: \u79FB\u52A8 \u00B7 \u7A7A\u884C Backspace: \u5220\u9664\",\n },\n de: {\n fontSize: \"Schriftgr\u00F6\u00DFe\",\n sizeDefault: \"Standard\",\n bold: \"Fett\",\n underline: \"Unterstrichen\",\n strike: \"Durchgestrichen\",\n textColor: \"Textfarbe\",\n background: \"Hintergrund\",\n noColor: \"Keine\",\n undo: \"R\u00FCckg\u00E4ngig\",\n redo: \"Wiederholen\",\n fold: \"Einklappen\",\n unfold: \"Ausklappen\",\n drag: \"Zum Verschieben ziehen\",\n root: \"Thema\",\n hint: \"Enter: neue Zeile \u00B7 Tab / Shift+Tab: ein- / ausr\u00FCcken \u00B7 Alt+\u2191\u2193: Reihenfolge \u00B7 Griff ziehen: verschieben \u00B7 Backspace leer: l\u00F6schen\",\n },\n fr: {\n fontSize: \"Taille\",\n sizeDefault: \"Par d\u00E9faut\",\n bold: \"Gras\",\n underline: \"Soulign\u00E9\",\n strike: \"Barr\u00E9\",\n textColor: \"Couleur du texte\",\n background: \"Arri\u00E8re-plan\",\n noColor: \"Aucune\",\n undo: \"Annuler\",\n redo: \"R\u00E9tablir\",\n fold: \"Replier\",\n unfold: \"D\u00E9plier\",\n drag: \"Glisser pour d\u00E9placer\",\n root: \"Sujet\",\n hint: \"Entr\u00E9e : nouvelle ligne \u00B7 Tab / Maj+Tab : indenter / d\u00E9sindenter \u00B7 Alt+\u2191\u2193 : ordre \u00B7 Glisser la poign\u00E9e : d\u00E9placer \u00B7 Retour arri\u00E8re vide : supprimer\",\n },\n it: {\n fontSize: \"Dimensione\",\n sizeDefault: \"Predefinita\",\n bold: \"Grassetto\",\n underline: \"Sottolineato\",\n strike: \"Barrato\",\n textColor: \"Colore testo\",\n background: \"Sfondo\",\n noColor: \"Nessuno\",\n undo: \"Annulla\",\n redo: \"Ripeti\",\n fold: \"Comprimi\",\n unfold: \"Espandi\",\n drag: \"Trascina per spostare\",\n root: \"Argomento\",\n hint: \"Invio: nuova riga \u00B7 Tab / Maiusc+Tab: rientro / riduci \u00B7 Alt+\u2191\u2193: ordine \u00B7 Trascina la maniglia: sposta \u00B7 Backspace su vuota: elimina\",\n },\n vi: {\n fontSize: \"C\u1EE1 ch\u1EEF\",\n sizeDefault: \"M\u1EB7c \u0111\u1ECBnh\",\n bold: \"\u0110\u1EADm\",\n underline: \"G\u1EA1ch ch\u00E2n\",\n strike: \"G\u1EA1ch ngang\",\n textColor: \"M\u00E0u ch\u1EEF\",\n background: \"M\u00E0u n\u1EC1n\",\n noColor: \"Kh\u00F4ng\",\n undo: \"Ho\u00E0n t\u00E1c\",\n redo: \"L\u00E0m l\u1EA1i\",\n fold: \"Thu g\u1ECDn\",\n unfold: \"M\u1EDF r\u1ED9ng\",\n drag: \"K\u00E9o \u0111\u1EC3 di chuy\u1EC3n\",\n root: \"Ch\u1EE7 \u0111\u1EC1\",\n hint: \"Enter: d\u00F2ng m\u1EDBi \u00B7 Tab / Shift+Tab: th\u1EE5t v\u00E0o / ra \u00B7 Alt+\u2191\u2193: th\u1EE9 t\u1EF1 \u00B7 K\u00E9o tay c\u1EA7m: di chuy\u1EC3n \u00B7 Backspace d\u00F2ng tr\u1ED1ng: x\u00F3a\",\n },\n} as const;\n\nexport type OutlinerStrings = { [K in keyof (typeof STRINGS)[\"en\"]]: string };\n\n/** Strings for a locale (\"ko\", \"ko-KR\", \u2026). `overrides` replaces single entries. */\nexport function outlinerStrings(locale?: string, overrides?: Partial<OutlinerStrings>): OutlinerStrings {\n const lang = (locale ?? \"en\").slice(0, 2).toLowerCase() as keyof typeof STRINGS;\n return { ...(STRINGS[lang] ?? STRINGS.en), ...overrides };\n}\n"],
5
- "mappings": "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",
6
- "names": ["useState", "Box", "useState", "Box", "ButtonBase", "Divider", "IconButton", "Menu", "MenuItem", "Popover", "Tooltip", "FormatBoldIcon", "FormatUnderlinedIcon", "StrikethroughSIcon", "FormatColorTextIcon", "FormatColorFillIcon", "UndoIcon", "RedoIcon", "ArrowDropDownIcon", "FormatColorResetIcon", "newNodeId", "createTree", "topic", "clone", "root", "locateNode", "id", "stack", "parent", "list", "i", "containsNode", "node", "child", "isFolded", "visibleRows", "rows", "walk", "depth", "parentId", "edit", "run", "copy", "focusId", "addChild", "first", "at", "fresh", "addSibling", "addBelow", "removeNode", "indentNode", "prev", "outdentNode", "up", "shiftNode", "step", "to", "moveNode", "from", "place", "src", "dst", "setTopic", "toggleFold", "expanded", "setNodeStyle", "ids", "patch", "changed", "next", "key", "value", "hasDecoration", "style", "kind", "toggleDecoration", "set", "Fragment", "jsx", "jsxs", "FONT_SIZES", "TEXT_COLORS", "BACKGROUND_COLORS", "btnSx", "active", "ToolButton", "label", "disabled", "onClick", "children", "Tooltip", "IconButton", "event", "ToolDivider", "Divider", "ColorButton", "icon", "value", "colors", "noneLabel", "onPick", "anchor", "setAnchor", "useState", "Box", "Popover", "color", "ButtonBase", "FormatColorResetIcon", "FormatToolbar", "strings", "style", "onStyle", "canUndo", "canRedo", "onUndo", "onRedo", "start", "end", "readOnly", "sizeAnchor", "setSizeAnchor", "size", "bold", "UndoIcon", "RedoIcon", "ArrowDropDownIcon", "Menu", "MenuItem", "FormatBoldIcon", "hasDecoration", "toggleDecoration", "FormatUnderlinedIcon", "StrikethroughSIcon", "FormatColorTextIcon", "FormatColorFillIcon", "useEffect", "useRef", "useState", "Box", "IconButton", "ArrowRightIcon", "ArrowDropDownIcon", "DragIndicatorIcon", "ctx", "cache", "DEFAULT_FONT_FAMILY", "measureText", "text", "fontSize", "fontWeight", "fontFamily", "font", "key", "hit", "width", "ch", "jsx", "jsxs", "INDENT", "BASE_FONT", "outlineTextStyle", "style", "depth", "OutlineList", "root", "onEdit", "selectedId", "onSelect", "strings", "readOnly", "onUndo", "onRedo", "paddingTop", "paddingBottom", "inputs", "useRef", "rowEls", "focus", "setFocus", "useState", "drop", "setDrop", "dragging", "setDragging", "rows", "visibleRows", "useEffect", "el", "apply", "result", "mergeKey", "onKey", "event", "index", "row", "id", "mod", "addBelow", "outdentNode", "indentNode", "shiftNode", "next", "removeNode", "dragNode", "locateNode", "onHandleDown", "onHandleMove", "r", "containsNode", "onHandleUp", "moveNode", "Box", "hasKids", "folded", "line", "text", "theme", "DragIndicatorIcon", "IconButton", "toggleFold", "ArrowRightIcon", "ArrowDropDownIcon", "setTopic", "measureText", "useCallback", "useRef", "useState", "useTreeHistory", "limit", "mergeMs", "past", "future", "last", "bump", "refresh", "n", "record", "before", "mergeKey", "now", "merge", "undo", "current", "prev", "redo", "next", "clear", "STRINGS", "outlinerStrings", "locale", "overrides", "lang", "jsx", "jsxs", "Outliner", "value", "onChange", "locale", "overrides", "readOnly", "toolbar", "toolbarStart", "toolbarEnd", "height", "strings", "outlinerStrings", "history", "useTreeHistory", "selected", "setSelected", "useState", "commit", "next", "mergeKey", "undo", "prev", "redo", "selectedNode", "locateNode", "Box", "FormatToolbar", "patch", "result", "setNodeStyle", "OutlineList"]
4
+ "sourcesContent": ["/**\n * Outliner \u2014 toolbar + rows, with its own undo history. Controlled: pass `value` and `onChange`.\n * For a custom layout use `OutlineList` + `FormatToolbar` + `useTreeHistory` directly (the mind map does).\n */\nimport { useState, type ReactNode } from \"react\";\nimport { Box } from \"@mui/material\";\nimport { FormatToolbar } from \"./FormatToolbar\";\nimport { OutlineList } from \"./OutlineList\";\nimport { useTreeHistory } from \"./history\";\nimport { outlinerStrings, type OutlinerStrings } from \"./i18n\";\nimport { locateNode, setNodeStyle, type TreeNode } from \"./tree\";\n\nexport interface OutlinerProps {\n value: TreeNode;\n onChange: (value: TreeNode) => void;\n locale?: string;\n strings?: Partial<OutlinerStrings>;\n readOnly?: boolean;\n /** Show the formatting toolbar (default true). */\n toolbar?: boolean;\n toolbarStart?: ReactNode;\n toolbarEnd?: ReactNode;\n height?: number | string;\n}\n\nexport function Outliner({ value, onChange, locale, strings: overrides, readOnly, toolbar = true, toolbarStart, toolbarEnd, height = \"100%\" }: OutlinerProps) {\n const strings = outlinerStrings(locale, overrides);\n const history = useTreeHistory();\n const [selected, setSelected] = useState<string | null>(null);\n const commit = (next: TreeNode, mergeKey?: string) => {\n history.record(value, mergeKey);\n onChange(next);\n };\n const undo = () => {\n const prev = history.undo(value);\n if (prev) onChange(prev);\n };\n const redo = () => {\n const next = history.redo(value);\n if (next) onChange(next);\n };\n const selectedNode = selected ? locateNode(value, selected)?.node : undefined;\n return (\n <Box sx={{ display: \"flex\", flexDirection: \"column\", height, minHeight: 0, bgcolor: \"#fff\" }}>\n {toolbar ? (\n <FormatToolbar\n strings={strings}\n style={selectedNode ? (selectedNode.style ?? {}) : undefined}\n onStyle={(patch) => {\n if (!selected) return;\n const result = setNodeStyle(value, [selected], patch);\n if (result) commit(result.root);\n }}\n canUndo={history.canUndo}\n canRedo={history.canRedo}\n onUndo={undo}\n onRedo={redo}\n start={toolbarStart}\n end={toolbarEnd}\n readOnly={readOnly}\n />\n ) : null}\n <Box sx={{ flex: 1, minHeight: 0 }}>\n <OutlineList root={value} onEdit={commit} selectedId={selected} onSelect={setSelected} strings={strings} readOnly={readOnly} onUndo={undo} onRedo={redo} />\n </Box>\n </Box>\n );\n}\n", "/**\n * Formatting toolbar \u2014 font size \u00B7 bold \u00B7 underline \u00B7 strike \u00B7 text color \u00B7 background \u00B7 clear format, plus undo / redo.\n * Shared by the outline and the mind map; it edits the style of the selected node.\n * Looks like the @ehfuse/editor toolbar on purpose: same icons (@ehfuse/toolbar-icons), same 32px buttons,\n * same black tooltip and the same color picker (@ehfuse/mui-color-picker).\n * `start` / `end` / `children` let the host add its own controls (view switch, map tools, \u2026).\n */\nimport { useState, type MouseEvent, type ReactNode } from \"react\";\nimport { Box, ButtonBase, Menu, MenuItem, Tooltip } from \"@mui/material\";\nimport { ColorPicker } from \"@ehfuse/mui-color-picker\";\nimport { BoldIcon, FontColorIcon, FontFillIcon, RedoIcon, RemoveFormatIcon, StrikeIcon, UnderlineIcon, UndoIcon } from \"@ehfuse/toolbar-icons\";\nimport { hasDecoration, toggleDecoration, type TreeNodeStyle } from \"./tree\";\nimport type { OutlinerStrings } from \"./i18n\";\n\nexport const FONT_SIZES = [12, 14, 16, 18, 20, 24, 28, 32];\n\nexport interface FormatToolbarProps {\n strings: OutlinerStrings;\n /** Style of the node being edited (undefined \u2192 nothing selected; format buttons are disabled). */\n style: TreeNodeStyle | undefined;\n onStyle: (patch: Partial<TreeNodeStyle>) => void;\n canUndo?: boolean;\n canRedo?: boolean;\n onUndo?: () => void;\n onRedo?: () => void;\n start?: ReactNode;\n children?: ReactNode;\n end?: ReactNode;\n readOnly?: boolean;\n}\n\n/** Same tooltip as the editor toolbar \u2014 black, 14px, arrow, below. */\nexport function ToolTip({ title, children }: { title: string; children: ReactNode }) {\n return (\n <Tooltip\n title={title}\n placement=\"bottom\"\n arrow\n disableInteractive\n leaveDelay={0}\n slotProps={{ tooltip: { sx: { bgcolor: \"#000000\", color: \"#ffffff\", fontSize: \"14px\", fontWeight: \"normal\", \"& .MuiTooltip-arrow\": { color: \"#000000\" } } } }}\n >\n {/* inline-flex \u2014 a plain span adds line descent under the button and lifts it 2px off center. */}\n <span style={{ display: \"inline-flex\" }}>{children}</span>\n </Tooltip>\n );\n}\n\n/** Same button as the editor toolbar \u2014 32px, 4px radius, light grey when on. */\nexport function ToolButton({ label, active = false, disabled = false, onClick, children }: { label: string; active?: boolean; disabled?: boolean; onClick: (event: MouseEvent<HTMLElement>) => void; children: ReactNode }) {\n return (\n <ToolTip title={label}>\n <Box\n component=\"button\"\n type=\"button\"\n aria-label={label}\n aria-pressed={active}\n disabled={disabled}\n onMouseDown={(event: MouseEvent) => event.preventDefault()}\n onClick={(event: MouseEvent<HTMLElement>) => {\n event.preventDefault();\n if (!disabled) onClick(event);\n }}\n sx={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 32,\n height: 32,\n p: \"6px\",\n border: \"none\",\n borderRadius: \"4px\",\n bgcolor: active ? \"rgba(0, 0, 0, 0.08)\" : \"transparent\",\n color: disabled ? \"rgba(0, 0, 0, 0.26)\" : \"inherit\",\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n transition: \"background-color 150ms cubic-bezier(0.4, 0, 0.2, 1)\",\n \"&:hover:not(:disabled)\": { bgcolor: active ? \"rgba(0, 0, 0, 0.08)\" : \"rgba(0, 0, 0, 0.04)\" },\n \"&:focus\": { outline: \"none\" },\n \"& svg\": { width: 20, height: 20 },\n }}\n >\n {children}\n </Box>\n </ToolTip>\n );\n}\n\nexport const ToolDivider = () => <Box sx={{ width: \"1px\", alignSelf: \"stretch\", my: \"8px\", mx: \"4px\", bgcolor: \"#e0e0e0\" }} />;\n\nfunction ColorButton({ label, type, value, disabled, onPick }: { label: string; type: \"color\" | \"background\"; value?: string; disabled: boolean; onPick: (color: string) => void }) {\n const [anchor, setAnchor] = useState<HTMLElement | null>(null);\n const shown = value ?? (type === \"color\" ? \"#000000\" : \"#FFFFFF\");\n return (\n <>\n <ToolButton label={label} disabled={disabled} onClick={(event) => setAnchor(event.currentTarget)}>\n {type === \"color\" ? <FontColorIcon width=\"20px\" height=\"20px\" barColor={shown} /> : <FontFillIcon width=\"20px\" fillColor={shown} />}\n </ToolButton>\n {anchor ? (\n <ColorPicker\n value={shown}\n onChange={(hex: string) => {\n onPick(hex);\n setAnchor(null);\n }}\n anchor={anchor}\n anchorMode=\"auto\"\n onClose={() => setAnchor(null)}\n position=\"bottomCenter\"\n advanced={{ position: \"bottom\" }}\n shape=\"square\"\n colorSize={16}\n gap={4}\n padding={5}\n popover={{ disableEnforceFocus: true, disableAutoFocus: true, disableRestoreFocus: true, sx: { zIndex: 10001 } }}\n />\n ) : null}\n </>\n );\n}\n\nexport function FormatToolbar({ strings, style, onStyle, canUndo, canRedo, onUndo, onRedo, start, children, end, readOnly }: FormatToolbarProps) {\n const [sizeAnchor, setSizeAnchor] = useState<HTMLElement | null>(null);\n const disabled = Boolean(readOnly) || !style;\n const size = style?.fontSize ? parseFloat(style.fontSize) : null;\n const bold = style?.fontWeight === \"bold\" || Number(style?.fontWeight) >= 600;\n const hasStyle = Boolean(style && Object.keys(style).length > 0);\n return (\n <Box sx={{ display: \"flex\", alignItems: \"center\", flexWrap: \"wrap\", gap: \"2px\", minHeight: 44, px: 1, py: \"4px\", borderBottom: \"1px solid #e0e0e0\", bgcolor: \"#fff\", color: \"#333\", flexShrink: 0 }}>\n {start}\n {start ? <ToolDivider /> : null}\n {onUndo ? (\n <>\n <ToolButton label={strings.undo} disabled={readOnly || !canUndo} onClick={onUndo}>\n <UndoIcon />\n </ToolButton>\n <ToolButton label={strings.redo} disabled={readOnly || !canRedo} onClick={() => onRedo?.()}>\n <RedoIcon />\n </ToolButton>\n <ToolDivider />\n </>\n ) : null}\n <ToolTip title={strings.fontSize}>\n <ButtonBase\n disabled={disabled}\n onMouseDown={(event) => event.preventDefault()}\n onClick={(event) => setSizeAnchor(event.currentTarget)}\n sx={{ height: 32, minWidth: 64, px: 1, gap: 0.5, justifyContent: \"space-between\", border: \"1px solid #d0d0d0\", borderRadius: \"4px\", fontSize: 14, color: disabled ? \"rgba(0,0,0,0.26)\" : \"#333\", bgcolor: \"#fff\", \"&:hover\": { borderColor: \"#999\" } }}\n >\n {size ?? strings.sizeDefault}\n <Box component=\"span\" sx={{ fontSize: 10, color: \"#888\" }}>\n \u25BC\n </Box>\n </ButtonBase>\n </ToolTip>\n <Menu open={Boolean(sizeAnchor)} anchorEl={sizeAnchor} onClose={() => setSizeAnchor(null)} transitionDuration={0} disableRestoreFocus slotProps={{ paper: { sx: { maxHeight: 320 } } }}>\n <MenuItem\n dense\n selected={size === null}\n onClick={() => {\n onStyle({ fontSize: undefined });\n setSizeAnchor(null);\n }}\n >\n {strings.sizeDefault}\n </MenuItem>\n {FONT_SIZES.map((value) => (\n <MenuItem\n key={value}\n dense\n selected={size === value}\n onClick={() => {\n onStyle({ fontSize: `${value}px` });\n setSizeAnchor(null);\n }}\n >\n {value}\n </MenuItem>\n ))}\n </Menu>\n <ToolButton label={strings.bold} active={bold} disabled={disabled} onClick={() => onStyle({ fontWeight: bold ? undefined : \"bold\" })}>\n <BoldIcon />\n </ToolButton>\n <ToolButton label={strings.underline} active={hasDecoration(style, \"underline\")} disabled={disabled} onClick={() => onStyle({ textDecoration: toggleDecoration(style, \"underline\") })}>\n <UnderlineIcon />\n </ToolButton>\n <ToolButton label={strings.strike} active={hasDecoration(style, \"line-through\")} disabled={disabled} onClick={() => onStyle({ textDecoration: toggleDecoration(style, \"line-through\") })}>\n <StrikeIcon />\n </ToolButton>\n <ColorButton label={strings.textColor} type=\"color\" value={style?.color} disabled={disabled} onPick={(color) => onStyle({ color })} />\n <ColorButton label={strings.background} type=\"background\" value={style?.background} disabled={disabled} onPick={(color) => onStyle({ background: color.toLowerCase() === \"#ffffff\" ? undefined : color })} />\n <ToolButton\n label={strings.clearFormat}\n disabled={disabled || !hasStyle}\n onClick={() => onStyle({ fontSize: undefined, color: undefined, background: undefined, fontWeight: undefined, textDecoration: undefined })}\n >\n <RemoveFormatIcon />\n </ToolButton>\n {children ? <ToolDivider /> : null}\n {children}\n <Box sx={{ flex: 1 }} />\n {end}\n </Box>\n );\n}\n", "/**\n * Tree data and edit operations shared by the outline and the mind map.\n *\n * The shape follows Mind Elixir's `nodeData` so data saved by it opens unchanged:\n * `{ id, topic, children?, expanded?, style? }` \u2014 unknown keys are carried along untouched.\n * Every operation is pure: it returns a new root (structural copy) and, when useful,\n * the id that should be focused next.\n */\n\n/** Text style of one node (same keys as Mind Elixir `style`). */\nexport interface TreeNodeStyle {\n fontSize?: string;\n color?: string;\n background?: string;\n fontWeight?: string;\n textDecoration?: string;\n}\n\nexport interface TreeNode {\n id: string;\n topic: string;\n children?: TreeNode[];\n /** `false` = folded. Missing means expanded. */\n expanded?: boolean;\n style?: TreeNodeStyle;\n [key: string]: unknown;\n}\n\nexport interface TreeEdit {\n root: TreeNode;\n /** Node to select / focus after the edit. */\n focusId?: string;\n}\n\nexport interface TreeRow {\n node: TreeNode;\n depth: number;\n parentId: string | null;\n}\n\n/** Short random id (hex, like Mind Elixir). */\nexport const newNodeId = () => Math.random().toString(16).slice(2, 18);\n\nexport const createTree = (topic: string): TreeNode => ({ id: \"root\", topic, children: [] });\n\nconst clone = (root: TreeNode): TreeNode => structuredClone(root) as TreeNode;\n\n/** Finds a node with its parent and index (in the given tree). */\nexport function locateNode(root: TreeNode, id: string): { node: TreeNode; parent: TreeNode | null; index: number } | null {\n if (root.id === id) return { node: root, parent: null, index: 0 };\n const stack: TreeNode[] = [root];\n while (stack.length) {\n const parent = stack.pop()!;\n const list = parent.children ?? [];\n for (let i = 0; i < list.length; i++) {\n if (list[i].id === id) return { node: list[i], parent, index: i };\n stack.push(list[i]);\n }\n }\n return null;\n}\n\n/** True when `id` is `node` itself or one of its descendants. */\nexport const containsNode = (node: TreeNode, id: string): boolean => node.id === id || (node.children ?? []).some((child) => containsNode(child, id));\n\nexport const isFolded = (node: TreeNode) => node.expanded === false && (node.children?.length ?? 0) > 0;\n\n/** Rows that are visible (folded subtrees hidden), in reading order. */\nexport function visibleRows(root: TreeNode): TreeRow[] {\n const rows: TreeRow[] = [];\n const walk = (node: TreeNode, depth: number, parentId: string | null) => {\n rows.push({ node, depth, parentId });\n if (node.expanded !== false) for (const child of node.children ?? []) walk(child, depth + 1, node.id);\n };\n walk(root, 0, null);\n return rows;\n}\n\n/** Runs `run` on a copy; returns null when nothing changed (run returned false). */\nfunction edit(root: TreeNode, run: (copy: TreeNode) => string | void | false): TreeEdit | null {\n const copy = clone(root);\n const focusId = run(copy);\n if (focusId === false) return null;\n return { root: copy, focusId: focusId || undefined };\n}\n\n/** New child at the end (or `first`). */\nexport const addChild = (root: TreeNode, id: string, topic = \"\", first = false) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at) return false;\n const fresh: TreeNode = { id: newNodeId(), topic };\n at.node.children = first ? [fresh, ...(at.node.children ?? [])] : [...(at.node.children ?? []), fresh];\n at.node.expanded = true;\n return fresh.id;\n });\n\n/** New sibling right after (root \u2192 first child). */\nexport const addSibling = (root: TreeNode, id: string, topic = \"\") =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at) return false;\n const fresh: TreeNode = { id: newNodeId(), topic };\n if (!at.parent) {\n at.node.children = [fresh, ...(at.node.children ?? [])];\n at.node.expanded = true;\n } else at.parent.children!.splice(at.index + 1, 0, fresh);\n return fresh.id;\n });\n\n/** Outline \"Enter\": first child when the row is an open parent, otherwise next sibling. */\nexport const addBelow = (root: TreeNode, id: string) => {\n const at = locateNode(root, id);\n if (at && (!at.parent || ((at.node.children?.length ?? 0) > 0 && at.node.expanded !== false))) return addChild(root, id, \"\", true);\n return addSibling(root, id);\n};\n\n/** Removes the node (not the root). Focus goes to the previous sibling, else the parent. */\nexport const removeNode = (root: TreeNode, id: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent) return false;\n at.parent.children!.splice(at.index, 1);\n return at.parent.children![at.index - 1]?.id ?? at.parent.id;\n });\n\n/** Becomes the last child of the previous sibling. */\nexport const indentNode = (root: TreeNode, id: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent || at.index === 0) return false;\n const prev = at.parent.children![at.index - 1];\n at.parent.children!.splice(at.index, 1);\n prev.children = [...(prev.children ?? []), at.node];\n prev.expanded = true;\n return id;\n });\n\n/** Becomes the sibling right after its parent. */\nexport const outdentNode = (root: TreeNode, id: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent) return false;\n const up = locateNode(copy, at.parent.id);\n if (!up?.parent) return false;\n at.parent.children!.splice(at.index, 1);\n up.parent.children!.splice(up.index + 1, 0, at.node);\n return id;\n });\n\n/** Moves one step among its siblings. */\nexport const shiftNode = (root: TreeNode, id: string, step: -1 | 1) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent) return false;\n const list = at.parent.children!;\n const to = at.index + step;\n if (to < 0 || to >= list.length) return false;\n [list[at.index], list[to]] = [list[to], list[at.index]];\n return id;\n });\n\n/** Moves `from` before / after `to`, or into `to` as its last child. */\nexport const moveNode = (root: TreeNode, from: string, to: string, place: \"before\" | \"after\" | \"child\") =>\n edit(root, (copy) => {\n const src = locateNode(copy, from);\n if (!src?.parent || containsNode(src.node, to)) return false;\n src.parent.children!.splice(src.index, 1);\n const dst = locateNode(copy, to);\n if (!dst) return false;\n if (place === \"child\" || !dst.parent) {\n dst.node.children = [...(dst.node.children ?? []), src.node];\n dst.node.expanded = true;\n } else dst.parent.children!.splice(dst.index + (place === \"after\" ? 1 : 0), 0, src.node);\n return from;\n });\n\nexport const setTopic = (root: TreeNode, id: string, topic: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at || at.node.topic === topic) return false;\n at.node.topic = topic;\n });\n\nexport const toggleFold = (root: TreeNode, id: string, expanded?: boolean) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at || !(at.node.children?.length ?? 0)) return false;\n at.node.expanded = expanded ?? at.node.expanded === false;\n });\n\n/** Merges a style patch; `undefined` values remove the key. */\nexport const setNodeStyle = (root: TreeNode, ids: string[], patch: Partial<TreeNodeStyle>) =>\n edit(root, (copy) => {\n let changed = false;\n for (const id of ids) {\n const at = locateNode(copy, id);\n if (!at) continue;\n const next: TreeNodeStyle = { ...(at.node.style ?? {}) };\n for (const [key, value] of Object.entries(patch) as [keyof TreeNodeStyle, string | undefined][]) {\n if (value === undefined || value === \"\") delete next[key];\n else next[key] = value;\n }\n at.node.style = Object.keys(next).length ? next : undefined;\n if (!at.node.style) delete at.node.style;\n changed = true;\n }\n return changed ? undefined : false;\n });\n\n/** `textDecoration` holds both underline and line-through. */\nexport function hasDecoration(style: TreeNodeStyle | undefined, kind: \"underline\" | \"line-through\") {\n return (style?.textDecoration ?? \"\").split(/\\s+/).includes(kind);\n}\nexport function toggleDecoration(style: TreeNodeStyle | undefined, kind: \"underline\" | \"line-through\"): string | undefined {\n const set = new Set((style?.textDecoration ?? \"\").split(/\\s+/).filter(Boolean));\n if (set.has(kind)) set.delete(kind);\n else set.add(kind);\n return set.size ? [...set].join(\" \") : undefined;\n}\n", "/**\n * Outline rows \u2014 one node per line, fold / unfold, indent / outdent, reorder, drag to move, per-node style.\n *\n * Keys: Enter new line \u00B7 Tab indent \u00B7 Shift+Tab outdent \u00B7 Alt+\u2191/\u2193 reorder \u00B7 \u2191/\u2193 previous / next row \u00B7\n * Backspace on an empty row deletes it \u00B7 Ctrl/\u2318+Z undo \u00B7 Ctrl/\u2318+Shift+Z or Ctrl+Y redo.\n * Dragging follows the pointer directly (native drag & drop doesn't fire drops reliably inside drawers / modals).\n */\nimport { useEffect, useRef, useState, type CSSProperties, type KeyboardEvent, type PointerEvent } from \"react\";\nimport { Box, IconButton } from \"@mui/material\";\nimport ArrowRightIcon from \"@mui/icons-material/ArrowRight\";\nimport ArrowDropDownIcon from \"@mui/icons-material/ArrowDropDown\";\nimport DragIndicatorIcon from \"@mui/icons-material/DragIndicator\";\nimport {\n addBelow,\n containsNode,\n indentNode,\n locateNode,\n moveNode,\n outdentNode,\n removeNode,\n setTopic,\n shiftNode,\n toggleFold,\n visibleRows,\n type TreeEdit,\n type TreeNode,\n type TreeNodeStyle,\n} from \"./tree\";\nimport type { OutlinerStrings } from \"./i18n\";\nimport { measureText } from \"./measure\";\n\nconst INDENT = 22;\nconst BASE_FONT = 15;\n\nexport interface OutlineListProps {\n root: TreeNode;\n /** A change; `mergeKey` is set for typing so history can merge it. */\n onEdit: (root: TreeNode, mergeKey?: string) => void;\n selectedId?: string | null;\n onSelect?: (id: string) => void;\n strings: OutlinerStrings;\n readOnly?: boolean;\n onUndo?: () => void;\n onRedo?: () => void;\n /** Extra space above the first row / below the last row (px). */\n paddingTop?: number;\n paddingBottom?: number;\n}\n\n/** Node style \u2192 input style (font size is clamped so the list stays a list). */\nexport function outlineTextStyle(style: TreeNodeStyle | undefined, depth: number): CSSProperties {\n const size = style?.fontSize ? Math.min(28, Math.max(12, parseFloat(style.fontSize))) : BASE_FONT;\n return {\n fontSize: size,\n fontWeight: style?.fontWeight ?? (depth === 0 ? 700 : 400),\n color: style?.color,\n textDecoration: style?.textDecoration,\n background: style?.background,\n };\n}\n\nexport function OutlineList({ root, onEdit, selectedId, onSelect, strings, readOnly, onUndo, onRedo, paddingTop = 8, paddingBottom = 40 }: OutlineListProps) {\n const inputs = useRef(new Map<string, HTMLInputElement>());\n const rowEls = useRef(new Map<string, HTMLDivElement>());\n const [focus, setFocus] = useState<string | null>(null);\n const [drop, setDrop] = useState<{ id: string; place: \"before\" | \"after\" } | null>(null);\n const [dragging, setDragging] = useState<string | null>(null);\n const rows = visibleRows(root);\n\n useEffect(() => {\n if (!focus) return;\n const el = inputs.current.get(focus);\n if (!el) return;\n el.focus();\n el.setSelectionRange(el.value.length, el.value.length);\n setFocus(null);\n }, [focus, root]);\n\n const apply = (result: TreeEdit | null, mergeKey?: string) => {\n if (!result) return;\n onEdit(result.root, mergeKey);\n if (result.focusId) {\n setFocus(result.focusId);\n onSelect?.(result.focusId);\n }\n };\n\n const onKey = (event: KeyboardEvent<HTMLInputElement>, index: number) => {\n if (event.nativeEvent.isComposing) return;\n const row = rows[index];\n const id = row.node.id;\n const mod = event.ctrlKey || event.metaKey;\n if (mod && (event.key === \"z\" || event.key === \"Z\")) {\n event.preventDefault();\n if (event.shiftKey) onRedo?.();\n else onUndo?.();\n return;\n }\n if (mod && (event.key === \"y\" || event.key === \"Y\")) {\n event.preventDefault();\n onRedo?.();\n return;\n }\n if (readOnly) return;\n if (event.key === \"Enter\") {\n event.preventDefault();\n apply(addBelow(root, id));\n } else if (event.key === \"Tab\") {\n event.preventDefault();\n apply(event.shiftKey ? outdentNode(root, id) : indentNode(root, id));\n } else if (event.altKey && (event.key === \"ArrowUp\" || event.key === \"ArrowDown\")) {\n event.preventDefault();\n apply(shiftNode(root, id, event.key === \"ArrowUp\" ? -1 : 1));\n } else if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\n const next = rows[index + (event.key === \"ArrowUp\" ? -1 : 1)];\n if (next) {\n event.preventDefault();\n setFocus(next.node.id);\n onSelect?.(next.node.id);\n }\n } else if (event.key === \"Backspace\" && event.currentTarget.value === \"\" && row.depth > 0 && !(row.node.children?.length ?? 0)) {\n event.preventDefault();\n const result = removeNode(root, id);\n if (result) apply({ root: result.root, focusId: rows[index - 1]?.node.id });\n }\n };\n\n // Drag \u2014 follow the pointer on the handle; drop before / after the row under it (never into itself).\n const dragNode = dragging ? locateNode(root, dragging)?.node ?? null : null;\n const onHandleDown = (event: PointerEvent<HTMLDivElement>, id: string) => {\n if (event.button !== 0 || readOnly) return;\n event.preventDefault();\n event.currentTarget.setPointerCapture(event.pointerId);\n setDragging(id);\n setDrop(null);\n };\n const onHandleMove = (event: PointerEvent<HTMLDivElement>) => {\n if (!dragging || !dragNode) return;\n let next: { id: string; place: \"before\" | \"after\" } | null = null;\n for (const row of rows) {\n const el = rowEls.current.get(row.node.id);\n if (!el) continue;\n const r = el.getBoundingClientRect();\n if (event.clientY < r.top || event.clientY >= r.bottom) continue;\n if (!containsNode(dragNode, row.node.id)) next = { id: row.node.id, place: event.clientY < r.top + r.height / 2 ? \"before\" : \"after\" };\n break;\n }\n if (next?.id !== drop?.id || next?.place !== drop?.place) setDrop(next);\n };\n const onHandleUp = (event: PointerEvent<HTMLDivElement>) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);\n if (dragging && drop) apply(moveNode(root, dragging, drop.id, drop.place));\n setDragging(null);\n setDrop(null);\n };\n\n return (\n <Box sx={{ position: \"relative\", height: \"100%\", overflowY: \"auto\", bgcolor: \"#fff\", pt: `${paddingTop}px`, pb: `${paddingBottom}px`, px: 1.5 }}>\n {rows.map((row, index) => {\n const hasKids = (row.node.children?.length ?? 0) > 0;\n const folded = row.node.expanded === false;\n const line = drop?.id === row.node.id ? drop.place : null;\n const text = outlineTextStyle(row.node.style, row.depth);\n return (\n <Box\n key={row.node.id}\n ref={(el: HTMLDivElement | null) => {\n if (el) rowEls.current.set(row.node.id, el);\n else rowEls.current.delete(row.node.id);\n }}\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n minHeight: 26,\n pl: `${row.depth * INDENT}px`,\n borderRadius: 0.75,\n bgcolor: selectedId === row.node.id ? \"rgba(26,115,232,0.06)\" : \"transparent\",\n // Drop line \u2014 inset shadow so it takes no height.\n boxShadow: (theme) =>\n line === \"before\" ? `inset 0 2px 0 ${theme.palette.primary.main}` : line === \"after\" ? `inset 0 -2px 0 ${theme.palette.primary.main}` : \"none\",\n opacity: dragging === row.node.id ? 0.4 : 1,\n \"&:hover .ol-handle\": { visibility: \"visible\" },\n }}\n >\n <Box\n className=\"ol-handle\"\n title={strings.drag}\n onPointerDown={row.depth > 0 ? (event: PointerEvent<HTMLDivElement>) => onHandleDown(event, row.node.id) : undefined}\n onPointerMove={onHandleMove}\n onPointerUp={onHandleUp}\n onPointerCancel={onHandleUp}\n sx={{\n display: \"flex\",\n color: \"#b0b4ba\",\n cursor: row.depth > 0 && !readOnly ? (dragging ? \"grabbing\" : \"grab\") : \"default\",\n visibility: dragging === row.node.id ? \"visible\" : \"hidden\",\n width: 18,\n flexShrink: 0,\n touchAction: \"none\",\n }}\n >\n {row.depth > 0 && !readOnly ? <DragIndicatorIcon sx={{ fontSize: 16 }} /> : null}\n </Box>\n {hasKids ? (\n <IconButton\n size=\"small\"\n aria-label={folded ? strings.unfold : strings.fold}\n title={folded ? strings.unfold : strings.fold}\n onClick={() => apply(toggleFold(root, row.node.id))}\n sx={{ width: 22, height: 22, p: 0, color: \"text.secondary\" }}\n >\n {folded ? <ArrowRightIcon sx={{ fontSize: 20 }} /> : <ArrowDropDownIcon sx={{ fontSize: 20 }} />}\n </IconButton>\n ) : (\n <Box sx={{ width: 22, display: \"flex\", justifyContent: \"center\", flexShrink: 0 }}>\n <Box sx={{ width: 5, height: 5, borderRadius: \"50%\", bgcolor: \"#9aa0a6\" }} />\n </Box>\n )}\n <Box sx={{ flex: 1, minWidth: 0, display: \"flex\", ml: 0.5 }}>\n <input\n ref={(el) => {\n if (el) inputs.current.set(row.node.id, el);\n else inputs.current.delete(row.node.id);\n }}\n value={row.node.topic}\n readOnly={readOnly}\n placeholder={row.depth === 0 ? strings.root : \"\"}\n spellCheck={false}\n autoComplete=\"off\"\n onFocus={() => onSelect?.(row.node.id)}\n onChange={(event) => apply(setTopic(root, row.node.id, event.target.value), `topic:${row.node.id}`)}\n onKeyDown={(event) => onKey(event, index)}\n style={{\n // Background hugs the text like a highlighter; the input keeps full width for clicks.\n width: text.background ? Math.ceil(measureText(row.node.topic || \" \", Number(text.fontSize), text.fontWeight as string)) + 16 : \"100%\",\n maxWidth: \"100%\",\n border: 0,\n outline: 0,\n font: \"inherit\",\n padding: text.background ? \"2px 6px\" : \"2px 0\",\n borderRadius: 4,\n background: text.background ?? \"transparent\",\n color: text.color ?? \"inherit\",\n fontSize: text.fontSize,\n fontWeight: text.fontWeight,\n textDecoration: [text.textDecoration, folded && hasKids ? \"underline dotted #9aa0a6\" : \"\"].filter(Boolean).join(\" \") || undefined,\n }}\n />\n </Box>\n </Box>\n );\n })}\n </Box>\n );\n}\n", "/** Text width with a cached canvas (used for highlight width in the outline and node sizes in the map). */\nlet ctx: CanvasRenderingContext2D | null = null;\nconst cache = new Map<string, number>();\n\nexport const DEFAULT_FONT_FAMILY = \"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif\";\n\nexport function measureText(text: string, fontSize: number, fontWeight: string | number = 400, fontFamily = DEFAULT_FONT_FAMILY): number {\n const font = `${fontWeight} ${fontSize}px ${fontFamily}`;\n const key = `${font}|${text}`;\n const hit = cache.get(key);\n if (hit !== undefined) return hit;\n if (!ctx && typeof document !== \"undefined\") ctx = document.createElement(\"canvas\").getContext(\"2d\");\n // No canvas (SSR / tests) \u2014 rough guess: wide glyphs 1em, others 0.55em.\n let width = 0;\n if (ctx) {\n ctx.font = font;\n width = ctx.measureText(text).width;\n } else for (const ch of text) width += (/[\u1100-\uFFDC]/.test(ch) ? 1 : 0.55) * fontSize;\n if (cache.size > 5000) cache.clear();\n cache.set(key, width);\n return width;\n}\n", "/**\n * Undo / redo for a controlled tree.\n * Typing into one node within `mergeMs` is merged into one step, so undo doesn't go back one letter at a time.\n */\nimport { useCallback, useRef, useState } from \"react\";\nimport type { TreeNode } from \"./tree\";\n\nexport interface TreeHistory {\n canUndo: boolean;\n canRedo: boolean;\n /** Records the tree before a change. `mergeKey` merges consecutive changes with the same key (e.g. typing in one node). */\n record: (before: TreeNode, mergeKey?: string) => void;\n undo: (current: TreeNode) => TreeNode | null;\n redo: (current: TreeNode) => TreeNode | null;\n clear: () => void;\n}\n\nexport function useTreeHistory(limit = 100, mergeMs = 1200): TreeHistory {\n const past = useRef<TreeNode[]>([]);\n const future = useRef<TreeNode[]>([]);\n const last = useRef<{ key: string; at: number } | null>(null);\n const [, bump] = useState(0);\n const refresh = () => bump((n) => n + 1);\n\n const record = useCallback(\n (before: TreeNode, mergeKey?: string) => {\n const now = Date.now();\n const merge = mergeKey && last.current?.key === mergeKey && now - last.current.at < mergeMs;\n last.current = mergeKey ? { key: mergeKey, at: now } : null;\n future.current = [];\n if (!merge) {\n past.current.push(before);\n if (past.current.length > limit) past.current.shift();\n }\n refresh();\n },\n [limit, mergeMs]\n );\n const undo = useCallback((current: TreeNode) => {\n const prev = past.current.pop();\n if (!prev) return null;\n future.current.push(current);\n last.current = null;\n refresh();\n return prev;\n }, []);\n const redo = useCallback((current: TreeNode) => {\n const next = future.current.pop();\n if (!next) return null;\n past.current.push(current);\n last.current = null;\n refresh();\n return next;\n }, []);\n const clear = useCallback(() => {\n past.current = [];\n future.current = [];\n last.current = null;\n refresh();\n }, []);\n return { canUndo: past.current.length > 0, canRedo: future.current.length > 0, record, undo, redo, clear };\n}\n", "/** UI strings (ko \u00B7 en \u00B7 ja \u00B7 zh \u00B7 de \u00B7 fr \u00B7 it \u00B7 vi). Unknown locale \u2192 English. */\nconst STRINGS = {\n ko: {\n clearFormat: \"\uC11C\uC2DD \uC9C0\uC6B0\uAE30\",\n fontSize: \"\uAE00\uC790 \uD06C\uAE30\",\n sizeDefault: \"\uAE30\uBCF8\",\n bold: \"\uC9C4\uD558\uAC8C\",\n underline: \"\uBC11\uC904\",\n strike: \"\uCDE8\uC18C\uC120\",\n textColor: \"\uAE00\uC790\uC0C9\",\n background: \"\uBC30\uACBD\uC0C9\",\n noColor: \"\uC5C6\uC74C\",\n undo: \"\uB418\uB3CC\uB9AC\uAE30\",\n redo: \"\uB2E4\uC2DC \uD558\uAE30\",\n fold: \"\uC811\uAE30\",\n unfold: \"\uD3BC\uCE58\uAE30\",\n drag: \"\uB04C\uC5B4\uC11C \uC62E\uAE30\uAE30\",\n root: \"\uC8FC\uC81C\",\n hint: \"Enter: \uC0C8 \uC904 \u00B7 Tab / Shift+Tab: \uB4E4\uC5EC\uC4F0\uAE30 / \uB0B4\uC5B4\uC4F0\uAE30 \u00B7 Alt+\u2191\u2193: \uC21C\uC11C \u00B7 \uC904 \uC55E \uC190\uC7A1\uC774 \uB04C\uAE30: \uC62E\uAE30\uAE30 \u00B7 \uBE48 \uC904 Backspace: \uC9C0\uC6B0\uAE30\",\n },\n en: {\n clearFormat: \"Clear format\",\n fontSize: \"Font size\",\n sizeDefault: \"Default\",\n bold: \"Bold\",\n underline: \"Underline\",\n strike: \"Strikethrough\",\n textColor: \"Text color\",\n background: \"Background\",\n noColor: \"None\",\n undo: \"Undo\",\n redo: \"Redo\",\n fold: \"Collapse\",\n unfold: \"Expand\",\n drag: \"Drag to move\",\n root: \"Topic\",\n hint: \"Enter: new line \u00B7 Tab / Shift+Tab: indent / outdent \u00B7 Alt+\u2191\u2193: reorder \u00B7 Drag the row handle: move \u00B7 Backspace on empty: delete\",\n },\n ja: {\n clearFormat: \"\u66F8\u5F0F\u3092\u30AF\u30EA\u30A2\",\n fontSize: \"\u6587\u5B57\u30B5\u30A4\u30BA\",\n sizeDefault: \"\u6A19\u6E96\",\n bold: \"\u592A\u5B57\",\n underline: \"\u4E0B\u7DDA\",\n strike: \"\u53D6\u308A\u6D88\u3057\u7DDA\",\n textColor: \"\u6587\u5B57\u8272\",\n background: \"\u80CC\u666F\u8272\",\n noColor: \"\u306A\u3057\",\n undo: \"\u5143\u306B\u623B\u3059\",\n redo: \"\u3084\u308A\u76F4\u3059\",\n fold: \"\u6298\u308A\u305F\u305F\u3080\",\n unfold: \"\u5C55\u958B\",\n drag: \"\u30C9\u30E9\u30C3\u30B0\u3067\u79FB\u52D5\",\n root: \"\u30C6\u30FC\u30DE\",\n hint: \"Enter: \u65B0\u3057\u3044\u884C \u00B7 Tab / Shift+Tab: \u5B57\u4E0B\u3052 / \u5B57\u4E0A\u3052 \u00B7 Alt+\u2191\u2193: \u4E26\u3079\u66FF\u3048 \u00B7 \u884C\u982D\u306E\u30CF\u30F3\u30C9\u30EB\u3092\u30C9\u30E9\u30C3\u30B0: \u79FB\u52D5 \u00B7 \u7A7A\u884C\u3067 Backspace: \u524A\u9664\",\n },\n zh: {\n clearFormat: \"\u6E05\u9664\u683C\u5F0F\",\n fontSize: \"\u5B57\u53F7\",\n sizeDefault: \"\u9ED8\u8BA4\",\n bold: \"\u52A0\u7C97\",\n underline: \"\u4E0B\u5212\u7EBF\",\n strike: \"\u5220\u9664\u7EBF\",\n textColor: \"\u6587\u5B57\u989C\u8272\",\n background: \"\u80CC\u666F\u8272\",\n noColor: \"\u65E0\",\n undo: \"\u64A4\u9500\",\n redo: \"\u91CD\u505A\",\n fold: \"\u6298\u53E0\",\n unfold: \"\u5C55\u5F00\",\n drag: \"\u62D6\u52A8\u4EE5\u79FB\u52A8\",\n root: \"\u4E3B\u9898\",\n hint: \"Enter: \u65B0\u884C \u00B7 Tab / Shift+Tab: \u7F29\u8FDB / \u53D6\u6D88\u7F29\u8FDB \u00B7 Alt+\u2191\u2193: \u987A\u5E8F \u00B7 \u62D6\u52A8\u884C\u9996\u624B\u67C4: \u79FB\u52A8 \u00B7 \u7A7A\u884C Backspace: \u5220\u9664\",\n },\n de: {\n clearFormat: \"Formatierung l\u00F6schen\",\n fontSize: \"Schriftgr\u00F6\u00DFe\",\n sizeDefault: \"Standard\",\n bold: \"Fett\",\n underline: \"Unterstrichen\",\n strike: \"Durchgestrichen\",\n textColor: \"Textfarbe\",\n background: \"Hintergrund\",\n noColor: \"Keine\",\n undo: \"R\u00FCckg\u00E4ngig\",\n redo: \"Wiederholen\",\n fold: \"Einklappen\",\n unfold: \"Ausklappen\",\n drag: \"Zum Verschieben ziehen\",\n root: \"Thema\",\n hint: \"Enter: neue Zeile \u00B7 Tab / Shift+Tab: ein- / ausr\u00FCcken \u00B7 Alt+\u2191\u2193: Reihenfolge \u00B7 Griff ziehen: verschieben \u00B7 Backspace leer: l\u00F6schen\",\n },\n fr: {\n clearFormat: \"Effacer la mise en forme\",\n fontSize: \"Taille\",\n sizeDefault: \"Par d\u00E9faut\",\n bold: \"Gras\",\n underline: \"Soulign\u00E9\",\n strike: \"Barr\u00E9\",\n textColor: \"Couleur du texte\",\n background: \"Arri\u00E8re-plan\",\n noColor: \"Aucune\",\n undo: \"Annuler\",\n redo: \"R\u00E9tablir\",\n fold: \"Replier\",\n unfold: \"D\u00E9plier\",\n drag: \"Glisser pour d\u00E9placer\",\n root: \"Sujet\",\n hint: \"Entr\u00E9e : nouvelle ligne \u00B7 Tab / Maj+Tab : indenter / d\u00E9sindenter \u00B7 Alt+\u2191\u2193 : ordre \u00B7 Glisser la poign\u00E9e : d\u00E9placer \u00B7 Retour arri\u00E8re vide : supprimer\",\n },\n it: {\n clearFormat: \"Cancella formattazione\",\n fontSize: \"Dimensione\",\n sizeDefault: \"Predefinita\",\n bold: \"Grassetto\",\n underline: \"Sottolineato\",\n strike: \"Barrato\",\n textColor: \"Colore testo\",\n background: \"Sfondo\",\n noColor: \"Nessuno\",\n undo: \"Annulla\",\n redo: \"Ripeti\",\n fold: \"Comprimi\",\n unfold: \"Espandi\",\n drag: \"Trascina per spostare\",\n root: \"Argomento\",\n hint: \"Invio: nuova riga \u00B7 Tab / Maiusc+Tab: rientro / riduci \u00B7 Alt+\u2191\u2193: ordine \u00B7 Trascina la maniglia: sposta \u00B7 Backspace su vuota: elimina\",\n },\n vi: {\n clearFormat: \"X\u00F3a \u0111\u1ECBnh d\u1EA1ng\",\n fontSize: \"C\u1EE1 ch\u1EEF\",\n sizeDefault: \"M\u1EB7c \u0111\u1ECBnh\",\n bold: \"\u0110\u1EADm\",\n underline: \"G\u1EA1ch ch\u00E2n\",\n strike: \"G\u1EA1ch ngang\",\n textColor: \"M\u00E0u ch\u1EEF\",\n background: \"M\u00E0u n\u1EC1n\",\n noColor: \"Kh\u00F4ng\",\n undo: \"Ho\u00E0n t\u00E1c\",\n redo: \"L\u00E0m l\u1EA1i\",\n fold: \"Thu g\u1ECDn\",\n unfold: \"M\u1EDF r\u1ED9ng\",\n drag: \"K\u00E9o \u0111\u1EC3 di chuy\u1EC3n\",\n root: \"Ch\u1EE7 \u0111\u1EC1\",\n hint: \"Enter: d\u00F2ng m\u1EDBi \u00B7 Tab / Shift+Tab: th\u1EE5t v\u00E0o / ra \u00B7 Alt+\u2191\u2193: th\u1EE9 t\u1EF1 \u00B7 K\u00E9o tay c\u1EA7m: di chuy\u1EC3n \u00B7 Backspace d\u00F2ng tr\u1ED1ng: x\u00F3a\",\n },\n} as const;\n\nexport type OutlinerStrings = { [K in keyof (typeof STRINGS)[\"en\"]]: string };\n\n/** Strings for a locale (\"ko\", \"ko-KR\", \u2026). `overrides` replaces single entries. */\nexport function outlinerStrings(locale?: string, overrides?: Partial<OutlinerStrings>): OutlinerStrings {\n const lang = (locale ?? \"en\").slice(0, 2).toLowerCase() as keyof typeof STRINGS;\n return { ...(STRINGS[lang] ?? STRINGS.en), ...overrides };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["useState", "Box", "useState", "Box", "ButtonBase", "Menu", "MenuItem", "Tooltip", "ColorPicker", "BoldIcon", "FontColorIcon", "FontFillIcon", "RedoIcon", "RemoveFormatIcon", "StrikeIcon", "UnderlineIcon", "UndoIcon", "newNodeId", "createTree", "topic", "clone", "root", "locateNode", "id", "stack", "parent", "list", "i", "containsNode", "node", "child", "isFolded", "visibleRows", "rows", "walk", "depth", "parentId", "edit", "run", "copy", "focusId", "addChild", "first", "at", "fresh", "addSibling", "addBelow", "removeNode", "indentNode", "prev", "outdentNode", "up", "shiftNode", "step", "to", "moveNode", "from", "place", "src", "dst", "setTopic", "toggleFold", "expanded", "setNodeStyle", "ids", "patch", "changed", "next", "key", "value", "hasDecoration", "style", "kind", "toggleDecoration", "set", "Fragment", "jsx", "jsxs", "FONT_SIZES", "ToolTip", "title", "children", "Tooltip", "ToolButton", "label", "active", "disabled", "onClick", "Box", "event", "ToolDivider", "ColorButton", "type", "value", "onPick", "anchor", "setAnchor", "useState", "shown", "FontColorIcon", "FontFillIcon", "ColorPicker", "hex", "FormatToolbar", "strings", "style", "onStyle", "canUndo", "canRedo", "onUndo", "onRedo", "start", "end", "readOnly", "sizeAnchor", "setSizeAnchor", "size", "bold", "hasStyle", "UndoIcon", "RedoIcon", "ButtonBase", "Menu", "MenuItem", "BoldIcon", "hasDecoration", "toggleDecoration", "UnderlineIcon", "StrikeIcon", "color", "RemoveFormatIcon", "useEffect", "useRef", "useState", "Box", "IconButton", "ArrowRightIcon", "ArrowDropDownIcon", "DragIndicatorIcon", "ctx", "cache", "DEFAULT_FONT_FAMILY", "measureText", "text", "fontSize", "fontWeight", "fontFamily", "font", "key", "hit", "width", "ch", "jsx", "jsxs", "INDENT", "BASE_FONT", "outlineTextStyle", "style", "depth", "OutlineList", "root", "onEdit", "selectedId", "onSelect", "strings", "readOnly", "onUndo", "onRedo", "paddingTop", "paddingBottom", "inputs", "useRef", "rowEls", "focus", "setFocus", "useState", "drop", "setDrop", "dragging", "setDragging", "rows", "visibleRows", "useEffect", "el", "apply", "result", "mergeKey", "onKey", "event", "index", "row", "id", "mod", "addBelow", "outdentNode", "indentNode", "shiftNode", "next", "removeNode", "dragNode", "locateNode", "onHandleDown", "onHandleMove", "r", "containsNode", "onHandleUp", "moveNode", "Box", "hasKids", "folded", "line", "text", "theme", "DragIndicatorIcon", "IconButton", "toggleFold", "ArrowRightIcon", "ArrowDropDownIcon", "setTopic", "measureText", "useCallback", "useRef", "useState", "useTreeHistory", "limit", "mergeMs", "past", "future", "last", "bump", "refresh", "n", "record", "before", "mergeKey", "now", "merge", "undo", "current", "prev", "redo", "next", "clear", "STRINGS", "outlinerStrings", "locale", "overrides", "lang", "jsx", "jsxs", "Outliner", "value", "onChange", "locale", "overrides", "readOnly", "toolbar", "toolbarStart", "toolbarEnd", "height", "strings", "outlinerStrings", "history", "useTreeHistory", "selected", "setSelected", "useState", "commit", "next", "mergeKey", "undo", "prev", "redo", "selectedNode", "locateNode", "Box", "FormatToolbar", "patch", "result", "setNodeStyle", "OutlineList"]
7
7
  }
package/dist/index.js CHANGED
@@ -1,2 +1,2 @@
1
- "use strict";var He=Object.create;var K=Object.defineProperty;var Ue=Object.getOwnPropertyDescriptor;var Ke=Object.getOwnPropertyNames;var Ge=Object.getPrototypeOf,We=Object.prototype.hasOwnProperty;var $e=(e,o)=>{for(var n in o)K(e,n,{get:o[n],enumerable:!0})},xe=(e,o,n,i)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of Ke(o))!We.call(e,r)&&r!==n&&K(e,r,{get:()=>o[r],enumerable:!(i=Ue(o,r))||i.enumerable});return e};var z=(e,o,n)=>(n=e!=null?He(Ge(e)):{},xe(o||!e||!e.__esModule?K(n,"default",{value:e,enumerable:!0}):n,e)),_e=e=>xe(K({},"__esModule",{value:!0}),e);var qe={};$e(qe,{BACKGROUND_COLORS:()=>ce,DEFAULT_FONT_FAMILY:()=>ue,FONT_SIZES:()=>ae,FormatToolbar:()=>$,OutlineList:()=>j,Outliner:()=>Ae,TEXT_COLORS:()=>se,ToolButton:()=>F,ToolDivider:()=>H,addBelow:()=>J,addChild:()=>be,addSibling:()=>me,containsNode:()=>L,createTree:()=>Ye,hasDecoration:()=>G,indentNode:()=>ee,isFolded:()=>Ze,locateNode:()=>x,measureText:()=>Y,moveNode:()=>te,newNodeId:()=>V,outdentNode:()=>oe,outlineTextStyle:()=>fe,outlinerStrings:()=>X,removeNode:()=>Q,setNodeStyle:()=>le,setTopic:()=>re,shiftNode:()=>ne,toggleDecoration:()=>W,toggleFold:()=>ie,useTreeHistory:()=>Z,visibleRows:()=>q});module.exports=_e(qe);var we=require("react"),pe=require("@mui/material");var de=require("react"),s=require("@mui/material"),Se=z(require("@mui/icons-material/FormatBold")),Ne=z(require("@mui/icons-material/FormatUnderlined")),ye=z(require("@mui/icons-material/StrikethroughS")),ke=z(require("@mui/icons-material/FormatColorText")),De=z(require("@mui/icons-material/FormatColorFill")),Ce=z(require("@mui/icons-material/Undo")),ze=z(require("@mui/icons-material/Redo")),Be=z(require("@mui/icons-material/ArrowDropDown")),Re=z(require("@mui/icons-material/FormatColorReset"));var V=()=>Math.random().toString(16).slice(2,18),Ye=e=>({id:"root",topic:e,children:[]}),je=e=>structuredClone(e);function x(e,o){if(e.id===o)return{node:e,parent:null,index:0};let n=[e];for(;n.length;){let i=n.pop(),r=i.children??[];for(let l=0;l<r.length;l++){if(r[l].id===o)return{node:r[l],parent:i,index:l};n.push(r[l])}}return null}var L=(e,o)=>e.id===o||(e.children??[]).some(n=>L(n,o)),Ze=e=>e.expanded===!1&&(e.children?.length??0)>0;function q(e){let o=[],n=(i,r,l)=>{if(o.push({node:i,depth:r,parentId:l}),i.expanded!==!1)for(let a of i.children??[])n(a,r+1,i.id)};return n(e,0,null),o}function E(e,o){let n=je(e),i=o(n);return i===!1?null:{root:n,focusId:i||void 0}}var be=(e,o,n="",i=!1)=>E(e,r=>{let l=x(r,o);if(!l)return!1;let a={id:V(),topic:n};return l.node.children=i?[a,...l.node.children??[]]:[...l.node.children??[],a],l.node.expanded=!0,a.id}),me=(e,o,n="")=>E(e,i=>{let r=x(i,o);if(!r)return!1;let l={id:V(),topic:n};return r.parent?r.parent.children.splice(r.index+1,0,l):(r.node.children=[l,...r.node.children??[]],r.node.expanded=!0),l.id}),J=(e,o)=>{let n=x(e,o);return n&&(!n.parent||(n.node.children?.length??0)>0&&n.node.expanded!==!1)?be(e,o,"",!0):me(e,o)},Q=(e,o)=>E(e,n=>{let i=x(n,o);return i?.parent?(i.parent.children.splice(i.index,1),i.parent.children[i.index-1]?.id??i.parent.id):!1}),ee=(e,o)=>E(e,n=>{let i=x(n,o);if(!i?.parent||i.index===0)return!1;let r=i.parent.children[i.index-1];return i.parent.children.splice(i.index,1),r.children=[...r.children??[],i.node],r.expanded=!0,o}),oe=(e,o)=>E(e,n=>{let i=x(n,o);if(!i?.parent)return!1;let r=x(n,i.parent.id);return r?.parent?(i.parent.children.splice(i.index,1),r.parent.children.splice(r.index+1,0,i.node),o):!1}),ne=(e,o,n)=>E(e,i=>{let r=x(i,o);if(!r?.parent)return!1;let l=r.parent.children,a=r.index+n;return a<0||a>=l.length?!1:([l[r.index],l[a]]=[l[a],l[r.index]],o)}),te=(e,o,n,i)=>E(e,r=>{let l=x(r,o);if(!l?.parent||L(l.node,n))return!1;l.parent.children.splice(l.index,1);let a=x(r,n);return a?(i==="child"||!a.parent?(a.node.children=[...a.node.children??[],l.node],a.node.expanded=!0):a.parent.children.splice(a.index+(i==="after"?1:0),0,l.node),o):!1}),re=(e,o,n)=>E(e,i=>{let r=x(i,o);if(!r||r.node.topic===n)return!1;r.node.topic=n}),ie=(e,o,n)=>E(e,i=>{let r=x(i,o);if(!r||!(r.node.children?.length??0))return!1;r.node.expanded=n??r.node.expanded===!1}),le=(e,o,n)=>E(e,i=>{let r=!1;for(let l of o){let a=x(i,l);if(!a)continue;let f={...a.node.style??{}};for(let[h,c]of Object.entries(n))c===void 0||c===""?delete f[h]:f[h]=c;a.node.style=Object.keys(f).length?f:void 0,a.node.style||delete a.node.style,r=!0}return r?void 0:!1});function G(e,o){return(e?.textDecoration??"").split(/\s+/).includes(o)}function W(e,o){let n=new Set((e?.textDecoration??"").split(/\s+/).filter(Boolean));return n.has(o)?n.delete(o):n.add(o),n.size?[...n].join(" "):void 0}var d=require("react/jsx-runtime"),ae=[12,14,16,18,20,24,28],se=["#1f2328","#5f6368","#d93025","#e8710a","#f9ab00","#188038","#1a73e8","#9334e6","#c2185b","#ffffff"],ce=["#fde2e1","#feefc3","#fff8c5","#ceead6","#d2e3fc","#e9d7fe","#fad2e1","#e8eaed","#3c4043","#1a73e8"],Ie=(e=!1)=>({width:30,height:30,borderRadius:1,color:e?"primary.main":"text.secondary",bgcolor:e?"rgba(25,118,210,0.10)":"transparent","&:hover":{bgcolor:e?"rgba(25,118,210,0.16)":"rgba(0,0,0,0.06)"}});function F({label:e,active:o,disabled:n,onClick:i,children:r}){return(0,d.jsx)(s.Tooltip,{title:e,disableInteractive:!0,children:(0,d.jsx)("span",{children:(0,d.jsx)(s.IconButton,{size:"small","aria-label":e,"aria-pressed":o,disabled:n,onMouseDown:l=>l.preventDefault(),onClick:i,sx:Ie(o),children:r})})})}var H=()=>(0,d.jsx)(s.Divider,{orientation:"vertical",flexItem:!0,sx:{mx:.5,my:.75}});function Te({label:e,icon:o,value:n,colors:i,noneLabel:r,disabled:l,onPick:a}){let[f,h]=(0,de.useState)(null);return(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(s.Tooltip,{title:e,disableInteractive:!0,children:(0,d.jsx)("span",{children:(0,d.jsxs)(s.IconButton,{size:"small","aria-label":e,disabled:l,onMouseDown:c=>c.preventDefault(),onClick:c=>h(c.currentTarget),sx:{...Ie(!1),flexDirection:"column",gap:0},children:[o,(0,d.jsx)(s.Box,{sx:{width:16,height:3,mt:"-3px",borderRadius:.5,bgcolor:n??"transparent",border:n?0:"1px solid #c4c7cc"}})]})})}),(0,d.jsx)(s.Popover,{open:!!f,anchorEl:f,onClose:()=>h(null),transitionDuration:0,anchorOrigin:{vertical:"bottom",horizontal:"left"},disableRestoreFocus:!0,children:(0,d.jsxs)(s.Box,{sx:{p:1,display:"grid",gridTemplateColumns:"repeat(5, 24px)",gap:.75},children:[i.map(c=>(0,d.jsx)(s.ButtonBase,{"aria-label":c,onMouseDown:b=>b.preventDefault(),onClick:()=>{a(c),h(null)},sx:{width:24,height:24,borderRadius:.75,bgcolor:c,border:"1px solid rgba(0,0,0,0.12)",outline:n?.toLowerCase()===c?"2px solid #1a73e8":"none",outlineOffset:1}},c)),(0,d.jsxs)(s.ButtonBase,{onMouseDown:c=>c.preventDefault(),onClick:()=>{a(void 0),h(null)},sx:{gridColumn:"1 / -1",height:26,borderRadius:.75,fontSize:13,color:"text.secondary",gap:.5,"&:hover":{bgcolor:"rgba(0,0,0,0.05)"}},children:[(0,d.jsx)(Re.default,{sx:{fontSize:16}}),r]})]})})]})}function $({strings:e,style:o,onStyle:n,canUndo:i,canRedo:r,onUndo:l,onRedo:a,start:f,children:h,end:c,readOnly:b}){let[g,p]=(0,de.useState)(null),m=b||!o,T=o?.fontSize?parseFloat(o.fontSize):null,O=o?.fontWeight==="bold"||Number(o?.fontWeight)>=600;return(0,d.jsxs)(s.Box,{sx:{display:"flex",alignItems:"center",flexWrap:"wrap",gap:.25,minHeight:40,px:1,borderBottom:"1px solid #e0e0e0",bgcolor:"#fff",flexShrink:0},children:[f,f?(0,d.jsx)(H,{}):null,l?(0,d.jsxs)(d.Fragment,{children:[(0,d.jsx)(F,{label:e.undo,disabled:b||!i,onClick:l,children:(0,d.jsx)(Ce.default,{sx:{fontSize:18}})}),(0,d.jsx)(F,{label:e.redo,disabled:b||!r,onClick:()=>a?.(),children:(0,d.jsx)(ze.default,{sx:{fontSize:18}})}),(0,d.jsx)(H,{})]}):null,(0,d.jsx)(s.Tooltip,{title:e.fontSize,disableInteractive:!0,children:(0,d.jsx)("span",{children:(0,d.jsxs)(s.ButtonBase,{disabled:m,onMouseDown:u=>u.preventDefault(),onClick:u=>p(u.currentTarget),sx:{height:30,px:.75,borderRadius:1,fontSize:13,color:m?"text.disabled":"text.primary",minWidth:52,justifyContent:"space-between","&:hover":{bgcolor:"rgba(0,0,0,0.06)"}},children:[T??e.sizeDefault,(0,d.jsx)(Be.default,{sx:{fontSize:18,color:"text.secondary"}})]})})}),(0,d.jsxs)(s.Menu,{open:!!g,anchorEl:g,onClose:()=>p(null),transitionDuration:0,disableRestoreFocus:!0,children:[(0,d.jsx)(s.MenuItem,{dense:!0,selected:T===null,onClick:()=>{n({fontSize:void 0}),p(null)},children:e.sizeDefault}),ae.map(u=>(0,d.jsx)(s.MenuItem,{dense:!0,selected:T===u,onClick:()=>{n({fontSize:`${u}px`}),p(null)},children:u},u))]}),(0,d.jsx)(F,{label:e.bold,active:O,disabled:m,onClick:()=>n({fontWeight:O?void 0:"bold"}),children:(0,d.jsx)(Se.default,{sx:{fontSize:19}})}),(0,d.jsx)(F,{label:e.underline,active:G(o,"underline"),disabled:m,onClick:()=>n({textDecoration:W(o,"underline")}),children:(0,d.jsx)(Ne.default,{sx:{fontSize:19}})}),(0,d.jsx)(F,{label:e.strike,active:G(o,"line-through"),disabled:m,onClick:()=>n({textDecoration:W(o,"line-through")}),children:(0,d.jsx)(ye.default,{sx:{fontSize:19}})}),(0,d.jsx)(Te,{label:e.textColor,icon:(0,d.jsx)(ke.default,{sx:{fontSize:17}}),value:o?.color,colors:se,noneLabel:e.noColor,disabled:m,onPick:u=>n({color:u})}),(0,d.jsx)(Te,{label:e.background,icon:(0,d.jsx)(De.default,{sx:{fontSize:17}}),value:o?.background,colors:ce,noneLabel:e.noColor,disabled:m,onPick:u=>n({background:u})}),h?(0,d.jsx)(H,{}):null,h,(0,d.jsx)(s.Box,{sx:{flex:1}}),c]})}var w=require("react"),M=require("@mui/material"),ve=z(require("@mui/icons-material/ArrowRight")),Ee=z(require("@mui/icons-material/ArrowDropDown")),Oe=z(require("@mui/icons-material/DragIndicator"));var U=null,_=new Map,ue="-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif";function Y(e,o,n=400,i=ue){let r=`${n} ${o}px ${i}`,l=`${r}|${e}`,a=_.get(l);if(a!==void 0)return a;!U&&typeof document<"u"&&(U=document.createElement("canvas").getContext("2d"));let f=0;if(U)U.font=r,f=U.measureText(e).width;else for(let h of e)f+=(/[ᄀ-ᅵ]/.test(h)?1:.55)*o;return _.size>5e3&&_.clear(),_.set(l,f),f}var D=require("react/jsx-runtime"),Xe=22,Ve=15;function fe(e,o){return{fontSize:e?.fontSize?Math.min(28,Math.max(12,parseFloat(e.fontSize))):Ve,fontWeight:e?.fontWeight??(o===0?700:400),color:e?.color,textDecoration:e?.textDecoration,background:e?.background}}function j({root:e,onEdit:o,selectedId:n,onSelect:i,strings:r,readOnly:l,onUndo:a,onRedo:f,paddingTop:h=8,paddingBottom:c=40}){let b=(0,w.useRef)(new Map),g=(0,w.useRef)(new Map),[p,m]=(0,w.useState)(null),[T,O]=(0,w.useState)(null),[u,C]=(0,w.useState)(null),R=q(e);(0,w.useEffect)(()=>{if(!p)return;let t=b.current.get(p);t&&(t.focus(),t.setSelectionRange(t.value.length,t.value.length),m(null))},[p,e]);let A=(t,N)=>{t&&(o(t.root,N),t.focusId&&(m(t.focusId),i?.(t.focusId)))},Fe=(t,N)=>{if(t.nativeEvent.isComposing)return;let I=R[N],k=I.node.id,v=t.ctrlKey||t.metaKey;if(v&&(t.key==="z"||t.key==="Z")){t.preventDefault(),t.shiftKey?f?.():a?.();return}if(v&&(t.key==="y"||t.key==="Y")){t.preventDefault(),f?.();return}if(!l){if(t.key==="Enter")t.preventDefault(),A(J(e,k));else if(t.key==="Tab")t.preventDefault(),A(t.shiftKey?oe(e,k):ee(e,k));else if(t.altKey&&(t.key==="ArrowUp"||t.key==="ArrowDown"))t.preventDefault(),A(ne(e,k,t.key==="ArrowUp"?-1:1));else if(t.key==="ArrowUp"||t.key==="ArrowDown"){let S=R[N+(t.key==="ArrowUp"?-1:1)];S&&(t.preventDefault(),m(S.node.id),i?.(S.node.id))}else if(t.key==="Backspace"&&t.currentTarget.value===""&&I.depth>0&&!(I.node.children?.length??0)){t.preventDefault();let S=Q(e,k);S&&A({root:S.root,focusId:R[N-1]?.node.id})}}},ge=u?x(e,u)?.node??null:null,Pe=(t,N)=>{t.button!==0||l||(t.preventDefault(),t.currentTarget.setPointerCapture(t.pointerId),C(N),O(null))},Le=t=>{if(!u||!ge)return;let N=null;for(let I of R){let k=g.current.get(I.node.id);if(!k)continue;let v=k.getBoundingClientRect();if(!(t.clientY<v.top||t.clientY>=v.bottom)){L(ge,I.node.id)||(N={id:I.node.id,place:t.clientY<v.top+v.height/2?"before":"after"});break}}(N?.id!==T?.id||N?.place!==T?.place)&&O(N)},he=t=>{t.currentTarget.hasPointerCapture(t.pointerId)&&t.currentTarget.releasePointerCapture(t.pointerId),u&&T&&A(te(e,u,T.id,T.place)),C(null),O(null)};return(0,D.jsx)(M.Box,{sx:{position:"relative",height:"100%",overflowY:"auto",bgcolor:"#fff",pt:`${h}px`,pb:`${c}px`,px:1.5},children:R.map((t,N)=>{let I=(t.node.children?.length??0)>0,k=t.node.expanded===!1,v=T?.id===t.node.id?T.place:null,S=fe(t.node.style,t.depth);return(0,D.jsxs)(M.Box,{ref:y=>{y?g.current.set(t.node.id,y):g.current.delete(t.node.id)},sx:{display:"flex",alignItems:"center",minHeight:26,pl:`${t.depth*Xe}px`,borderRadius:.75,bgcolor:n===t.node.id?"rgba(26,115,232,0.06)":"transparent",boxShadow:y=>v==="before"?`inset 0 2px 0 ${y.palette.primary.main}`:v==="after"?`inset 0 -2px 0 ${y.palette.primary.main}`:"none",opacity:u===t.node.id?.4:1,"&:hover .ol-handle":{visibility:"visible"}},children:[(0,D.jsx)(M.Box,{className:"ol-handle",title:r.drag,onPointerDown:t.depth>0?y=>Pe(y,t.node.id):void 0,onPointerMove:Le,onPointerUp:he,onPointerCancel:he,sx:{display:"flex",color:"#b0b4ba",cursor:t.depth>0&&!l?u?"grabbing":"grab":"default",visibility:u===t.node.id?"visible":"hidden",width:18,flexShrink:0,touchAction:"none"},children:t.depth>0&&!l?(0,D.jsx)(Oe.default,{sx:{fontSize:16}}):null}),I?(0,D.jsx)(M.IconButton,{size:"small","aria-label":k?r.unfold:r.fold,title:k?r.unfold:r.fold,onClick:()=>A(ie(e,t.node.id)),sx:{width:22,height:22,p:0,color:"text.secondary"},children:k?(0,D.jsx)(ve.default,{sx:{fontSize:20}}):(0,D.jsx)(Ee.default,{sx:{fontSize:20}})}):(0,D.jsx)(M.Box,{sx:{width:22,display:"flex",justifyContent:"center",flexShrink:0},children:(0,D.jsx)(M.Box,{sx:{width:5,height:5,borderRadius:"50%",bgcolor:"#9aa0a6"}})}),(0,D.jsx)(M.Box,{sx:{flex:1,minWidth:0,display:"flex",ml:.5},children:(0,D.jsx)("input",{ref:y=>{y?b.current.set(t.node.id,y):b.current.delete(t.node.id)},value:t.node.topic,readOnly:l,placeholder:t.depth===0?r.root:"",spellCheck:!1,autoComplete:"off",onFocus:()=>i?.(t.node.id),onChange:y=>A(re(e,t.node.id,y.target.value),`topic:${t.node.id}`),onKeyDown:y=>Fe(y,N),style:{width:S.background?Math.ceil(Y(t.node.topic||" ",Number(S.fontSize),S.fontWeight))+16:"100%",maxWidth:"100%",border:0,outline:0,font:"inherit",padding:S.background?"2px 6px":"2px 0",borderRadius:4,background:S.background??"transparent",color:S.color??"inherit",fontSize:S.fontSize,fontWeight:S.fontWeight,textDecoration:[S.textDecoration,k&&I?"underline dotted #9aa0a6":""].filter(Boolean).join(" ")||void 0}})})]},t.node.id)})})}var B=require("react");function Z(e=100,o=1200){let n=(0,B.useRef)([]),i=(0,B.useRef)([]),r=(0,B.useRef)(null),[,l]=(0,B.useState)(0),a=()=>l(g=>g+1),f=(0,B.useCallback)((g,p)=>{let m=Date.now(),T=p&&r.current?.key===p&&m-r.current.at<o;r.current=p?{key:p,at:m}:null,i.current=[],T||(n.current.push(g),n.current.length>e&&n.current.shift()),a()},[e,o]),h=(0,B.useCallback)(g=>{let p=n.current.pop();return p?(i.current.push(g),r.current=null,a(),p):null},[]),c=(0,B.useCallback)(g=>{let p=i.current.pop();return p?(n.current.push(g),r.current=null,a(),p):null},[]),b=(0,B.useCallback)(()=>{n.current=[],i.current=[],r.current=null,a()},[]);return{canUndo:n.current.length>0,canRedo:i.current.length>0,record:f,undo:h,redo:c,clear:b}}var Me={ko:{fontSize:"\uAE00\uC790 \uD06C\uAE30",sizeDefault:"\uAE30\uBCF8",bold:"\uC9C4\uD558\uAC8C",underline:"\uBC11\uC904",strike:"\uCDE8\uC18C\uC120",textColor:"\uAE00\uC790\uC0C9",background:"\uBC30\uACBD\uC0C9",noColor:"\uC5C6\uC74C",undo:"\uB418\uB3CC\uB9AC\uAE30",redo:"\uB2E4\uC2DC \uD558\uAE30",fold:"\uC811\uAE30",unfold:"\uD3BC\uCE58\uAE30",drag:"\uB04C\uC5B4\uC11C \uC62E\uAE30\uAE30",root:"\uC8FC\uC81C",hint:"Enter: \uC0C8 \uC904 \xB7 Tab / Shift+Tab: \uB4E4\uC5EC\uC4F0\uAE30 / \uB0B4\uC5B4\uC4F0\uAE30 \xB7 Alt+\u2191\u2193: \uC21C\uC11C \xB7 \uC904 \uC55E \uC190\uC7A1\uC774 \uB04C\uAE30: \uC62E\uAE30\uAE30 \xB7 \uBE48 \uC904 Backspace: \uC9C0\uC6B0\uAE30"},en:{fontSize:"Font size",sizeDefault:"Default",bold:"Bold",underline:"Underline",strike:"Strikethrough",textColor:"Text color",background:"Background",noColor:"None",undo:"Undo",redo:"Redo",fold:"Collapse",unfold:"Expand",drag:"Drag to move",root:"Topic",hint:"Enter: new line \xB7 Tab / Shift+Tab: indent / outdent \xB7 Alt+\u2191\u2193: reorder \xB7 Drag the row handle: move \xB7 Backspace on empty: delete"},ja:{fontSize:"\u6587\u5B57\u30B5\u30A4\u30BA",sizeDefault:"\u6A19\u6E96",bold:"\u592A\u5B57",underline:"\u4E0B\u7DDA",strike:"\u53D6\u308A\u6D88\u3057\u7DDA",textColor:"\u6587\u5B57\u8272",background:"\u80CC\u666F\u8272",noColor:"\u306A\u3057",undo:"\u5143\u306B\u623B\u3059",redo:"\u3084\u308A\u76F4\u3059",fold:"\u6298\u308A\u305F\u305F\u3080",unfold:"\u5C55\u958B",drag:"\u30C9\u30E9\u30C3\u30B0\u3067\u79FB\u52D5",root:"\u30C6\u30FC\u30DE",hint:"Enter: \u65B0\u3057\u3044\u884C \xB7 Tab / Shift+Tab: \u5B57\u4E0B\u3052 / \u5B57\u4E0A\u3052 \xB7 Alt+\u2191\u2193: \u4E26\u3079\u66FF\u3048 \xB7 \u884C\u982D\u306E\u30CF\u30F3\u30C9\u30EB\u3092\u30C9\u30E9\u30C3\u30B0: \u79FB\u52D5 \xB7 \u7A7A\u884C\u3067 Backspace: \u524A\u9664"},zh:{fontSize:"\u5B57\u53F7",sizeDefault:"\u9ED8\u8BA4",bold:"\u52A0\u7C97",underline:"\u4E0B\u5212\u7EBF",strike:"\u5220\u9664\u7EBF",textColor:"\u6587\u5B57\u989C\u8272",background:"\u80CC\u666F\u8272",noColor:"\u65E0",undo:"\u64A4\u9500",redo:"\u91CD\u505A",fold:"\u6298\u53E0",unfold:"\u5C55\u5F00",drag:"\u62D6\u52A8\u4EE5\u79FB\u52A8",root:"\u4E3B\u9898",hint:"Enter: \u65B0\u884C \xB7 Tab / Shift+Tab: \u7F29\u8FDB / \u53D6\u6D88\u7F29\u8FDB \xB7 Alt+\u2191\u2193: \u987A\u5E8F \xB7 \u62D6\u52A8\u884C\u9996\u624B\u67C4: \u79FB\u52A8 \xB7 \u7A7A\u884C Backspace: \u5220\u9664"},de:{fontSize:"Schriftgr\xF6\xDFe",sizeDefault:"Standard",bold:"Fett",underline:"Unterstrichen",strike:"Durchgestrichen",textColor:"Textfarbe",background:"Hintergrund",noColor:"Keine",undo:"R\xFCckg\xE4ngig",redo:"Wiederholen",fold:"Einklappen",unfold:"Ausklappen",drag:"Zum Verschieben ziehen",root:"Thema",hint:"Enter: neue Zeile \xB7 Tab / Shift+Tab: ein- / ausr\xFCcken \xB7 Alt+\u2191\u2193: Reihenfolge \xB7 Griff ziehen: verschieben \xB7 Backspace leer: l\xF6schen"},fr:{fontSize:"Taille",sizeDefault:"Par d\xE9faut",bold:"Gras",underline:"Soulign\xE9",strike:"Barr\xE9",textColor:"Couleur du texte",background:"Arri\xE8re-plan",noColor:"Aucune",undo:"Annuler",redo:"R\xE9tablir",fold:"Replier",unfold:"D\xE9plier",drag:"Glisser pour d\xE9placer",root:"Sujet",hint:"Entr\xE9e : nouvelle ligne \xB7 Tab / Maj+Tab : indenter / d\xE9sindenter \xB7 Alt+\u2191\u2193 : ordre \xB7 Glisser la poign\xE9e : d\xE9placer \xB7 Retour arri\xE8re vide : supprimer"},it:{fontSize:"Dimensione",sizeDefault:"Predefinita",bold:"Grassetto",underline:"Sottolineato",strike:"Barrato",textColor:"Colore testo",background:"Sfondo",noColor:"Nessuno",undo:"Annulla",redo:"Ripeti",fold:"Comprimi",unfold:"Espandi",drag:"Trascina per spostare",root:"Argomento",hint:"Invio: nuova riga \xB7 Tab / Maiusc+Tab: rientro / riduci \xB7 Alt+\u2191\u2193: ordine \xB7 Trascina la maniglia: sposta \xB7 Backspace su vuota: elimina"},vi:{fontSize:"C\u1EE1 ch\u1EEF",sizeDefault:"M\u1EB7c \u0111\u1ECBnh",bold:"\u0110\u1EADm",underline:"G\u1EA1ch ch\xE2n",strike:"G\u1EA1ch ngang",textColor:"M\xE0u ch\u1EEF",background:"M\xE0u n\u1EC1n",noColor:"Kh\xF4ng",undo:"Ho\xE0n t\xE1c",redo:"L\xE0m l\u1EA1i",fold:"Thu g\u1ECDn",unfold:"M\u1EDF r\u1ED9ng",drag:"K\xE9o \u0111\u1EC3 di chuy\u1EC3n",root:"Ch\u1EE7 \u0111\u1EC1",hint:"Enter: d\xF2ng m\u1EDBi \xB7 Tab / Shift+Tab: th\u1EE5t v\xE0o / ra \xB7 Alt+\u2191\u2193: th\u1EE9 t\u1EF1 \xB7 K\xE9o tay c\u1EA7m: di chuy\u1EC3n \xB7 Backspace d\xF2ng tr\u1ED1ng: x\xF3a"}};function X(e,o){let n=(e??"en").slice(0,2).toLowerCase();return{...Me[n]??Me.en,...o}}var P=require("react/jsx-runtime");function Ae({value:e,onChange:o,locale:n,strings:i,readOnly:r,toolbar:l=!0,toolbarStart:a,toolbarEnd:f,height:h="100%"}){let c=X(n,i),b=Z(),[g,p]=(0,we.useState)(null),m=(C,R)=>{b.record(e,R),o(C)},T=()=>{let C=b.undo(e);C&&o(C)},O=()=>{let C=b.redo(e);C&&o(C)},u=g?x(e,g)?.node:void 0;return(0,P.jsxs)(pe.Box,{sx:{display:"flex",flexDirection:"column",height:h,minHeight:0,bgcolor:"#fff"},children:[l?(0,P.jsx)($,{strings:c,style:u?u.style??{}:void 0,onStyle:C=>{if(!g)return;let R=le(e,[g],C);R&&m(R.root)},canUndo:b.canUndo,canRedo:b.canRedo,onUndo:T,onRedo:O,start:a,end:f,readOnly:r}):null,(0,P.jsx)(pe.Box,{sx:{flex:1,minHeight:0},children:(0,P.jsx)(j,{root:e,onEdit:m,selectedId:g,onSelect:p,strings:c,readOnly:r,onUndo:T,onRedo:O})})]})}
1
+ "use strict";var Fe=Object.create;var W=Object.defineProperty;var Ie=Object.getOwnPropertyDescriptor;var Re=Object.getOwnPropertyNames;var Me=Object.getPrototypeOf,we=Object.prototype.hasOwnProperty;var Pe=(e,o)=>{for(var n in o)W(e,n,{get:o[n],enumerable:!0})},xe=(e,o,n,i)=>{if(o&&typeof o=="object"||typeof o=="function")for(let r of Re(o))!we.call(e,r)&&r!==n&&W(e,r,{get:()=>o[r],enumerable:!(i=Ie(o,r))||i.enumerable});return e};var X=(e,o,n)=>(n=e!=null?Fe(Me(e)):{},xe(o||!e||!e.__esModule?W(n,"default",{value:e,enumerable:!0}):n,e)),Ae=e=>xe(W({},"__esModule",{value:!0}),e);var Ke={};Pe(Ke,{DEFAULT_FONT_FAMILY:()=>ue,FONT_SIZES:()=>ce,FormatToolbar:()=>j,OutlineList:()=>Z,Outliner:()=>ve,ToolButton:()=>M,ToolDivider:()=>L,ToolTip:()=>$,addBelow:()=>ee,addChild:()=>be,addSibling:()=>me,containsNode:()=>O,createTree:()=>He,hasDecoration:()=>K,indentNode:()=>ne,isFolded:()=>Le,locateNode:()=>g,measureText:()=>_,moveNode:()=>ie,newNodeId:()=>J,outdentNode:()=>te,outlineTextStyle:()=>fe,outlinerStrings:()=>V,removeNode:()=>oe,setNodeStyle:()=>ae,setTopic:()=>le,shiftNode:()=>re,toggleDecoration:()=>G,toggleFold:()=>de,useTreeHistory:()=>q,visibleRows:()=>Q});module.exports=Ae(Ke);var Ce=require("react"),pe=require("@mui/material");var se=require("react"),N=require("@mui/material"),Ne=require("@ehfuse/mui-color-picker"),m=require("@ehfuse/toolbar-icons");var J=()=>Math.random().toString(16).slice(2,18),He=e=>({id:"root",topic:e,children:[]}),Oe=e=>structuredClone(e);function g(e,o){if(e.id===o)return{node:e,parent:null,index:0};let n=[e];for(;n.length;){let i=n.pop(),r=i.children??[];for(let l=0;l<r.length;l++){if(r[l].id===o)return{node:r[l],parent:i,index:l};n.push(r[l])}}return null}var O=(e,o)=>e.id===o||(e.children??[]).some(n=>O(n,o)),Le=e=>e.expanded===!1&&(e.children?.length??0)>0;function Q(e){let o=[],n=(i,r,l)=>{if(o.push({node:i,depth:r,parentId:l}),i.expanded!==!1)for(let d of i.children??[])n(d,r+1,i.id)};return n(e,0,null),o}function I(e,o){let n=Oe(e),i=o(n);return i===!1?null:{root:n,focusId:i||void 0}}var be=(e,o,n="",i=!1)=>I(e,r=>{let l=g(r,o);if(!l)return!1;let d={id:J(),topic:n};return l.node.children=i?[d,...l.node.children??[]]:[...l.node.children??[],d],l.node.expanded=!0,d.id}),me=(e,o,n="")=>I(e,i=>{let r=g(i,o);if(!r)return!1;let l={id:J(),topic:n};return r.parent?r.parent.children.splice(r.index+1,0,l):(r.node.children=[l,...r.node.children??[]],r.node.expanded=!0),l.id}),ee=(e,o)=>{let n=g(e,o);return n&&(!n.parent||(n.node.children?.length??0)>0&&n.node.expanded!==!1)?be(e,o,"",!0):me(e,o)},oe=(e,o)=>I(e,n=>{let i=g(n,o);return i?.parent?(i.parent.children.splice(i.index,1),i.parent.children[i.index-1]?.id??i.parent.id):!1}),ne=(e,o)=>I(e,n=>{let i=g(n,o);if(!i?.parent||i.index===0)return!1;let r=i.parent.children[i.index-1];return i.parent.children.splice(i.index,1),r.children=[...r.children??[],i.node],r.expanded=!0,o}),te=(e,o)=>I(e,n=>{let i=g(n,o);if(!i?.parent)return!1;let r=g(n,i.parent.id);return r?.parent?(i.parent.children.splice(i.index,1),r.parent.children.splice(r.index+1,0,i.node),o):!1}),re=(e,o,n)=>I(e,i=>{let r=g(i,o);if(!r?.parent)return!1;let l=r.parent.children,d=r.index+n;return d<0||d>=l.length?!1:([l[r.index],l[d]]=[l[d],l[r.index]],o)}),ie=(e,o,n,i)=>I(e,r=>{let l=g(r,o);if(!l?.parent||O(l.node,n))return!1;l.parent.children.splice(l.index,1);let d=g(r,n);return d?(i==="child"||!d.parent?(d.node.children=[...d.node.children??[],l.node],d.node.expanded=!0):d.parent.children.splice(d.index+(i==="after"?1:0),0,l.node),o):!1}),le=(e,o,n)=>I(e,i=>{let r=g(i,o);if(!r||r.node.topic===n)return!1;r.node.topic=n}),de=(e,o,n)=>I(e,i=>{let r=g(i,o);if(!r||!(r.node.children?.length??0))return!1;r.node.expanded=n??r.node.expanded===!1}),ae=(e,o,n)=>I(e,i=>{let r=!1;for(let l of o){let d=g(i,l);if(!d)continue;let c={...d.node.style??{}};for(let[h,v]of Object.entries(n))v===void 0||v===""?delete c[h]:c[h]=v;d.node.style=Object.keys(c).length?c:void 0,d.node.style||delete d.node.style,r=!0}return r?void 0:!1});function K(e,o){return(e?.textDecoration??"").split(/\s+/).includes(o)}function G(e,o){let n=new Set((e?.textDecoration??"").split(/\s+/).filter(Boolean));return n.has(o)?n.delete(o):n.add(o),n.size?[...n].join(" "):void 0}var a=require("react/jsx-runtime"),ce=[12,14,16,18,20,24,28,32];function $({title:e,children:o}){return(0,a.jsx)(N.Tooltip,{title:e,placement:"bottom",arrow:!0,disableInteractive:!0,leaveDelay:0,slotProps:{tooltip:{sx:{bgcolor:"#000000",color:"#ffffff",fontSize:"14px",fontWeight:"normal","& .MuiTooltip-arrow":{color:"#000000"}}}},children:(0,a.jsx)("span",{style:{display:"inline-flex"},children:o})})}function M({label:e,active:o=!1,disabled:n=!1,onClick:i,children:r}){return(0,a.jsx)($,{title:e,children:(0,a.jsx)(N.Box,{component:"button",type:"button","aria-label":e,"aria-pressed":o,disabled:n,onMouseDown:l=>l.preventDefault(),onClick:l=>{l.preventDefault(),n||i(l)},sx:{display:"inline-flex",alignItems:"center",justifyContent:"center",width:32,height:32,p:"6px",border:"none",borderRadius:"4px",bgcolor:o?"rgba(0, 0, 0, 0.08)":"transparent",color:n?"rgba(0, 0, 0, 0.26)":"inherit",cursor:n?"not-allowed":"pointer",transition:"background-color 150ms cubic-bezier(0.4, 0, 0.2, 1)","&:hover:not(:disabled)":{bgcolor:o?"rgba(0, 0, 0, 0.08)":"rgba(0, 0, 0, 0.04)"},"&:focus":{outline:"none"},"& svg":{width:20,height:20}},children:r})})}var L=()=>(0,a.jsx)(N.Box,{sx:{width:"1px",alignSelf:"stretch",my:"8px",mx:"4px",bgcolor:"#e0e0e0"}});function Te({label:e,type:o,value:n,disabled:i,onPick:r}){let[l,d]=(0,se.useState)(null),c=n??(o==="color"?"#000000":"#FFFFFF");return(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(M,{label:e,disabled:i,onClick:h=>d(h.currentTarget),children:o==="color"?(0,a.jsx)(m.FontColorIcon,{width:"20px",height:"20px",barColor:c}):(0,a.jsx)(m.FontFillIcon,{width:"20px",fillColor:c})}),l?(0,a.jsx)(Ne.ColorPicker,{value:c,onChange:h=>{r(h),d(null)},anchor:l,anchorMode:"auto",onClose:()=>d(null),position:"bottomCenter",advanced:{position:"bottom"},shape:"square",colorSize:16,gap:4,padding:5,popover:{disableEnforceFocus:!0,disableAutoFocus:!0,disableRestoreFocus:!0,sx:{zIndex:10001}}}):null]})}function j({strings:e,style:o,onStyle:n,canUndo:i,canRedo:r,onUndo:l,onRedo:d,start:c,children:h,end:v,readOnly:T}){let[f,u]=(0,se.useState)(null),p=!!T||!o,x=o?.fontSize?parseFloat(o.fontSize):null,R=o?.fontWeight==="bold"||Number(o?.fontWeight)>=600,k=!!(o&&Object.keys(o).length>0);return(0,a.jsxs)(N.Box,{sx:{display:"flex",alignItems:"center",flexWrap:"wrap",gap:"2px",minHeight:44,px:1,py:"4px",borderBottom:"1px solid #e0e0e0",bgcolor:"#fff",color:"#333",flexShrink:0},children:[c,c?(0,a.jsx)(L,{}):null,l?(0,a.jsxs)(a.Fragment,{children:[(0,a.jsx)(M,{label:e.undo,disabled:T||!i,onClick:l,children:(0,a.jsx)(m.UndoIcon,{})}),(0,a.jsx)(M,{label:e.redo,disabled:T||!r,onClick:()=>d?.(),children:(0,a.jsx)(m.RedoIcon,{})}),(0,a.jsx)(L,{})]}):null,(0,a.jsx)($,{title:e.fontSize,children:(0,a.jsxs)(N.ButtonBase,{disabled:p,onMouseDown:s=>s.preventDefault(),onClick:s=>u(s.currentTarget),sx:{height:32,minWidth:64,px:1,gap:.5,justifyContent:"space-between",border:"1px solid #d0d0d0",borderRadius:"4px",fontSize:14,color:p?"rgba(0,0,0,0.26)":"#333",bgcolor:"#fff","&:hover":{borderColor:"#999"}},children:[x??e.sizeDefault,(0,a.jsx)(N.Box,{component:"span",sx:{fontSize:10,color:"#888"},children:"\u25BC"})]})}),(0,a.jsxs)(N.Menu,{open:!!f,anchorEl:f,onClose:()=>u(null),transitionDuration:0,disableRestoreFocus:!0,slotProps:{paper:{sx:{maxHeight:320}}},children:[(0,a.jsx)(N.MenuItem,{dense:!0,selected:x===null,onClick:()=>{n({fontSize:void 0}),u(null)},children:e.sizeDefault}),ce.map(s=>(0,a.jsx)(N.MenuItem,{dense:!0,selected:x===s,onClick:()=>{n({fontSize:`${s}px`}),u(null)},children:s},s))]}),(0,a.jsx)(M,{label:e.bold,active:R,disabled:p,onClick:()=>n({fontWeight:R?void 0:"bold"}),children:(0,a.jsx)(m.BoldIcon,{})}),(0,a.jsx)(M,{label:e.underline,active:K(o,"underline"),disabled:p,onClick:()=>n({textDecoration:G(o,"underline")}),children:(0,a.jsx)(m.UnderlineIcon,{})}),(0,a.jsx)(M,{label:e.strike,active:K(o,"line-through"),disabled:p,onClick:()=>n({textDecoration:G(o,"line-through")}),children:(0,a.jsx)(m.StrikeIcon,{})}),(0,a.jsx)(Te,{label:e.textColor,type:"color",value:o?.color,disabled:p,onPick:s=>n({color:s})}),(0,a.jsx)(Te,{label:e.background,type:"background",value:o?.background,disabled:p,onPick:s=>n({background:s.toLowerCase()==="#ffffff"?void 0:s})}),(0,a.jsx)(M,{label:e.clearFormat,disabled:p||!k,onClick:()=>n({fontSize:void 0,color:void 0,background:void 0,fontWeight:void 0,textDecoration:void 0}),children:(0,a.jsx)(m.RemoveFormatIcon,{})}),h?(0,a.jsx)(L,{}):null,h,(0,a.jsx)(N.Box,{sx:{flex:1}}),v]})}var P=require("react"),w=require("@mui/material"),ye=X(require("@mui/icons-material/ArrowRight")),Se=X(require("@mui/icons-material/ArrowDropDown")),ke=X(require("@mui/icons-material/DragIndicator"));var U=null,Y=new Map,ue="-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif";function _(e,o,n=400,i=ue){let r=`${n} ${o}px ${i}`,l=`${r}|${e}`,d=Y.get(l);if(d!==void 0)return d;!U&&typeof document<"u"&&(U=document.createElement("canvas").getContext("2d"));let c=0;if(U)U.font=r,c=U.measureText(e).width;else for(let h of e)c+=(/[ᄀ-ᅵ]/.test(h)?1:.55)*o;return Y.size>5e3&&Y.clear(),Y.set(l,c),c}var C=require("react/jsx-runtime"),Ue=22,We=15;function fe(e,o){return{fontSize:e?.fontSize?Math.min(28,Math.max(12,parseFloat(e.fontSize))):We,fontWeight:e?.fontWeight??(o===0?700:400),color:e?.color,textDecoration:e?.textDecoration,background:e?.background}}function Z({root:e,onEdit:o,selectedId:n,onSelect:i,strings:r,readOnly:l,onUndo:d,onRedo:c,paddingTop:h=8,paddingBottom:v=40}){let T=(0,P.useRef)(new Map),f=(0,P.useRef)(new Map),[u,p]=(0,P.useState)(null),[x,R]=(0,P.useState)(null),[k,s]=(0,P.useState)(null),E=Q(e);(0,P.useEffect)(()=>{if(!u)return;let t=T.current.get(u);t&&(t.focus(),t.setSelectionRange(t.value.length,t.value.length),p(null))},[u,e]);let A=(t,y)=>{t&&(o(t.root,y),t.focusId&&(p(t.focusId),i?.(t.focusId)))},Be=(t,y)=>{if(t.nativeEvent.isComposing)return;let z=E[y],D=z.node.id,F=t.ctrlKey||t.metaKey;if(F&&(t.key==="z"||t.key==="Z")){t.preventDefault(),t.shiftKey?c?.():d?.();return}if(F&&(t.key==="y"||t.key==="Y")){t.preventDefault(),c?.();return}if(!l){if(t.key==="Enter")t.preventDefault(),A(ee(e,D));else if(t.key==="Tab")t.preventDefault(),A(t.shiftKey?te(e,D):ne(e,D));else if(t.altKey&&(t.key==="ArrowUp"||t.key==="ArrowDown"))t.preventDefault(),A(re(e,D,t.key==="ArrowUp"?-1:1));else if(t.key==="ArrowUp"||t.key==="ArrowDown"){let b=E[y+(t.key==="ArrowUp"?-1:1)];b&&(t.preventDefault(),p(b.node.id),i?.(b.node.id))}else if(t.key==="Backspace"&&t.currentTarget.value===""&&z.depth>0&&!(z.node.children?.length??0)){t.preventDefault();let b=oe(e,D);b&&A({root:b.root,focusId:E[y-1]?.node.id})}}},ge=k?g(e,k)?.node??null:null,Ee=(t,y)=>{t.button!==0||l||(t.preventDefault(),t.currentTarget.setPointerCapture(t.pointerId),s(y),R(null))},ze=t=>{if(!k||!ge)return;let y=null;for(let z of E){let D=f.current.get(z.node.id);if(!D)continue;let F=D.getBoundingClientRect();if(!(t.clientY<F.top||t.clientY>=F.bottom)){O(ge,z.node.id)||(y={id:z.node.id,place:t.clientY<F.top+F.height/2?"before":"after"});break}}(y?.id!==x?.id||y?.place!==x?.place)&&R(y)},he=t=>{t.currentTarget.hasPointerCapture(t.pointerId)&&t.currentTarget.releasePointerCapture(t.pointerId),k&&x&&A(ie(e,k,x.id,x.place)),s(null),R(null)};return(0,C.jsx)(w.Box,{sx:{position:"relative",height:"100%",overflowY:"auto",bgcolor:"#fff",pt:`${h}px`,pb:`${v}px`,px:1.5},children:E.map((t,y)=>{let z=(t.node.children?.length??0)>0,D=t.node.expanded===!1,F=x?.id===t.node.id?x.place:null,b=fe(t.node.style,t.depth);return(0,C.jsxs)(w.Box,{ref:S=>{S?f.current.set(t.node.id,S):f.current.delete(t.node.id)},sx:{display:"flex",alignItems:"center",minHeight:26,pl:`${t.depth*Ue}px`,borderRadius:.75,bgcolor:n===t.node.id?"rgba(26,115,232,0.06)":"transparent",boxShadow:S=>F==="before"?`inset 0 2px 0 ${S.palette.primary.main}`:F==="after"?`inset 0 -2px 0 ${S.palette.primary.main}`:"none",opacity:k===t.node.id?.4:1,"&:hover .ol-handle":{visibility:"visible"}},children:[(0,C.jsx)(w.Box,{className:"ol-handle",title:r.drag,onPointerDown:t.depth>0?S=>Ee(S,t.node.id):void 0,onPointerMove:ze,onPointerUp:he,onPointerCancel:he,sx:{display:"flex",color:"#b0b4ba",cursor:t.depth>0&&!l?k?"grabbing":"grab":"default",visibility:k===t.node.id?"visible":"hidden",width:18,flexShrink:0,touchAction:"none"},children:t.depth>0&&!l?(0,C.jsx)(ke.default,{sx:{fontSize:16}}):null}),z?(0,C.jsx)(w.IconButton,{size:"small","aria-label":D?r.unfold:r.fold,title:D?r.unfold:r.fold,onClick:()=>A(de(e,t.node.id)),sx:{width:22,height:22,p:0,color:"text.secondary"},children:D?(0,C.jsx)(ye.default,{sx:{fontSize:20}}):(0,C.jsx)(Se.default,{sx:{fontSize:20}})}):(0,C.jsx)(w.Box,{sx:{width:22,display:"flex",justifyContent:"center",flexShrink:0},children:(0,C.jsx)(w.Box,{sx:{width:5,height:5,borderRadius:"50%",bgcolor:"#9aa0a6"}})}),(0,C.jsx)(w.Box,{sx:{flex:1,minWidth:0,display:"flex",ml:.5},children:(0,C.jsx)("input",{ref:S=>{S?T.current.set(t.node.id,S):T.current.delete(t.node.id)},value:t.node.topic,readOnly:l,placeholder:t.depth===0?r.root:"",spellCheck:!1,autoComplete:"off",onFocus:()=>i?.(t.node.id),onChange:S=>A(le(e,t.node.id,S.target.value),`topic:${t.node.id}`),onKeyDown:S=>Be(S,y),style:{width:b.background?Math.ceil(_(t.node.topic||" ",Number(b.fontSize),b.fontWeight))+16:"100%",maxWidth:"100%",border:0,outline:0,font:"inherit",padding:b.background?"2px 6px":"2px 0",borderRadius:4,background:b.background??"transparent",color:b.color??"inherit",fontSize:b.fontSize,fontWeight:b.fontWeight,textDecoration:[b.textDecoration,D&&z?"underline dotted #9aa0a6":""].filter(Boolean).join(" ")||void 0}})})]},t.node.id)})})}var B=require("react");function q(e=100,o=1200){let n=(0,B.useRef)([]),i=(0,B.useRef)([]),r=(0,B.useRef)(null),[,l]=(0,B.useState)(0),d=()=>l(f=>f+1),c=(0,B.useCallback)((f,u)=>{let p=Date.now(),x=u&&r.current?.key===u&&p-r.current.at<o;r.current=u?{key:u,at:p}:null,i.current=[],x||(n.current.push(f),n.current.length>e&&n.current.shift()),d()},[e,o]),h=(0,B.useCallback)(f=>{let u=n.current.pop();return u?(i.current.push(f),r.current=null,d(),u):null},[]),v=(0,B.useCallback)(f=>{let u=i.current.pop();return u?(n.current.push(f),r.current=null,d(),u):null},[]),T=(0,B.useCallback)(()=>{n.current=[],i.current=[],r.current=null,d()},[]);return{canUndo:n.current.length>0,canRedo:i.current.length>0,record:c,undo:h,redo:v,clear:T}}var De={ko:{clearFormat:"\uC11C\uC2DD \uC9C0\uC6B0\uAE30",fontSize:"\uAE00\uC790 \uD06C\uAE30",sizeDefault:"\uAE30\uBCF8",bold:"\uC9C4\uD558\uAC8C",underline:"\uBC11\uC904",strike:"\uCDE8\uC18C\uC120",textColor:"\uAE00\uC790\uC0C9",background:"\uBC30\uACBD\uC0C9",noColor:"\uC5C6\uC74C",undo:"\uB418\uB3CC\uB9AC\uAE30",redo:"\uB2E4\uC2DC \uD558\uAE30",fold:"\uC811\uAE30",unfold:"\uD3BC\uCE58\uAE30",drag:"\uB04C\uC5B4\uC11C \uC62E\uAE30\uAE30",root:"\uC8FC\uC81C",hint:"Enter: \uC0C8 \uC904 \xB7 Tab / Shift+Tab: \uB4E4\uC5EC\uC4F0\uAE30 / \uB0B4\uC5B4\uC4F0\uAE30 \xB7 Alt+\u2191\u2193: \uC21C\uC11C \xB7 \uC904 \uC55E \uC190\uC7A1\uC774 \uB04C\uAE30: \uC62E\uAE30\uAE30 \xB7 \uBE48 \uC904 Backspace: \uC9C0\uC6B0\uAE30"},en:{clearFormat:"Clear format",fontSize:"Font size",sizeDefault:"Default",bold:"Bold",underline:"Underline",strike:"Strikethrough",textColor:"Text color",background:"Background",noColor:"None",undo:"Undo",redo:"Redo",fold:"Collapse",unfold:"Expand",drag:"Drag to move",root:"Topic",hint:"Enter: new line \xB7 Tab / Shift+Tab: indent / outdent \xB7 Alt+\u2191\u2193: reorder \xB7 Drag the row handle: move \xB7 Backspace on empty: delete"},ja:{clearFormat:"\u66F8\u5F0F\u3092\u30AF\u30EA\u30A2",fontSize:"\u6587\u5B57\u30B5\u30A4\u30BA",sizeDefault:"\u6A19\u6E96",bold:"\u592A\u5B57",underline:"\u4E0B\u7DDA",strike:"\u53D6\u308A\u6D88\u3057\u7DDA",textColor:"\u6587\u5B57\u8272",background:"\u80CC\u666F\u8272",noColor:"\u306A\u3057",undo:"\u5143\u306B\u623B\u3059",redo:"\u3084\u308A\u76F4\u3059",fold:"\u6298\u308A\u305F\u305F\u3080",unfold:"\u5C55\u958B",drag:"\u30C9\u30E9\u30C3\u30B0\u3067\u79FB\u52D5",root:"\u30C6\u30FC\u30DE",hint:"Enter: \u65B0\u3057\u3044\u884C \xB7 Tab / Shift+Tab: \u5B57\u4E0B\u3052 / \u5B57\u4E0A\u3052 \xB7 Alt+\u2191\u2193: \u4E26\u3079\u66FF\u3048 \xB7 \u884C\u982D\u306E\u30CF\u30F3\u30C9\u30EB\u3092\u30C9\u30E9\u30C3\u30B0: \u79FB\u52D5 \xB7 \u7A7A\u884C\u3067 Backspace: \u524A\u9664"},zh:{clearFormat:"\u6E05\u9664\u683C\u5F0F",fontSize:"\u5B57\u53F7",sizeDefault:"\u9ED8\u8BA4",bold:"\u52A0\u7C97",underline:"\u4E0B\u5212\u7EBF",strike:"\u5220\u9664\u7EBF",textColor:"\u6587\u5B57\u989C\u8272",background:"\u80CC\u666F\u8272",noColor:"\u65E0",undo:"\u64A4\u9500",redo:"\u91CD\u505A",fold:"\u6298\u53E0",unfold:"\u5C55\u5F00",drag:"\u62D6\u52A8\u4EE5\u79FB\u52A8",root:"\u4E3B\u9898",hint:"Enter: \u65B0\u884C \xB7 Tab / Shift+Tab: \u7F29\u8FDB / \u53D6\u6D88\u7F29\u8FDB \xB7 Alt+\u2191\u2193: \u987A\u5E8F \xB7 \u62D6\u52A8\u884C\u9996\u624B\u67C4: \u79FB\u52A8 \xB7 \u7A7A\u884C Backspace: \u5220\u9664"},de:{clearFormat:"Formatierung l\xF6schen",fontSize:"Schriftgr\xF6\xDFe",sizeDefault:"Standard",bold:"Fett",underline:"Unterstrichen",strike:"Durchgestrichen",textColor:"Textfarbe",background:"Hintergrund",noColor:"Keine",undo:"R\xFCckg\xE4ngig",redo:"Wiederholen",fold:"Einklappen",unfold:"Ausklappen",drag:"Zum Verschieben ziehen",root:"Thema",hint:"Enter: neue Zeile \xB7 Tab / Shift+Tab: ein- / ausr\xFCcken \xB7 Alt+\u2191\u2193: Reihenfolge \xB7 Griff ziehen: verschieben \xB7 Backspace leer: l\xF6schen"},fr:{clearFormat:"Effacer la mise en forme",fontSize:"Taille",sizeDefault:"Par d\xE9faut",bold:"Gras",underline:"Soulign\xE9",strike:"Barr\xE9",textColor:"Couleur du texte",background:"Arri\xE8re-plan",noColor:"Aucune",undo:"Annuler",redo:"R\xE9tablir",fold:"Replier",unfold:"D\xE9plier",drag:"Glisser pour d\xE9placer",root:"Sujet",hint:"Entr\xE9e : nouvelle ligne \xB7 Tab / Maj+Tab : indenter / d\xE9sindenter \xB7 Alt+\u2191\u2193 : ordre \xB7 Glisser la poign\xE9e : d\xE9placer \xB7 Retour arri\xE8re vide : supprimer"},it:{clearFormat:"Cancella formattazione",fontSize:"Dimensione",sizeDefault:"Predefinita",bold:"Grassetto",underline:"Sottolineato",strike:"Barrato",textColor:"Colore testo",background:"Sfondo",noColor:"Nessuno",undo:"Annulla",redo:"Ripeti",fold:"Comprimi",unfold:"Espandi",drag:"Trascina per spostare",root:"Argomento",hint:"Invio: nuova riga \xB7 Tab / Maiusc+Tab: rientro / riduci \xB7 Alt+\u2191\u2193: ordine \xB7 Trascina la maniglia: sposta \xB7 Backspace su vuota: elimina"},vi:{clearFormat:"X\xF3a \u0111\u1ECBnh d\u1EA1ng",fontSize:"C\u1EE1 ch\u1EEF",sizeDefault:"M\u1EB7c \u0111\u1ECBnh",bold:"\u0110\u1EADm",underline:"G\u1EA1ch ch\xE2n",strike:"G\u1EA1ch ngang",textColor:"M\xE0u ch\u1EEF",background:"M\xE0u n\u1EC1n",noColor:"Kh\xF4ng",undo:"Ho\xE0n t\xE1c",redo:"L\xE0m l\u1EA1i",fold:"Thu g\u1ECDn",unfold:"M\u1EDF r\u1ED9ng",drag:"K\xE9o \u0111\u1EC3 di chuy\u1EC3n",root:"Ch\u1EE7 \u0111\u1EC1",hint:"Enter: d\xF2ng m\u1EDBi \xB7 Tab / Shift+Tab: th\u1EE5t v\xE0o / ra \xB7 Alt+\u2191\u2193: th\u1EE9 t\u1EF1 \xB7 K\xE9o tay c\u1EA7m: di chuy\u1EC3n \xB7 Backspace d\xF2ng tr\u1ED1ng: x\xF3a"}};function V(e,o){let n=(e??"en").slice(0,2).toLowerCase();return{...De[n]??De.en,...o}}var H=require("react/jsx-runtime");function ve({value:e,onChange:o,locale:n,strings:i,readOnly:r,toolbar:l=!0,toolbarStart:d,toolbarEnd:c,height:h="100%"}){let v=V(n,i),T=q(),[f,u]=(0,Ce.useState)(null),p=(s,E)=>{T.record(e,E),o(s)},x=()=>{let s=T.undo(e);s&&o(s)},R=()=>{let s=T.redo(e);s&&o(s)},k=f?g(e,f)?.node:void 0;return(0,H.jsxs)(pe.Box,{sx:{display:"flex",flexDirection:"column",height:h,minHeight:0,bgcolor:"#fff"},children:[l?(0,H.jsx)(j,{strings:v,style:k?k.style??{}:void 0,onStyle:s=>{if(!f)return;let E=ae(e,[f],s);E&&p(E.root)},canUndo:T.canUndo,canRedo:T.canRedo,onUndo:x,onRedo:R,start:d,end:c,readOnly:r}):null,(0,H.jsx)(pe.Box,{sx:{flex:1,minHeight:0},children:(0,H.jsx)(Z,{root:e,onEdit:p,selectedId:f,onSelect:u,strings:v,readOnly:r,onUndo:x,onRedo:R})})]})}
2
2
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../src/index.ts", "../src/Outliner.tsx", "../src/FormatToolbar.tsx", "../src/tree.ts", "../src/OutlineList.tsx", "../src/measure.ts", "../src/history.ts", "../src/i18n.ts"],
4
- "sourcesContent": ["export { Outliner, type OutlinerProps } from \"./Outliner\";\nexport { OutlineList, outlineTextStyle, type OutlineListProps } from \"./OutlineList\";\nexport { FormatToolbar, ToolButton, ToolDivider, FONT_SIZES, TEXT_COLORS, BACKGROUND_COLORS, type FormatToolbarProps } from \"./FormatToolbar\";\nexport { useTreeHistory, type TreeHistory } from \"./history\";\nexport { outlinerStrings, type OutlinerStrings } from \"./i18n\";\nexport { measureText, DEFAULT_FONT_FAMILY } from \"./measure\";\nexport * from \"./tree\";\n", "/**\n * Outliner \u2014 toolbar + rows, with its own undo history. Controlled: pass `value` and `onChange`.\n * For a custom layout use `OutlineList` + `FormatToolbar` + `useTreeHistory` directly (the mind map does).\n */\nimport { useState, type ReactNode } from \"react\";\nimport { Box } from \"@mui/material\";\nimport { FormatToolbar } from \"./FormatToolbar\";\nimport { OutlineList } from \"./OutlineList\";\nimport { useTreeHistory } from \"./history\";\nimport { outlinerStrings, type OutlinerStrings } from \"./i18n\";\nimport { locateNode, setNodeStyle, type TreeNode } from \"./tree\";\n\nexport interface OutlinerProps {\n value: TreeNode;\n onChange: (value: TreeNode) => void;\n locale?: string;\n strings?: Partial<OutlinerStrings>;\n readOnly?: boolean;\n /** Show the formatting toolbar (default true). */\n toolbar?: boolean;\n toolbarStart?: ReactNode;\n toolbarEnd?: ReactNode;\n height?: number | string;\n}\n\nexport function Outliner({ value, onChange, locale, strings: overrides, readOnly, toolbar = true, toolbarStart, toolbarEnd, height = \"100%\" }: OutlinerProps) {\n const strings = outlinerStrings(locale, overrides);\n const history = useTreeHistory();\n const [selected, setSelected] = useState<string | null>(null);\n const commit = (next: TreeNode, mergeKey?: string) => {\n history.record(value, mergeKey);\n onChange(next);\n };\n const undo = () => {\n const prev = history.undo(value);\n if (prev) onChange(prev);\n };\n const redo = () => {\n const next = history.redo(value);\n if (next) onChange(next);\n };\n const selectedNode = selected ? locateNode(value, selected)?.node : undefined;\n return (\n <Box sx={{ display: \"flex\", flexDirection: \"column\", height, minHeight: 0, bgcolor: \"#fff\" }}>\n {toolbar ? (\n <FormatToolbar\n strings={strings}\n style={selectedNode ? (selectedNode.style ?? {}) : undefined}\n onStyle={(patch) => {\n if (!selected) return;\n const result = setNodeStyle(value, [selected], patch);\n if (result) commit(result.root);\n }}\n canUndo={history.canUndo}\n canRedo={history.canRedo}\n onUndo={undo}\n onRedo={redo}\n start={toolbarStart}\n end={toolbarEnd}\n readOnly={readOnly}\n />\n ) : null}\n <Box sx={{ flex: 1, minHeight: 0 }}>\n <OutlineList root={value} onEdit={commit} selectedId={selected} onSelect={setSelected} strings={strings} readOnly={readOnly} onUndo={undo} onRedo={redo} />\n </Box>\n </Box>\n );\n}\n", "/**\n * Formatting toolbar \u2014 font size \u00B7 bold \u00B7 underline \u00B7 strike \u00B7 text color \u00B7 background, plus undo / redo.\n * Shared by the outline and the mind map; it edits the style of the selected node(s).\n * `start` / `end` / `children` let the host add its own controls (view switch, map tools, \u2026).\n */\nimport { useState, type ReactNode } from \"react\";\nimport { Box, ButtonBase, Divider, IconButton, Menu, MenuItem, Popover, Tooltip } from \"@mui/material\";\nimport FormatBoldIcon from \"@mui/icons-material/FormatBold\";\nimport FormatUnderlinedIcon from \"@mui/icons-material/FormatUnderlined\";\nimport StrikethroughSIcon from \"@mui/icons-material/StrikethroughS\";\nimport FormatColorTextIcon from \"@mui/icons-material/FormatColorText\";\nimport FormatColorFillIcon from \"@mui/icons-material/FormatColorFill\";\nimport UndoIcon from \"@mui/icons-material/Undo\";\nimport RedoIcon from \"@mui/icons-material/Redo\";\nimport ArrowDropDownIcon from \"@mui/icons-material/ArrowDropDown\";\nimport FormatColorResetIcon from \"@mui/icons-material/FormatColorReset\";\nimport { hasDecoration, toggleDecoration, type TreeNodeStyle } from \"./tree\";\nimport type { OutlinerStrings } from \"./i18n\";\n\nexport const FONT_SIZES = [12, 14, 16, 18, 20, 24, 28];\nexport const TEXT_COLORS = [\"#1f2328\", \"#5f6368\", \"#d93025\", \"#e8710a\", \"#f9ab00\", \"#188038\", \"#1a73e8\", \"#9334e6\", \"#c2185b\", \"#ffffff\"];\nexport const BACKGROUND_COLORS = [\"#fde2e1\", \"#feefc3\", \"#fff8c5\", \"#ceead6\", \"#d2e3fc\", \"#e9d7fe\", \"#fad2e1\", \"#e8eaed\", \"#3c4043\", \"#1a73e8\"];\n\nexport interface FormatToolbarProps {\n strings: OutlinerStrings;\n /** Style of the node being edited (undefined \u2192 nothing selected; format buttons are disabled). */\n style: TreeNodeStyle | undefined;\n onStyle: (patch: Partial<TreeNodeStyle>) => void;\n canUndo?: boolean;\n canRedo?: boolean;\n onUndo?: () => void;\n onRedo?: () => void;\n start?: ReactNode;\n children?: ReactNode;\n end?: ReactNode;\n readOnly?: boolean;\n}\n\nconst btnSx = (active = false) => ({\n width: 30,\n height: 30,\n borderRadius: 1,\n color: active ? \"primary.main\" : \"text.secondary\",\n bgcolor: active ? \"rgba(25,118,210,0.10)\" : \"transparent\",\n \"&:hover\": { bgcolor: active ? \"rgba(25,118,210,0.16)\" : \"rgba(0,0,0,0.06)\" },\n});\n\nexport function ToolButton({ label, active, disabled, onClick, children }: { label: string; active?: boolean; disabled?: boolean; onClick: () => void; children: ReactNode }) {\n return (\n <Tooltip title={label} disableInteractive>\n <span>\n <IconButton size=\"small\" aria-label={label} aria-pressed={active} disabled={disabled} onMouseDown={(event) => event.preventDefault()} onClick={onClick} sx={btnSx(active)}>\n {children}\n </IconButton>\n </span>\n </Tooltip>\n );\n}\n\nexport const ToolDivider = () => <Divider orientation=\"vertical\" flexItem sx={{ mx: 0.5, my: 0.75 }} />;\n\nfunction ColorButton({ label, icon, value, colors, noneLabel, disabled, onPick }: { label: string; icon: ReactNode; value?: string; colors: string[]; noneLabel: string; disabled: boolean; onPick: (color: string | undefined) => void }) {\n const [anchor, setAnchor] = useState<HTMLElement | null>(null);\n return (\n <>\n <Tooltip title={label} disableInteractive>\n <span>\n <IconButton size=\"small\" aria-label={label} disabled={disabled} onMouseDown={(event) => event.preventDefault()} onClick={(event) => setAnchor(event.currentTarget)} sx={{ ...btnSx(false), flexDirection: \"column\", gap: 0 }}>\n {icon}\n <Box sx={{ width: 16, height: 3, mt: \"-3px\", borderRadius: 0.5, bgcolor: value ?? \"transparent\", border: value ? 0 : \"1px solid #c4c7cc\" }} />\n </IconButton>\n </span>\n </Tooltip>\n <Popover open={Boolean(anchor)} anchorEl={anchor} onClose={() => setAnchor(null)} transitionDuration={0} anchorOrigin={{ vertical: \"bottom\", horizontal: \"left\" }} disableRestoreFocus>\n <Box sx={{ p: 1, display: \"grid\", gridTemplateColumns: \"repeat(5, 24px)\", gap: 0.75 }}>\n {colors.map((color) => (\n <ButtonBase\n key={color}\n aria-label={color}\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n onPick(color);\n setAnchor(null);\n }}\n sx={{ width: 24, height: 24, borderRadius: 0.75, bgcolor: color, border: \"1px solid rgba(0,0,0,0.12)\", outline: value?.toLowerCase() === color ? \"2px solid #1a73e8\" : \"none\", outlineOffset: 1 }}\n />\n ))}\n <ButtonBase\n onMouseDown={(event) => event.preventDefault()}\n onClick={() => {\n onPick(undefined);\n setAnchor(null);\n }}\n sx={{ gridColumn: \"1 / -1\", height: 26, borderRadius: 0.75, fontSize: 13, color: \"text.secondary\", gap: 0.5, \"&:hover\": { bgcolor: \"rgba(0,0,0,0.05)\" } }}\n >\n <FormatColorResetIcon sx={{ fontSize: 16 }} />\n {noneLabel}\n </ButtonBase>\n </Box>\n </Popover>\n </>\n );\n}\n\nexport function FormatToolbar({ strings, style, onStyle, canUndo, canRedo, onUndo, onRedo, start, children, end, readOnly }: FormatToolbarProps) {\n const [sizeAnchor, setSizeAnchor] = useState<HTMLElement | null>(null);\n const disabled = readOnly || !style;\n const size = style?.fontSize ? parseFloat(style.fontSize) : null;\n const bold = style?.fontWeight === \"bold\" || Number(style?.fontWeight) >= 600;\n return (\n <Box\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n flexWrap: \"wrap\",\n gap: 0.25,\n minHeight: 40,\n px: 1,\n borderBottom: \"1px solid #e0e0e0\",\n bgcolor: \"#fff\",\n flexShrink: 0,\n }}\n >\n {start}\n {start ? <ToolDivider /> : null}\n {onUndo ? (\n <>\n <ToolButton label={strings.undo} disabled={readOnly || !canUndo} onClick={onUndo}>\n <UndoIcon sx={{ fontSize: 18 }} />\n </ToolButton>\n <ToolButton label={strings.redo} disabled={readOnly || !canRedo} onClick={() => onRedo?.()}>\n <RedoIcon sx={{ fontSize: 18 }} />\n </ToolButton>\n <ToolDivider />\n </>\n ) : null}\n <Tooltip title={strings.fontSize} disableInteractive>\n <span>\n <ButtonBase\n disabled={disabled}\n onMouseDown={(event) => event.preventDefault()}\n onClick={(event) => setSizeAnchor(event.currentTarget)}\n sx={{ height: 30, px: 0.75, borderRadius: 1, fontSize: 13, color: disabled ? \"text.disabled\" : \"text.primary\", minWidth: 52, justifyContent: \"space-between\", \"&:hover\": { bgcolor: \"rgba(0,0,0,0.06)\" } }}\n >\n {size ?? strings.sizeDefault}\n <ArrowDropDownIcon sx={{ fontSize: 18, color: \"text.secondary\" }} />\n </ButtonBase>\n </span>\n </Tooltip>\n <Menu open={Boolean(sizeAnchor)} anchorEl={sizeAnchor} onClose={() => setSizeAnchor(null)} transitionDuration={0} disableRestoreFocus>\n <MenuItem\n dense\n selected={size === null}\n onClick={() => {\n onStyle({ fontSize: undefined });\n setSizeAnchor(null);\n }}\n >\n {strings.sizeDefault}\n </MenuItem>\n {FONT_SIZES.map((value) => (\n <MenuItem\n key={value}\n dense\n selected={size === value}\n onClick={() => {\n onStyle({ fontSize: `${value}px` });\n setSizeAnchor(null);\n }}\n >\n {value}\n </MenuItem>\n ))}\n </Menu>\n <ToolButton label={strings.bold} active={bold} disabled={disabled} onClick={() => onStyle({ fontWeight: bold ? undefined : \"bold\" })}>\n <FormatBoldIcon sx={{ fontSize: 19 }} />\n </ToolButton>\n <ToolButton label={strings.underline} active={hasDecoration(style, \"underline\")} disabled={disabled} onClick={() => onStyle({ textDecoration: toggleDecoration(style, \"underline\") })}>\n <FormatUnderlinedIcon sx={{ fontSize: 19 }} />\n </ToolButton>\n <ToolButton label={strings.strike} active={hasDecoration(style, \"line-through\")} disabled={disabled} onClick={() => onStyle({ textDecoration: toggleDecoration(style, \"line-through\") })}>\n <StrikethroughSIcon sx={{ fontSize: 19 }} />\n </ToolButton>\n <ColorButton label={strings.textColor} icon={<FormatColorTextIcon sx={{ fontSize: 17 }} />} value={style?.color} colors={TEXT_COLORS} noneLabel={strings.noColor} disabled={disabled} onPick={(color) => onStyle({ color })} />\n <ColorButton label={strings.background} icon={<FormatColorFillIcon sx={{ fontSize: 17 }} />} value={style?.background} colors={BACKGROUND_COLORS} noneLabel={strings.noColor} disabled={disabled} onPick={(color) => onStyle({ background: color })} />\n {children ? <ToolDivider /> : null}\n {children}\n <Box sx={{ flex: 1 }} />\n {end}\n </Box>\n );\n}\n", "/**\n * Tree data and edit operations shared by the outline and the mind map.\n *\n * The shape follows Mind Elixir's `nodeData` so data saved by it opens unchanged:\n * `{ id, topic, children?, expanded?, style? }` \u2014 unknown keys are carried along untouched.\n * Every operation is pure: it returns a new root (structural copy) and, when useful,\n * the id that should be focused next.\n */\n\n/** Text style of one node (same keys as Mind Elixir `style`). */\nexport interface TreeNodeStyle {\n fontSize?: string;\n color?: string;\n background?: string;\n fontWeight?: string;\n textDecoration?: string;\n}\n\nexport interface TreeNode {\n id: string;\n topic: string;\n children?: TreeNode[];\n /** `false` = folded. Missing means expanded. */\n expanded?: boolean;\n style?: TreeNodeStyle;\n [key: string]: unknown;\n}\n\nexport interface TreeEdit {\n root: TreeNode;\n /** Node to select / focus after the edit. */\n focusId?: string;\n}\n\nexport interface TreeRow {\n node: TreeNode;\n depth: number;\n parentId: string | null;\n}\n\n/** Short random id (hex, like Mind Elixir). */\nexport const newNodeId = () => Math.random().toString(16).slice(2, 18);\n\nexport const createTree = (topic: string): TreeNode => ({ id: \"root\", topic, children: [] });\n\nconst clone = (root: TreeNode): TreeNode => structuredClone(root) as TreeNode;\n\n/** Finds a node with its parent and index (in the given tree). */\nexport function locateNode(root: TreeNode, id: string): { node: TreeNode; parent: TreeNode | null; index: number } | null {\n if (root.id === id) return { node: root, parent: null, index: 0 };\n const stack: TreeNode[] = [root];\n while (stack.length) {\n const parent = stack.pop()!;\n const list = parent.children ?? [];\n for (let i = 0; i < list.length; i++) {\n if (list[i].id === id) return { node: list[i], parent, index: i };\n stack.push(list[i]);\n }\n }\n return null;\n}\n\n/** True when `id` is `node` itself or one of its descendants. */\nexport const containsNode = (node: TreeNode, id: string): boolean => node.id === id || (node.children ?? []).some((child) => containsNode(child, id));\n\nexport const isFolded = (node: TreeNode) => node.expanded === false && (node.children?.length ?? 0) > 0;\n\n/** Rows that are visible (folded subtrees hidden), in reading order. */\nexport function visibleRows(root: TreeNode): TreeRow[] {\n const rows: TreeRow[] = [];\n const walk = (node: TreeNode, depth: number, parentId: string | null) => {\n rows.push({ node, depth, parentId });\n if (node.expanded !== false) for (const child of node.children ?? []) walk(child, depth + 1, node.id);\n };\n walk(root, 0, null);\n return rows;\n}\n\n/** Runs `run` on a copy; returns null when nothing changed (run returned false). */\nfunction edit(root: TreeNode, run: (copy: TreeNode) => string | void | false): TreeEdit | null {\n const copy = clone(root);\n const focusId = run(copy);\n if (focusId === false) return null;\n return { root: copy, focusId: focusId || undefined };\n}\n\n/** New child at the end (or `first`). */\nexport const addChild = (root: TreeNode, id: string, topic = \"\", first = false) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at) return false;\n const fresh: TreeNode = { id: newNodeId(), topic };\n at.node.children = first ? [fresh, ...(at.node.children ?? [])] : [...(at.node.children ?? []), fresh];\n at.node.expanded = true;\n return fresh.id;\n });\n\n/** New sibling right after (root \u2192 first child). */\nexport const addSibling = (root: TreeNode, id: string, topic = \"\") =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at) return false;\n const fresh: TreeNode = { id: newNodeId(), topic };\n if (!at.parent) {\n at.node.children = [fresh, ...(at.node.children ?? [])];\n at.node.expanded = true;\n } else at.parent.children!.splice(at.index + 1, 0, fresh);\n return fresh.id;\n });\n\n/** Outline \"Enter\": first child when the row is an open parent, otherwise next sibling. */\nexport const addBelow = (root: TreeNode, id: string) => {\n const at = locateNode(root, id);\n if (at && (!at.parent || ((at.node.children?.length ?? 0) > 0 && at.node.expanded !== false))) return addChild(root, id, \"\", true);\n return addSibling(root, id);\n};\n\n/** Removes the node (not the root). Focus goes to the previous sibling, else the parent. */\nexport const removeNode = (root: TreeNode, id: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent) return false;\n at.parent.children!.splice(at.index, 1);\n return at.parent.children![at.index - 1]?.id ?? at.parent.id;\n });\n\n/** Becomes the last child of the previous sibling. */\nexport const indentNode = (root: TreeNode, id: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent || at.index === 0) return false;\n const prev = at.parent.children![at.index - 1];\n at.parent.children!.splice(at.index, 1);\n prev.children = [...(prev.children ?? []), at.node];\n prev.expanded = true;\n return id;\n });\n\n/** Becomes the sibling right after its parent. */\nexport const outdentNode = (root: TreeNode, id: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent) return false;\n const up = locateNode(copy, at.parent.id);\n if (!up?.parent) return false;\n at.parent.children!.splice(at.index, 1);\n up.parent.children!.splice(up.index + 1, 0, at.node);\n return id;\n });\n\n/** Moves one step among its siblings. */\nexport const shiftNode = (root: TreeNode, id: string, step: -1 | 1) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent) return false;\n const list = at.parent.children!;\n const to = at.index + step;\n if (to < 0 || to >= list.length) return false;\n [list[at.index], list[to]] = [list[to], list[at.index]];\n return id;\n });\n\n/** Moves `from` before / after `to`, or into `to` as its last child. */\nexport const moveNode = (root: TreeNode, from: string, to: string, place: \"before\" | \"after\" | \"child\") =>\n edit(root, (copy) => {\n const src = locateNode(copy, from);\n if (!src?.parent || containsNode(src.node, to)) return false;\n src.parent.children!.splice(src.index, 1);\n const dst = locateNode(copy, to);\n if (!dst) return false;\n if (place === \"child\" || !dst.parent) {\n dst.node.children = [...(dst.node.children ?? []), src.node];\n dst.node.expanded = true;\n } else dst.parent.children!.splice(dst.index + (place === \"after\" ? 1 : 0), 0, src.node);\n return from;\n });\n\nexport const setTopic = (root: TreeNode, id: string, topic: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at || at.node.topic === topic) return false;\n at.node.topic = topic;\n });\n\nexport const toggleFold = (root: TreeNode, id: string, expanded?: boolean) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at || !(at.node.children?.length ?? 0)) return false;\n at.node.expanded = expanded ?? at.node.expanded === false;\n });\n\n/** Merges a style patch; `undefined` values remove the key. */\nexport const setNodeStyle = (root: TreeNode, ids: string[], patch: Partial<TreeNodeStyle>) =>\n edit(root, (copy) => {\n let changed = false;\n for (const id of ids) {\n const at = locateNode(copy, id);\n if (!at) continue;\n const next: TreeNodeStyle = { ...(at.node.style ?? {}) };\n for (const [key, value] of Object.entries(patch) as [keyof TreeNodeStyle, string | undefined][]) {\n if (value === undefined || value === \"\") delete next[key];\n else next[key] = value;\n }\n at.node.style = Object.keys(next).length ? next : undefined;\n if (!at.node.style) delete at.node.style;\n changed = true;\n }\n return changed ? undefined : false;\n });\n\n/** `textDecoration` holds both underline and line-through. */\nexport function hasDecoration(style: TreeNodeStyle | undefined, kind: \"underline\" | \"line-through\") {\n return (style?.textDecoration ?? \"\").split(/\\s+/).includes(kind);\n}\nexport function toggleDecoration(style: TreeNodeStyle | undefined, kind: \"underline\" | \"line-through\"): string | undefined {\n const set = new Set((style?.textDecoration ?? \"\").split(/\\s+/).filter(Boolean));\n if (set.has(kind)) set.delete(kind);\n else set.add(kind);\n return set.size ? [...set].join(\" \") : undefined;\n}\n", "/**\n * Outline rows \u2014 one node per line, fold / unfold, indent / outdent, reorder, drag to move, per-node style.\n *\n * Keys: Enter new line \u00B7 Tab indent \u00B7 Shift+Tab outdent \u00B7 Alt+\u2191/\u2193 reorder \u00B7 \u2191/\u2193 previous / next row \u00B7\n * Backspace on an empty row deletes it \u00B7 Ctrl/\u2318+Z undo \u00B7 Ctrl/\u2318+Shift+Z or Ctrl+Y redo.\n * Dragging follows the pointer directly (native drag & drop doesn't fire drops reliably inside drawers / modals).\n */\nimport { useEffect, useRef, useState, type CSSProperties, type KeyboardEvent, type PointerEvent } from \"react\";\nimport { Box, IconButton } from \"@mui/material\";\nimport ArrowRightIcon from \"@mui/icons-material/ArrowRight\";\nimport ArrowDropDownIcon from \"@mui/icons-material/ArrowDropDown\";\nimport DragIndicatorIcon from \"@mui/icons-material/DragIndicator\";\nimport {\n addBelow,\n containsNode,\n indentNode,\n locateNode,\n moveNode,\n outdentNode,\n removeNode,\n setTopic,\n shiftNode,\n toggleFold,\n visibleRows,\n type TreeEdit,\n type TreeNode,\n type TreeNodeStyle,\n} from \"./tree\";\nimport type { OutlinerStrings } from \"./i18n\";\nimport { measureText } from \"./measure\";\n\nconst INDENT = 22;\nconst BASE_FONT = 15;\n\nexport interface OutlineListProps {\n root: TreeNode;\n /** A change; `mergeKey` is set for typing so history can merge it. */\n onEdit: (root: TreeNode, mergeKey?: string) => void;\n selectedId?: string | null;\n onSelect?: (id: string) => void;\n strings: OutlinerStrings;\n readOnly?: boolean;\n onUndo?: () => void;\n onRedo?: () => void;\n /** Extra space above the first row / below the last row (px). */\n paddingTop?: number;\n paddingBottom?: number;\n}\n\n/** Node style \u2192 input style (font size is clamped so the list stays a list). */\nexport function outlineTextStyle(style: TreeNodeStyle | undefined, depth: number): CSSProperties {\n const size = style?.fontSize ? Math.min(28, Math.max(12, parseFloat(style.fontSize))) : BASE_FONT;\n return {\n fontSize: size,\n fontWeight: style?.fontWeight ?? (depth === 0 ? 700 : 400),\n color: style?.color,\n textDecoration: style?.textDecoration,\n background: style?.background,\n };\n}\n\nexport function OutlineList({ root, onEdit, selectedId, onSelect, strings, readOnly, onUndo, onRedo, paddingTop = 8, paddingBottom = 40 }: OutlineListProps) {\n const inputs = useRef(new Map<string, HTMLInputElement>());\n const rowEls = useRef(new Map<string, HTMLDivElement>());\n const [focus, setFocus] = useState<string | null>(null);\n const [drop, setDrop] = useState<{ id: string; place: \"before\" | \"after\" } | null>(null);\n const [dragging, setDragging] = useState<string | null>(null);\n const rows = visibleRows(root);\n\n useEffect(() => {\n if (!focus) return;\n const el = inputs.current.get(focus);\n if (!el) return;\n el.focus();\n el.setSelectionRange(el.value.length, el.value.length);\n setFocus(null);\n }, [focus, root]);\n\n const apply = (result: TreeEdit | null, mergeKey?: string) => {\n if (!result) return;\n onEdit(result.root, mergeKey);\n if (result.focusId) {\n setFocus(result.focusId);\n onSelect?.(result.focusId);\n }\n };\n\n const onKey = (event: KeyboardEvent<HTMLInputElement>, index: number) => {\n if (event.nativeEvent.isComposing) return;\n const row = rows[index];\n const id = row.node.id;\n const mod = event.ctrlKey || event.metaKey;\n if (mod && (event.key === \"z\" || event.key === \"Z\")) {\n event.preventDefault();\n if (event.shiftKey) onRedo?.();\n else onUndo?.();\n return;\n }\n if (mod && (event.key === \"y\" || event.key === \"Y\")) {\n event.preventDefault();\n onRedo?.();\n return;\n }\n if (readOnly) return;\n if (event.key === \"Enter\") {\n event.preventDefault();\n apply(addBelow(root, id));\n } else if (event.key === \"Tab\") {\n event.preventDefault();\n apply(event.shiftKey ? outdentNode(root, id) : indentNode(root, id));\n } else if (event.altKey && (event.key === \"ArrowUp\" || event.key === \"ArrowDown\")) {\n event.preventDefault();\n apply(shiftNode(root, id, event.key === \"ArrowUp\" ? -1 : 1));\n } else if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\n const next = rows[index + (event.key === \"ArrowUp\" ? -1 : 1)];\n if (next) {\n event.preventDefault();\n setFocus(next.node.id);\n onSelect?.(next.node.id);\n }\n } else if (event.key === \"Backspace\" && event.currentTarget.value === \"\" && row.depth > 0 && !(row.node.children?.length ?? 0)) {\n event.preventDefault();\n const result = removeNode(root, id);\n if (result) apply({ root: result.root, focusId: rows[index - 1]?.node.id });\n }\n };\n\n // Drag \u2014 follow the pointer on the handle; drop before / after the row under it (never into itself).\n const dragNode = dragging ? locateNode(root, dragging)?.node ?? null : null;\n const onHandleDown = (event: PointerEvent<HTMLDivElement>, id: string) => {\n if (event.button !== 0 || readOnly) return;\n event.preventDefault();\n event.currentTarget.setPointerCapture(event.pointerId);\n setDragging(id);\n setDrop(null);\n };\n const onHandleMove = (event: PointerEvent<HTMLDivElement>) => {\n if (!dragging || !dragNode) return;\n let next: { id: string; place: \"before\" | \"after\" } | null = null;\n for (const row of rows) {\n const el = rowEls.current.get(row.node.id);\n if (!el) continue;\n const r = el.getBoundingClientRect();\n if (event.clientY < r.top || event.clientY >= r.bottom) continue;\n if (!containsNode(dragNode, row.node.id)) next = { id: row.node.id, place: event.clientY < r.top + r.height / 2 ? \"before\" : \"after\" };\n break;\n }\n if (next?.id !== drop?.id || next?.place !== drop?.place) setDrop(next);\n };\n const onHandleUp = (event: PointerEvent<HTMLDivElement>) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);\n if (dragging && drop) apply(moveNode(root, dragging, drop.id, drop.place));\n setDragging(null);\n setDrop(null);\n };\n\n return (\n <Box sx={{ position: \"relative\", height: \"100%\", overflowY: \"auto\", bgcolor: \"#fff\", pt: `${paddingTop}px`, pb: `${paddingBottom}px`, px: 1.5 }}>\n {rows.map((row, index) => {\n const hasKids = (row.node.children?.length ?? 0) > 0;\n const folded = row.node.expanded === false;\n const line = drop?.id === row.node.id ? drop.place : null;\n const text = outlineTextStyle(row.node.style, row.depth);\n return (\n <Box\n key={row.node.id}\n ref={(el: HTMLDivElement | null) => {\n if (el) rowEls.current.set(row.node.id, el);\n else rowEls.current.delete(row.node.id);\n }}\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n minHeight: 26,\n pl: `${row.depth * INDENT}px`,\n borderRadius: 0.75,\n bgcolor: selectedId === row.node.id ? \"rgba(26,115,232,0.06)\" : \"transparent\",\n // Drop line \u2014 inset shadow so it takes no height.\n boxShadow: (theme) =>\n line === \"before\" ? `inset 0 2px 0 ${theme.palette.primary.main}` : line === \"after\" ? `inset 0 -2px 0 ${theme.palette.primary.main}` : \"none\",\n opacity: dragging === row.node.id ? 0.4 : 1,\n \"&:hover .ol-handle\": { visibility: \"visible\" },\n }}\n >\n <Box\n className=\"ol-handle\"\n title={strings.drag}\n onPointerDown={row.depth > 0 ? (event: PointerEvent<HTMLDivElement>) => onHandleDown(event, row.node.id) : undefined}\n onPointerMove={onHandleMove}\n onPointerUp={onHandleUp}\n onPointerCancel={onHandleUp}\n sx={{\n display: \"flex\",\n color: \"#b0b4ba\",\n cursor: row.depth > 0 && !readOnly ? (dragging ? \"grabbing\" : \"grab\") : \"default\",\n visibility: dragging === row.node.id ? \"visible\" : \"hidden\",\n width: 18,\n flexShrink: 0,\n touchAction: \"none\",\n }}\n >\n {row.depth > 0 && !readOnly ? <DragIndicatorIcon sx={{ fontSize: 16 }} /> : null}\n </Box>\n {hasKids ? (\n <IconButton\n size=\"small\"\n aria-label={folded ? strings.unfold : strings.fold}\n title={folded ? strings.unfold : strings.fold}\n onClick={() => apply(toggleFold(root, row.node.id))}\n sx={{ width: 22, height: 22, p: 0, color: \"text.secondary\" }}\n >\n {folded ? <ArrowRightIcon sx={{ fontSize: 20 }} /> : <ArrowDropDownIcon sx={{ fontSize: 20 }} />}\n </IconButton>\n ) : (\n <Box sx={{ width: 22, display: \"flex\", justifyContent: \"center\", flexShrink: 0 }}>\n <Box sx={{ width: 5, height: 5, borderRadius: \"50%\", bgcolor: \"#9aa0a6\" }} />\n </Box>\n )}\n <Box sx={{ flex: 1, minWidth: 0, display: \"flex\", ml: 0.5 }}>\n <input\n ref={(el) => {\n if (el) inputs.current.set(row.node.id, el);\n else inputs.current.delete(row.node.id);\n }}\n value={row.node.topic}\n readOnly={readOnly}\n placeholder={row.depth === 0 ? strings.root : \"\"}\n spellCheck={false}\n autoComplete=\"off\"\n onFocus={() => onSelect?.(row.node.id)}\n onChange={(event) => apply(setTopic(root, row.node.id, event.target.value), `topic:${row.node.id}`)}\n onKeyDown={(event) => onKey(event, index)}\n style={{\n // Background hugs the text like a highlighter; the input keeps full width for clicks.\n width: text.background ? Math.ceil(measureText(row.node.topic || \" \", Number(text.fontSize), text.fontWeight as string)) + 16 : \"100%\",\n maxWidth: \"100%\",\n border: 0,\n outline: 0,\n font: \"inherit\",\n padding: text.background ? \"2px 6px\" : \"2px 0\",\n borderRadius: 4,\n background: text.background ?? \"transparent\",\n color: text.color ?? \"inherit\",\n fontSize: text.fontSize,\n fontWeight: text.fontWeight,\n textDecoration: [text.textDecoration, folded && hasKids ? \"underline dotted #9aa0a6\" : \"\"].filter(Boolean).join(\" \") || undefined,\n }}\n />\n </Box>\n </Box>\n );\n })}\n </Box>\n );\n}\n", "/** Text width with a cached canvas (used for highlight width in the outline and node sizes in the map). */\nlet ctx: CanvasRenderingContext2D | null = null;\nconst cache = new Map<string, number>();\n\nexport const DEFAULT_FONT_FAMILY = \"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif\";\n\nexport function measureText(text: string, fontSize: number, fontWeight: string | number = 400, fontFamily = DEFAULT_FONT_FAMILY): number {\n const font = `${fontWeight} ${fontSize}px ${fontFamily}`;\n const key = `${font}|${text}`;\n const hit = cache.get(key);\n if (hit !== undefined) return hit;\n if (!ctx && typeof document !== \"undefined\") ctx = document.createElement(\"canvas\").getContext(\"2d\");\n // No canvas (SSR / tests) \u2014 rough guess: wide glyphs 1em, others 0.55em.\n let width = 0;\n if (ctx) {\n ctx.font = font;\n width = ctx.measureText(text).width;\n } else for (const ch of text) width += (/[\u1100-\uFFDC]/.test(ch) ? 1 : 0.55) * fontSize;\n if (cache.size > 5000) cache.clear();\n cache.set(key, width);\n return width;\n}\n", "/**\n * Undo / redo for a controlled tree.\n * Typing into one node within `mergeMs` is merged into one step, so undo doesn't go back one letter at a time.\n */\nimport { useCallback, useRef, useState } from \"react\";\nimport type { TreeNode } from \"./tree\";\n\nexport interface TreeHistory {\n canUndo: boolean;\n canRedo: boolean;\n /** Records the tree before a change. `mergeKey` merges consecutive changes with the same key (e.g. typing in one node). */\n record: (before: TreeNode, mergeKey?: string) => void;\n undo: (current: TreeNode) => TreeNode | null;\n redo: (current: TreeNode) => TreeNode | null;\n clear: () => void;\n}\n\nexport function useTreeHistory(limit = 100, mergeMs = 1200): TreeHistory {\n const past = useRef<TreeNode[]>([]);\n const future = useRef<TreeNode[]>([]);\n const last = useRef<{ key: string; at: number } | null>(null);\n const [, bump] = useState(0);\n const refresh = () => bump((n) => n + 1);\n\n const record = useCallback(\n (before: TreeNode, mergeKey?: string) => {\n const now = Date.now();\n const merge = mergeKey && last.current?.key === mergeKey && now - last.current.at < mergeMs;\n last.current = mergeKey ? { key: mergeKey, at: now } : null;\n future.current = [];\n if (!merge) {\n past.current.push(before);\n if (past.current.length > limit) past.current.shift();\n }\n refresh();\n },\n [limit, mergeMs]\n );\n const undo = useCallback((current: TreeNode) => {\n const prev = past.current.pop();\n if (!prev) return null;\n future.current.push(current);\n last.current = null;\n refresh();\n return prev;\n }, []);\n const redo = useCallback((current: TreeNode) => {\n const next = future.current.pop();\n if (!next) return null;\n past.current.push(current);\n last.current = null;\n refresh();\n return next;\n }, []);\n const clear = useCallback(() => {\n past.current = [];\n future.current = [];\n last.current = null;\n refresh();\n }, []);\n return { canUndo: past.current.length > 0, canRedo: future.current.length > 0, record, undo, redo, clear };\n}\n", "/** UI strings (ko \u00B7 en \u00B7 ja \u00B7 zh \u00B7 de \u00B7 fr \u00B7 it \u00B7 vi). Unknown locale \u2192 English. */\nconst STRINGS = {\n ko: {\n fontSize: \"\uAE00\uC790 \uD06C\uAE30\",\n sizeDefault: \"\uAE30\uBCF8\",\n bold: \"\uC9C4\uD558\uAC8C\",\n underline: \"\uBC11\uC904\",\n strike: \"\uCDE8\uC18C\uC120\",\n textColor: \"\uAE00\uC790\uC0C9\",\n background: \"\uBC30\uACBD\uC0C9\",\n noColor: \"\uC5C6\uC74C\",\n undo: \"\uB418\uB3CC\uB9AC\uAE30\",\n redo: \"\uB2E4\uC2DC \uD558\uAE30\",\n fold: \"\uC811\uAE30\",\n unfold: \"\uD3BC\uCE58\uAE30\",\n drag: \"\uB04C\uC5B4\uC11C \uC62E\uAE30\uAE30\",\n root: \"\uC8FC\uC81C\",\n hint: \"Enter: \uC0C8 \uC904 \u00B7 Tab / Shift+Tab: \uB4E4\uC5EC\uC4F0\uAE30 / \uB0B4\uC5B4\uC4F0\uAE30 \u00B7 Alt+\u2191\u2193: \uC21C\uC11C \u00B7 \uC904 \uC55E \uC190\uC7A1\uC774 \uB04C\uAE30: \uC62E\uAE30\uAE30 \u00B7 \uBE48 \uC904 Backspace: \uC9C0\uC6B0\uAE30\",\n },\n en: {\n fontSize: \"Font size\",\n sizeDefault: \"Default\",\n bold: \"Bold\",\n underline: \"Underline\",\n strike: \"Strikethrough\",\n textColor: \"Text color\",\n background: \"Background\",\n noColor: \"None\",\n undo: \"Undo\",\n redo: \"Redo\",\n fold: \"Collapse\",\n unfold: \"Expand\",\n drag: \"Drag to move\",\n root: \"Topic\",\n hint: \"Enter: new line \u00B7 Tab / Shift+Tab: indent / outdent \u00B7 Alt+\u2191\u2193: reorder \u00B7 Drag the row handle: move \u00B7 Backspace on empty: delete\",\n },\n ja: {\n fontSize: \"\u6587\u5B57\u30B5\u30A4\u30BA\",\n sizeDefault: \"\u6A19\u6E96\",\n bold: \"\u592A\u5B57\",\n underline: \"\u4E0B\u7DDA\",\n strike: \"\u53D6\u308A\u6D88\u3057\u7DDA\",\n textColor: \"\u6587\u5B57\u8272\",\n background: \"\u80CC\u666F\u8272\",\n noColor: \"\u306A\u3057\",\n undo: \"\u5143\u306B\u623B\u3059\",\n redo: \"\u3084\u308A\u76F4\u3059\",\n fold: \"\u6298\u308A\u305F\u305F\u3080\",\n unfold: \"\u5C55\u958B\",\n drag: \"\u30C9\u30E9\u30C3\u30B0\u3067\u79FB\u52D5\",\n root: \"\u30C6\u30FC\u30DE\",\n hint: \"Enter: \u65B0\u3057\u3044\u884C \u00B7 Tab / Shift+Tab: \u5B57\u4E0B\u3052 / \u5B57\u4E0A\u3052 \u00B7 Alt+\u2191\u2193: \u4E26\u3079\u66FF\u3048 \u00B7 \u884C\u982D\u306E\u30CF\u30F3\u30C9\u30EB\u3092\u30C9\u30E9\u30C3\u30B0: \u79FB\u52D5 \u00B7 \u7A7A\u884C\u3067 Backspace: \u524A\u9664\",\n },\n zh: {\n fontSize: \"\u5B57\u53F7\",\n sizeDefault: \"\u9ED8\u8BA4\",\n bold: \"\u52A0\u7C97\",\n underline: \"\u4E0B\u5212\u7EBF\",\n strike: \"\u5220\u9664\u7EBF\",\n textColor: \"\u6587\u5B57\u989C\u8272\",\n background: \"\u80CC\u666F\u8272\",\n noColor: \"\u65E0\",\n undo: \"\u64A4\u9500\",\n redo: \"\u91CD\u505A\",\n fold: \"\u6298\u53E0\",\n unfold: \"\u5C55\u5F00\",\n drag: \"\u62D6\u52A8\u4EE5\u79FB\u52A8\",\n root: \"\u4E3B\u9898\",\n hint: \"Enter: \u65B0\u884C \u00B7 Tab / Shift+Tab: \u7F29\u8FDB / \u53D6\u6D88\u7F29\u8FDB \u00B7 Alt+\u2191\u2193: \u987A\u5E8F \u00B7 \u62D6\u52A8\u884C\u9996\u624B\u67C4: \u79FB\u52A8 \u00B7 \u7A7A\u884C Backspace: \u5220\u9664\",\n },\n de: {\n fontSize: \"Schriftgr\u00F6\u00DFe\",\n sizeDefault: \"Standard\",\n bold: \"Fett\",\n underline: \"Unterstrichen\",\n strike: \"Durchgestrichen\",\n textColor: \"Textfarbe\",\n background: \"Hintergrund\",\n noColor: \"Keine\",\n undo: \"R\u00FCckg\u00E4ngig\",\n redo: \"Wiederholen\",\n fold: \"Einklappen\",\n unfold: \"Ausklappen\",\n drag: \"Zum Verschieben ziehen\",\n root: \"Thema\",\n hint: \"Enter: neue Zeile \u00B7 Tab / Shift+Tab: ein- / ausr\u00FCcken \u00B7 Alt+\u2191\u2193: Reihenfolge \u00B7 Griff ziehen: verschieben \u00B7 Backspace leer: l\u00F6schen\",\n },\n fr: {\n fontSize: \"Taille\",\n sizeDefault: \"Par d\u00E9faut\",\n bold: \"Gras\",\n underline: \"Soulign\u00E9\",\n strike: \"Barr\u00E9\",\n textColor: \"Couleur du texte\",\n background: \"Arri\u00E8re-plan\",\n noColor: \"Aucune\",\n undo: \"Annuler\",\n redo: \"R\u00E9tablir\",\n fold: \"Replier\",\n unfold: \"D\u00E9plier\",\n drag: \"Glisser pour d\u00E9placer\",\n root: \"Sujet\",\n hint: \"Entr\u00E9e : nouvelle ligne \u00B7 Tab / Maj+Tab : indenter / d\u00E9sindenter \u00B7 Alt+\u2191\u2193 : ordre \u00B7 Glisser la poign\u00E9e : d\u00E9placer \u00B7 Retour arri\u00E8re vide : supprimer\",\n },\n it: {\n fontSize: \"Dimensione\",\n sizeDefault: \"Predefinita\",\n bold: \"Grassetto\",\n underline: \"Sottolineato\",\n strike: \"Barrato\",\n textColor: \"Colore testo\",\n background: \"Sfondo\",\n noColor: \"Nessuno\",\n undo: \"Annulla\",\n redo: \"Ripeti\",\n fold: \"Comprimi\",\n unfold: \"Espandi\",\n drag: \"Trascina per spostare\",\n root: \"Argomento\",\n hint: \"Invio: nuova riga \u00B7 Tab / Maiusc+Tab: rientro / riduci \u00B7 Alt+\u2191\u2193: ordine \u00B7 Trascina la maniglia: sposta \u00B7 Backspace su vuota: elimina\",\n },\n vi: {\n fontSize: \"C\u1EE1 ch\u1EEF\",\n sizeDefault: \"M\u1EB7c \u0111\u1ECBnh\",\n bold: \"\u0110\u1EADm\",\n underline: \"G\u1EA1ch ch\u00E2n\",\n strike: \"G\u1EA1ch ngang\",\n textColor: \"M\u00E0u ch\u1EEF\",\n background: \"M\u00E0u n\u1EC1n\",\n noColor: \"Kh\u00F4ng\",\n undo: \"Ho\u00E0n t\u00E1c\",\n redo: \"L\u00E0m l\u1EA1i\",\n fold: \"Thu g\u1ECDn\",\n unfold: \"M\u1EDF r\u1ED9ng\",\n drag: \"K\u00E9o \u0111\u1EC3 di chuy\u1EC3n\",\n root: \"Ch\u1EE7 \u0111\u1EC1\",\n hint: \"Enter: d\u00F2ng m\u1EDBi \u00B7 Tab / Shift+Tab: th\u1EE5t v\u00E0o / ra \u00B7 Alt+\u2191\u2193: th\u1EE9 t\u1EF1 \u00B7 K\u00E9o tay c\u1EA7m: di chuy\u1EC3n \u00B7 Backspace d\u00F2ng tr\u1ED1ng: x\u00F3a\",\n },\n} as const;\n\nexport type OutlinerStrings = { [K in keyof (typeof STRINGS)[\"en\"]]: string };\n\n/** Strings for a locale (\"ko\", \"ko-KR\", \u2026). `overrides` replaces single entries. */\nexport function outlinerStrings(locale?: string, overrides?: Partial<OutlinerStrings>): OutlinerStrings {\n const lang = (locale ?? \"en\").slice(0, 2).toLowerCase() as keyof typeof STRINGS;\n return { ...(STRINGS[lang] ?? STRINGS.en), ...overrides };\n}\n"],
5
- "mappings": "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",
6
- "names": ["index_exports", "__export", "BACKGROUND_COLORS", "DEFAULT_FONT_FAMILY", "FONT_SIZES", "FormatToolbar", "OutlineList", "Outliner", "TEXT_COLORS", "ToolButton", "ToolDivider", "addBelow", "addChild", "addSibling", "containsNode", "createTree", "hasDecoration", "indentNode", "isFolded", "locateNode", "measureText", "moveNode", "newNodeId", "outdentNode", "outlineTextStyle", "outlinerStrings", "removeNode", "setNodeStyle", "setTopic", "shiftNode", "toggleDecoration", "toggleFold", "useTreeHistory", "visibleRows", "__toCommonJS", "import_react", "import_material", "import_react", "import_material", "import_FormatBold", "import_FormatUnderlined", "import_StrikethroughS", "import_FormatColorText", "import_FormatColorFill", "import_Undo", "import_Redo", "import_ArrowDropDown", "import_FormatColorReset", "newNodeId", "createTree", "topic", "clone", "root", "locateNode", "id", "stack", "parent", "list", "i", "containsNode", "node", "child", "isFolded", "visibleRows", "rows", "walk", "depth", "parentId", "edit", "run", "copy", "focusId", "addChild", "first", "at", "fresh", "addSibling", "addBelow", "removeNode", "indentNode", "prev", "outdentNode", "up", "shiftNode", "step", "to", "moveNode", "from", "place", "src", "dst", "setTopic", "toggleFold", "expanded", "setNodeStyle", "ids", "patch", "changed", "next", "key", "value", "hasDecoration", "style", "kind", "toggleDecoration", "set", "import_jsx_runtime", "FONT_SIZES", "TEXT_COLORS", "BACKGROUND_COLORS", "btnSx", "active", "ToolButton", "label", "disabled", "onClick", "children", "event", "ToolDivider", "ColorButton", "icon", "value", "colors", "noneLabel", "onPick", "anchor", "setAnchor", "color", "FormatColorResetIcon", "FormatToolbar", "strings", "style", "onStyle", "canUndo", "canRedo", "onUndo", "onRedo", "start", "end", "readOnly", "sizeAnchor", "setSizeAnchor", "size", "bold", "UndoIcon", "RedoIcon", "ArrowDropDownIcon", "FormatBoldIcon", "hasDecoration", "toggleDecoration", "FormatUnderlinedIcon", "StrikethroughSIcon", "FormatColorTextIcon", "FormatColorFillIcon", "import_react", "import_material", "import_ArrowRight", "import_ArrowDropDown", "import_DragIndicator", "ctx", "cache", "DEFAULT_FONT_FAMILY", "measureText", "text", "fontSize", "fontWeight", "fontFamily", "font", "key", "hit", "width", "ch", "import_jsx_runtime", "INDENT", "BASE_FONT", "outlineTextStyle", "style", "depth", "OutlineList", "root", "onEdit", "selectedId", "onSelect", "strings", "readOnly", "onUndo", "onRedo", "paddingTop", "paddingBottom", "inputs", "rowEls", "focus", "setFocus", "drop", "setDrop", "dragging", "setDragging", "rows", "visibleRows", "el", "apply", "result", "mergeKey", "onKey", "event", "index", "row", "id", "mod", "addBelow", "outdentNode", "indentNode", "shiftNode", "next", "removeNode", "dragNode", "locateNode", "onHandleDown", "onHandleMove", "r", "containsNode", "onHandleUp", "moveNode", "hasKids", "folded", "line", "text", "theme", "DragIndicatorIcon", "toggleFold", "ArrowRightIcon", "ArrowDropDownIcon", "setTopic", "measureText", "import_react", "useTreeHistory", "limit", "mergeMs", "past", "future", "last", "bump", "refresh", "n", "record", "before", "mergeKey", "now", "merge", "undo", "current", "prev", "redo", "next", "clear", "STRINGS", "outlinerStrings", "locale", "overrides", "lang", "import_jsx_runtime", "Outliner", "value", "onChange", "locale", "overrides", "readOnly", "toolbar", "toolbarStart", "toolbarEnd", "height", "strings", "outlinerStrings", "history", "useTreeHistory", "selected", "setSelected", "commit", "next", "mergeKey", "undo", "prev", "redo", "selectedNode", "locateNode", "FormatToolbar", "patch", "result", "setNodeStyle", "OutlineList"]
4
+ "sourcesContent": ["export { Outliner, type OutlinerProps } from \"./Outliner\";\nexport { OutlineList, outlineTextStyle, type OutlineListProps } from \"./OutlineList\";\nexport { FormatToolbar, ToolButton, ToolDivider, ToolTip, FONT_SIZES, type FormatToolbarProps } from \"./FormatToolbar\";\nexport { useTreeHistory, type TreeHistory } from \"./history\";\nexport { outlinerStrings, type OutlinerStrings } from \"./i18n\";\nexport { measureText, DEFAULT_FONT_FAMILY } from \"./measure\";\nexport * from \"./tree\";\n", "/**\n * Outliner \u2014 toolbar + rows, with its own undo history. Controlled: pass `value` and `onChange`.\n * For a custom layout use `OutlineList` + `FormatToolbar` + `useTreeHistory` directly (the mind map does).\n */\nimport { useState, type ReactNode } from \"react\";\nimport { Box } from \"@mui/material\";\nimport { FormatToolbar } from \"./FormatToolbar\";\nimport { OutlineList } from \"./OutlineList\";\nimport { useTreeHistory } from \"./history\";\nimport { outlinerStrings, type OutlinerStrings } from \"./i18n\";\nimport { locateNode, setNodeStyle, type TreeNode } from \"./tree\";\n\nexport interface OutlinerProps {\n value: TreeNode;\n onChange: (value: TreeNode) => void;\n locale?: string;\n strings?: Partial<OutlinerStrings>;\n readOnly?: boolean;\n /** Show the formatting toolbar (default true). */\n toolbar?: boolean;\n toolbarStart?: ReactNode;\n toolbarEnd?: ReactNode;\n height?: number | string;\n}\n\nexport function Outliner({ value, onChange, locale, strings: overrides, readOnly, toolbar = true, toolbarStart, toolbarEnd, height = \"100%\" }: OutlinerProps) {\n const strings = outlinerStrings(locale, overrides);\n const history = useTreeHistory();\n const [selected, setSelected] = useState<string | null>(null);\n const commit = (next: TreeNode, mergeKey?: string) => {\n history.record(value, mergeKey);\n onChange(next);\n };\n const undo = () => {\n const prev = history.undo(value);\n if (prev) onChange(prev);\n };\n const redo = () => {\n const next = history.redo(value);\n if (next) onChange(next);\n };\n const selectedNode = selected ? locateNode(value, selected)?.node : undefined;\n return (\n <Box sx={{ display: \"flex\", flexDirection: \"column\", height, minHeight: 0, bgcolor: \"#fff\" }}>\n {toolbar ? (\n <FormatToolbar\n strings={strings}\n style={selectedNode ? (selectedNode.style ?? {}) : undefined}\n onStyle={(patch) => {\n if (!selected) return;\n const result = setNodeStyle(value, [selected], patch);\n if (result) commit(result.root);\n }}\n canUndo={history.canUndo}\n canRedo={history.canRedo}\n onUndo={undo}\n onRedo={redo}\n start={toolbarStart}\n end={toolbarEnd}\n readOnly={readOnly}\n />\n ) : null}\n <Box sx={{ flex: 1, minHeight: 0 }}>\n <OutlineList root={value} onEdit={commit} selectedId={selected} onSelect={setSelected} strings={strings} readOnly={readOnly} onUndo={undo} onRedo={redo} />\n </Box>\n </Box>\n );\n}\n", "/**\n * Formatting toolbar \u2014 font size \u00B7 bold \u00B7 underline \u00B7 strike \u00B7 text color \u00B7 background \u00B7 clear format, plus undo / redo.\n * Shared by the outline and the mind map; it edits the style of the selected node.\n * Looks like the @ehfuse/editor toolbar on purpose: same icons (@ehfuse/toolbar-icons), same 32px buttons,\n * same black tooltip and the same color picker (@ehfuse/mui-color-picker).\n * `start` / `end` / `children` let the host add its own controls (view switch, map tools, \u2026).\n */\nimport { useState, type MouseEvent, type ReactNode } from \"react\";\nimport { Box, ButtonBase, Menu, MenuItem, Tooltip } from \"@mui/material\";\nimport { ColorPicker } from \"@ehfuse/mui-color-picker\";\nimport { BoldIcon, FontColorIcon, FontFillIcon, RedoIcon, RemoveFormatIcon, StrikeIcon, UnderlineIcon, UndoIcon } from \"@ehfuse/toolbar-icons\";\nimport { hasDecoration, toggleDecoration, type TreeNodeStyle } from \"./tree\";\nimport type { OutlinerStrings } from \"./i18n\";\n\nexport const FONT_SIZES = [12, 14, 16, 18, 20, 24, 28, 32];\n\nexport interface FormatToolbarProps {\n strings: OutlinerStrings;\n /** Style of the node being edited (undefined \u2192 nothing selected; format buttons are disabled). */\n style: TreeNodeStyle | undefined;\n onStyle: (patch: Partial<TreeNodeStyle>) => void;\n canUndo?: boolean;\n canRedo?: boolean;\n onUndo?: () => void;\n onRedo?: () => void;\n start?: ReactNode;\n children?: ReactNode;\n end?: ReactNode;\n readOnly?: boolean;\n}\n\n/** Same tooltip as the editor toolbar \u2014 black, 14px, arrow, below. */\nexport function ToolTip({ title, children }: { title: string; children: ReactNode }) {\n return (\n <Tooltip\n title={title}\n placement=\"bottom\"\n arrow\n disableInteractive\n leaveDelay={0}\n slotProps={{ tooltip: { sx: { bgcolor: \"#000000\", color: \"#ffffff\", fontSize: \"14px\", fontWeight: \"normal\", \"& .MuiTooltip-arrow\": { color: \"#000000\" } } } }}\n >\n {/* inline-flex \u2014 a plain span adds line descent under the button and lifts it 2px off center. */}\n <span style={{ display: \"inline-flex\" }}>{children}</span>\n </Tooltip>\n );\n}\n\n/** Same button as the editor toolbar \u2014 32px, 4px radius, light grey when on. */\nexport function ToolButton({ label, active = false, disabled = false, onClick, children }: { label: string; active?: boolean; disabled?: boolean; onClick: (event: MouseEvent<HTMLElement>) => void; children: ReactNode }) {\n return (\n <ToolTip title={label}>\n <Box\n component=\"button\"\n type=\"button\"\n aria-label={label}\n aria-pressed={active}\n disabled={disabled}\n onMouseDown={(event: MouseEvent) => event.preventDefault()}\n onClick={(event: MouseEvent<HTMLElement>) => {\n event.preventDefault();\n if (!disabled) onClick(event);\n }}\n sx={{\n display: \"inline-flex\",\n alignItems: \"center\",\n justifyContent: \"center\",\n width: 32,\n height: 32,\n p: \"6px\",\n border: \"none\",\n borderRadius: \"4px\",\n bgcolor: active ? \"rgba(0, 0, 0, 0.08)\" : \"transparent\",\n color: disabled ? \"rgba(0, 0, 0, 0.26)\" : \"inherit\",\n cursor: disabled ? \"not-allowed\" : \"pointer\",\n transition: \"background-color 150ms cubic-bezier(0.4, 0, 0.2, 1)\",\n \"&:hover:not(:disabled)\": { bgcolor: active ? \"rgba(0, 0, 0, 0.08)\" : \"rgba(0, 0, 0, 0.04)\" },\n \"&:focus\": { outline: \"none\" },\n \"& svg\": { width: 20, height: 20 },\n }}\n >\n {children}\n </Box>\n </ToolTip>\n );\n}\n\nexport const ToolDivider = () => <Box sx={{ width: \"1px\", alignSelf: \"stretch\", my: \"8px\", mx: \"4px\", bgcolor: \"#e0e0e0\" }} />;\n\nfunction ColorButton({ label, type, value, disabled, onPick }: { label: string; type: \"color\" | \"background\"; value?: string; disabled: boolean; onPick: (color: string) => void }) {\n const [anchor, setAnchor] = useState<HTMLElement | null>(null);\n const shown = value ?? (type === \"color\" ? \"#000000\" : \"#FFFFFF\");\n return (\n <>\n <ToolButton label={label} disabled={disabled} onClick={(event) => setAnchor(event.currentTarget)}>\n {type === \"color\" ? <FontColorIcon width=\"20px\" height=\"20px\" barColor={shown} /> : <FontFillIcon width=\"20px\" fillColor={shown} />}\n </ToolButton>\n {anchor ? (\n <ColorPicker\n value={shown}\n onChange={(hex: string) => {\n onPick(hex);\n setAnchor(null);\n }}\n anchor={anchor}\n anchorMode=\"auto\"\n onClose={() => setAnchor(null)}\n position=\"bottomCenter\"\n advanced={{ position: \"bottom\" }}\n shape=\"square\"\n colorSize={16}\n gap={4}\n padding={5}\n popover={{ disableEnforceFocus: true, disableAutoFocus: true, disableRestoreFocus: true, sx: { zIndex: 10001 } }}\n />\n ) : null}\n </>\n );\n}\n\nexport function FormatToolbar({ strings, style, onStyle, canUndo, canRedo, onUndo, onRedo, start, children, end, readOnly }: FormatToolbarProps) {\n const [sizeAnchor, setSizeAnchor] = useState<HTMLElement | null>(null);\n const disabled = Boolean(readOnly) || !style;\n const size = style?.fontSize ? parseFloat(style.fontSize) : null;\n const bold = style?.fontWeight === \"bold\" || Number(style?.fontWeight) >= 600;\n const hasStyle = Boolean(style && Object.keys(style).length > 0);\n return (\n <Box sx={{ display: \"flex\", alignItems: \"center\", flexWrap: \"wrap\", gap: \"2px\", minHeight: 44, px: 1, py: \"4px\", borderBottom: \"1px solid #e0e0e0\", bgcolor: \"#fff\", color: \"#333\", flexShrink: 0 }}>\n {start}\n {start ? <ToolDivider /> : null}\n {onUndo ? (\n <>\n <ToolButton label={strings.undo} disabled={readOnly || !canUndo} onClick={onUndo}>\n <UndoIcon />\n </ToolButton>\n <ToolButton label={strings.redo} disabled={readOnly || !canRedo} onClick={() => onRedo?.()}>\n <RedoIcon />\n </ToolButton>\n <ToolDivider />\n </>\n ) : null}\n <ToolTip title={strings.fontSize}>\n <ButtonBase\n disabled={disabled}\n onMouseDown={(event) => event.preventDefault()}\n onClick={(event) => setSizeAnchor(event.currentTarget)}\n sx={{ height: 32, minWidth: 64, px: 1, gap: 0.5, justifyContent: \"space-between\", border: \"1px solid #d0d0d0\", borderRadius: \"4px\", fontSize: 14, color: disabled ? \"rgba(0,0,0,0.26)\" : \"#333\", bgcolor: \"#fff\", \"&:hover\": { borderColor: \"#999\" } }}\n >\n {size ?? strings.sizeDefault}\n <Box component=\"span\" sx={{ fontSize: 10, color: \"#888\" }}>\n \u25BC\n </Box>\n </ButtonBase>\n </ToolTip>\n <Menu open={Boolean(sizeAnchor)} anchorEl={sizeAnchor} onClose={() => setSizeAnchor(null)} transitionDuration={0} disableRestoreFocus slotProps={{ paper: { sx: { maxHeight: 320 } } }}>\n <MenuItem\n dense\n selected={size === null}\n onClick={() => {\n onStyle({ fontSize: undefined });\n setSizeAnchor(null);\n }}\n >\n {strings.sizeDefault}\n </MenuItem>\n {FONT_SIZES.map((value) => (\n <MenuItem\n key={value}\n dense\n selected={size === value}\n onClick={() => {\n onStyle({ fontSize: `${value}px` });\n setSizeAnchor(null);\n }}\n >\n {value}\n </MenuItem>\n ))}\n </Menu>\n <ToolButton label={strings.bold} active={bold} disabled={disabled} onClick={() => onStyle({ fontWeight: bold ? undefined : \"bold\" })}>\n <BoldIcon />\n </ToolButton>\n <ToolButton label={strings.underline} active={hasDecoration(style, \"underline\")} disabled={disabled} onClick={() => onStyle({ textDecoration: toggleDecoration(style, \"underline\") })}>\n <UnderlineIcon />\n </ToolButton>\n <ToolButton label={strings.strike} active={hasDecoration(style, \"line-through\")} disabled={disabled} onClick={() => onStyle({ textDecoration: toggleDecoration(style, \"line-through\") })}>\n <StrikeIcon />\n </ToolButton>\n <ColorButton label={strings.textColor} type=\"color\" value={style?.color} disabled={disabled} onPick={(color) => onStyle({ color })} />\n <ColorButton label={strings.background} type=\"background\" value={style?.background} disabled={disabled} onPick={(color) => onStyle({ background: color.toLowerCase() === \"#ffffff\" ? undefined : color })} />\n <ToolButton\n label={strings.clearFormat}\n disabled={disabled || !hasStyle}\n onClick={() => onStyle({ fontSize: undefined, color: undefined, background: undefined, fontWeight: undefined, textDecoration: undefined })}\n >\n <RemoveFormatIcon />\n </ToolButton>\n {children ? <ToolDivider /> : null}\n {children}\n <Box sx={{ flex: 1 }} />\n {end}\n </Box>\n );\n}\n", "/**\n * Tree data and edit operations shared by the outline and the mind map.\n *\n * The shape follows Mind Elixir's `nodeData` so data saved by it opens unchanged:\n * `{ id, topic, children?, expanded?, style? }` \u2014 unknown keys are carried along untouched.\n * Every operation is pure: it returns a new root (structural copy) and, when useful,\n * the id that should be focused next.\n */\n\n/** Text style of one node (same keys as Mind Elixir `style`). */\nexport interface TreeNodeStyle {\n fontSize?: string;\n color?: string;\n background?: string;\n fontWeight?: string;\n textDecoration?: string;\n}\n\nexport interface TreeNode {\n id: string;\n topic: string;\n children?: TreeNode[];\n /** `false` = folded. Missing means expanded. */\n expanded?: boolean;\n style?: TreeNodeStyle;\n [key: string]: unknown;\n}\n\nexport interface TreeEdit {\n root: TreeNode;\n /** Node to select / focus after the edit. */\n focusId?: string;\n}\n\nexport interface TreeRow {\n node: TreeNode;\n depth: number;\n parentId: string | null;\n}\n\n/** Short random id (hex, like Mind Elixir). */\nexport const newNodeId = () => Math.random().toString(16).slice(2, 18);\n\nexport const createTree = (topic: string): TreeNode => ({ id: \"root\", topic, children: [] });\n\nconst clone = (root: TreeNode): TreeNode => structuredClone(root) as TreeNode;\n\n/** Finds a node with its parent and index (in the given tree). */\nexport function locateNode(root: TreeNode, id: string): { node: TreeNode; parent: TreeNode | null; index: number } | null {\n if (root.id === id) return { node: root, parent: null, index: 0 };\n const stack: TreeNode[] = [root];\n while (stack.length) {\n const parent = stack.pop()!;\n const list = parent.children ?? [];\n for (let i = 0; i < list.length; i++) {\n if (list[i].id === id) return { node: list[i], parent, index: i };\n stack.push(list[i]);\n }\n }\n return null;\n}\n\n/** True when `id` is `node` itself or one of its descendants. */\nexport const containsNode = (node: TreeNode, id: string): boolean => node.id === id || (node.children ?? []).some((child) => containsNode(child, id));\n\nexport const isFolded = (node: TreeNode) => node.expanded === false && (node.children?.length ?? 0) > 0;\n\n/** Rows that are visible (folded subtrees hidden), in reading order. */\nexport function visibleRows(root: TreeNode): TreeRow[] {\n const rows: TreeRow[] = [];\n const walk = (node: TreeNode, depth: number, parentId: string | null) => {\n rows.push({ node, depth, parentId });\n if (node.expanded !== false) for (const child of node.children ?? []) walk(child, depth + 1, node.id);\n };\n walk(root, 0, null);\n return rows;\n}\n\n/** Runs `run` on a copy; returns null when nothing changed (run returned false). */\nfunction edit(root: TreeNode, run: (copy: TreeNode) => string | void | false): TreeEdit | null {\n const copy = clone(root);\n const focusId = run(copy);\n if (focusId === false) return null;\n return { root: copy, focusId: focusId || undefined };\n}\n\n/** New child at the end (or `first`). */\nexport const addChild = (root: TreeNode, id: string, topic = \"\", first = false) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at) return false;\n const fresh: TreeNode = { id: newNodeId(), topic };\n at.node.children = first ? [fresh, ...(at.node.children ?? [])] : [...(at.node.children ?? []), fresh];\n at.node.expanded = true;\n return fresh.id;\n });\n\n/** New sibling right after (root \u2192 first child). */\nexport const addSibling = (root: TreeNode, id: string, topic = \"\") =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at) return false;\n const fresh: TreeNode = { id: newNodeId(), topic };\n if (!at.parent) {\n at.node.children = [fresh, ...(at.node.children ?? [])];\n at.node.expanded = true;\n } else at.parent.children!.splice(at.index + 1, 0, fresh);\n return fresh.id;\n });\n\n/** Outline \"Enter\": first child when the row is an open parent, otherwise next sibling. */\nexport const addBelow = (root: TreeNode, id: string) => {\n const at = locateNode(root, id);\n if (at && (!at.parent || ((at.node.children?.length ?? 0) > 0 && at.node.expanded !== false))) return addChild(root, id, \"\", true);\n return addSibling(root, id);\n};\n\n/** Removes the node (not the root). Focus goes to the previous sibling, else the parent. */\nexport const removeNode = (root: TreeNode, id: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent) return false;\n at.parent.children!.splice(at.index, 1);\n return at.parent.children![at.index - 1]?.id ?? at.parent.id;\n });\n\n/** Becomes the last child of the previous sibling. */\nexport const indentNode = (root: TreeNode, id: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent || at.index === 0) return false;\n const prev = at.parent.children![at.index - 1];\n at.parent.children!.splice(at.index, 1);\n prev.children = [...(prev.children ?? []), at.node];\n prev.expanded = true;\n return id;\n });\n\n/** Becomes the sibling right after its parent. */\nexport const outdentNode = (root: TreeNode, id: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent) return false;\n const up = locateNode(copy, at.parent.id);\n if (!up?.parent) return false;\n at.parent.children!.splice(at.index, 1);\n up.parent.children!.splice(up.index + 1, 0, at.node);\n return id;\n });\n\n/** Moves one step among its siblings. */\nexport const shiftNode = (root: TreeNode, id: string, step: -1 | 1) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at?.parent) return false;\n const list = at.parent.children!;\n const to = at.index + step;\n if (to < 0 || to >= list.length) return false;\n [list[at.index], list[to]] = [list[to], list[at.index]];\n return id;\n });\n\n/** Moves `from` before / after `to`, or into `to` as its last child. */\nexport const moveNode = (root: TreeNode, from: string, to: string, place: \"before\" | \"after\" | \"child\") =>\n edit(root, (copy) => {\n const src = locateNode(copy, from);\n if (!src?.parent || containsNode(src.node, to)) return false;\n src.parent.children!.splice(src.index, 1);\n const dst = locateNode(copy, to);\n if (!dst) return false;\n if (place === \"child\" || !dst.parent) {\n dst.node.children = [...(dst.node.children ?? []), src.node];\n dst.node.expanded = true;\n } else dst.parent.children!.splice(dst.index + (place === \"after\" ? 1 : 0), 0, src.node);\n return from;\n });\n\nexport const setTopic = (root: TreeNode, id: string, topic: string) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at || at.node.topic === topic) return false;\n at.node.topic = topic;\n });\n\nexport const toggleFold = (root: TreeNode, id: string, expanded?: boolean) =>\n edit(root, (copy) => {\n const at = locateNode(copy, id);\n if (!at || !(at.node.children?.length ?? 0)) return false;\n at.node.expanded = expanded ?? at.node.expanded === false;\n });\n\n/** Merges a style patch; `undefined` values remove the key. */\nexport const setNodeStyle = (root: TreeNode, ids: string[], patch: Partial<TreeNodeStyle>) =>\n edit(root, (copy) => {\n let changed = false;\n for (const id of ids) {\n const at = locateNode(copy, id);\n if (!at) continue;\n const next: TreeNodeStyle = { ...(at.node.style ?? {}) };\n for (const [key, value] of Object.entries(patch) as [keyof TreeNodeStyle, string | undefined][]) {\n if (value === undefined || value === \"\") delete next[key];\n else next[key] = value;\n }\n at.node.style = Object.keys(next).length ? next : undefined;\n if (!at.node.style) delete at.node.style;\n changed = true;\n }\n return changed ? undefined : false;\n });\n\n/** `textDecoration` holds both underline and line-through. */\nexport function hasDecoration(style: TreeNodeStyle | undefined, kind: \"underline\" | \"line-through\") {\n return (style?.textDecoration ?? \"\").split(/\\s+/).includes(kind);\n}\nexport function toggleDecoration(style: TreeNodeStyle | undefined, kind: \"underline\" | \"line-through\"): string | undefined {\n const set = new Set((style?.textDecoration ?? \"\").split(/\\s+/).filter(Boolean));\n if (set.has(kind)) set.delete(kind);\n else set.add(kind);\n return set.size ? [...set].join(\" \") : undefined;\n}\n", "/**\n * Outline rows \u2014 one node per line, fold / unfold, indent / outdent, reorder, drag to move, per-node style.\n *\n * Keys: Enter new line \u00B7 Tab indent \u00B7 Shift+Tab outdent \u00B7 Alt+\u2191/\u2193 reorder \u00B7 \u2191/\u2193 previous / next row \u00B7\n * Backspace on an empty row deletes it \u00B7 Ctrl/\u2318+Z undo \u00B7 Ctrl/\u2318+Shift+Z or Ctrl+Y redo.\n * Dragging follows the pointer directly (native drag & drop doesn't fire drops reliably inside drawers / modals).\n */\nimport { useEffect, useRef, useState, type CSSProperties, type KeyboardEvent, type PointerEvent } from \"react\";\nimport { Box, IconButton } from \"@mui/material\";\nimport ArrowRightIcon from \"@mui/icons-material/ArrowRight\";\nimport ArrowDropDownIcon from \"@mui/icons-material/ArrowDropDown\";\nimport DragIndicatorIcon from \"@mui/icons-material/DragIndicator\";\nimport {\n addBelow,\n containsNode,\n indentNode,\n locateNode,\n moveNode,\n outdentNode,\n removeNode,\n setTopic,\n shiftNode,\n toggleFold,\n visibleRows,\n type TreeEdit,\n type TreeNode,\n type TreeNodeStyle,\n} from \"./tree\";\nimport type { OutlinerStrings } from \"./i18n\";\nimport { measureText } from \"./measure\";\n\nconst INDENT = 22;\nconst BASE_FONT = 15;\n\nexport interface OutlineListProps {\n root: TreeNode;\n /** A change; `mergeKey` is set for typing so history can merge it. */\n onEdit: (root: TreeNode, mergeKey?: string) => void;\n selectedId?: string | null;\n onSelect?: (id: string) => void;\n strings: OutlinerStrings;\n readOnly?: boolean;\n onUndo?: () => void;\n onRedo?: () => void;\n /** Extra space above the first row / below the last row (px). */\n paddingTop?: number;\n paddingBottom?: number;\n}\n\n/** Node style \u2192 input style (font size is clamped so the list stays a list). */\nexport function outlineTextStyle(style: TreeNodeStyle | undefined, depth: number): CSSProperties {\n const size = style?.fontSize ? Math.min(28, Math.max(12, parseFloat(style.fontSize))) : BASE_FONT;\n return {\n fontSize: size,\n fontWeight: style?.fontWeight ?? (depth === 0 ? 700 : 400),\n color: style?.color,\n textDecoration: style?.textDecoration,\n background: style?.background,\n };\n}\n\nexport function OutlineList({ root, onEdit, selectedId, onSelect, strings, readOnly, onUndo, onRedo, paddingTop = 8, paddingBottom = 40 }: OutlineListProps) {\n const inputs = useRef(new Map<string, HTMLInputElement>());\n const rowEls = useRef(new Map<string, HTMLDivElement>());\n const [focus, setFocus] = useState<string | null>(null);\n const [drop, setDrop] = useState<{ id: string; place: \"before\" | \"after\" } | null>(null);\n const [dragging, setDragging] = useState<string | null>(null);\n const rows = visibleRows(root);\n\n useEffect(() => {\n if (!focus) return;\n const el = inputs.current.get(focus);\n if (!el) return;\n el.focus();\n el.setSelectionRange(el.value.length, el.value.length);\n setFocus(null);\n }, [focus, root]);\n\n const apply = (result: TreeEdit | null, mergeKey?: string) => {\n if (!result) return;\n onEdit(result.root, mergeKey);\n if (result.focusId) {\n setFocus(result.focusId);\n onSelect?.(result.focusId);\n }\n };\n\n const onKey = (event: KeyboardEvent<HTMLInputElement>, index: number) => {\n if (event.nativeEvent.isComposing) return;\n const row = rows[index];\n const id = row.node.id;\n const mod = event.ctrlKey || event.metaKey;\n if (mod && (event.key === \"z\" || event.key === \"Z\")) {\n event.preventDefault();\n if (event.shiftKey) onRedo?.();\n else onUndo?.();\n return;\n }\n if (mod && (event.key === \"y\" || event.key === \"Y\")) {\n event.preventDefault();\n onRedo?.();\n return;\n }\n if (readOnly) return;\n if (event.key === \"Enter\") {\n event.preventDefault();\n apply(addBelow(root, id));\n } else if (event.key === \"Tab\") {\n event.preventDefault();\n apply(event.shiftKey ? outdentNode(root, id) : indentNode(root, id));\n } else if (event.altKey && (event.key === \"ArrowUp\" || event.key === \"ArrowDown\")) {\n event.preventDefault();\n apply(shiftNode(root, id, event.key === \"ArrowUp\" ? -1 : 1));\n } else if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\n const next = rows[index + (event.key === \"ArrowUp\" ? -1 : 1)];\n if (next) {\n event.preventDefault();\n setFocus(next.node.id);\n onSelect?.(next.node.id);\n }\n } else if (event.key === \"Backspace\" && event.currentTarget.value === \"\" && row.depth > 0 && !(row.node.children?.length ?? 0)) {\n event.preventDefault();\n const result = removeNode(root, id);\n if (result) apply({ root: result.root, focusId: rows[index - 1]?.node.id });\n }\n };\n\n // Drag \u2014 follow the pointer on the handle; drop before / after the row under it (never into itself).\n const dragNode = dragging ? locateNode(root, dragging)?.node ?? null : null;\n const onHandleDown = (event: PointerEvent<HTMLDivElement>, id: string) => {\n if (event.button !== 0 || readOnly) return;\n event.preventDefault();\n event.currentTarget.setPointerCapture(event.pointerId);\n setDragging(id);\n setDrop(null);\n };\n const onHandleMove = (event: PointerEvent<HTMLDivElement>) => {\n if (!dragging || !dragNode) return;\n let next: { id: string; place: \"before\" | \"after\" } | null = null;\n for (const row of rows) {\n const el = rowEls.current.get(row.node.id);\n if (!el) continue;\n const r = el.getBoundingClientRect();\n if (event.clientY < r.top || event.clientY >= r.bottom) continue;\n if (!containsNode(dragNode, row.node.id)) next = { id: row.node.id, place: event.clientY < r.top + r.height / 2 ? \"before\" : \"after\" };\n break;\n }\n if (next?.id !== drop?.id || next?.place !== drop?.place) setDrop(next);\n };\n const onHandleUp = (event: PointerEvent<HTMLDivElement>) => {\n if (event.currentTarget.hasPointerCapture(event.pointerId)) event.currentTarget.releasePointerCapture(event.pointerId);\n if (dragging && drop) apply(moveNode(root, dragging, drop.id, drop.place));\n setDragging(null);\n setDrop(null);\n };\n\n return (\n <Box sx={{ position: \"relative\", height: \"100%\", overflowY: \"auto\", bgcolor: \"#fff\", pt: `${paddingTop}px`, pb: `${paddingBottom}px`, px: 1.5 }}>\n {rows.map((row, index) => {\n const hasKids = (row.node.children?.length ?? 0) > 0;\n const folded = row.node.expanded === false;\n const line = drop?.id === row.node.id ? drop.place : null;\n const text = outlineTextStyle(row.node.style, row.depth);\n return (\n <Box\n key={row.node.id}\n ref={(el: HTMLDivElement | null) => {\n if (el) rowEls.current.set(row.node.id, el);\n else rowEls.current.delete(row.node.id);\n }}\n sx={{\n display: \"flex\",\n alignItems: \"center\",\n minHeight: 26,\n pl: `${row.depth * INDENT}px`,\n borderRadius: 0.75,\n bgcolor: selectedId === row.node.id ? \"rgba(26,115,232,0.06)\" : \"transparent\",\n // Drop line \u2014 inset shadow so it takes no height.\n boxShadow: (theme) =>\n line === \"before\" ? `inset 0 2px 0 ${theme.palette.primary.main}` : line === \"after\" ? `inset 0 -2px 0 ${theme.palette.primary.main}` : \"none\",\n opacity: dragging === row.node.id ? 0.4 : 1,\n \"&:hover .ol-handle\": { visibility: \"visible\" },\n }}\n >\n <Box\n className=\"ol-handle\"\n title={strings.drag}\n onPointerDown={row.depth > 0 ? (event: PointerEvent<HTMLDivElement>) => onHandleDown(event, row.node.id) : undefined}\n onPointerMove={onHandleMove}\n onPointerUp={onHandleUp}\n onPointerCancel={onHandleUp}\n sx={{\n display: \"flex\",\n color: \"#b0b4ba\",\n cursor: row.depth > 0 && !readOnly ? (dragging ? \"grabbing\" : \"grab\") : \"default\",\n visibility: dragging === row.node.id ? \"visible\" : \"hidden\",\n width: 18,\n flexShrink: 0,\n touchAction: \"none\",\n }}\n >\n {row.depth > 0 && !readOnly ? <DragIndicatorIcon sx={{ fontSize: 16 }} /> : null}\n </Box>\n {hasKids ? (\n <IconButton\n size=\"small\"\n aria-label={folded ? strings.unfold : strings.fold}\n title={folded ? strings.unfold : strings.fold}\n onClick={() => apply(toggleFold(root, row.node.id))}\n sx={{ width: 22, height: 22, p: 0, color: \"text.secondary\" }}\n >\n {folded ? <ArrowRightIcon sx={{ fontSize: 20 }} /> : <ArrowDropDownIcon sx={{ fontSize: 20 }} />}\n </IconButton>\n ) : (\n <Box sx={{ width: 22, display: \"flex\", justifyContent: \"center\", flexShrink: 0 }}>\n <Box sx={{ width: 5, height: 5, borderRadius: \"50%\", bgcolor: \"#9aa0a6\" }} />\n </Box>\n )}\n <Box sx={{ flex: 1, minWidth: 0, display: \"flex\", ml: 0.5 }}>\n <input\n ref={(el) => {\n if (el) inputs.current.set(row.node.id, el);\n else inputs.current.delete(row.node.id);\n }}\n value={row.node.topic}\n readOnly={readOnly}\n placeholder={row.depth === 0 ? strings.root : \"\"}\n spellCheck={false}\n autoComplete=\"off\"\n onFocus={() => onSelect?.(row.node.id)}\n onChange={(event) => apply(setTopic(root, row.node.id, event.target.value), `topic:${row.node.id}`)}\n onKeyDown={(event) => onKey(event, index)}\n style={{\n // Background hugs the text like a highlighter; the input keeps full width for clicks.\n width: text.background ? Math.ceil(measureText(row.node.topic || \" \", Number(text.fontSize), text.fontWeight as string)) + 16 : \"100%\",\n maxWidth: \"100%\",\n border: 0,\n outline: 0,\n font: \"inherit\",\n padding: text.background ? \"2px 6px\" : \"2px 0\",\n borderRadius: 4,\n background: text.background ?? \"transparent\",\n color: text.color ?? \"inherit\",\n fontSize: text.fontSize,\n fontWeight: text.fontWeight,\n textDecoration: [text.textDecoration, folded && hasKids ? \"underline dotted #9aa0a6\" : \"\"].filter(Boolean).join(\" \") || undefined,\n }}\n />\n </Box>\n </Box>\n );\n })}\n </Box>\n );\n}\n", "/** Text width with a cached canvas (used for highlight width in the outline and node sizes in the map). */\nlet ctx: CanvasRenderingContext2D | null = null;\nconst cache = new Map<string, number>();\n\nexport const DEFAULT_FONT_FAMILY = \"-apple-system, BlinkMacSystemFont, 'Segoe UI', 'Noto Sans KR', 'Apple SD Gothic Neo', 'Malgun Gothic', sans-serif\";\n\nexport function measureText(text: string, fontSize: number, fontWeight: string | number = 400, fontFamily = DEFAULT_FONT_FAMILY): number {\n const font = `${fontWeight} ${fontSize}px ${fontFamily}`;\n const key = `${font}|${text}`;\n const hit = cache.get(key);\n if (hit !== undefined) return hit;\n if (!ctx && typeof document !== \"undefined\") ctx = document.createElement(\"canvas\").getContext(\"2d\");\n // No canvas (SSR / tests) \u2014 rough guess: wide glyphs 1em, others 0.55em.\n let width = 0;\n if (ctx) {\n ctx.font = font;\n width = ctx.measureText(text).width;\n } else for (const ch of text) width += (/[\u1100-\uFFDC]/.test(ch) ? 1 : 0.55) * fontSize;\n if (cache.size > 5000) cache.clear();\n cache.set(key, width);\n return width;\n}\n", "/**\n * Undo / redo for a controlled tree.\n * Typing into one node within `mergeMs` is merged into one step, so undo doesn't go back one letter at a time.\n */\nimport { useCallback, useRef, useState } from \"react\";\nimport type { TreeNode } from \"./tree\";\n\nexport interface TreeHistory {\n canUndo: boolean;\n canRedo: boolean;\n /** Records the tree before a change. `mergeKey` merges consecutive changes with the same key (e.g. typing in one node). */\n record: (before: TreeNode, mergeKey?: string) => void;\n undo: (current: TreeNode) => TreeNode | null;\n redo: (current: TreeNode) => TreeNode | null;\n clear: () => void;\n}\n\nexport function useTreeHistory(limit = 100, mergeMs = 1200): TreeHistory {\n const past = useRef<TreeNode[]>([]);\n const future = useRef<TreeNode[]>([]);\n const last = useRef<{ key: string; at: number } | null>(null);\n const [, bump] = useState(0);\n const refresh = () => bump((n) => n + 1);\n\n const record = useCallback(\n (before: TreeNode, mergeKey?: string) => {\n const now = Date.now();\n const merge = mergeKey && last.current?.key === mergeKey && now - last.current.at < mergeMs;\n last.current = mergeKey ? { key: mergeKey, at: now } : null;\n future.current = [];\n if (!merge) {\n past.current.push(before);\n if (past.current.length > limit) past.current.shift();\n }\n refresh();\n },\n [limit, mergeMs]\n );\n const undo = useCallback((current: TreeNode) => {\n const prev = past.current.pop();\n if (!prev) return null;\n future.current.push(current);\n last.current = null;\n refresh();\n return prev;\n }, []);\n const redo = useCallback((current: TreeNode) => {\n const next = future.current.pop();\n if (!next) return null;\n past.current.push(current);\n last.current = null;\n refresh();\n return next;\n }, []);\n const clear = useCallback(() => {\n past.current = [];\n future.current = [];\n last.current = null;\n refresh();\n }, []);\n return { canUndo: past.current.length > 0, canRedo: future.current.length > 0, record, undo, redo, clear };\n}\n", "/** UI strings (ko \u00B7 en \u00B7 ja \u00B7 zh \u00B7 de \u00B7 fr \u00B7 it \u00B7 vi). Unknown locale \u2192 English. */\nconst STRINGS = {\n ko: {\n clearFormat: \"\uC11C\uC2DD \uC9C0\uC6B0\uAE30\",\n fontSize: \"\uAE00\uC790 \uD06C\uAE30\",\n sizeDefault: \"\uAE30\uBCF8\",\n bold: \"\uC9C4\uD558\uAC8C\",\n underline: \"\uBC11\uC904\",\n strike: \"\uCDE8\uC18C\uC120\",\n textColor: \"\uAE00\uC790\uC0C9\",\n background: \"\uBC30\uACBD\uC0C9\",\n noColor: \"\uC5C6\uC74C\",\n undo: \"\uB418\uB3CC\uB9AC\uAE30\",\n redo: \"\uB2E4\uC2DC \uD558\uAE30\",\n fold: \"\uC811\uAE30\",\n unfold: \"\uD3BC\uCE58\uAE30\",\n drag: \"\uB04C\uC5B4\uC11C \uC62E\uAE30\uAE30\",\n root: \"\uC8FC\uC81C\",\n hint: \"Enter: \uC0C8 \uC904 \u00B7 Tab / Shift+Tab: \uB4E4\uC5EC\uC4F0\uAE30 / \uB0B4\uC5B4\uC4F0\uAE30 \u00B7 Alt+\u2191\u2193: \uC21C\uC11C \u00B7 \uC904 \uC55E \uC190\uC7A1\uC774 \uB04C\uAE30: \uC62E\uAE30\uAE30 \u00B7 \uBE48 \uC904 Backspace: \uC9C0\uC6B0\uAE30\",\n },\n en: {\n clearFormat: \"Clear format\",\n fontSize: \"Font size\",\n sizeDefault: \"Default\",\n bold: \"Bold\",\n underline: \"Underline\",\n strike: \"Strikethrough\",\n textColor: \"Text color\",\n background: \"Background\",\n noColor: \"None\",\n undo: \"Undo\",\n redo: \"Redo\",\n fold: \"Collapse\",\n unfold: \"Expand\",\n drag: \"Drag to move\",\n root: \"Topic\",\n hint: \"Enter: new line \u00B7 Tab / Shift+Tab: indent / outdent \u00B7 Alt+\u2191\u2193: reorder \u00B7 Drag the row handle: move \u00B7 Backspace on empty: delete\",\n },\n ja: {\n clearFormat: \"\u66F8\u5F0F\u3092\u30AF\u30EA\u30A2\",\n fontSize: \"\u6587\u5B57\u30B5\u30A4\u30BA\",\n sizeDefault: \"\u6A19\u6E96\",\n bold: \"\u592A\u5B57\",\n underline: \"\u4E0B\u7DDA\",\n strike: \"\u53D6\u308A\u6D88\u3057\u7DDA\",\n textColor: \"\u6587\u5B57\u8272\",\n background: \"\u80CC\u666F\u8272\",\n noColor: \"\u306A\u3057\",\n undo: \"\u5143\u306B\u623B\u3059\",\n redo: \"\u3084\u308A\u76F4\u3059\",\n fold: \"\u6298\u308A\u305F\u305F\u3080\",\n unfold: \"\u5C55\u958B\",\n drag: \"\u30C9\u30E9\u30C3\u30B0\u3067\u79FB\u52D5\",\n root: \"\u30C6\u30FC\u30DE\",\n hint: \"Enter: \u65B0\u3057\u3044\u884C \u00B7 Tab / Shift+Tab: \u5B57\u4E0B\u3052 / \u5B57\u4E0A\u3052 \u00B7 Alt+\u2191\u2193: \u4E26\u3079\u66FF\u3048 \u00B7 \u884C\u982D\u306E\u30CF\u30F3\u30C9\u30EB\u3092\u30C9\u30E9\u30C3\u30B0: \u79FB\u52D5 \u00B7 \u7A7A\u884C\u3067 Backspace: \u524A\u9664\",\n },\n zh: {\n clearFormat: \"\u6E05\u9664\u683C\u5F0F\",\n fontSize: \"\u5B57\u53F7\",\n sizeDefault: \"\u9ED8\u8BA4\",\n bold: \"\u52A0\u7C97\",\n underline: \"\u4E0B\u5212\u7EBF\",\n strike: \"\u5220\u9664\u7EBF\",\n textColor: \"\u6587\u5B57\u989C\u8272\",\n background: \"\u80CC\u666F\u8272\",\n noColor: \"\u65E0\",\n undo: \"\u64A4\u9500\",\n redo: \"\u91CD\u505A\",\n fold: \"\u6298\u53E0\",\n unfold: \"\u5C55\u5F00\",\n drag: \"\u62D6\u52A8\u4EE5\u79FB\u52A8\",\n root: \"\u4E3B\u9898\",\n hint: \"Enter: \u65B0\u884C \u00B7 Tab / Shift+Tab: \u7F29\u8FDB / \u53D6\u6D88\u7F29\u8FDB \u00B7 Alt+\u2191\u2193: \u987A\u5E8F \u00B7 \u62D6\u52A8\u884C\u9996\u624B\u67C4: \u79FB\u52A8 \u00B7 \u7A7A\u884C Backspace: \u5220\u9664\",\n },\n de: {\n clearFormat: \"Formatierung l\u00F6schen\",\n fontSize: \"Schriftgr\u00F6\u00DFe\",\n sizeDefault: \"Standard\",\n bold: \"Fett\",\n underline: \"Unterstrichen\",\n strike: \"Durchgestrichen\",\n textColor: \"Textfarbe\",\n background: \"Hintergrund\",\n noColor: \"Keine\",\n undo: \"R\u00FCckg\u00E4ngig\",\n redo: \"Wiederholen\",\n fold: \"Einklappen\",\n unfold: \"Ausklappen\",\n drag: \"Zum Verschieben ziehen\",\n root: \"Thema\",\n hint: \"Enter: neue Zeile \u00B7 Tab / Shift+Tab: ein- / ausr\u00FCcken \u00B7 Alt+\u2191\u2193: Reihenfolge \u00B7 Griff ziehen: verschieben \u00B7 Backspace leer: l\u00F6schen\",\n },\n fr: {\n clearFormat: \"Effacer la mise en forme\",\n fontSize: \"Taille\",\n sizeDefault: \"Par d\u00E9faut\",\n bold: \"Gras\",\n underline: \"Soulign\u00E9\",\n strike: \"Barr\u00E9\",\n textColor: \"Couleur du texte\",\n background: \"Arri\u00E8re-plan\",\n noColor: \"Aucune\",\n undo: \"Annuler\",\n redo: \"R\u00E9tablir\",\n fold: \"Replier\",\n unfold: \"D\u00E9plier\",\n drag: \"Glisser pour d\u00E9placer\",\n root: \"Sujet\",\n hint: \"Entr\u00E9e : nouvelle ligne \u00B7 Tab / Maj+Tab : indenter / d\u00E9sindenter \u00B7 Alt+\u2191\u2193 : ordre \u00B7 Glisser la poign\u00E9e : d\u00E9placer \u00B7 Retour arri\u00E8re vide : supprimer\",\n },\n it: {\n clearFormat: \"Cancella formattazione\",\n fontSize: \"Dimensione\",\n sizeDefault: \"Predefinita\",\n bold: \"Grassetto\",\n underline: \"Sottolineato\",\n strike: \"Barrato\",\n textColor: \"Colore testo\",\n background: \"Sfondo\",\n noColor: \"Nessuno\",\n undo: \"Annulla\",\n redo: \"Ripeti\",\n fold: \"Comprimi\",\n unfold: \"Espandi\",\n drag: \"Trascina per spostare\",\n root: \"Argomento\",\n hint: \"Invio: nuova riga \u00B7 Tab / Maiusc+Tab: rientro / riduci \u00B7 Alt+\u2191\u2193: ordine \u00B7 Trascina la maniglia: sposta \u00B7 Backspace su vuota: elimina\",\n },\n vi: {\n clearFormat: \"X\u00F3a \u0111\u1ECBnh d\u1EA1ng\",\n fontSize: \"C\u1EE1 ch\u1EEF\",\n sizeDefault: \"M\u1EB7c \u0111\u1ECBnh\",\n bold: \"\u0110\u1EADm\",\n underline: \"G\u1EA1ch ch\u00E2n\",\n strike: \"G\u1EA1ch ngang\",\n textColor: \"M\u00E0u ch\u1EEF\",\n background: \"M\u00E0u n\u1EC1n\",\n noColor: \"Kh\u00F4ng\",\n undo: \"Ho\u00E0n t\u00E1c\",\n redo: \"L\u00E0m l\u1EA1i\",\n fold: \"Thu g\u1ECDn\",\n unfold: \"M\u1EDF r\u1ED9ng\",\n drag: \"K\u00E9o \u0111\u1EC3 di chuy\u1EC3n\",\n root: \"Ch\u1EE7 \u0111\u1EC1\",\n hint: \"Enter: d\u00F2ng m\u1EDBi \u00B7 Tab / Shift+Tab: th\u1EE5t v\u00E0o / ra \u00B7 Alt+\u2191\u2193: th\u1EE9 t\u1EF1 \u00B7 K\u00E9o tay c\u1EA7m: di chuy\u1EC3n \u00B7 Backspace d\u00F2ng tr\u1ED1ng: x\u00F3a\",\n },\n} as const;\n\nexport type OutlinerStrings = { [K in keyof (typeof STRINGS)[\"en\"]]: string };\n\n/** Strings for a locale (\"ko\", \"ko-KR\", \u2026). `overrides` replaces single entries. */\nexport function outlinerStrings(locale?: string, overrides?: Partial<OutlinerStrings>): OutlinerStrings {\n const lang = (locale ?? \"en\").slice(0, 2).toLowerCase() as keyof typeof STRINGS;\n return { ...(STRINGS[lang] ?? STRINGS.en), ...overrides };\n}\n"],
5
+ "mappings": "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",
6
+ "names": ["index_exports", "__export", "DEFAULT_FONT_FAMILY", "FONT_SIZES", "FormatToolbar", "OutlineList", "Outliner", "ToolButton", "ToolDivider", "ToolTip", "addBelow", "addChild", "addSibling", "containsNode", "createTree", "hasDecoration", "indentNode", "isFolded", "locateNode", "measureText", "moveNode", "newNodeId", "outdentNode", "outlineTextStyle", "outlinerStrings", "removeNode", "setNodeStyle", "setTopic", "shiftNode", "toggleDecoration", "toggleFold", "useTreeHistory", "visibleRows", "__toCommonJS", "import_react", "import_material", "import_react", "import_material", "import_mui_color_picker", "import_toolbar_icons", "newNodeId", "createTree", "topic", "clone", "root", "locateNode", "id", "stack", "parent", "list", "i", "containsNode", "node", "child", "isFolded", "visibleRows", "rows", "walk", "depth", "parentId", "edit", "run", "copy", "focusId", "addChild", "first", "at", "fresh", "addSibling", "addBelow", "removeNode", "indentNode", "prev", "outdentNode", "up", "shiftNode", "step", "to", "moveNode", "from", "place", "src", "dst", "setTopic", "toggleFold", "expanded", "setNodeStyle", "ids", "patch", "changed", "next", "key", "value", "hasDecoration", "style", "kind", "toggleDecoration", "set", "import_jsx_runtime", "FONT_SIZES", "ToolTip", "title", "children", "ToolButton", "label", "active", "disabled", "onClick", "event", "ToolDivider", "ColorButton", "type", "value", "onPick", "anchor", "setAnchor", "shown", "hex", "FormatToolbar", "strings", "style", "onStyle", "canUndo", "canRedo", "onUndo", "onRedo", "start", "end", "readOnly", "sizeAnchor", "setSizeAnchor", "size", "bold", "hasStyle", "hasDecoration", "toggleDecoration", "color", "import_react", "import_material", "import_ArrowRight", "import_ArrowDropDown", "import_DragIndicator", "ctx", "cache", "DEFAULT_FONT_FAMILY", "measureText", "text", "fontSize", "fontWeight", "fontFamily", "font", "key", "hit", "width", "ch", "import_jsx_runtime", "INDENT", "BASE_FONT", "outlineTextStyle", "style", "depth", "OutlineList", "root", "onEdit", "selectedId", "onSelect", "strings", "readOnly", "onUndo", "onRedo", "paddingTop", "paddingBottom", "inputs", "rowEls", "focus", "setFocus", "drop", "setDrop", "dragging", "setDragging", "rows", "visibleRows", "el", "apply", "result", "mergeKey", "onKey", "event", "index", "row", "id", "mod", "addBelow", "outdentNode", "indentNode", "shiftNode", "next", "removeNode", "dragNode", "locateNode", "onHandleDown", "onHandleMove", "r", "containsNode", "onHandleUp", "moveNode", "hasKids", "folded", "line", "text", "theme", "DragIndicatorIcon", "toggleFold", "ArrowRightIcon", "ArrowDropDownIcon", "setTopic", "measureText", "import_react", "useTreeHistory", "limit", "mergeMs", "past", "future", "last", "bump", "refresh", "n", "record", "before", "mergeKey", "now", "merge", "undo", "current", "prev", "redo", "next", "clear", "STRINGS", "outlinerStrings", "locale", "overrides", "lang", "import_jsx_runtime", "Outliner", "value", "onChange", "locale", "overrides", "readOnly", "toolbar", "toolbarStart", "toolbarEnd", "height", "strings", "outlinerStrings", "history", "useTreeHistory", "selected", "setSelected", "commit", "next", "mergeKey", "undo", "prev", "redo", "selectedNode", "locateNode", "FormatToolbar", "patch", "result", "setNodeStyle", "OutlineList"]
7
7
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ehfuse/outliner",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "Outliner for React + MUI — one row per node, fold, indent / outdent, drag to reorder, formatting toolbar (size · color · background · bold · underline · strike), undo",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.esm.js",
@@ -59,5 +59,9 @@
59
59
  "react": "^19.0.0",
60
60
  "react-dom": "^19.0.0",
61
61
  "typescript": "^5.6.3"
62
+ },
63
+ "dependencies": {
64
+ "@ehfuse/mui-color-picker": "^1.5.4",
65
+ "@ehfuse/toolbar-icons": "^0.1.0"
62
66
  }
63
67
  }