UNPKG

openalgo-charts

Version:

From-scratch, dependency-free canvas charting engine for OpenAlgo: professional-grade interactive rendering, advanced on-chart trading, and a one-call widget tier that adds the toolbar, drawing rail, dialogs and shortcuts.

3 lines (2 loc) • 16.4 kB
import{a,m as t,n as e,o,widgetText as n,b as r,p as i,q as c,e as l}from"./openalgo-charts.widget.mjs";import"./openalgo-charts.mjs";import"./openalgo-charts.draw.mjs";const s={save:"The layout could not be saved: {error}",open:"The layout could not be opened: {error}",rename:"The layout could not be renamed: {error}",delete:"The layout could not be deleted: {error}",reload:"The saved layouts could not be read: {error}",overwrite:"The layout could not be overwritten: {error}",autosave:"Autosave could not be changed: {error}"};let d=0;const u=a=>null===a.layoutId?null:a.catalog?.workspaces.find(t=>t.id===a.layoutId)?.name??null;function p(a,t,e=Date.now()){const o=a.chart.timezone(),n=a=>new Intl.DateTimeFormat("en-CA",{timeZone:o,year:"numeric",month:"2-digit",day:"2-digit"}).format(a),r=n(t)===n(e)?{timeZone:o,hour:"2-digit",minute:"2-digit"}:{timeZone:o,day:"numeric",month:"short",hour:"2-digit",minute:"2-digit"};try{return new Intl.DateTimeFormat(a.locale,r).format(t)}catch{return new Intl.DateTimeFormat("en-US",r).format(t)}}function y(y,g,f){const m=y.document;a(m,v);const _=c(y),w=_("title","Layouts"),h=t(m,{translate:y.translate,title:w,className:"oac-layouts",onClose:()=>ha.close()}),b=e(m,"div","oac-layouts__current"),x=e(m,"div","oac-layouts__heading"),k=e(m,"strong","oac-layouts__name"),A=e(m,"div","oac-layouts__tools"),C=o(m,{label:_("rename","Rename"),icon:"rename",onClick:()=>sa("rename",C)});C.dataset.action="rename";const I=o(m,{label:_("delete","Delete"),icon:"trash",onClick:()=>function(){const a=g.state(),t=a.layoutId;if(null===t||a.busy)return;ua(_("deleteQuestion","Delete {name}? The chart stays as it is.",{name:u(a)??""}),[{label:n(y,"Cancel"),action:"keep",run:()=>la()},{label:_("delete","Delete"),action:"confirm-delete",variant:"danger",run:()=>{ta=()=>P,la(),ca("delete",()=>g.remove(t)).then(()=>{Y||P.focus()})}}],()=>I)}()});I.dataset.action="delete",I.classList.add("oac-btn--danger"),A.append(C,I),x.append(k,A);const S=e(m,"div","oac-layouts__line");S.setAttribute("role","status"),S.setAttribute("aria-live","polite"),b.append(x,S);const L=e(m,"form","oac-layouts__form");L.hidden=!0;const D=e(m,"label","oac-layouts__label"),O=e(m,"input","oac-layouts__input");O.type="text",O.maxLength=120,O.autocomplete="off",O.id="oac-layouts-name-"+ ++d,D.htmlFor=O.id;const T=e(m,"p","oac-input-error");T.setAttribute("role","alert"),T.hidden=!0;const E=e(m,"div","oac-layouts__row-controls"),z=o(m,{label:n(y,"Cancel"),onClick:()=>la()}),N=o(m,{label:n(y,"Save"),variant:"primary",onClick:()=>{da()}});z.dataset.action="cancel-name",N.dataset.action="submit-name",E.append(O,z,N),L.append(D,E,T);const F=e(m,"div","oac-layouts__confirm");F.hidden=!0,F.setAttribute("role","alertdialog");const j=e(m,"p","oac-layouts__confirm-text");j.id=`oac-layouts-confirm-${d}`,F.setAttribute("aria-describedby",j.id);const q=e(m,"div","oac-layouts__row-controls");F.append(j,q);const R=e(m,"div","oac-layouts__conflict");R.hidden=!0,R.setAttribute("role","alert");const $=e(m,"p","oac-layouts__conflict-text"),Q=e(m,"div","oac-layouts__row-controls"),Z=o(m,{label:_("reload","Reload list"),icon:"refresh",onClick:()=>{ca("reload",()=>g.reload())}});Z.dataset.action="reload";const U=o(m,{label:_("copy","Save as a copy"),onClick:()=>sa("copy",U)});U.dataset.action="copy";const W=o(m,{label:_("overwrite","Overwrite"),variant:"danger",onClick:()=>{ca("overwrite",()=>g.overwrite())}});W.dataset.action="overwrite",Q.append(Z,U,W),R.append($,Q);const X=e(m,"p","oac-layouts__error");X.setAttribute("role","alert"),X.hidden=!0;const B=e(m,"div","oac-layouts__lists");h.body.append(b,L,F,R,X,B);const G=e(m,"button","oac-layouts__switch");G.type="button",G.setAttribute("role","switch"),G.dataset.action="autosave";const H=e(m,"span","oac-layouts__switch-label",_("autosave","Autosave")),J=e(m,"span","oac-layouts__switch-value");G.append(e(m,"span","oac-layouts__track"),H,J),G.addEventListener("click",()=>{if("true"===G.getAttribute("aria-disabled"))return;const a=!0===g.state().catalog?.autosave;ca("autosave",()=>g.setAutosave(!a))});const K=e(m,"span","oac-layouts__autosave-state");K.setAttribute("aria-live","polite"),h.lead.append(G,K);const M=o(m,{label:_("saveAs","Save as..."),icon:"save-as",onClick:()=>sa("save-as",M)});M.dataset.action="save-as";const P=o(m,{label:n(y,"Save"),variant:"primary",onClick:()=>{"true"!==P.getAttribute("aria-disabled")&&(null===g.state().layoutId?sa("save-as",P):ca("save",()=>g.save()))}});P.dataset.action="save",h.actions.append(M,P);let V=null,Y=!1,aa=null,ta=null;const ea=(a,t,e)=>{a.setAttribute("aria-disabled",String(t)),t&&void 0!==e?a.title=e:a.removeAttribute("title")},oa=a=>l(y,a),na=a=>Array.from(B.querySelectorAll(".oac-layouts__row")).find(t=>t.dataset.layoutId===a)??null,ra=(a,t)=>{const e=!t&&!a.hidden&&a.contains(m.activeElement);return a.hidden=!t,e},ia=()=>{if(Y)return;const a=ta?.()??null;(null===a||R.hidden&&R.contains(a)?P:a).focus()};async function ca(a,t){aa=null;try{return await t(),!0}catch(t){return aa=_(`failed.${a}`,s[a],{error:oa(t)}),!1}finally{ga()}}function la(){V=null;const a=[ra(L,!1),ra(F,!1)].includes(!0);T.hidden=!0,O.removeAttribute("aria-invalid"),ga(),a&&ia(),ta=null}function sa(a,t){const e=g.state();if(e.busy)return;if("rename"===a&&null===e.layoutId)return;la(),V=a,ta=()=>t;const o=u(e),r=y.symbol();D.textContent="rename"===a?_("renameLabel","New name for {name}",{name:o??""}):"copy"===a?_("copyLabel","Name for the copy"):_("nameLabel","Layout name"),O.value="rename"===a?o??"":"copy"===a?_("copyName","{name} copy",{name:o??w}):[r.symbol,y.interval()].filter(a=>""!==a).join(" "),N.textContent="rename"===a?_("renameSubmit","Rename"):n(y,"Save"),L.hidden=!1,O.focus(),O.select()}async function da(){const a=V,t=O.value.trim();if(null===a||g.state().busy)return;if(""===t)return T.textContent=n(y,"Enter a name"),T.hidden=!1,O.setAttribute("aria-invalid","true"),void O.focus();const e=g.state().layoutId;await ca("rename"===a?"rename":"save",()=>"rename"===a&&null!==e?g.rename(e,t):g.saveAs(t))&&!Y&&(ta=()=>P,la())}function ua(a,t,e){la(),ta=e,j.textContent=a,q.textContent="";for(const a of t){const t=o(m,{label:a.label,variant:a.variant,onClick:a.run});t.dataset.action=a.action,q.appendChild(t)}F.hidden=!1,q.querySelector("button")?.focus()}async function pa(a){ra(F,!1)&&ia();let t=!1;await ca("open",async()=>{const e=await g.open(a);if(t=e.applied,!e.applied)throw new Error(e.reason??_("notShown","the layout cannot show here"))})&&t&&ha.close()}function ya(a,t,o){const r=e(m,"button","oac-layouts__row");r.type="button",r.dataset.layoutId=a.id;const i=a.id===t.layoutId;i&&r.setAttribute("aria-current","true"),r.append(e(m,"span","oac-layouts__row-name",a.name)),r.append(e(m,"span","oac-layouts__row-meta",i?_("current","on the chart"):p(y,a.updatedAt))),ea(r,t.busy||t.suspended,t.suspended?_("suspendedOpen","Stop the replay to open a layout"):void 0),r.addEventListener("click",()=>{"true"!==r.getAttribute("aria-disabled")&&async function(a){if(g.state().busy||g.state().suspended)return;if(aa=null,await g.flush(),Y)return;const t=g.state();if(null!==t.layoutId&&t.dirty){const e=u(t)??"",o=[{label:n(y,"Cancel"),action:"stay",run:()=>la()},{label:_("discard","Open without saving"),action:"discard",variant:"danger",run:()=>{pa(a)}}];return t.conflict||o.push({label:_("saveAndOpen","Save and open"),action:"save-and-open",variant:"primary",run:()=>{ca("save",()=>g.save()).then(t=>{t&&pa(a)})}}),void ua(a===t.layoutId?_("revertQuestion","{name} has unsaved changes. Open the saved version?",{name:e}):_("discardQuestion","{name} has unsaved changes. Save them before opening {target}?",{name:e,target:t.catalog?.workspaces.find(t=>t.id===a)?.name??""}),o,()=>na(a))}await pa(a)}(a.id)});const c=e(m,"li","oac-layouts__item");c.appendChild(r),o.appendChild(c)}function va(a,t,o,n){if(0===t.length)return;const r=e(m,"div","oac-head",a);r.id=`oac-layouts-${n}-${d}`;const i=e(m,"ul","oac-layouts__list");i.setAttribute("aria-labelledby",r.id),i.dataset.list=n;for(const a of t)ya(a,o,i);B.append(r,i)}function ga(){if(Y)return;const a=g.state(),t=m.activeElement,o=t?.dataset.layoutId,n=u(a);k.textContent=n??_("none","No layout open"),k.classList.toggle("is-none",null===n);const i=a.catalog?.workspaces.find(t=>t.id===a.layoutId);S.textContent=void 0===i||a.conflict||a.dirty||"failed"===a.autosave||"saving"===a.autosave?r(y,a):_("savedAt","Saved {time}",{time:p(y,i.updatedAt)}),S.dataset.state=a.conflict?"conflict":"failed"===a.autosave?"failed":a.dirty?"dirty":"clean",ea(C,null===a.layoutId||a.busy),ea(I,null===a.layoutId||a.busy),ea(P,a.busy||a.conflict||null!==a.layoutId&&!a.dirty&&"failed"!==a.autosave,a.conflict?_("conflictSave","Choose how to settle the change from the other window"):void 0),ea(M,a.busy);const c=!0===a.catalog?.autosave;G.setAttribute("aria-checked",String(c)),J.textContent=c?_("on","On"):_("off","Off"),ea(G,a.busy||null===a.catalog),K.textContent=c&&null!==a.layoutId&&!a.conflict?r(y,a):"",K.dataset.state=a.autosave,ra(R,a.conflict)&&P.focus(),$.textContent=_("conflictText","{name} was changed in another window. This chart is not saved over it.",{name:n??""});for(const t of[Z,U,W])ea(t,a.busy);const l=aa??("failed"!==a.autosave||null===a.error||a.conflict?null:_("failed.autosaveWrite","Autosave could not save the layout: {error}",{error:oa(a.error)}));X.hidden=null===l,X.textContent=l??"",B.textContent="";const s=a.catalog?.workspaces??[];null===a.catalog?a.busy&&B.appendChild(e(m,"p","oac-empty",_("loading","Loading layouts"))):0===s.length&&B.appendChild(e(m,"p","oac-empty",_("empty","No saved layouts yet. Save this chart to start one.")));const d=(a.catalog?.recentWorkspaceIds??[]).slice(0,10).map(a=>s.find(t=>t.id===a)).filter(a=>void 0!==a),v=s.filter(a=>!d.includes(a)).sort((a,t)=>a.name.localeCompare(t.name));va(_("recent","Recent"),d,a,"recent"),va(d.length>0?_("others","Other layouts"):_("all","Layouts"),v,a,"others"),void 0!==o&&Array.from(B.querySelectorAll(".oac-layouts__row")).find(a=>a.dataset.layoutId===o)?.focus()}B.addEventListener("keydown",a=>{const t=a.key;if("ArrowDown"!==t&&"ArrowUp"!==t)return;const e=Array.from(B.querySelectorAll(".oac-layouts__row")),o=e.indexOf(m.activeElement);0!==e.length&&(a.preventDefault(),e[(o+("ArrowDown"===t?1:-1)+e.length)%e.length].focus())}),L.addEventListener("submit",a=>{a.preventDefault(),da()}),O.addEventListener("input",()=>{T.hidden=!0,O.removeAttribute("aria-invalid")});const fa=g.subscribe(()=>ga());ga();const ma=y.root.classList.contains("is-mobile"),_a=i(y,h.el,void 0===f||ma?{placement:"center",modal:!0,initialFocus:P}:{anchor:f,placement:"below",initialFocus:P},()=>wa());function wa(){Y||(Y=!0,fa())}const ha={el:_a.el,isOpen:_a.isOpen,close:()=>{_a.isOpen()&&(wa(),_a.close())}};return ca("reload",async()=>{await g.reload(),await g.flush()}),ha}const v='\n.oac-widget .oac-layouts { width: 380px; }\n.oac-widget .oac-layouts .oac-dialog__body { display: flex; flex-direction: column; gap: 8px; padding-top: 2px; }\n.oac-widget .oac-layouts__current { display: grid; gap: 2px; padding: 8px 10px; border: 1px solid var(--oac-bd-soft); border-radius: 8px; background: var(--oac-elev); }\n.oac-widget .oac-layouts__heading { display: flex; align-items: center; gap: 6px; min-width: 0; }\n.oac-widget .oac-layouts__name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; color: var(--oac-tx-strong); font-size: 13px; }\n.oac-widget .oac-layouts__name.is-none { color: var(--oac-mut); font-weight: 500; }\n.oac-widget .oac-layouts__tools { display: flex; gap: 2px; flex: none; }\n.oac-widget .oac-layouts__tools .oac-btn { height: 24px; padding: 0 6px; font-size: 11.5px; }\n.oac-widget .oac-layouts__line { color: var(--oac-mut); font-size: 11px; }\n.oac-widget .oac-layouts__line[data-state="dirty"] { color: var(--oac-amber); }\n.oac-widget .oac-layouts__line[data-state="failed"], .oac-widget .oac-layouts__line[data-state="conflict"] { color: var(--oac-danger); }\n.oac-widget .oac-layouts__form, .oac-widget .oac-layouts__confirm, .oac-widget .oac-layouts__conflict { display: grid; gap: 6px; padding: 8px 10px;\n border: 1px solid var(--oac-bd-soft); border-radius: 8px; }\n.oac-widget .oac-layouts__conflict { border-color: var(--oac-danger); }\n.oac-widget .oac-layouts__label { color: var(--oac-mut); font-size: 11px; }\n.oac-widget .oac-layouts__row-controls { display: flex; flex-wrap: wrap; align-items: center; justify-content: flex-end; gap: 6px; min-width: 0; }\n.oac-widget .oac-layouts__row-controls .oac-btn:not(.oac-btn--primary) { border-color: var(--oac-bd-soft); }\n/* Nothing to save: the primary button steps back rather than show faint text on the accent, and a\n disabled Delete takes no danger colour from a hover or a tap. */\n.oac-widget .oac-layouts .oac-btn--primary[aria-disabled="true"] { background: var(--oac-elev); color: var(--oac-faint); }\n.oac-widget .oac-layouts .oac-btn[aria-disabled="true"]:hover { color: var(--oac-faint); }\n.oac-widget .oac-layouts__input { flex: 1 1 160px; min-width: 0; }\n.oac-widget .oac-layouts__confirm-text, .oac-widget .oac-layouts__conflict-text { margin: 0; line-height: 1.45; overflow-wrap: anywhere; }\n.oac-widget .oac-layouts__error { margin: 0; color: var(--oac-danger); font-size: 11px; overflow-wrap: anywhere; }\n.oac-widget .oac-layouts__lists { display: flex; flex-direction: column; min-height: 0; }\n.oac-widget .oac-layouts__lists > .oac-head { padding: 6px 2px 3px; }\n.oac-widget .oac-layouts__list { list-style: none; margin: 0; padding: 0; display: grid; gap: 1px; }\n.oac-widget .oac-layouts__row { display: flex; align-items: center; gap: 8px; width: 100%; min-height: 30px; padding: 5px 8px; border: 0; border-radius: 6px;\n background: transparent; color: var(--oac-tx); text-align: left; }\n.oac-widget .oac-layouts__row:hover, .oac-widget .oac-layouts__row:focus-visible { background: var(--oac-elev-2); outline: none; }\n.oac-widget .oac-layouts__row[aria-current="true"] { color: var(--oac-acc-2); box-shadow: inset 2px 0 0 var(--oac-acc); }\n.oac-widget .oac-layouts__row[aria-disabled="true"] { color: var(--oac-faint); cursor: default; background: transparent; }\n.oac-widget .oac-layouts__row-name { flex: 1 1 auto; min-width: 0; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }\n.oac-widget .oac-layouts__row-meta { flex: none; color: var(--oac-mut); font-size: 11px; }\n.oac-widget .oac-layouts__switch { display: inline-flex; align-items: center; gap: 7px; height: var(--oac-ctl-h); padding: 0 8px 0 4px; border: 1px solid transparent;\n border-radius: var(--oac-radius); background: transparent; color: var(--oac-tx); }\n.oac-widget .oac-layouts__switch:hover { background: var(--oac-elev); border-color: var(--oac-bd-soft); }\n.oac-widget .oac-layouts__switch[aria-disabled="true"] { color: var(--oac-faint); cursor: default; background: transparent; border-color: transparent; }\n.oac-widget .oac-layouts__track { position: relative; width: 26px; height: 15px; flex: none; border-radius: 999px; background: var(--oac-elev-3);\n border: 1px solid var(--oac-bd); transition: background .12s, border-color .12s; }\n.oac-widget .oac-layouts__track::after { content: \'\'; position: absolute; top: 2px; left: 2px; width: 9px; height: 9px; border-radius: 50%;\n background: var(--oac-mut); transition: transform .12s, background .12s; }\n.oac-widget .oac-layouts__switch[aria-checked="true"] .oac-layouts__track { background: var(--oac-acc); border-color: var(--oac-acc); }\n.oac-widget .oac-layouts__switch[aria-checked="true"] .oac-layouts__track::after { transform: translateX(11px); background: var(--oac-bg); }\n.oac-widget .oac-layouts__switch-value { color: var(--oac-mut); font-size: 11px; }\n.oac-widget .oac-layouts__autosave-state { color: var(--oac-mut); font-size: 11px; }\n.oac-widget .oac-layouts__autosave-state[data-state="failed"] { color: var(--oac-danger); }\n.oac-widget.is-mobile .oac-layouts { width: 100%; }\n.oac-widget.is-mobile .oac-layouts__row { min-height: 44px; }\n.oac-widget.is-mobile .oac-layouts .oac-btn, .oac-widget.is-mobile .oac-layouts__switch { min-height: 40px; }\n@media (prefers-reduced-motion: reduce) {\n .oac-widget .oac-layouts__track, .oac-widget .oac-layouts__track::after { transition: none; }\n}\n';export{y as mountLayoutsMenu}; //# sourceMappingURL=openalgo-charts.widget.layouts-menu-B7XYKPAW.mjs.map