@alwith/module-editor 0.1.0-rc.12 → 0.1.0-rc.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import { type ReactNode } from "react";
2
+ import type { EditorShortcutRenderer } from "./shortcut-hint.js";
3
+ export type { EditorShortcutRenderer } from "./shortcut-hint.js";
2
4
  import type { EditorController, EditorDocument } from "./core.js";
3
5
  export * from "./core.js";
4
6
  export * from "./workspace.js";
@@ -50,6 +52,7 @@ export interface EditorTabLabels {
50
52
  }
51
53
  export declare const defaultEditorTabLabels: EditorTabLabels;
52
54
  export interface EditorWorkbenchProps {
55
+ renderShortcutHint?: EditorShortcutRenderer;
53
56
  tabBar?: (prefix: string) => ReactNode;
54
57
  contentOverride?: (prefix: string) => ReactNode;
55
58
  tabLabels?: Partial<EditorTabLabels>;
@@ -69,7 +72,7 @@ export interface EditorWorkbenchProps {
69
72
  sourceReadOnly?: boolean;
70
73
  onError: (error: unknown) => void;
71
74
  }
72
- export declare function EditorWorkbench({ controller, tabBar, contentOverride, tabLabels: tabLabelOverrides, rootPath, onRevealPath, onReveal, onCopyPath, compactToolbar, actionsLabel, labels, previews, renderTextEditor, requestSaveAs, onOpenExternal, readOnly, sourceReadOnly, onError }: EditorWorkbenchProps): ReactNode;
75
+ export declare function EditorWorkbench({ renderShortcutHint, controller, tabBar, contentOverride, tabLabels: tabLabelOverrides, rootPath, onRevealPath, onReveal, onCopyPath, compactToolbar, actionsLabel, labels, previews, renderTextEditor, requestSaveAs, onOpenExternal, readOnly, sourceReadOnly, onError }: EditorWorkbenchProps): ReactNode;
73
76
  export interface ImagePreviewLabels {
74
77
  failed: string;
75
78
  zoomIn: string;
package/dist/index.js CHANGED
@@ -1 +1 @@
1
- import{jsx as a,jsxs as u,Fragment as Q}from"react/jsx-runtime";import{basename as H}from"@alwith/module-fs/core";import{Button as S}from"@base-ui/react/button";import{ContextMenu as h}from"@base-ui/react/context-menu";import{Menu as j}from"@base-ui/react/menu";import{Component as te,Suspense as ie,useCallback as ae,useEffect as _,useEffectEvent as re,useId as ne,useMemo as O,useRef as F,useState as Z,useSyncExternalStore as se}from"react";import{PreviewSourceModeToggle as le}from"./preview-source-mode-toggle.js";export*from"./core.js";export*from"./workspace.js";export*from"./workspace-tabs.js";export*from"./new-tab.js";import{quickStartAssets as Se}from"./quick-start-assets.js";var oe={empty:"Select a file to open",save:"Save",saveAs:"Save as",saving:"Saving…",close:"Close",edit:"Edit",preview:"Preview",reload:"Reload",changed:"This file changed on disk. Reload before saving.",unsupported:"No preview is available for this file.",openExternal:"Open externally"},de={closeOthers:"Close others",closeRight:"Close to the right",closeSaved:"Close saved",closeAll:"Close all",copyPath:"Copy path",reveal:"Reveal in file tree"};class ee extends te{state={error:null};static getDerivedStateFromError(t){return{error:t instanceof Error?t.message:String(t)}}componentDidCatch(t){this.props.onError(t)}componentDidUpdate(t){if(t.resetKey!==this.props.resetKey&&this.state.error!==null)this.setState({error:null})}render(){return this.state.error===null?this.props.children:u("div",{className:"alwith-editor-empty",role:"alert",children:[this.props.label,a("br",{}),this.state.error]})}}function ce({provider:t,document:b,context:y}){return t.render(b,y)}function ke({controller:t,tabBar:b,contentOverride:y,tabLabels:g,rootPath:v,onRevealPath:x,onReveal:R,onCopyPath:N,compactToolbar:I=!1,actionsLabel:A="More actions",labels:n=oe,previews:T=[],renderTextEditor:k,requestSaveAs:z,onOpenExternal:L,readOnly:C=!1,sourceReadOnly:w=!1,onError:P}){let s=se(t.subscribe,t.getSnapshot,t.getSnapshot),i=s.documents.find((e)=>e.id===s.activeId),K=F(null),D=ne(),l=F(null),c={...de,...g};_(()=>{let e=K.current;if(!e)return;let m=(r)=>{if(r.ctrlKey||r.metaKey||e.scrollWidth<=e.clientWidth)return;let M=Math.abs(r.deltaX)>Math.abs(r.deltaY)?r.deltaX:r.deltaY,B=r.deltaMode===1?M*16:r.deltaMode===2?M*e.clientWidth:M,Y=e.scrollLeft;if(e.scrollLeft+=B,Y!==e.scrollLeft)r.preventDefault()};return e.addEventListener("wheel",m,{passive:!1}),()=>e.removeEventListener("wheel",m)},[]),_(()=>{K.current?.querySelector('[aria-selected="true"]')?.scrollIntoView({block:"nearest",inline:"nearest"})},[s.activeId]);let[o,p]=Z({}),E=i?.id,[W,f]=Z(null),X=ae((e)=>{if(!E)return;f((m)=>e===null?m?.id===E?null:m:{id:E,node:e})},[E]);function d(e){e().catch(P)}let U=i?.status==="loaded"?T.find((e)=>e.supports(i)):void 0,q=i?o[i.id]??(U?"preview":"edit"):"edit",V=C||q==="edit"&&w;function G(e,m,r=!1){return I?a(j.Item,{className:"alwith-editor-menu-item",disabled:r,onClick:m,children:e}):a(S,{type:"button",disabled:r,onClick:m,children:e})}function J(){if(!i)return null;return u(Q,{children:[i.kind==="text"&&G(i.saving?n.saving:n.save,()=>d(()=>t.save(i.id)),V||i.locked||i.status!=="loaded"||!i.dirty||i.saving),L&&G(n.openExternal,()=>d(()=>L(i))),z&&i.kind==="text"&&G(n.saveAs,()=>d(async()=>{let e=await z(i);if(e!==null)await t.saveAs(i.id,e)}),V||i.locked||i.status!=="loaded"||i.saving)]})}return u("section",{className:"alwith-editor",onKeyDown:(e)=>{if((e.metaKey||e.ctrlKey)&&e.key.toLowerCase()==="s"&&i&&!y){if(e.preventDefault(),!V&&!i.locked&&i.status==="loaded")d(()=>t.save(i.id))}},children:[b?b(D):a("div",{className:"alwith-editor-tabs",role:"tablist",ref:K,onDragOver:(e)=>{if(l.current)e.preventDefault()},onDrop:(e)=>{if(!l.current)return;e.preventDefault(),t.reorder(l.current,null),l.current=null},children:s.documents.map((e,m)=>u(h.Root,{children:[u(h.Trigger,{className:"alwith-editor-tab","data-active":e.id===s.activeId,"data-transient":!e.pinned,draggable:!0,onDragStart:(r)=>{l.current=e.id,r.dataTransfer.effectAllowed="move",r.dataTransfer.setData("text/plain",e.path)},onDragEnd:()=>{l.current=null},onDragOver:(r)=>{if(l.current)r.preventDefault()},onDrop:(r)=>{if(!l.current)return;r.preventDefault(),r.stopPropagation();let M=r.currentTarget.getBoundingClientRect(),B=r.clientX<M.left+M.width/2?e.id:s.documents[m+1]?.id??null;t.reorder(l.current,B),l.current=null},children:[u(S,{type:"button",role:"tab",id:`${D}-tab-${e.id}`,"aria-controls":`${D}-panel-${e.id}`,"aria-selected":e.id===s.activeId,tabIndex:e.id===s.activeId?0:-1,title:e.path,onClick:()=>t.activate(e.id),onDoubleClick:()=>t.pin(e.id),onKeyDown:(r)=>{let M=r.key==="ArrowRight"?1:r.key==="ArrowLeft"?-1:0,B=r.key==="Home"?0:r.key==="End"?s.documents.length-1:M?(m+M+s.documents.length)%s.documents.length:null;if(B===null)return;r.preventDefault();let Y=s.documents[B];if(Y)t.activate(Y.id),globalThis.document.getElementById(`${D}-tab-${Y.id}`)?.focus()},children:[H(e.path),e.dirty?" •":""]}),a(S,{type:"button","aria-label":`${n.close} ${H(e.path)}`,onClick:()=>d(()=>t.requestClose(e.id)),children:"×"})]}),a(h.Portal,{children:a(h.Positioner,{children:u(h.Popup,{className:"alwith-editor-menu",children:[a(h.Item,{className:"alwith-editor-menu-item",onClick:()=>d(()=>t.requestClose(e.id)),children:n.close}),a(h.Item,{className:"alwith-editor-menu-item",disabled:s.documents.length<2,onClick:()=>d(()=>t.requestCloseMany(s.documents.filter((r)=>r.id!==e.id).map((r)=>r.id))),children:c.closeOthers}),a(h.Item,{className:"alwith-editor-menu-item",disabled:m===s.documents.length-1,onClick:()=>d(()=>t.requestCloseMany(s.documents.slice(m+1).map((r)=>r.id))),children:c.closeRight}),a(h.Item,{className:"alwith-editor-menu-item",disabled:!s.documents.some((r)=>!r.dirty),onClick:()=>d(()=>t.requestCloseMany(s.documents.filter((r)=>!r.dirty).map((r)=>r.id))),children:c.closeSaved}),a(h.Item,{className:"alwith-editor-menu-item",onClick:()=>d(()=>t.requestCloseMany(s.documents.map((r)=>r.id))),children:c.closeAll}),N&&a(h.Item,{className:"alwith-editor-menu-item",onClick:()=>d(()=>N(e)),children:c.copyPath}),R&&a(h.Item,{className:"alwith-editor-menu-item",onClick:()=>d(()=>R(e)),children:c.reveal}),a(h.Separator,{className:"alwith-editor-menu-separator"}),e.kind==="text"&&a(h.Item,{className:"alwith-editor-menu-item",disabled:C||w||e.locked||e.status!=="loaded"||!e.dirty||e.saving,onClick:()=>d(()=>t.save(e.id)),children:e.saving?n.saving:n.save}),z&&e.kind==="text"&&a(h.Item,{className:"alwith-editor-menu-item",disabled:C||w||e.locked||e.status!=="loaded"||e.saving,onClick:()=>d(async()=>{let r=await z(e);if(r!==null)await t.saveAs(e.id,r)}),children:n.saveAs}),L&&a(h.Item,{className:"alwith-editor-menu-item",onClick:()=>d(()=>L(e)),children:n.openExternal})]})})})]},e.id))}),y?y(D):i?u(Q,{children:[u("div",{className:"alwith-editor-toolbar",children:[a(ue,{path:i.path,rootPath:v,onRevealPath:x,onError:P}),u("div",{className:"alwith-editor-toolbar-actions",children:[q==="preview"&&W?.id===i.id&&W.node,U&&i.kind==="text"&&a(le,{mode:q,preview:n.preview,source:n.source??"Source",label:n.viewMode??"View mode",onModeChange:(e)=>p((m)=>({...m,[i.id]:e}))}),I?U&&i.kind==="text"?null:u(j.Root,{children:[a(j.Trigger,{"aria-label":A,title:A,children:"⋯"}),a(j.Portal,{children:a(j.Positioner,{sideOffset:4,children:a(j.Popup,{className:"alwith-editor-menu",children:J()})})})]}):J()]})]}),i.externalChange&&u("div",{className:"alwith-editor-notice",role:"status",children:[n.changed,a(S,{type:"button",onClick:()=>d(()=>t.reload(i.id)),children:n.reload})]}),a("div",{className:"alwith-editor-content",role:"tabpanel",id:`${D}-panel-${i.id}`,"aria-labelledby":`${D}-tab-${i.id}`,children:i.status==="error"?u("div",{className:"alwith-editor-empty",role:"alert",children:[a("p",{children:n.loadFailed??"Unable to load file"}),a("p",{children:i.loadError}),a(S,{onClick:()=>d(()=>t.ensureLoaded(i.id)),children:n.retry??"Retry"})]}):i.status!=="loaded"?a("div",{className:"alwith-editor-empty",role:"status","aria-busy":"true",children:n.loading??"Loading…"}):U&&(q==="preview"||i.kind==="binary")?a(ee,{resetKey:i.version,label:n.unsupported,onError:P,children:a(ie,{fallback:a("div",{"aria-busy":"true"}),children:a(ce,{provider:U,document:i,context:{setToolbarActions:X,readOnly:C||i.locked,onChange:(e)=>t.update(i.id,e),onSave:()=>d(()=>t.save(i.id)),onError:P}})})},`${i.id}:${U.id}`):i.kind==="text"?k?k({document:i,readOnly:C||w||i.locked,onChange:(e)=>t.update(i.id,e),onSave:()=>{if(!C&&!w&&!i.locked)d(()=>t.save(i.id))}}):a("textarea",{"aria-label":H(i.path),className:"alwith-editor-text",spellCheck:!1,readOnly:C||w||i.locked,value:i.text,onChange:(e)=>t.update(i.id,e.target.value)}):a("div",{className:"alwith-editor-empty",children:n.unsupported})},i.id)]}):a("div",{className:"alwith-editor-empty",children:n.empty})]})}function ue({path:t,rootPath:b,onRevealPath:y,onError:g}){let v=b?.replace(/\/$/,""),R=(v&&t.startsWith(`${v}/`)?t.slice(v.length+1):t).split("/").filter(Boolean),N=v&&t.startsWith(`${v}/`)?v:t.startsWith("/")?"":void 0;return a("nav",{className:"alwith-editor-breadcrumbs","aria-label":"File path",title:t,children:R.map((I,A)=>{N=N===void 0?I:`${N}/${I}`;let n=N;return u("span",{children:[A>0&&a("span",{"aria-hidden":"true",className:"alwith-editor-breadcrumb-separator",children:"›"}),y?a(S,{type:"button",onClick:()=>{y(n).catch(g)},children:I}):I]},n)})})}var he={failed:"Unable to display this image",zoomIn:"Zoom in",zoomOut:"Zoom out",resetZoom:"Reset zoom"};function me({document:t,labels:b,onError:y}){let g={...he,...b},v=O(()=>/\.svg$/i.test(t.path)&&t.kind==="text"?new TextEncoder().encode(t.text):t.bytes,[t.text,t.bytes,t.path,t.kind]),x=O(()=>({bytes:v,path:t.path,id:t.id,version:t.version}),[v,t.path,t.id,t.version]),[R,N]=Z(null),[I,A]=Z(null),n=R?.source===x?R.url:null,T=I===x,[k,z]=Z(1),[L,C]=Z({width:0,height:0}),w=F(null),P=F(null),s=F(1);function i(l,c){let o=Math.min(4,Math.max(0.25,l)),p=w.current,E=P.current?.getBoundingClientRect(),W=p?.getBoundingClientRect(),f=p&&E&&W?{x:c?.x??W.left+p.clientWidth/2,y:c?.y??W.top+p.clientHeight/2,imageX:0,imageY:0}:null;if(f&&E)f.imageX=(f.x-E.left)/s.current,f.imageY=(f.y-E.top)/s.current;if(s.current=o,z(o),f&&p)requestAnimationFrame(()=>{let X=P.current?.getBoundingClientRect();if(!X)return;p.scrollLeft+=X.left+f.imageX*o-f.x,p.scrollTop+=X.top+f.imageY*o-f.y})}let K=F(i);K.current=i,_(()=>{let l=w.current;if(!l)return;let c=(o)=>{if(!o.ctrlKey&&!o.metaKey)return;o.preventDefault(),K.current(s.current*Math.exp(-o.deltaY*0.002),{x:o.clientX,y:o.clientY})};return l.addEventListener("wheel",c,{passive:!1}),()=>l.removeEventListener("wheel",c)},[]);let D=re(()=>t.path);return _(()=>{let l=D().split(".").pop()?.toLowerCase(),c=l==="svg"?"image/svg+xml":l==="ico"?"image/x-icon":void 0,o=URL.createObjectURL(new Blob([new Uint8Array(x.bytes)],{type:c}));return N({source:x,url:o}),A(null),C({width:0,height:0}),z(1),s.current=1,()=>URL.revokeObjectURL(o)},[x]),u("div",{className:"alwith-editor-image-preview",children:[u("div",{className:"alwith-editor-image-controls",children:[a(S,{"aria-label":g.zoomOut,title:g.zoomOut,disabled:T||k<=0.25,onClick:()=>i(k/1.25),children:"−"}),u(S,{"aria-label":g.resetZoom,title:g.resetZoom,disabled:T,onClick:()=>i(1),children:[Math.round(k*100),"%"]}),a(S,{"aria-label":g.zoomIn,title:g.zoomIn,disabled:T||k>=4,onClick:()=>i(k*1.25),children:"+"})]}),a("div",{className:"alwith-editor-image-viewport",ref:w,onDoubleClick:()=>i(1),children:T?a("div",{className:"alwith-editor-empty",role:"alert",children:g.failed}):n&&a("div",{className:"alwith-editor-image-canvas",children:a("img",{ref:P,className:"alwith-editor-image",src:n,alt:H(t.path),style:L.width?{width:L.width*k,height:L.height*k}:void 0,onLoad:(l)=>{let c=w.current,o=l.currentTarget,p=c?Math.min(1,(c.clientWidth-40)/o.naturalWidth,(c.clientHeight-40)/o.naturalHeight):1;C({width:o.naturalWidth*Math.max(0.01,p),height:o.naturalHeight*Math.max(0.01,p)})},onError:()=>{A(x),y?.(Error(`Unable to decode image: ${t.path}`))}})})})]})}var Ce={id:"image",supports:(t)=>/\.(png|jpe?g|webp|gif|bmp|avif|svg|ico)$/i.test(t.path),render:(t,b)=>a(me,{document:t,onError:b.onError})};export{ke as EditorWorkbench,me as ImagePreview,oe as defaultEditorLabels,de as defaultEditorTabLabels,Ce as imagePreview,Se as quickStartAssets};
1
+ import{jsx as i,jsxs as h,Fragment as Q}from"react/jsx-runtime";import{basename as H}from"@alwith/module-fs/core";import{Button as L}from"@base-ui/react/button";import{ContextMenu as m}from"@base-ui/react/context-menu";import{Menu as U}from"@base-ui/react/menu";import{Component as ie,Suspense as ae,useCallback as re,useEffect as _,useEffectEvent as ne,useId as se,useMemo as O,useRef as B,useState as j,useSyncExternalStore as le}from"react";import{PreviewSourceModeToggle as oe}from"./preview-source-mode-toggle.js";export*from"./core.js";export*from"./workspace.js";export*from"./workspace-tabs.js";export*from"./new-tab.js";import{quickStartAssets as Se}from"./quick-start-assets.js";var de={empty:"Select a file to open",save:"Save",saveAs:"Save as",saving:"Saving…",close:"Close",edit:"Edit",preview:"Preview",reload:"Reload",changed:"This file changed on disk. Reload before saving.",unsupported:"No preview is available for this file.",openExternal:"Open externally"},ce={closeOthers:"Close others",closeRight:"Close to the right",closeSaved:"Close saved",closeAll:"Close all",copyPath:"Copy path",reveal:"Reveal in file tree"};class ee extends ie{state={error:null};static getDerivedStateFromError(r){return{error:r instanceof Error?r.message:String(r)}}componentDidCatch(r){this.props.onError(r)}componentDidUpdate(r){if(r.resetKey!==this.props.resetKey&&this.state.error!==null)this.setState({error:null})}render(){return this.state.error===null?this.props.children:h("div",{className:"alwith-editor-empty",role:"alert",children:[this.props.label,i("br",{}),this.state.error]})}}function ue({provider:r,document:n,context:x}){return r.render(n,x)}function Ce({renderShortcutHint:r,controller:n,tabBar:x,contentOverride:f,tabLabels:y,rootPath:N,onRevealPath:T,onReveal:I,onCopyPath:D,compactToolbar:A=!1,actionsLabel:S="More actions",labels:s=de,previews:E=[],renderTextEditor:F,requestSaveAs:P,onOpenExternal:z,readOnly:v=!1,sourceReadOnly:k=!1,onError:C}){let l=le(n.subscribe,n.getSnapshot,n.getSnapshot),t=l.documents.find((e)=>e.id===l.activeId),Z=B(null),u=se(),d=B(null),o={...ce,...y};_(()=>{let e=Z.current;if(!e)return;let p=(a)=>{if(a.ctrlKey||a.metaKey||e.scrollWidth<=e.clientWidth)return;let b=Math.abs(a.deltaX)>Math.abs(a.deltaY)?a.deltaX:a.deltaY,M=a.deltaMode===1?b*16:a.deltaMode===2?b*e.clientWidth:b,Y=e.scrollLeft;if(e.scrollLeft+=M,Y!==e.scrollLeft)a.preventDefault()};return e.addEventListener("wheel",p,{passive:!1}),()=>e.removeEventListener("wheel",p)},[]),_(()=>{Z.current?.querySelector('[aria-selected="true"]')?.scrollIntoView({block:"nearest",inline:"nearest"})},[l.activeId]);let[w,K]=j({}),R=t?.id,[g,X]=j(null),te=re((e)=>{if(!R)return;X((p)=>e===null?p?.id===R?null:p:{id:R,node:e})},[R]);function c(e){e().catch(C)}let W=t?.status==="loaded"?E.find((e)=>e.supports(t)):void 0,q=t?w[t.id]??(W?"preview":"edit"):"edit",V=v||q==="edit"&&k;function G(e,p,a=!1,b){let M=A?i(U.Item,{className:"alwith-editor-menu-item",disabled:a,onClick:p,children:e}):i(L,{type:"button",disabled:a,onClick:p,children:e});return b&&r?r(b,e,M):M}function J(){if(!t)return null;return h(Q,{children:[t.kind==="text"&&G(t.saving?s.saving:s.save,()=>c(()=>n.save(t.id)),V||t.locked||t.status!=="loaded"||!t.dirty||t.saving,"save"),z&&G(s.openExternal,()=>c(()=>z(t))),P&&t.kind==="text"&&G(s.saveAs,()=>c(async()=>{let e=await P(t);if(e!==null)await n.saveAs(t.id,e)}),V||t.locked||t.status!=="loaded"||t.saving)]})}return h("section",{className:"alwith-editor",onKeyDown:(e)=>{if((e.metaKey||e.ctrlKey)&&e.key.toLowerCase()==="s"&&t&&!f){if(e.preventDefault(),!V&&!t.locked&&t.status==="loaded")c(()=>n.save(t.id))}},children:[x?x(u):i("div",{className:"alwith-editor-tabs",role:"tablist",ref:Z,onDragOver:(e)=>{if(d.current)e.preventDefault()},onDrop:(e)=>{if(!d.current)return;e.preventDefault(),n.reorder(d.current,null),d.current=null},children:l.documents.map((e,p)=>h(m.Root,{children:[h(m.Trigger,{className:"alwith-editor-tab","data-active":e.id===l.activeId,"data-transient":!e.pinned,draggable:!0,onDragStart:(a)=>{d.current=e.id,a.dataTransfer.effectAllowed="move",a.dataTransfer.setData("text/plain",e.path)},onDragEnd:()=>{d.current=null},onDragOver:(a)=>{if(d.current)a.preventDefault()},onDrop:(a)=>{if(!d.current)return;a.preventDefault(),a.stopPropagation();let b=a.currentTarget.getBoundingClientRect(),M=a.clientX<b.left+b.width/2?e.id:l.documents[p+1]?.id??null;n.reorder(d.current,M),d.current=null},children:[h(L,{type:"button",role:"tab",id:`${u}-tab-${e.id}`,"aria-controls":`${u}-panel-${e.id}`,"aria-selected":e.id===l.activeId,tabIndex:e.id===l.activeId?0:-1,title:e.path,onClick:()=>n.activate(e.id),onDoubleClick:()=>n.pin(e.id),onKeyDown:(a)=>{let b=a.key==="ArrowRight"?1:a.key==="ArrowLeft"?-1:0,M=a.key==="Home"?0:a.key==="End"?l.documents.length-1:b?(p+b+l.documents.length)%l.documents.length:null;if(M===null)return;a.preventDefault();let Y=l.documents[M];if(Y)n.activate(Y.id),globalThis.document.getElementById(`${u}-tab-${Y.id}`)?.focus()},children:[H(e.path),e.dirty?" •":""]}),i(L,{type:"button","aria-label":`${s.close} ${H(e.path)}`,onClick:()=>c(()=>n.requestClose(e.id)),children:"×"})]}),i(m.Portal,{children:i(m.Positioner,{children:h(m.Popup,{className:"alwith-editor-menu",children:[i(m.Item,{className:"alwith-editor-menu-item",onClick:()=>c(()=>n.requestClose(e.id)),children:s.close}),i(m.Item,{className:"alwith-editor-menu-item",disabled:l.documents.length<2,onClick:()=>c(()=>n.requestCloseMany(l.documents.filter((a)=>a.id!==e.id).map((a)=>a.id))),children:o.closeOthers}),i(m.Item,{className:"alwith-editor-menu-item",disabled:p===l.documents.length-1,onClick:()=>c(()=>n.requestCloseMany(l.documents.slice(p+1).map((a)=>a.id))),children:o.closeRight}),i(m.Item,{className:"alwith-editor-menu-item",disabled:!l.documents.some((a)=>!a.dirty),onClick:()=>c(()=>n.requestCloseMany(l.documents.filter((a)=>!a.dirty).map((a)=>a.id))),children:o.closeSaved}),i(m.Item,{className:"alwith-editor-menu-item",onClick:()=>c(()=>n.requestCloseMany(l.documents.map((a)=>a.id))),children:o.closeAll}),D&&i(m.Item,{className:"alwith-editor-menu-item",onClick:()=>c(()=>D(e)),children:o.copyPath}),I&&i(m.Item,{className:"alwith-editor-menu-item",onClick:()=>c(()=>I(e)),children:o.reveal}),i(m.Separator,{className:"alwith-editor-menu-separator"}),e.kind==="text"&&i(m.Item,{className:"alwith-editor-menu-item",disabled:v||k||e.locked||e.status!=="loaded"||!e.dirty||e.saving,onClick:()=>c(()=>n.save(e.id)),children:e.saving?s.saving:s.save}),P&&e.kind==="text"&&i(m.Item,{className:"alwith-editor-menu-item",disabled:v||k||e.locked||e.status!=="loaded"||e.saving,onClick:()=>c(async()=>{let a=await P(e);if(a!==null)await n.saveAs(e.id,a)}),children:s.saveAs}),z&&i(m.Item,{className:"alwith-editor-menu-item",onClick:()=>c(()=>z(e)),children:s.openExternal})]})})})]},e.id))}),f?f(u):t?h(Q,{children:[h("div",{className:"alwith-editor-toolbar",children:[i(he,{path:t.path,rootPath:N,onRevealPath:T,onError:C}),h("div",{className:"alwith-editor-toolbar-actions",children:[q==="preview"&&g?.id===t.id&&g.node,W&&t.kind==="text"&&i(oe,{mode:q,preview:s.preview,source:s.source??"Source",label:s.viewMode??"View mode",onModeChange:(e)=>K((p)=>({...p,[t.id]:e}))}),A?W&&t.kind==="text"?null:h(U.Root,{children:[i(U.Trigger,{"aria-label":S,title:S,children:"⋯"}),i(U.Portal,{children:i(U.Positioner,{sideOffset:4,children:i(U.Popup,{className:"alwith-editor-menu",children:J()})})})]}):J()]})]}),t.externalChange&&h("div",{className:"alwith-editor-notice",role:"status",children:[s.changed,i(L,{type:"button",onClick:()=>c(()=>n.reload(t.id)),children:s.reload})]}),i("div",{className:"alwith-editor-content",role:"tabpanel",id:`${u}-panel-${t.id}`,"aria-labelledby":`${u}-tab-${t.id}`,children:t.status==="error"?h("div",{className:"alwith-editor-empty",role:"alert",children:[i("p",{children:s.loadFailed??"Unable to load file"}),i("p",{children:t.loadError}),i(L,{onClick:()=>c(()=>n.ensureLoaded(t.id)),children:s.retry??"Retry"})]}):t.status!=="loaded"?i("div",{className:"alwith-editor-empty",role:"status","aria-busy":"true",children:s.loading??"Loading…"}):W&&(q==="preview"||t.kind==="binary")?i(ee,{resetKey:t.version,label:s.unsupported,onError:C,children:i(ae,{fallback:i("div",{"aria-busy":"true"}),children:i(ue,{provider:W,document:t,context:{setToolbarActions:te,readOnly:v||t.locked,onChange:(e)=>n.update(t.id,e),onSave:()=>c(()=>n.save(t.id)),onError:C}})})},`${t.id}:${W.id}`):t.kind==="text"?F?F({document:t,readOnly:v||k||t.locked,onChange:(e)=>n.update(t.id,e),onSave:()=>{if(!v&&!k&&!t.locked)c(()=>n.save(t.id))}}):i("textarea",{"aria-label":H(t.path),className:"alwith-editor-text",spellCheck:!1,readOnly:v||k||t.locked,value:t.text,onChange:(e)=>n.update(t.id,e.target.value)}):i("div",{className:"alwith-editor-empty",children:s.unsupported})},t.id)]}):i("div",{className:"alwith-editor-empty",children:s.empty})]})}function he({path:r,rootPath:n,onRevealPath:x,onError:f}){let y=n?.replace(/\/$/,""),T=(y&&r.startsWith(`${y}/`)?r.slice(y.length+1):r).split("/").filter(Boolean),I=y&&r.startsWith(`${y}/`)?y:r.startsWith("/")?"":void 0;return i("nav",{className:"alwith-editor-breadcrumbs","aria-label":"File path",title:r,children:T.map((D,A)=>{I=I===void 0?D:`${I}/${D}`;let S=I;return h("span",{children:[A>0&&i("span",{"aria-hidden":"true",className:"alwith-editor-breadcrumb-separator",children:"›"}),x?i(L,{type:"button",onClick:()=>{x(S).catch(f)},children:D}):D]},S)})})}var me={failed:"Unable to display this image",zoomIn:"Zoom in",zoomOut:"Zoom out",resetZoom:"Reset zoom"};function pe({document:r,labels:n,onError:x}){let f={...me,...n},y=O(()=>/\.svg$/i.test(r.path)&&r.kind==="text"?new TextEncoder().encode(r.text):r.bytes,[r.text,r.bytes,r.path,r.kind]),N=O(()=>({bytes:y,path:r.path,id:r.id,version:r.version}),[y,r.path,r.id,r.version]),[T,I]=j(null),[D,A]=j(null),S=T?.source===N?T.url:null,s=D===N,[E,F]=j(1),[P,z]=j({width:0,height:0}),v=B(null),k=B(null),C=B(1);function l(u,d){let o=Math.min(4,Math.max(0.25,u)),w=v.current,K=k.current?.getBoundingClientRect(),R=w?.getBoundingClientRect(),g=w&&K&&R?{x:d?.x??R.left+w.clientWidth/2,y:d?.y??R.top+w.clientHeight/2,imageX:0,imageY:0}:null;if(g&&K)g.imageX=(g.x-K.left)/C.current,g.imageY=(g.y-K.top)/C.current;if(C.current=o,F(o),g&&w)requestAnimationFrame(()=>{let X=k.current?.getBoundingClientRect();if(!X)return;w.scrollLeft+=X.left+g.imageX*o-g.x,w.scrollTop+=X.top+g.imageY*o-g.y})}let t=B(l);t.current=l,_(()=>{let u=v.current;if(!u)return;let d=(o)=>{if(!o.ctrlKey&&!o.metaKey)return;o.preventDefault(),t.current(C.current*Math.exp(-o.deltaY*0.002),{x:o.clientX,y:o.clientY})};return u.addEventListener("wheel",d,{passive:!1}),()=>u.removeEventListener("wheel",d)},[]);let Z=ne(()=>r.path);return _(()=>{let u=Z().split(".").pop()?.toLowerCase(),d=u==="svg"?"image/svg+xml":u==="ico"?"image/x-icon":void 0,o=URL.createObjectURL(new Blob([new Uint8Array(N.bytes)],{type:d}));return I({source:N,url:o}),A(null),z({width:0,height:0}),F(1),C.current=1,()=>URL.revokeObjectURL(o)},[N]),h("div",{className:"alwith-editor-image-preview",children:[h("div",{className:"alwith-editor-image-controls",children:[i(L,{"aria-label":f.zoomOut,title:f.zoomOut,disabled:s||E<=0.25,onClick:()=>l(E/1.25),children:"−"}),h(L,{"aria-label":f.resetZoom,title:f.resetZoom,disabled:s,onClick:()=>l(1),children:[Math.round(E*100),"%"]}),i(L,{"aria-label":f.zoomIn,title:f.zoomIn,disabled:s||E>=4,onClick:()=>l(E*1.25),children:"+"})]}),i("div",{className:"alwith-editor-image-viewport",ref:v,onDoubleClick:()=>l(1),children:s?i("div",{className:"alwith-editor-empty",role:"alert",children:f.failed}):S&&i("div",{className:"alwith-editor-image-canvas",children:i("img",{ref:k,className:"alwith-editor-image",src:S,alt:H(r.path),style:P.width?{width:P.width*E,height:P.height*E}:void 0,onLoad:(u)=>{let d=v.current,o=u.currentTarget,w=d?Math.min(1,(d.clientWidth-40)/o.naturalWidth,(d.clientHeight-40)/o.naturalHeight):1;z({width:o.naturalWidth*Math.max(0.01,w),height:o.naturalHeight*Math.max(0.01,w)})},onError:()=>{A(N),x?.(Error(`Unable to decode image: ${r.path}`))}})})})]})}var xe={id:"image",supports:(r)=>/\.(png|jpe?g|webp|gif|bmp|avif|svg|ico)$/i.test(r.path),render:(r,n)=>i(pe,{document:r,onError:n.onError})};export{Ce as EditorWorkbench,pe as ImagePreview,de as defaultEditorLabels,ce as defaultEditorTabLabels,xe as imagePreview,Se as quickStartAssets};
@@ -0,0 +1,4 @@
1
+ import type { ReactElement, ReactNode } from "react";
2
+ export type EditorShortcutRenderer = (action: "save", label: string, trigger: ReactElement<{
3
+ title?: string;
4
+ }>) => ReactNode;
File without changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@alwith/module-editor",
3
- "version": "0.1.0-rc.12",
3
+ "version": "0.1.0-rc.13",
4
4
  "type": "module",
5
5
  "license": "SEE LICENSE IN LICENSE",
6
6
  "files": [