@tradecanvas/chart 1.74.0 → 1.75.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/Chart.d.ts +2 -1
- package/dist/Chart.d.ts.map +1 -1
- package/dist/LayoutSession-DK0-RkCh.cjs +2 -0
- package/dist/LayoutSession-DK0-RkCh.cjs.map +1 -0
- package/dist/{LayoutSession-DbJAOYso.js → LayoutSession-Ds8eBT3q.js} +8 -6
- package/dist/LayoutSession-Ds8eBT3q.js.map +1 -0
- package/dist/WidgetDrawingSettings-B_mi8DUh.cjs +2 -0
- package/dist/WidgetDrawingSettings-B_mi8DUh.cjs.map +1 -0
- package/dist/{WidgetDrawingSettings-BeW8fX7r.js → WidgetDrawingSettings-CJsNm1Bf.js} +78 -79
- package/dist/WidgetDrawingSettings-CJsNm1Bf.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/widget/ChartWidget.d.ts.map +1 -1
- package/dist/widget/WidgetSelectionToolbar.d.ts.map +1 -1
- package/dist/widget/drawingSettingsTabs.d.ts.map +1 -1
- package/dist/widget/drawingText.d.ts +1 -1
- package/dist/widget/drawingText.d.ts.map +1 -1
- package/dist/widget/index.cjs +3 -3
- package/dist/widget/index.cjs.map +1 -1
- package/dist/widget/index.js +989 -988
- package/dist/widget/index.js.map +1 -1
- package/package.json +3 -3
- package/dist/LayoutSession-DbJAOYso.js.map +0 -1
- package/dist/LayoutSession-WcHEheSo.cjs +0 -2
- package/dist/LayoutSession-WcHEheSo.cjs.map +0 -1
- package/dist/WidgetDrawingSettings-BeW8fX7r.js.map +0 -1
- package/dist/WidgetDrawingSettings-Cyl2u_u8.cjs +0 -2
- package/dist/WidgetDrawingSettings-Cyl2u_u8.cjs.map +0 -1
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
const e=require(`./focusTrap-DrhhmG0V.cjs`),t=require(`./settingsControls-Tn8_vJJv.cjs`),n=require(`./i18n-C2nQBZTY.cjs`),r=require(`./indicatorSettingsTabs-B0liE3ST.cjs`);let i=require(`@tradecanvas/commons`);var a=[1,2,3,4],o=[`solid`,`dashed`,`dotted`],s=[10,11,13,14,16,18,20,24,28,32],c=14,l=12,u=48,d=.5,f=.12,p=[`leftEnd`,`rightEnd`];function m(e,t,n){let r=`drawingOption.${t}`,i=e(r);return i===r?n:i}function h(){let e=document.createElement(`div`);return e.className=`tcw-settings-section`,e}function g(e,...t){let n=document.createElement(`div`);n.className=`tcw-settings-row`;let r=document.createElement(`span`);r.className=`tcw-settings-label`,r.textContent=e;let i=document.createElement(`span`);return i.className=`tcw-indi-plot-controls`,i.append(...t),n.append(r,i),n}function _(e,t){return e.setAttribute(`aria-label`,t),e}function v(e,n,r,i){let a=[],o=h();o.appendChild(y(n.style(),r,a,i));let s=p.filter(e=>n.defs[e]?.kind===`choice`);s.length>0&&o.appendChild(g(i(`drawingSettings.lineEnds`),...s.map(e=>_(t.o([{value:`normal`,label:i(`drawingSettings.lineEnd.normal`)},{value:`arrow`,label:i(`drawingSettings.lineEnd.arrow`)}],String(n.options()[e]??`normal`),t=>r.options({[e]:t})),m(i,e,n.defs[e].label))))),n.fill&&o.appendChild(b(n.style(),r,a,i)),e.appendChild(o);let c=Object.entries(n.defs).filter(([e,t])=>t.kind!==`levels`&&!s.includes(e));if(c.length>0){let t=h();for(let[e,a]of c)t.appendChild(x(e,a,n.options(),r,i));e.appendChild(t)}for(let[t,o]of Object.entries(n.defs))o.kind===`levels`&&e.appendChild(S(t,o,n,r,a,i))}function y(e,n,r,i){let s=_(t.r(e.color,e=>{n.style({color:e});for(let t of r)t(e)}),i(`drawingSettings.color`)),c=_(t.o(a.map(e=>({value:String(e),label:`${e} px`})),String(e.lineWidth),e=>n.style({lineWidth:Number(e)})),i(`drawingSettings.lineWidth`)),l=_(t.o(o.map(e=>({value:e,label:i(`drawingSettings.lineStyle.${e}`)})),e.lineStyle,e=>n.style({lineStyle:e})),i(`drawingSettings.lineStyle`));return g(i(`drawingSettings.line`),s,c,l)}function b(e,n,r,a){let o=(0,i.ownFillColor)(e)??t.d(e.color,f),s=t.l(o),c=t.n(o),l=(0,i.ownFillColor)(e)!==void 0,u=()=>{l=!0,n.style({fillColor:t.d(s,c),fillOpacity:c})},d=_(t.r(s,e=>{s=e,u()}),a(`drawingSettings.fill`));r.push(e=>{l||(s=t.l(e),d.value=s)});let p=_(t.i(Math.round(c*100),{min:0,max:100,step:5},e=>{c=e/100,u()}),a(`drawingSettings.opacity`)),m=document.createElement(`span`);return m.className=`tcw-unit`,m.setAttribute(`aria-hidden`,`true`),m.textContent=`%`,g(a(`drawingSettings.fill`),d,p,m)}function x(e,n,r,i,a){let o=m(a,e,n.label),s=r[e];switch(n.kind){case`boolean`:return t.t(o,!!s,t=>i.options({[e]:t}));case`number`:return t.s(o,t.i(Number(s),{min:n.min,max:n.max,step:n.step},t=>i.options({[e]:t})));case`choice`:return t.s(o,t.o(n.choices.map(t=>({value:t.value,label:m(a,`${e}.${t.value}`,t.label)})),String(s),t=>i.options({[e]:t})));case`text`:{let n=document.createElement(`input`);return n.type=`text`,n.className=`tcw-indi-input`,n.value=String(s??``),n.addEventListener(`change`,()=>i.options({[e]:n.value})),t.s(o,n)}}}function S(n,r,i,a,o,s){let c=document.createElement(`div`);c.className=`tcw-settings-section tcw-levels-editor`;let l=document.createElement(`div`);l.className=`tcw-settings-section-title`,l.textContent=m(s,n,r.label),c.appendChild(l);let f=()=>{let e=i.options()[n];return Array.isArray(e)?e:[]},p=e=>a.options({[n]:e}),h=document.createElement(`div`);h.className=`tcw-levels-grid`,f().forEach((n,r)=>{let c=document.createElement(`div`);c.className=`tcw-level-row`;let l=` ${r+1}`,u=document.createElement(`input`);u.type=`checkbox`,u.checked=n.visible,u.setAttribute(`aria-label`,s(`drawingSettings.levelVisible`)+l),u.addEventListener(`change`,()=>p(f().map((e,t)=>t===r?{...e,visible:u.checked}:e)));let d=_(t.i(n.value,{step:.001},e=>p(f().map((t,n)=>n===r?{...t,value:e}:t))),s(`drawingSettings.levelValue`)+l),m=_(t.r(n.color??i.style().color,e=>p(f().map((t,n)=>n===r?{...t,color:e}:t))),s(`drawingSettings.levelColor`)+l);o.push(e=>{f()[r]?.color===void 0&&(m.value=t.l(e))});let g=document.createElement(`button`);g.type=`button`,g.className=`tcw-level-remove`,g.setAttribute(`aria-label`,s(`drawingSettings.removeLevel`)+l),g.innerHTML=e.i(`x`,12),g.addEventListener(`click`,()=>{p(f().filter((e,t)=>t!==r)),a.redraw([`.tcw-level-row:nth-child(${r+1}) .tcw-level-remove`,`.tcw-level-row:last-child .tcw-level-remove`,`.tcw-level-add`])}),c.append(u,d,m,g),h.appendChild(c)}),c.appendChild(h);let g=document.createElement(`button`);return g.type=`button`,g.className=`tcw-reset-link tcw-level-add`,g.textContent=s(`drawingSettings.addLevel`),g.disabled=f().length>=u,g.addEventListener(`click`,()=>{let e=f().at(-1)?.value??0;p([...f(),{value:Math.round((e+d)*1e3)/1e3,visible:!0}]),a.redraw([`.tcw-level-row:last-child input[type="number"]`])}),c.appendChild(g),c}var C=240,w=40,T=4e3,E=10,D=[`left`,`center`,`right`],O=[`top`,`middle`,`bottom`];function k(e,t,n,r=!1){let i=document.createElement(`label`);i.className=`tcw-inline-check`;let a=document.createElement(`input`);if(a.type=`checkbox`,a.checked=t,a.setAttribute(`aria-label`,e),a.addEventListener(`change`,()=>n(a.checked)),i.append(a),!r){let t=document.createElement(`span`);t.textContent=e,i.append(t)}return i}function A(e,n,r,i,a,o,u=!1){let d=h(),f=document.createElement(`textarea`);f.className=`tcw-indi-input tcw-drawing-text`,f.rows=3,f.value=n.text??``,f.addEventListener(`input`,()=>r({text:f.value}));let p=t.s(i(`drawingSettings.text`),f);p.classList.add(`tcw-text-row`),d.appendChild(p);let m=_(t.o(s.map(e=>({value:String(e),label:`${e} px`})),String((n.fontSize===l?void 0:n.fontSize)??a?.fontSize??c),e=>r({fontSize:Number(e)})),i(`drawingSettings.fontSize`));d.appendChild(g(i(`drawingSettings.fontSize`),m,k(i(`drawingSettings.bold`),n.bold===!0,e=>r({bold:e})),k(i(`drawingSettings.italic`),n.italic===!0,e=>r({italic:e})))),d.appendChild(g(i(`drawingSettings.textColor`),_(t.r(n.textColor??o??n.color,e=>r({textColor:e})),i(`drawingSettings.textColor`)))),e.appendChild(d),a&&e.appendChild(M(n,r,i,a)),u&&e.appendChild(j(n,r,i))}function j(e,n,r){let i=h();return i.appendChild(g(r(`drawingSettings.align`),_(t.o(D.map(e=>({value:e,label:r(`drawingSettings.align.${e}`)})),e.textAlign??`center`,e=>n({textAlign:e})),r(`drawingSettings.align`)))),i.appendChild(g(r(`drawingSettings.vAlign`),_(t.o(O.map(e=>({value:e,label:r(`drawingSettings.vAlign.${e}`)})),e.textVAlign??`top`,e=>n({textVAlign:e})),r(`drawingSettings.vAlign`)))),i}function M(e,n,r,a){let o=h();o.appendChild(g(r(`drawingSettings.align`),_(t.o(D.map(e=>({value:e,label:r(`drawingSettings.align.${e}`)})),e.textAlign??`left`,e=>n({textAlign:e})),r(`drawingSettings.align`))));let s=(0,i.ownFillColor)(e)??t.d(e.color,f);o.appendChild(g(r(`drawingSettings.background`),k(r(`drawingSettings.background`),e.textBackground??a.box,e=>n({textBackground:e}),!0),_(t.r(s,e=>n({fillColor:t.d(e,t.n(s))})),r(`drawingSettings.backgroundColor`)))),o.appendChild(g(r(`drawingSettings.border`),k(r(`drawingSettings.border`),e.textBorder??a.border,e=>n({textBorder:e}),!0),_(t.r(e.borderColor??e.color,e=>n({borderColor:e})),r(`drawingSettings.borderColor`))));let c=e.textWrap??a.wrap,l=c>0?c:a.wrap>0?a.wrap:C,u=c>0,d=_(t.i(l,{min:w,max:T,step:E},e=>{l=e,u&&n({textWrap:e})}),r(`drawingSettings.wrapWidth`));return d.disabled=!u,o.appendChild(g(r(`drawingSettings.wrap`),k(r(`drawingSettings.wrap`),u,e=>{u=e,d.disabled=!e,n({textWrap:e?l:0})},!0),d)),o}function N(e,t,r,i){let a=h();t.forEach((e,t)=>{let o=n.r(i(`drawingSettings.point`),{n:t+1}),s=r.toWallTime(e.time),c=document.createElement(`input`);c.type=`date`,c.className=`tcw-indi-input`,c.value=s.date;let l=document.createElement(`input`);l.type=`time`,l.className=`tcw-indi-input`,l.value=s.time;let u=()=>{let e=r.fromWallTime(c.value,l.value);e!==null&&r.move(t,{time:e})};c.addEventListener(`change`,u),l.addEventListener(`change`,u);let d=g(o,_(P(e.price,r,e=>r.move(t,{price:e})),`${o}: ${i(`drawingSettings.price`)}`),_(c,`${o}: ${i(`drawingSettings.date`)}`),_(l,`${o}: ${i(`drawingSettings.time`)}`));d.classList.add(`tcw-draw-point`),a.appendChild(d)}),e.appendChild(a)}function P(e,n,r){let i=n.roundPrice??(e=>e),a=n.priceStep?.(),o=t.i(i(e),{step:a!==void 0&&a>0?a:`any`},e=>{let t=i(e);o.value=String(t),r(t)});return o}var F=12,I=`t:`,L=1,R=class{backdrop;modal;titleEl;tabsEl;bodyEl;templateBtn;menu=null;tabButtons=[];target=null;style;options={};anchors=[];intervals=null;tab=`style`;returnFocus=null;uid=L++;constructor(t,r,i=n.t){this.callbacks=r,this.t=i,this.backdrop=document.createElement(`div`),this.backdrop.className=`tcw-modal-backdrop`,this.backdrop.hidden=!0;let a=!1;this.backdrop.addEventListener(`pointerdown`,e=>{a=e.target===this.backdrop}),this.backdrop.addEventListener(`click`,e=>{e.target===this.backdrop&&a&&this.close(!0),a=!1}),this.modal=document.createElement(`div`),this.modal.className=`tcw-modal tcw-modal-narrow tcw-drawing-settings`,this.modal.setAttribute(`role`,`dialog`),this.modal.setAttribute(`aria-modal`,`true`),this.modal.setAttribute(`aria-labelledby`,`tcw-draw-title-${this.uid}`),this.modal.tabIndex=-1,this.modal.addEventListener(`keydown`,e=>this.onKeyDown(e));let o=document.createElement(`div`);o.className=`tcw-modal-header`,this.titleEl=document.createElement(`h3`),this.titleEl.id=`tcw-draw-title-${this.uid}`;let s=document.createElement(`button`);s.type=`button`,s.className=`tcw-modal-close`,s.setAttribute(`aria-label`,this.t(`common.close`)),s.innerHTML=e.i(`x`,16),s.addEventListener(`click`,()=>this.close(!0)),o.append(this.titleEl,s),this.tabsEl=document.createElement(`div`),this.tabsEl.className=`tcw-modal-tabs`,this.tabsEl.setAttribute(`role`,`tablist`),this.tabsEl.addEventListener(`keydown`,e=>this.onTabKey(e)),this.bodyEl=document.createElement(`div`),this.bodyEl.className=`tcw-modal-body`,this.bodyEl.id=`tcw-draw-panel-${this.uid}`,this.bodyEl.setAttribute(`role`,`tabpanel`),this.templateBtn=this.footerButton(`template`,`tcw-footer-menu`,()=>this.openTemplates()),this.modal.append(o,this.tabsEl,this.bodyEl,this.buildFooter()),this.backdrop.appendChild(this.modal),t.appendChild(this.backdrop)}buildFooter(){this.templateBtn.setAttribute(`aria-haspopup`,`menu`),this.templateBtn.setAttribute(`aria-expanded`,`false`),this.templateBtn.innerHTML=`<span></span>${e.i(`chevronDown`,12)}`,this.templateBtn.querySelector(`span`).textContent=this.t(`settings.template`);let t=document.createElement(`div`);t.className=`tcw-footer-end`,t.append(this.footerButton(`cancel`,`tcw-footer-cancel`,()=>this.close(!0),this.t(`common.cancel`)),this.footerButton(`ok`,`tcw-done-btn`,()=>this.close(!1),this.t(`drawingSettings.ok`)));let n=document.createElement(`div`);return n.className=`tcw-modal-footer`,n.append(this.templateBtn,t),n}open(e,t={}){this.target&&this.close(!1),this.returnFocus=document.activeElement instanceof HTMLElement?document.activeElement:null,this.target=e,this.style={...e.style},this.options=structuredClone(e.options),this.anchors=e.anchors.map(e=>({...e})),this.intervals=e.intervals??null,this.titleEl.textContent=e.name,this.tab=t.tab===`text`&&e.text?`text`:`style`,this.callbacks.onBegin(e.id);try{this.renderTabs(),this.renderBody()}catch(t){throw this.target=null,this.callbacks.onEnd(e.id,!0),t}this.backdrop.hidden=!1;let n=this.tab===`text`?this.bodyEl.querySelector(`textarea`):null;n?(n.focus(),n.select()):(this.tabButtons[0]??this.modal).focus()}close(e){let t=this.target;if(!t)return;let n=document.activeElement;!e&&(n instanceof HTMLInputElement||n instanceof HTMLTextAreaElement)&&this.modal.contains(n)&&n.dispatchEvent(new Event(`change`)),this.target=null,this.menu?.close(),this.backdrop.hidden=!0,this.callbacks.onEnd(t.id,e),this.returnFocus?.isConnected&&this.returnFocus.focus(),this.returnFocus=null}isOpen(){return this.target!==null}editing(){return this.target?.id??null}destroy(){this.close(!0),this.menu?.destroy(),this.backdrop.remove()}tabs(){let e=this.target;return e?[`style`,...e.text?[`text`]:[],...e.coordinates!==!1&&e.anchors.length<=F?[`coordinates`]:[],`visibility`]:[]}renderTabs(){this.tabButtons=this.tabs().map(e=>{let t=document.createElement(`button`);return t.type=`button`,t.className=`tcw-modal-tab`,t.id=`tcw-draw-tab-${this.uid}-${e}`,t.setAttribute(`role`,`tab`),t.setAttribute(`aria-controls`,this.bodyEl.id),t.dataset.tab=e,t.textContent=this.t(`drawingSettings.tab.${e}`),t.addEventListener(`click`,()=>this.selectTab(e)),t}),this.tabsEl.replaceChildren(...this.tabButtons),this.markTabs()}markTabs(){for(let e of this.tabButtons){let t=e.dataset.tab===this.tab;e.classList.toggle(`tcw-active`,t),e.setAttribute(`aria-selected`,String(t)),e.tabIndex=t?0:-1,t&&this.bodyEl.setAttribute(`aria-labelledby`,e.id)}}selectTab(e,t=!1){this.tab=e,this.markTabs(),this.renderBody(),t&&this.tabButtons.find(t=>t.dataset.tab===e)?.focus()}onTabKey(e){let t=this.tabButtons.map(e=>e.dataset.tab),n=t.indexOf(this.tab),[r,i]=this.modal.closest(`[dir]`)?.getAttribute(`dir`)===`rtl`?[`ArrowLeft`,`ArrowRight`]:[`ArrowRight`,`ArrowLeft`],a=e.key===r?(n+1)%t.length:e.key===i?(n-1+t.length)%t.length:e.key===`Home`?0:e.key===`End`?t.length-1:-1;a<0||(e.preventDefault(),this.selectTab(t[a],!0))}onKeyDown(t){if(t.key===`Escape`){t.preventDefault(),t.stopPropagation(),this.close(!0);return}e.n(t,this.modal)}renderBody(){this.bodyEl.replaceChildren();let e=this.target;if(e)switch(this.tab){case`text`:A(this.bodyEl,this.style,e=>this.setStyle(e),this.t,e.textLayout,e.textColor,e.textPlace);break;case`coordinates`:N(this.bodyEl,this.anchors,{toWallTime:this.callbacks.toWallTime,fromWallTime:this.callbacks.fromWallTime,roundPrice:this.callbacks.roundPrice,priceStep:this.callbacks.priceStep,move:(e,t)=>this.setAnchor(e,t)},this.t);break;case`visibility`:r.n(this.bodyEl,this.intervals,e=>this.setIntervals(e),this.t);break;default:v(this.bodyEl,{style:()=>this.style,options:()=>this.options,defs:e.defs,fill:e.fill},{style:e=>this.setStyle(e),options:e=>this.setOptions(e),redraw:(e=[])=>{this.renderBody();for(let t of e){let e=this.bodyEl.querySelector(t);if(e){e.focus();break}}}},this.t)}}change(e){this.target&&this.callbacks.onChange(this.target.id,e)}setStyle(e){this.target&&(this.style={...this.style,...e},this.change({style:e}))}setOptions(e){this.target&&(this.options={...this.options,...structuredClone(e)},this.change({options:e}))}setAnchor(e,t){this.target&&(this.anchors=this.anchors.map((n,r)=>r===e?{...n,...t}:n),this.change({anchors:this.anchors.map(e=>({...e}))}))}setIntervals(e){this.target&&(this.intervals=e,this.change({intervals:e}))}openTemplates(){let e=this.target;if(!e)return;if(this.menu?.isOpen()){this.menu.close();return}let r=this.callbacks.templates,i=r?.list(e.type)??[],a=[...i.map((e,t)=>({id:`${I}${t}`,label:e.name,icon:`layers`,remove:n.r(this.t(`templates.delete`),{name:e.name})})),...i.length>0?[`separator`]:[],...r?[{id:`save`,label:this.t(`settings.saveTemplate`),icon:`save`}]:[],...this.callbacks.onSaveDefault?[{id:`default`,label:this.t(`drawingSettings.saveDefault`),icon:`pin`}]:[],{id:`reset`,label:this.t(`settings.resetToDefaults`),icon:`reset`}],o=e=>i[Number(e.slice(2))];this.menu??=new t.f(this.modal,this.t(`settings.template`));let s=this.templateBtn.getBoundingClientRect(),c=this.modal.getBoundingClientRect();this.menu.open(a,s.left-c.left,s.top-c.top,t=>{t===`save`?r?.save({type:e.type,style:{...this.style},options:structuredClone(this.options)}):t===`default`?this.callbacks.onSaveDefault?.(e.type,structuredClone(this.options)):t===`reset`?this.resetOptions():t.startsWith(I)&&this.applyTemplate(o(t))},this.templateBtn,e=>{let t=o(e);t&&r?.remove(t.name,t.type)})}applyTemplate(e){let t=this.target;!e||!t||(Object.keys(e.style).length>0&&this.setStyle(e.style),e.options&&this.setOptions((0,i.sanitizeDrawingOptions)(t.defs,e.options)),this.renderBody())}resetOptions(){let e=this.target;if(!e)return;let t={};for(let[n,r]of Object.entries(e.defs))t[n]=structuredClone(r.default);this.setOptions(t),this.renderBody()}footerButton(e,t,n,r){let i=document.createElement(`button`);return i.type=`button`,i.className=t,i.dataset.act=e,r&&(i.textContent=r),i.addEventListener(`click`,n),i}};exports.WidgetDrawingSettings=R;
|
|
2
|
+
//# sourceMappingURL=WidgetDrawingSettings-B_mi8DUh.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"WidgetDrawingSettings-B_mi8DUh.cjs","names":[],"sources":["../src/widget/drawingSettingsTabs.ts","../src/widget/WidgetDrawingSettings.ts"],"sourcesContent":["import type { AnchorPoint, DrawingLevel, DrawingOptionDef, DrawingOptionDefs, DrawingOptions, DrawingStyle } from '@tradecanvas/commons';\nimport { ownFillColor } from '@tradecanvas/commons';\nimport { createIcon } from './icons.js';\nimport { fill, type MessageKey, type Translator } from './i18n.js';\nimport type { TextLayout } from './drawingText.js';\nimport { checkRow, colorAlpha, colorInput, numberInput, selectInput, settingsRow, toHex, withAlpha } from './settingsControls.js';\n\nexport type { TextLayout };\n\nconst LINE_WIDTHS = [1, 2, 3, 4];\nconst LINE_STYLES: DrawingStyle['lineStyle'][] = ['solid', 'dashed', 'dotted'];\n/**\n * The sizes offered for a drawing's text. Not 12: drawings saved with the old default\n * all carry it, so the chart reads it as no size of their own and draws its default.\n */\nconst FONT_SIZES = [10, 11, 13, 14, 16, 18, 20, 24, 28, 32];\n/** The size a text tool without a layout of its own draws at (a price label, an arrow's label). */\nconst DEFAULT_FONT_SIZE = 14;\n/** The old default every drawing was saved with: the chart draws its own default for it. */\nconst LEGACY_FONT_SIZE = 12;\n/** Most levels the editor offers to add, like the chart keeps. */\nconst MAX_LEVELS = 48;\n/** A new level sits this far past the last one. */\nconst LEVEL_STEP = 0.5;\n/** The fill's opacity a drawing without one starts from. */\nconst DEFAULT_FILL_ALPHA = 0.12;\n/** Options set in the line's own row, not listed with the tool's others. */\nconst END_KEYS = ['leftEnd', 'rightEnd'] as const;\n\n/** What the Style tab shows. */\nexport interface StyleTabModel {\n /** The style and the options as they are now (a row edits what the last edit left). */\n style: () => DrawingStyle;\n options: () => DrawingOptions;\n defs: DrawingOptionDefs;\n /** Whether the tool fills an area (the Fill row). */\n fill: boolean;\n}\n\n/** What the Style tab changes. */\nexport interface StyleTabActions {\n style(patch: Partial<DrawingStyle>): void;\n options(patch: DrawingOptions): void;\n /** Draw the tab again (a level added or removed), the keyboard on the first of `focus` there is. */\n redraw(focus?: readonly string[]): void;\n}\n\n/** Told the line's new colour: what takes it while it has none of its own (the fill, a level). */\ntype ColorFollower = (color: string) => void;\n\n/** A label from the widget's strings (`drawingOption.<key>`), else the tool's own. */\nfunction optionLabel(t: Translator, key: string, fallback: string): string {\n const messageKey = `drawingOption.${key}` as MessageKey;\n const text = t(messageKey);\n return text === messageKey ? fallback : text;\n}\n\nfunction section(): HTMLDivElement {\n const el = document.createElement('div');\n el.className = 'tcw-settings-section';\n return el;\n}\n\n/** A row of several controls after a label (a `<label>` would only reach the first). */\nfunction controlsRow(label: string, ...controls: HTMLElement[]): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n const text = document.createElement('span');\n text.className = 'tcw-settings-label';\n text.textContent = label;\n const box = document.createElement('span');\n box.className = 'tcw-indi-plot-controls';\n box.append(...controls);\n row.append(text, box);\n return row;\n}\n\nfunction named<T extends HTMLElement>(el: T, label: string): T {\n el.setAttribute('aria-label', label);\n return el;\n}\n\n/**\n * The Style tab: the line (colour, width, dash), its ends, the fill, then\n * the tool's own switches and choices, and its levels last.\n */\nexport function renderStyleTab(body: HTMLElement, model: StyleTabModel, actions: StyleTabActions, t: Translator): void {\n const followers: ColorFollower[] = [];\n const look = section();\n look.appendChild(lineRow(model.style(), actions, followers, t));\n // A tool's ends only when they are the choice of plain or arrow; another option of that name is listed with the rest.\n const ends: string[] = END_KEYS.filter((key) => model.defs[key]?.kind === 'choice');\n if (ends.length > 0) {\n look.appendChild(controlsRow(t('drawingSettings.lineEnds'), ...ends.map((key) => named(selectInput(\n [{ value: 'normal', label: t('drawingSettings.lineEnd.normal') }, { value: 'arrow', label: t('drawingSettings.lineEnd.arrow') }],\n String(model.options()[key] ?? 'normal'),\n (v) => actions.options({ [key]: v }),\n ), optionLabel(t, key, model.defs[key].label)))));\n }\n if (model.fill) look.appendChild(fillRow(model.style(), actions, followers, t));\n body.appendChild(look);\n\n const rest = Object.entries(model.defs).filter(([key, def]) => def.kind !== 'levels' && !ends.includes(key));\n if (rest.length > 0) {\n const own = section();\n for (const [key, def] of rest) own.appendChild(optionRow(key, def as Exclude<DrawingOptionDef, { kind: 'levels' }>, model.options(), actions, t));\n body.appendChild(own);\n }\n for (const [key, def] of Object.entries(model.defs)) {\n if (def.kind === 'levels') body.appendChild(levelsEditor(key, def, model, actions, followers, t));\n }\n}\n\nfunction lineRow(style: DrawingStyle, actions: StyleTabActions, followers: readonly ColorFollower[], t: Translator): HTMLDivElement {\n const color = named(colorInput(style.color, (v) => {\n actions.style({ color: v });\n for (const follow of followers) follow(v);\n }), t('drawingSettings.color'));\n const width = named(selectInput(\n LINE_WIDTHS.map((w) => ({ value: String(w), label: `${w} px` })),\n String(style.lineWidth),\n (v) => actions.style({ lineWidth: Number(v) }),\n ), t('drawingSettings.lineWidth'));\n const dash = named(selectInput(\n LINE_STYLES.map((s) => ({ value: s, label: t(`drawingSettings.lineStyle.${s}`) })),\n style.lineStyle,\n (v) => actions.style({ lineStyle: v as DrawingStyle['lineStyle'] }),\n ), t('drawingSettings.lineStyle'));\n return controlsRow(t('drawingSettings.line'), color, width, dash);\n}\n\nfunction fillRow(style: DrawingStyle, actions: StyleTabActions, followers: ColorFollower[], t: Translator): HTMLDivElement {\n const current = ownFillColor(style) ?? withAlpha(style.color, DEFAULT_FILL_ALPHA);\n let hex = toHex(current);\n let alpha = colorAlpha(current);\n // Without a fill of its own the drawing fills in its line's colour, until one is set here.\n let own = ownFillColor(style) !== undefined;\n const apply = () => {\n own = true;\n actions.style({ fillColor: withAlpha(hex, alpha), fillOpacity: alpha });\n };\n const color = named(colorInput(hex, (v) => {\n hex = v;\n apply();\n }), t('drawingSettings.fill'));\n followers.push((line) => {\n if (own) return;\n hex = toHex(line);\n color.value = hex;\n });\n const opacity = named(numberInput(Math.round(alpha * 100), { min: 0, max: 100, step: 5 }, (v) => {\n alpha = v / 100;\n apply();\n }), t('drawingSettings.opacity'));\n const percent = document.createElement('span');\n percent.className = 'tcw-unit';\n percent.setAttribute('aria-hidden', 'true');\n percent.textContent = '%';\n return controlsRow(t('drawingSettings.fill'), color, opacity, percent);\n}\n\nfunction optionRow(\n key: string,\n def: Exclude<DrawingOptionDef, { kind: 'levels' }>,\n options: DrawingOptions,\n actions: StyleTabActions,\n t: Translator,\n): HTMLElement {\n const label = optionLabel(t, key, def.label);\n const value = options[key];\n switch (def.kind) {\n case 'boolean':\n return checkRow(label, Boolean(value), (v) => actions.options({ [key]: v }));\n case 'number':\n return settingsRow(label, numberInput(Number(value), { min: def.min, max: def.max, step: def.step }, (v) => actions.options({ [key]: v })));\n case 'choice':\n return settingsRow(label, selectInput(\n def.choices.map((c) => ({ value: c.value, label: optionLabel(t, `${key}.${c.value}`, c.label) })),\n String(value),\n (v) => actions.options({ [key]: v }),\n ));\n case 'text': {\n const input = document.createElement('input');\n input.type = 'text';\n input.className = 'tcw-indi-input';\n input.value = String(value ?? '');\n input.addEventListener('change', () => actions.options({ [key]: input.value }));\n return settingsRow(label, input);\n }\n }\n}\n\n/** One row per level: shown or not, its ratio, its colour, remove; and a button to add one. */\nfunction levelsEditor(\n key: string,\n def: Extract<DrawingOptionDef, { kind: 'levels' }>,\n model: StyleTabModel,\n actions: StyleTabActions,\n followers: ColorFollower[],\n t: Translator,\n): HTMLElement {\n const wrap = document.createElement('div');\n wrap.className = 'tcw-settings-section tcw-levels-editor';\n const head = document.createElement('div');\n head.className = 'tcw-settings-section-title';\n head.textContent = optionLabel(t, key, def.label);\n wrap.appendChild(head);\n\n const levels = (): DrawingLevel[] => {\n const value = model.options()[key];\n return Array.isArray(value) ? (value as DrawingLevel[]) : [];\n };\n const commit = (next: DrawingLevel[]) => actions.options({ [key]: next });\n const grid = document.createElement('div');\n grid.className = 'tcw-levels-grid';\n levels().forEach((level, index) => {\n const row = document.createElement('div');\n row.className = 'tcw-level-row';\n const nth = ` ${index + 1}`; // rows share labels; the number tells them apart\n const visible = document.createElement('input');\n visible.type = 'checkbox';\n visible.checked = level.visible;\n visible.setAttribute('aria-label', t('drawingSettings.levelVisible') + nth);\n visible.addEventListener('change', () => commit(levels().map((l, i) => (i === index ? { ...l, visible: visible.checked } : l))));\n const value = named(numberInput(level.value, { step: 0.001 }, (v) => commit(levels().map((l, i) => (i === index ? { ...l, value: v } : l)))), t('drawingSettings.levelValue') + nth);\n const color = named(colorInput(level.color ?? model.style().color, (v) => commit(levels().map((l, i) => (i === index ? { ...l, color: v } : l)))), t('drawingSettings.levelColor') + nth);\n // A level without a colour of its own is drawn in the line's.\n followers.push((line) => {\n if (levels()[index]?.color === undefined) color.value = toHex(line);\n });\n const remove = document.createElement('button');\n remove.type = 'button';\n remove.className = 'tcw-level-remove';\n remove.setAttribute('aria-label', t('drawingSettings.removeLevel') + nth);\n remove.innerHTML = createIcon('x', 12);\n remove.addEventListener('click', () => {\n commit(levels().filter((_, i) => i !== index));\n // The keyboard stays where it was: on the next level's remove button, else the last one's, else Add.\n actions.redraw([\n `.tcw-level-row:nth-child(${index + 1}) .tcw-level-remove`,\n '.tcw-level-row:last-child .tcw-level-remove',\n '.tcw-level-add',\n ]);\n });\n row.append(visible, value, color, remove);\n grid.appendChild(row);\n });\n wrap.appendChild(grid);\n\n const add = document.createElement('button');\n add.type = 'button';\n add.className = 'tcw-reset-link tcw-level-add';\n add.textContent = t('drawingSettings.addLevel');\n add.disabled = levels().length >= MAX_LEVELS;\n add.addEventListener('click', () => {\n const last = levels().at(-1)?.value ?? 0;\n commit([...levels(), { value: Math.round((last + LEVEL_STEP) * 1000) / 1000, visible: true }]);\n actions.redraw(['.tcw-level-row:last-child input[type=\"number\"]']);\n });\n wrap.appendChild(add);\n return wrap;\n}\n\n/** The width a text wraps at when wrapping is turned on and it has none of its own. */\nconst DEFAULT_WRAP = 240;\nconst MIN_WRAP = 40;\nconst MAX_WRAP = 4000;\nconst WRAP_STEP = 10;\nconst ALIGNS = ['left', 'center', 'right'] as const;\nconst VALIGNS = ['top', 'middle', 'bottom'] as const;\n\n/**\n * A box ticked or not inside a row of controls, its name written after it\n * unless the row already says it (`said`): a screen reader hears it either way.\n */\nfunction inlineCheck(label: string, value: boolean, onChange: (value: boolean) => void, said = false): HTMLLabelElement {\n const wrap = document.createElement('label');\n wrap.className = 'tcw-inline-check';\n const box = document.createElement('input');\n box.type = 'checkbox';\n box.checked = value;\n box.setAttribute('aria-label', label);\n box.addEventListener('change', () => onChange(box.checked));\n wrap.append(box);\n if (!said) {\n const text = document.createElement('span');\n text.textContent = label;\n wrap.append(text);\n }\n return wrap;\n}\n\n/**\n * The Text tab: what the drawing writes, its size, bold and italics, and its\n * colour; for a text box (`layout`), its alignment, background, border and\n * the width it wraps at; for a line's or a box's text (`place`), where it sits.\n */\nexport function renderTextTab(\n body: HTMLElement,\n style: DrawingStyle,\n onStyle: (patch: Partial<DrawingStyle>) => void,\n t: Translator,\n layout?: TextLayout,\n textColor?: string,\n place = false,\n): void {\n const block = section();\n const text = document.createElement('textarea');\n text.className = 'tcw-indi-input tcw-drawing-text';\n text.rows = 3;\n text.value = style.text ?? '';\n text.addEventListener('input', () => onStyle({ text: text.value }));\n const textRow = settingsRow(t('drawingSettings.text'), text);\n textRow.classList.add('tcw-text-row');\n block.appendChild(textRow);\n const size = named(selectInput(\n FONT_SIZES.map((s) => ({ value: String(s), label: `${s} px` })),\n String((style.fontSize !== LEGACY_FONT_SIZE ? style.fontSize : undefined) ?? layout?.fontSize ?? DEFAULT_FONT_SIZE),\n (v) => onStyle({ fontSize: Number(v) }),\n ), t('drawingSettings.fontSize'));\n block.appendChild(controlsRow(\n t('drawingSettings.fontSize'),\n size,\n inlineCheck(t('drawingSettings.bold'), style.bold === true, (on) => onStyle({ bold: on })),\n inlineCheck(t('drawingSettings.italic'), style.italic === true, (on) => onStyle({ italic: on })),\n ));\n block.appendChild(controlsRow(t('drawingSettings.textColor'), named(\n colorInput(style.textColor ?? textColor ?? style.color, (v) => onStyle({ textColor: v })),\n t('drawingSettings.textColor'),\n )));\n body.appendChild(block);\n if (layout) body.appendChild(textBoxSection(style, onStyle, t, layout));\n if (place) body.appendChild(textPlaceSection(style, onStyle, t));\n}\n\n/** Where a line's or a box's text sits: at an end or the middle, and above, on or under (at the top, middle or bottom). */\nfunction textPlaceSection(style: DrawingStyle, onStyle: (patch: Partial<DrawingStyle>) => void, t: Translator): HTMLElement {\n const place = section();\n place.appendChild(controlsRow(t('drawingSettings.align'), named(selectInput(\n ALIGNS.map((a) => ({ value: a, label: t(`drawingSettings.align.${a}`) })),\n style.textAlign ?? 'center',\n (v) => onStyle({ textAlign: v as DrawingStyle['textAlign'] }),\n ), t('drawingSettings.align'))));\n place.appendChild(controlsRow(t('drawingSettings.vAlign'), named(selectInput(\n VALIGNS.map((a) => ({ value: a, label: t(`drawingSettings.vAlign.${a}`) })),\n style.textVAlign ?? 'top',\n (v) => onStyle({ textVAlign: v as DrawingStyle['textVAlign'] }),\n ), t('drawingSettings.vAlign'))));\n return place;\n}\n\n/** A text box's rows: alignment, background, border, and the width it wraps at. */\nfunction textBoxSection(style: DrawingStyle, onStyle: (patch: Partial<DrawingStyle>) => void, t: Translator, layout: TextLayout): HTMLElement {\n const box = section();\n box.appendChild(controlsRow(t('drawingSettings.align'), named(selectInput(\n ALIGNS.map((a) => ({ value: a, label: t(`drawingSettings.align.${a}`) })),\n style.textAlign ?? 'left',\n (v) => onStyle({ textAlign: v as DrawingStyle['textAlign'] }),\n ), t('drawingSettings.align'))));\n\n const background = ownFillColor(style) ?? withAlpha(style.color, DEFAULT_FILL_ALPHA);\n box.appendChild(controlsRow(\n t('drawingSettings.background'),\n inlineCheck(t('drawingSettings.background'), style.textBackground ?? layout.box, (on) => onStyle({ textBackground: on }), true),\n named(colorInput(background, (v) => onStyle({ fillColor: withAlpha(v, colorAlpha(background)) })), t('drawingSettings.backgroundColor')),\n ));\n box.appendChild(controlsRow(\n t('drawingSettings.border'),\n inlineCheck(t('drawingSettings.border'), style.textBorder ?? layout.border, (on) => onStyle({ textBorder: on }), true),\n named(colorInput(style.borderColor ?? style.color, (v) => onStyle({ borderColor: v })), t('drawingSettings.borderColor')),\n ));\n\n // The width shows what wrapping on would use: the text's own, else the tool's, else a default.\n const own = style.textWrap ?? layout.wrap;\n let width = own > 0 ? own : layout.wrap > 0 ? layout.wrap : DEFAULT_WRAP;\n let wrapping = own > 0;\n const widthInput = named(numberInput(width, { min: MIN_WRAP, max: MAX_WRAP, step: WRAP_STEP }, (v) => {\n width = v;\n if (wrapping) onStyle({ textWrap: v });\n }), t('drawingSettings.wrapWidth'));\n // A width means something only while the text wraps.\n widthInput.disabled = !wrapping;\n box.appendChild(controlsRow(\n t('drawingSettings.wrap'),\n inlineCheck(t('drawingSettings.wrap'), wrapping, (on) => {\n wrapping = on;\n widthInput.disabled = !on;\n onStyle({ textWrap: on ? width : 0 });\n }, true),\n widthInput,\n ));\n return box;\n}\n\n/** What the Coordinates tab reads and changes. */\nexport interface CoordinatesTabActions {\n /** An anchor's time as the date and time fields show it (the chart's zone), and back. */\n toWallTime(time: number): { date: string; time: string };\n fromWallTime(date: string, time: string): number | null;\n /** A price on the market's grid. */\n roundPrice?(price: number): number;\n /** The market's smallest price step, for the price fields' arrows. */\n priceStep?(): number;\n move(index: number, patch: Partial<AnchorPoint>): void;\n}\n\n/** The Coordinates tab: a row per point, its price, date and time. */\nexport function renderCoordinatesTab(body: HTMLElement, anchors: readonly AnchorPoint[], actions: CoordinatesTabActions, t: Translator): void {\n const block = section();\n anchors.forEach((anchor, index) => {\n const point = fill(t('drawingSettings.point'), { n: index + 1 });\n const wall = actions.toWallTime(anchor.time);\n const date = document.createElement('input');\n date.type = 'date';\n date.className = 'tcw-indi-input';\n date.value = wall.date;\n const time = document.createElement('input');\n time.type = 'time';\n time.className = 'tcw-indi-input';\n time.value = wall.time;\n const onTime = () => {\n const at = actions.fromWallTime(date.value, time.value);\n if (at !== null) actions.move(index, { time: at });\n };\n date.addEventListener('change', onTime);\n time.addEventListener('change', onTime);\n const price = priceInput(anchor.price, actions, (p) => actions.move(index, { price: p }));\n const row = controlsRow(point,\n named(price, `${point}: ${t('drawingSettings.price')}`),\n named(date, `${point}: ${t('drawingSettings.date')}`),\n named(time, `${point}: ${t('drawingSettings.time')}`));\n row.classList.add('tcw-draw-point');\n block.appendChild(row);\n });\n body.appendChild(block);\n}\n\n/**\n * A price field on the market's grid. It shows the price rounded, and leaves\n * the point where it is until the field is edited.\n */\nfunction priceInput(price: number, actions: CoordinatesTabActions, onChange: (price: number) => void): HTMLInputElement {\n const round = actions.roundPrice ?? ((p: number) => p);\n const step = actions.priceStep?.();\n const input = numberInput(round(price), { step: step !== undefined && step > 0 ? step : 'any' }, (typed) => {\n const onGrid = round(typed);\n input.value = String(onGrid);\n onChange(onGrid);\n });\n return input;\n}\n","import type {\n AnchorPoint,\n DrawingOptionDefs,\n DrawingOptions,\n DrawingStyle,\n DrawingToolType,\n IndicatorIntervals,\n} from '@tradecanvas/commons';\nimport { sanitizeDrawingOptions } from '@tradecanvas/commons';\nimport { createIcon } from './icons.js';\nimport { keepTabInside } from './focusTrap.js';\nimport { EN_TRANSLATOR, fill, type Translator } from './i18n.js';\nimport { WidgetContextMenu, type ContextMenuEntry } from './WidgetContextMenu.js';\nimport type { DrawingStyleTemplate } from './DrawingTemplateStore.js';\nimport { renderCoordinatesTab, renderStyleTab, renderTextTab, type TextLayout } from './drawingSettingsTabs.js';\nimport { renderVisibilityTab } from './indicatorSettingsTabs.js';\n\n/** The drawing a settings dialog edits. */\nexport interface DrawingSettingsTarget {\n id: string;\n type: DrawingToolType;\n /** The tool's name in the widget's language. */\n name: string;\n style: DrawingStyle;\n /** Every option, defaults filled in. */\n options: DrawingOptions;\n defs: DrawingOptionDefs;\n anchors: AnchorPoint[];\n /** Whether the tool fills an area and draws text (the Fill row, the Text tab). */\n fill: boolean;\n text: boolean;\n /** How the tool lays its text out in a box (the Text tab's alignment, background, border and wrap rows); unset: font rows only. */\n textLayout?: TextLayout;\n /** The colour the tool writes in without one of its own, when it isn't the line's. */\n textColor?: string;\n /** It writes its text along a line or in a box: the Text tab offers where (`textAlign`, `textVAlign`). */\n textPlace?: boolean;\n /** False for a drawing kept to the screen: its points are places on the plot, not times and prices to edit. */\n coordinates?: boolean;\n /** The intervals it shows on; unset or null: all of them. */\n intervals?: IndicatorIntervals | null;\n}\n\nexport interface DrawingSettingsPatch {\n anchors?: AnchorPoint[];\n style?: Partial<DrawingStyle>;\n options?: DrawingOptions;\n /** Null: every interval. */\n intervals?: IndicatorIntervals | null;\n}\n\n/** A drawing's look as a template keeps it: its style, and its tool's options. */\nexport interface DrawingTemplateLook {\n type: DrawingToolType;\n style: Partial<DrawingStyle>;\n options: DrawingOptions;\n}\n\nexport interface DrawingSettingsCallbacks {\n /** The dialog opened on a drawing: edits until `onEnd` are one undo step. */\n onBegin: (id: string) => void;\n /** An edit, shown on the chart at once. */\n onChange: (id: string, patch: DrawingSettingsPatch) => void;\n /** OK keeps the edits; Cancel, Escape or the close button put the drawing back. */\n onEnd: (id: string, cancel: boolean) => void;\n /** An anchor's time as the date and time fields show it (the chart's zone), and back. */\n toWallTime: (time: number) => { date: string; time: string };\n fromWallTime: (date: string, time: string) => number | null;\n /** A price on the market's grid; the Coordinates tab shows and takes prices on it. */\n roundPrice?: (price: number) => number;\n /** The market's smallest price step, for the price fields' arrows. */\n priceStep?: () => number;\n /** Make these the options new drawings of the tool start with. */\n onSaveDefault?: (type: DrawingToolType, options: DrawingOptions) => void;\n /** Saved templates: listed and deleted in the Template menu, and \"Save as template…\" (which asks for a name). */\n templates?: {\n list: (type: DrawingToolType) => DrawingStyleTemplate[];\n save: (look: DrawingTemplateLook) => void;\n remove: (name: string, type?: DrawingToolType) => void;\n };\n}\n\ntype Tab = 'style' | 'text' | 'coordinates' | 'visibility';\n\n/** Most points the Coordinates tab lists. */\nconst MAX_COORDINATE_ROWS = 12;\n/** A saved template's entry in the Template menu, by its place in the list. */\nconst TEMPLATE_ID = 't:';\n\nlet nextDialogId = 1;\n\n/**\n * A drawing's settings, in tabs: Style (the line, its ends, the fill, the\n * tool's own switches and levels), Text, Coordinates (its points by price,\n * date and time) and Visibility (the intervals it shows on). Edits show on\n * the chart at once; OK keeps them as one undo step, Cancel puts it back.\n * The Template menu applies, saves and deletes templates, keeps the options\n * as the tool's default, or resets them.\n */\nexport class WidgetDrawingSettings {\n private backdrop: HTMLDivElement;\n private modal: HTMLDivElement;\n private titleEl: HTMLHeadingElement;\n private tabsEl: HTMLDivElement;\n private bodyEl: HTMLDivElement;\n private templateBtn: HTMLButtonElement;\n private menu: WidgetContextMenu | null = null;\n private tabButtons: HTMLButtonElement[] = [];\n private target: DrawingSettingsTarget | null = null;\n private style!: DrawingStyle;\n private options: DrawingOptions = {};\n private anchors: AnchorPoint[] = [];\n private intervals: IndicatorIntervals | null = null;\n private tab: Tab = 'style';\n private returnFocus: HTMLElement | null = null;\n private readonly uid = nextDialogId++;\n\n constructor(\n host: HTMLElement,\n private readonly callbacks: DrawingSettingsCallbacks,\n private readonly t: Translator = EN_TRANSLATOR,\n ) {\n this.backdrop = document.createElement('div');\n this.backdrop.className = 'tcw-modal-backdrop';\n this.backdrop.hidden = true;\n // A press that starts in the dialog (selecting text, say) and ends on the\n // backdrop doesn't close it.\n let pressedBackdrop = false;\n this.backdrop.addEventListener('pointerdown', (e) => {\n pressedBackdrop = e.target === this.backdrop;\n });\n this.backdrop.addEventListener('click', (e) => {\n if (e.target === this.backdrop && pressedBackdrop) this.close(true);\n pressedBackdrop = false;\n });\n\n this.modal = document.createElement('div');\n this.modal.className = 'tcw-modal tcw-modal-narrow tcw-drawing-settings';\n this.modal.setAttribute('role', 'dialog');\n this.modal.setAttribute('aria-modal', 'true');\n this.modal.setAttribute('aria-labelledby', `tcw-draw-title-${this.uid}`);\n this.modal.tabIndex = -1;\n this.modal.addEventListener('keydown', (e) => this.onKeyDown(e));\n\n const header = document.createElement('div');\n header.className = 'tcw-modal-header';\n this.titleEl = document.createElement('h3');\n this.titleEl.id = `tcw-draw-title-${this.uid}`;\n const closeBtn = document.createElement('button');\n closeBtn.type = 'button';\n closeBtn.className = 'tcw-modal-close';\n closeBtn.setAttribute('aria-label', this.t('common.close'));\n closeBtn.innerHTML = createIcon('x', 16);\n closeBtn.addEventListener('click', () => this.close(true));\n header.append(this.titleEl, closeBtn);\n\n this.tabsEl = document.createElement('div');\n this.tabsEl.className = 'tcw-modal-tabs';\n this.tabsEl.setAttribute('role', 'tablist');\n this.tabsEl.addEventListener('keydown', (e) => this.onTabKey(e));\n\n this.bodyEl = document.createElement('div');\n this.bodyEl.className = 'tcw-modal-body';\n this.bodyEl.id = `tcw-draw-panel-${this.uid}`;\n this.bodyEl.setAttribute('role', 'tabpanel');\n\n this.templateBtn = this.footerButton('template', 'tcw-footer-menu', () => this.openTemplates());\n this.modal.append(header, this.tabsEl, this.bodyEl, this.buildFooter());\n this.backdrop.appendChild(this.modal);\n host.appendChild(this.backdrop);\n }\n\n /** Template on the left; Cancel and OK on the right. */\n private buildFooter(): HTMLDivElement {\n this.templateBtn.setAttribute('aria-haspopup', 'menu');\n this.templateBtn.setAttribute('aria-expanded', 'false');\n this.templateBtn.innerHTML = `<span></span>${createIcon('chevronDown', 12)}`;\n this.templateBtn.querySelector('span')!.textContent = this.t('settings.template');\n const end = document.createElement('div');\n end.className = 'tcw-footer-end';\n end.append(\n this.footerButton('cancel', 'tcw-footer-cancel', () => this.close(true), this.t('common.cancel')),\n this.footerButton('ok', 'tcw-done-btn', () => this.close(false), this.t('drawingSettings.ok')),\n );\n const footer = document.createElement('div');\n footer.className = 'tcw-modal-footer';\n footer.append(this.templateBtn, end);\n return footer;\n }\n\n /**\n * Open on `target`. With `tab: 'text'` it opens on the Text tab (a tool\n * that writes), the text selected so typing replaces it.\n */\n open(target: DrawingSettingsTarget, how: { tab?: 'text' } = {}): void {\n if (this.target) this.close(false);\n this.returnFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n this.target = target;\n this.style = { ...target.style };\n this.options = structuredClone(target.options);\n this.anchors = target.anchors.map((a) => ({ ...a }));\n this.intervals = target.intervals ?? null;\n this.titleEl.textContent = target.name;\n this.tab = how.tab === 'text' && target.text ? 'text' : 'style';\n this.callbacks.onBegin(target.id);\n try {\n this.renderTabs();\n this.renderBody();\n } catch (err) {\n // A drawing the dialog can't show: end the edit it began.\n this.target = null;\n this.callbacks.onEnd(target.id, true);\n throw err;\n }\n this.backdrop.hidden = false;\n const text = this.tab === 'text' ? this.bodyEl.querySelector<HTMLTextAreaElement>('textarea') : null;\n if (text) {\n text.focus();\n text.select();\n } else {\n (this.tabButtons[0] ?? this.modal).focus();\n }\n }\n\n /** Close the dialog, keeping the edits or (with `cancel`) putting the drawing back. */\n close(cancel: boolean): void {\n const target = this.target;\n if (!target) return;\n // A value typed but not yet committed still applies on OK.\n const active = document.activeElement;\n if (!cancel && (active instanceof HTMLInputElement || active instanceof HTMLTextAreaElement) && this.modal.contains(active)) {\n active.dispatchEvent(new Event('change'));\n }\n this.target = null;\n this.menu?.close();\n this.backdrop.hidden = true;\n this.callbacks.onEnd(target.id, cancel);\n if (this.returnFocus?.isConnected) this.returnFocus.focus();\n this.returnFocus = null;\n }\n\n isOpen(): boolean {\n return this.target !== null;\n }\n\n /** The drawing being edited, if any. */\n editing(): string | null {\n return this.target?.id ?? null;\n }\n\n destroy(): void {\n this.close(true);\n this.menu?.destroy();\n this.backdrop.remove();\n }\n\n // --- Tabs ---\n\n private tabs(): Tab[] {\n const target = this.target;\n if (!target) return [];\n return [\n 'style',\n ...(target.text ? ['text' as const] : []),\n // A freehand stroke has hundreds of points: no table of them.\n ...(target.coordinates !== false && target.anchors.length <= MAX_COORDINATE_ROWS ? ['coordinates' as const] : []),\n 'visibility',\n ];\n }\n\n private renderTabs(): void {\n this.tabButtons = this.tabs().map((tab) => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'tcw-modal-tab';\n btn.id = `tcw-draw-tab-${this.uid}-${tab}`;\n btn.setAttribute('role', 'tab');\n btn.setAttribute('aria-controls', this.bodyEl.id);\n btn.dataset.tab = tab;\n btn.textContent = this.t(`drawingSettings.tab.${tab}`);\n btn.addEventListener('click', () => this.selectTab(tab));\n return btn;\n });\n this.tabsEl.replaceChildren(...this.tabButtons);\n this.markTabs();\n }\n\n private markTabs(): void {\n for (const btn of this.tabButtons) {\n const selected = btn.dataset.tab === this.tab;\n btn.classList.toggle('tcw-active', selected);\n btn.setAttribute('aria-selected', String(selected));\n btn.tabIndex = selected ? 0 : -1;\n if (selected) this.bodyEl.setAttribute('aria-labelledby', btn.id);\n }\n }\n\n private selectTab(tab: Tab, focus = false): void {\n this.tab = tab;\n this.markTabs();\n this.renderBody();\n if (focus) this.tabButtons.find((b) => b.dataset.tab === tab)?.focus();\n }\n\n /** Arrow keys (the other way right to left), Home and End move between tabs. */\n private onTabKey(e: KeyboardEvent): void {\n const tabs = this.tabButtons.map((b) => b.dataset.tab as Tab);\n const at = tabs.indexOf(this.tab);\n const rtl = this.modal.closest('[dir]')?.getAttribute('dir') === 'rtl';\n const [forward, back] = rtl ? ['ArrowLeft', 'ArrowRight'] : ['ArrowRight', 'ArrowLeft'];\n const next = e.key === forward ? (at + 1) % tabs.length\n : e.key === back ? (at - 1 + tabs.length) % tabs.length\n : e.key === 'Home' ? 0\n : e.key === 'End' ? tabs.length - 1\n : -1;\n if (next < 0) return;\n e.preventDefault();\n this.selectTab(tabs[next], true);\n }\n\n /** Escape cancels; Tab stays inside the dialog. */\n private onKeyDown(e: KeyboardEvent): void {\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n this.close(true);\n return;\n }\n keepTabInside(e, this.modal);\n }\n\n private renderBody(): void {\n this.bodyEl.replaceChildren();\n const target = this.target;\n if (!target) return;\n switch (this.tab) {\n case 'text':\n renderTextTab(this.bodyEl, this.style, (patch) => this.setStyle(patch), this.t, target.textLayout, target.textColor, target.textPlace);\n break;\n case 'coordinates':\n renderCoordinatesTab(this.bodyEl, this.anchors, {\n toWallTime: this.callbacks.toWallTime,\n fromWallTime: this.callbacks.fromWallTime,\n roundPrice: this.callbacks.roundPrice,\n priceStep: this.callbacks.priceStep,\n move: (index, patch) => this.setAnchor(index, patch),\n }, this.t);\n break;\n case 'visibility':\n renderVisibilityTab(this.bodyEl, this.intervals, (next) => this.setIntervals(next), this.t);\n break;\n default:\n renderStyleTab(this.bodyEl, { style: () => this.style, options: () => this.options, defs: target.defs, fill: target.fill }, {\n style: (patch) => this.setStyle(patch),\n options: (patch) => this.setOptions(patch),\n redraw: (focus = []) => {\n this.renderBody();\n for (const selector of focus) {\n const el = this.bodyEl.querySelector<HTMLElement>(selector);\n if (el) {\n el.focus();\n break;\n }\n }\n },\n }, this.t);\n }\n }\n\n // --- Edits ---\n\n private change(patch: DrawingSettingsPatch): void {\n if (this.target) this.callbacks.onChange(this.target.id, patch);\n }\n\n private setStyle(style: Partial<DrawingStyle>): void {\n if (!this.target) return;\n this.style = { ...this.style, ...style };\n this.change({ style });\n }\n\n private setOptions(options: DrawingOptions): void {\n if (!this.target) return;\n this.options = { ...this.options, ...structuredClone(options) };\n this.change({ options });\n }\n\n private setAnchor(index: number, patch: Partial<AnchorPoint>): void {\n if (!this.target) return;\n this.anchors = this.anchors.map((a, i) => (i === index ? { ...a, ...patch } : a));\n this.change({ anchors: this.anchors.map((a) => ({ ...a })) });\n }\n\n private setIntervals(intervals: IndicatorIntervals | null): void {\n if (!this.target) return;\n this.intervals = intervals;\n this.change({ intervals });\n }\n\n // --- Template ---\n\n /** The Template menu: the saved templates (each removable), Save as template, Save as default, Reset to defaults. */\n private openTemplates(): void {\n const target = this.target;\n if (!target) return;\n if (this.menu?.isOpen()) {\n this.menu.close();\n return;\n }\n const store = this.callbacks.templates;\n const saved = store?.list(target.type) ?? [];\n const entries: ContextMenuEntry[] = [\n ...saved.map((template, i): ContextMenuEntry => ({\n id: `${TEMPLATE_ID}${i}`, label: template.name, icon: 'layers', remove: fill(this.t('templates.delete'), { name: template.name }),\n })),\n ...(saved.length > 0 ? ['separator' as const] : []),\n ...(store ? [{ id: 'save', label: this.t('settings.saveTemplate'), icon: 'save' }] : []),\n ...(this.callbacks.onSaveDefault ? [{ id: 'default', label: this.t('drawingSettings.saveDefault'), icon: 'pin' }] : []),\n { id: 'reset', label: this.t('settings.resetToDefaults'), icon: 'reset' },\n ];\n const savedAt = (id: string) => saved[Number(id.slice(TEMPLATE_ID.length))];\n this.menu ??= new WidgetContextMenu(this.modal, this.t('settings.template'));\n const at = this.templateBtn.getBoundingClientRect();\n const box = this.modal.getBoundingClientRect();\n // From the button's top: in the footer there is no room below, so it opens above the button.\n this.menu.open(entries, at.left - box.left, at.top - box.top, (id) => {\n if (id === 'save') store?.save({ type: target.type, style: { ...this.style }, options: structuredClone(this.options) });\n else if (id === 'default') this.callbacks.onSaveDefault?.(target.type, structuredClone(this.options));\n else if (id === 'reset') this.resetOptions();\n else if (id.startsWith(TEMPLATE_ID)) this.applyTemplate(savedAt(id));\n }, this.templateBtn, (id) => {\n const template = savedAt(id);\n if (template) store?.remove(template.name, template.type);\n });\n }\n\n private applyTemplate(template: DrawingStyleTemplate | undefined): void {\n const target = this.target;\n if (!template || !target) return;\n if (Object.keys(template.style).length > 0) this.setStyle(template.style);\n // Templates come from storage: only options the tool takes apply.\n if (template.options) this.setOptions(sanitizeDrawingOptions(target.defs, template.options));\n this.renderBody();\n }\n\n /** The tool's options back to its defaults. */\n private resetOptions(): void {\n const target = this.target;\n if (!target) return;\n const defaults: DrawingOptions = {};\n for (const [key, def] of Object.entries(target.defs)) defaults[key] = structuredClone(def.default) as DrawingOptions[string];\n this.setOptions(defaults);\n this.renderBody();\n }\n\n private footerButton(act: string, className: string, onClick: () => void, text?: string): HTMLButtonElement {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = className;\n btn.dataset.act = act;\n if (text) btn.textContent = text;\n btn.addEventListener('click', onClick);\n return btn;\n }\n}\n"],"mappings":"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"}
|
|
@@ -2,21 +2,20 @@ import { i as e, n as t } from "./focusTrap-Br9Zfje0.js";
|
|
|
2
2
|
import { d as n, f as r, i, l as a, n as o, o as s, r as c, s as l, t as u } from "./settingsControls-DIjzCFHI.js";
|
|
3
3
|
import { r as d, t as f } from "./i18n-C5v6Tzp1.js";
|
|
4
4
|
import { n as p } from "./indicatorSettingsTabs-XcgMdbLp.js";
|
|
5
|
-
import {
|
|
5
|
+
import { ownFillColor as m, sanitizeDrawingOptions as h } from "@tradecanvas/commons";
|
|
6
6
|
//#region src/widget/drawingSettingsTabs.ts
|
|
7
|
-
var
|
|
7
|
+
var g = [
|
|
8
8
|
1,
|
|
9
9
|
2,
|
|
10
10
|
3,
|
|
11
11
|
4
|
|
12
|
-
],
|
|
12
|
+
], _ = [
|
|
13
13
|
"solid",
|
|
14
14
|
"dashed",
|
|
15
15
|
"dotted"
|
|
16
|
-
],
|
|
16
|
+
], v = [
|
|
17
17
|
10,
|
|
18
18
|
11,
|
|
19
|
-
12,
|
|
20
19
|
13,
|
|
21
20
|
14,
|
|
22
21
|
16,
|
|
@@ -25,16 +24,16 @@ var h = [
|
|
|
25
24
|
24,
|
|
26
25
|
28,
|
|
27
26
|
32
|
|
28
|
-
],
|
|
29
|
-
function
|
|
27
|
+
], y = 14, b = 12, x = 48, S = .5, C = .12, w = ["leftEnd", "rightEnd"];
|
|
28
|
+
function T(e, t, n) {
|
|
30
29
|
let r = `drawingOption.${t}`, i = e(r);
|
|
31
30
|
return i === r ? n : i;
|
|
32
31
|
}
|
|
33
|
-
function
|
|
32
|
+
function E() {
|
|
34
33
|
let e = document.createElement("div");
|
|
35
34
|
return e.className = "tcw-settings-section", e;
|
|
36
35
|
}
|
|
37
|
-
function
|
|
36
|
+
function D(e, ...t) {
|
|
38
37
|
let n = document.createElement("div");
|
|
39
38
|
n.className = "tcw-settings-row";
|
|
40
39
|
let r = document.createElement("span");
|
|
@@ -42,64 +41,64 @@ function T(e, ...t) {
|
|
|
42
41
|
let i = document.createElement("span");
|
|
43
42
|
return i.className = "tcw-indi-plot-controls", i.append(...t), n.append(r, i), n;
|
|
44
43
|
}
|
|
45
|
-
function
|
|
44
|
+
function O(e, t) {
|
|
46
45
|
return e.setAttribute("aria-label", t), e;
|
|
47
46
|
}
|
|
48
|
-
function
|
|
49
|
-
let i = [], a =
|
|
50
|
-
a.appendChild(
|
|
51
|
-
let o =
|
|
52
|
-
o.length > 0 && a.appendChild(
|
|
47
|
+
function k(e, t, n, r) {
|
|
48
|
+
let i = [], a = E();
|
|
49
|
+
a.appendChild(A(t.style(), n, i, r));
|
|
50
|
+
let o = w.filter((e) => t.defs[e]?.kind === "choice");
|
|
51
|
+
o.length > 0 && a.appendChild(D(r("drawingSettings.lineEnds"), ...o.map((e) => O(s([{
|
|
53
52
|
value: "normal",
|
|
54
53
|
label: r("drawingSettings.lineEnd.normal")
|
|
55
54
|
}, {
|
|
56
55
|
value: "arrow",
|
|
57
56
|
label: r("drawingSettings.lineEnd.arrow")
|
|
58
|
-
}], String(t.options()[e] ?? "normal"), (t) => n.options({ [e]: t })),
|
|
57
|
+
}], String(t.options()[e] ?? "normal"), (t) => n.options({ [e]: t })), T(r, e, t.defs[e].label))))), t.fill && a.appendChild(j(t.style(), n, i, r)), e.appendChild(a);
|
|
59
58
|
let c = Object.entries(t.defs).filter(([e, t]) => t.kind !== "levels" && !o.includes(e));
|
|
60
59
|
if (c.length > 0) {
|
|
61
|
-
let i =
|
|
62
|
-
for (let [e, a] of c) i.appendChild(
|
|
60
|
+
let i = E();
|
|
61
|
+
for (let [e, a] of c) i.appendChild(M(e, a, t.options(), n, r));
|
|
63
62
|
e.appendChild(i);
|
|
64
63
|
}
|
|
65
|
-
for (let [a, o] of Object.entries(t.defs)) o.kind === "levels" && e.appendChild(
|
|
64
|
+
for (let [a, o] of Object.entries(t.defs)) o.kind === "levels" && e.appendChild(N(a, o, t, n, i, r));
|
|
66
65
|
}
|
|
67
|
-
function
|
|
68
|
-
let i =
|
|
66
|
+
function A(e, t, n, r) {
|
|
67
|
+
let i = O(c(e.color, (e) => {
|
|
69
68
|
t.style({ color: e });
|
|
70
69
|
for (let t of n) t(e);
|
|
71
|
-
}), r("drawingSettings.color")), a =
|
|
70
|
+
}), r("drawingSettings.color")), a = O(s(g.map((e) => ({
|
|
72
71
|
value: String(e),
|
|
73
72
|
label: `${e} px`
|
|
74
|
-
})), String(e.lineWidth), (e) => t.style({ lineWidth: Number(e) })), r("drawingSettings.lineWidth")), o =
|
|
73
|
+
})), String(e.lineWidth), (e) => t.style({ lineWidth: Number(e) })), r("drawingSettings.lineWidth")), o = O(s(_.map((e) => ({
|
|
75
74
|
value: e,
|
|
76
75
|
label: r(`drawingSettings.lineStyle.${e}`)
|
|
77
76
|
})), e.lineStyle, (e) => t.style({ lineStyle: e })), r("drawingSettings.lineStyle"));
|
|
78
|
-
return
|
|
77
|
+
return D(r("drawingSettings.line"), i, a, o);
|
|
79
78
|
}
|
|
80
|
-
function
|
|
81
|
-
let l = e
|
|
79
|
+
function j(e, t, r, s) {
|
|
80
|
+
let l = m(e) ?? n(e.color, C), u = a(l), d = o(l), f = m(e) !== void 0, p = () => {
|
|
82
81
|
f = !0, t.style({
|
|
83
82
|
fillColor: n(u, d),
|
|
84
83
|
fillOpacity: d
|
|
85
84
|
});
|
|
86
|
-
},
|
|
85
|
+
}, h = O(c(u, (e) => {
|
|
87
86
|
u = e, p();
|
|
88
87
|
}), s("drawingSettings.fill"));
|
|
89
88
|
r.push((e) => {
|
|
90
|
-
f || (u = a(e),
|
|
89
|
+
f || (u = a(e), h.value = u);
|
|
91
90
|
});
|
|
92
|
-
let
|
|
91
|
+
let g = O(i(Math.round(d * 100), {
|
|
93
92
|
min: 0,
|
|
94
93
|
max: 100,
|
|
95
94
|
step: 5
|
|
96
95
|
}, (e) => {
|
|
97
96
|
d = e / 100, p();
|
|
98
|
-
}), s("drawingSettings.opacity")),
|
|
99
|
-
return
|
|
97
|
+
}), s("drawingSettings.opacity")), _ = document.createElement("span");
|
|
98
|
+
return _.className = "tcw-unit", _.setAttribute("aria-hidden", "true"), _.textContent = "%", D(s("drawingSettings.fill"), h, g, _);
|
|
100
99
|
}
|
|
101
|
-
function
|
|
102
|
-
let o =
|
|
100
|
+
function M(e, t, n, r, a) {
|
|
101
|
+
let o = T(a, e, t.label), c = n[e];
|
|
103
102
|
switch (t.kind) {
|
|
104
103
|
case "boolean": return u(o, !!c, (t) => r.options({ [e]: t }));
|
|
105
104
|
case "number": return l(o, i(Number(c), {
|
|
@@ -109,7 +108,7 @@ function A(e, t, n, r, a) {
|
|
|
109
108
|
}, (t) => r.options({ [e]: t })));
|
|
110
109
|
case "choice": return l(o, s(t.choices.map((t) => ({
|
|
111
110
|
value: t.value,
|
|
112
|
-
label:
|
|
111
|
+
label: T(a, `${e}.${t.value}`, t.label)
|
|
113
112
|
})), String(c), (t) => r.options({ [e]: t })));
|
|
114
113
|
case "text": {
|
|
115
114
|
let t = document.createElement("input");
|
|
@@ -117,11 +116,11 @@ function A(e, t, n, r, a) {
|
|
|
117
116
|
}
|
|
118
117
|
}
|
|
119
118
|
}
|
|
120
|
-
function
|
|
119
|
+
function N(t, n, r, o, s, l) {
|
|
121
120
|
let u = document.createElement("div");
|
|
122
121
|
u.className = "tcw-settings-section tcw-levels-editor";
|
|
123
122
|
let d = document.createElement("div");
|
|
124
|
-
d.className = "tcw-settings-section-title", d.textContent =
|
|
123
|
+
d.className = "tcw-settings-section-title", d.textContent = T(l, t, n.label), u.appendChild(d);
|
|
125
124
|
let f = () => {
|
|
126
125
|
let e = r.options()[t];
|
|
127
126
|
return Array.isArray(e) ? e : [];
|
|
@@ -134,10 +133,10 @@ function j(t, n, r, o, s, l) {
|
|
|
134
133
|
...e,
|
|
135
134
|
visible: h.checked
|
|
136
135
|
} : e)));
|
|
137
|
-
let g =
|
|
136
|
+
let g = O(i(t.value, { step: .001 }, (e) => p(f().map((t, r) => r === n ? {
|
|
138
137
|
...t,
|
|
139
138
|
value: e
|
|
140
|
-
} : t))), l("drawingSettings.levelValue") + d), _ =
|
|
139
|
+
} : t))), l("drawingSettings.levelValue") + d), _ = O(c(t.color ?? r.style().color, (e) => p(f().map((t, r) => r === n ? {
|
|
141
140
|
...t,
|
|
142
141
|
color: e
|
|
143
142
|
} : t))), l("drawingSettings.levelColor") + d);
|
|
@@ -154,24 +153,24 @@ function j(t, n, r, o, s, l) {
|
|
|
154
153
|
}), u.append(h, g, _, v), m.appendChild(u);
|
|
155
154
|
}), u.appendChild(m);
|
|
156
155
|
let h = document.createElement("button");
|
|
157
|
-
return h.type = "button", h.className = "tcw-reset-link tcw-level-add", h.textContent = l("drawingSettings.addLevel"), h.disabled = f().length >=
|
|
156
|
+
return h.type = "button", h.className = "tcw-reset-link tcw-level-add", h.textContent = l("drawingSettings.addLevel"), h.disabled = f().length >= x, h.addEventListener("click", () => {
|
|
158
157
|
let e = f().at(-1)?.value ?? 0;
|
|
159
158
|
p([...f(), {
|
|
160
|
-
value: Math.round((e +
|
|
159
|
+
value: Math.round((e + S) * 1e3) / 1e3,
|
|
161
160
|
visible: !0
|
|
162
161
|
}]), o.redraw([".tcw-level-row:last-child input[type=\"number\"]"]);
|
|
163
162
|
}), u.appendChild(h), u;
|
|
164
163
|
}
|
|
165
|
-
var
|
|
164
|
+
var P = 240, F = 40, I = 4e3, L = 10, R = [
|
|
166
165
|
"left",
|
|
167
166
|
"center",
|
|
168
167
|
"right"
|
|
169
|
-
],
|
|
168
|
+
], z = [
|
|
170
169
|
"top",
|
|
171
170
|
"middle",
|
|
172
171
|
"bottom"
|
|
173
172
|
];
|
|
174
|
-
function
|
|
173
|
+
function B(e, t, n, r = !1) {
|
|
175
174
|
let i = document.createElement("label");
|
|
176
175
|
i.className = "tcw-inline-check";
|
|
177
176
|
let a = document.createElement("input");
|
|
@@ -181,48 +180,48 @@ function R(e, t, n, r = !1) {
|
|
|
181
180
|
}
|
|
182
181
|
return i;
|
|
183
182
|
}
|
|
184
|
-
function
|
|
185
|
-
let u =
|
|
183
|
+
function V(e, t, n, r, i, a, o = !1) {
|
|
184
|
+
let u = E(), d = document.createElement("textarea");
|
|
186
185
|
d.className = "tcw-indi-input tcw-drawing-text", d.rows = 3, d.value = t.text ?? "", d.addEventListener("input", () => n({ text: d.value }));
|
|
187
186
|
let f = l(r("drawingSettings.text"), d);
|
|
188
187
|
f.classList.add("tcw-text-row"), u.appendChild(f);
|
|
189
|
-
let p =
|
|
188
|
+
let p = O(s(v.map((e) => ({
|
|
190
189
|
value: String(e),
|
|
191
190
|
label: `${e} px`
|
|
192
|
-
})), String(t.fontSize ?? i?.fontSize ??
|
|
193
|
-
u.appendChild(
|
|
191
|
+
})), String((t.fontSize === b ? void 0 : t.fontSize) ?? i?.fontSize ?? y), (e) => n({ fontSize: Number(e) })), r("drawingSettings.fontSize"));
|
|
192
|
+
u.appendChild(D(r("drawingSettings.fontSize"), p, B(r("drawingSettings.bold"), t.bold === !0, (e) => n({ bold: e })), B(r("drawingSettings.italic"), t.italic === !0, (e) => n({ italic: e })))), u.appendChild(D(r("drawingSettings.textColor"), O(c(t.textColor ?? a ?? t.color, (e) => n({ textColor: e })), r("drawingSettings.textColor")))), e.appendChild(u), i && e.appendChild(U(t, n, r, i)), o && e.appendChild(H(t, n, r));
|
|
194
193
|
}
|
|
195
|
-
function
|
|
196
|
-
let r =
|
|
197
|
-
return r.appendChild(
|
|
194
|
+
function H(e, t, n) {
|
|
195
|
+
let r = E();
|
|
196
|
+
return r.appendChild(D(n("drawingSettings.align"), O(s(R.map((e) => ({
|
|
198
197
|
value: e,
|
|
199
198
|
label: n(`drawingSettings.align.${e}`)
|
|
200
|
-
})), e.textAlign ?? "center", (e) => t({ textAlign: e })), n("drawingSettings.align")))), r.appendChild(
|
|
199
|
+
})), e.textAlign ?? "center", (e) => t({ textAlign: e })), n("drawingSettings.align")))), r.appendChild(D(n("drawingSettings.vAlign"), O(s(z.map((e) => ({
|
|
201
200
|
value: e,
|
|
202
201
|
label: n(`drawingSettings.vAlign.${e}`)
|
|
203
202
|
})), e.textVAlign ?? "top", (e) => t({ textVAlign: e })), n("drawingSettings.vAlign")))), r;
|
|
204
203
|
}
|
|
205
|
-
function
|
|
206
|
-
let l =
|
|
207
|
-
l.appendChild(
|
|
204
|
+
function U(e, t, r, a) {
|
|
205
|
+
let l = E();
|
|
206
|
+
l.appendChild(D(r("drawingSettings.align"), O(s(R.map((e) => ({
|
|
208
207
|
value: e,
|
|
209
208
|
label: r(`drawingSettings.align.${e}`)
|
|
210
209
|
})), e.textAlign ?? "left", (e) => t({ textAlign: e })), r("drawingSettings.align"))));
|
|
211
|
-
let u = e
|
|
212
|
-
l.appendChild(
|
|
213
|
-
let d = e.textWrap ?? a.wrap, f = d > 0 ? d : a.wrap > 0 ? a.wrap :
|
|
214
|
-
min:
|
|
215
|
-
max:
|
|
216
|
-
step:
|
|
210
|
+
let u = m(e) ?? n(e.color, C);
|
|
211
|
+
l.appendChild(D(r("drawingSettings.background"), B(r("drawingSettings.background"), e.textBackground ?? a.box, (e) => t({ textBackground: e }), !0), O(c(u, (e) => t({ fillColor: n(e, o(u)) })), r("drawingSettings.backgroundColor")))), l.appendChild(D(r("drawingSettings.border"), B(r("drawingSettings.border"), e.textBorder ?? a.border, (e) => t({ textBorder: e }), !0), O(c(e.borderColor ?? e.color, (e) => t({ borderColor: e })), r("drawingSettings.borderColor"))));
|
|
212
|
+
let d = e.textWrap ?? a.wrap, f = d > 0 ? d : a.wrap > 0 ? a.wrap : P, p = d > 0, h = O(i(f, {
|
|
213
|
+
min: F,
|
|
214
|
+
max: I,
|
|
215
|
+
step: L
|
|
217
216
|
}, (e) => {
|
|
218
217
|
f = e, p && t({ textWrap: e });
|
|
219
218
|
}), r("drawingSettings.wrapWidth"));
|
|
220
|
-
return
|
|
221
|
-
p = e,
|
|
222
|
-
}, !0),
|
|
219
|
+
return h.disabled = !p, l.appendChild(D(r("drawingSettings.wrap"), B(r("drawingSettings.wrap"), p, (e) => {
|
|
220
|
+
p = e, h.disabled = !e, t({ textWrap: e ? f : 0 });
|
|
221
|
+
}, !0), h)), l;
|
|
223
222
|
}
|
|
224
|
-
function
|
|
225
|
-
let i =
|
|
223
|
+
function W(e, t, n, r) {
|
|
224
|
+
let i = E();
|
|
226
225
|
t.forEach((e, t) => {
|
|
227
226
|
let a = d(r("drawingSettings.point"), { n: t + 1 }), o = n.toWallTime(e.time), s = document.createElement("input");
|
|
228
227
|
s.type = "date", s.className = "tcw-indi-input", s.value = o.date;
|
|
@@ -233,11 +232,11 @@ function H(e, t, n, r) {
|
|
|
233
232
|
e !== null && n.move(t, { time: e });
|
|
234
233
|
};
|
|
235
234
|
s.addEventListener("change", l), c.addEventListener("change", l);
|
|
236
|
-
let u =
|
|
235
|
+
let u = D(a, O(G(e.price, n, (e) => n.move(t, { price: e })), `${a}: ${r("drawingSettings.price")}`), O(s, `${a}: ${r("drawingSettings.date")}`), O(c, `${a}: ${r("drawingSettings.time")}`));
|
|
237
236
|
u.classList.add("tcw-draw-point"), i.appendChild(u);
|
|
238
237
|
}), e.appendChild(i);
|
|
239
238
|
}
|
|
240
|
-
function
|
|
239
|
+
function G(e, t, n) {
|
|
241
240
|
let r = t.roundPrice ?? ((e) => e), a = t.priceStep?.(), o = i(r(e), { step: a !== void 0 && a > 0 ? a : "any" }, (e) => {
|
|
242
241
|
let t = r(e);
|
|
243
242
|
o.value = String(t), n(t);
|
|
@@ -246,7 +245,7 @@ function U(e, t, n) {
|
|
|
246
245
|
}
|
|
247
246
|
//#endregion
|
|
248
247
|
//#region src/widget/WidgetDrawingSettings.ts
|
|
249
|
-
var
|
|
248
|
+
var K = 12, q = "t:", J = 1, Y = class {
|
|
250
249
|
backdrop;
|
|
251
250
|
modal;
|
|
252
251
|
titleEl;
|
|
@@ -262,7 +261,7 @@ var W = 12, G = "t:", K = 1, q = class {
|
|
|
262
261
|
intervals = null;
|
|
263
262
|
tab = "style";
|
|
264
263
|
returnFocus = null;
|
|
265
|
-
uid =
|
|
264
|
+
uid = J++;
|
|
266
265
|
constructor(t, n, r = f) {
|
|
267
266
|
this.callbacks = n, this.t = r, this.backdrop = document.createElement("div"), this.backdrop.className = "tcw-modal-backdrop", this.backdrop.hidden = !0;
|
|
268
267
|
let i = !1;
|
|
@@ -314,7 +313,7 @@ var W = 12, G = "t:", K = 1, q = class {
|
|
|
314
313
|
return e ? [
|
|
315
314
|
"style",
|
|
316
315
|
...e.text ? ["text"] : [],
|
|
317
|
-
...e.coordinates !== !1 && e.anchors.length <=
|
|
316
|
+
...e.coordinates !== !1 && e.anchors.length <= K ? ["coordinates"] : [],
|
|
318
317
|
"visibility"
|
|
319
318
|
] : [];
|
|
320
319
|
}
|
|
@@ -349,10 +348,10 @@ var W = 12, G = "t:", K = 1, q = class {
|
|
|
349
348
|
let e = this.target;
|
|
350
349
|
if (e) switch (this.tab) {
|
|
351
350
|
case "text":
|
|
352
|
-
|
|
351
|
+
V(this.bodyEl, this.style, (e) => this.setStyle(e), this.t, e.textLayout, e.textColor, e.textPlace);
|
|
353
352
|
break;
|
|
354
353
|
case "coordinates":
|
|
355
|
-
|
|
354
|
+
W(this.bodyEl, this.anchors, {
|
|
356
355
|
toWallTime: this.callbacks.toWallTime,
|
|
357
356
|
fromWallTime: this.callbacks.fromWallTime,
|
|
358
357
|
roundPrice: this.callbacks.roundPrice,
|
|
@@ -363,7 +362,7 @@ var W = 12, G = "t:", K = 1, q = class {
|
|
|
363
362
|
case "visibility":
|
|
364
363
|
p(this.bodyEl, this.intervals, (e) => this.setIntervals(e), this.t);
|
|
365
364
|
break;
|
|
366
|
-
default:
|
|
365
|
+
default: k(this.bodyEl, {
|
|
367
366
|
style: () => this.style,
|
|
368
367
|
options: () => this.options,
|
|
369
368
|
defs: e.defs,
|
|
@@ -417,7 +416,7 @@ var W = 12, G = "t:", K = 1, q = class {
|
|
|
417
416
|
}
|
|
418
417
|
let t = this.callbacks.templates, n = t?.list(e.type) ?? [], i = [
|
|
419
418
|
...n.map((e, t) => ({
|
|
420
|
-
id: `${
|
|
419
|
+
id: `${q}${t}`,
|
|
421
420
|
label: e.name,
|
|
422
421
|
icon: "layers",
|
|
423
422
|
remove: d(this.t("templates.delete"), { name: e.name })
|
|
@@ -446,7 +445,7 @@ var W = 12, G = "t:", K = 1, q = class {
|
|
|
446
445
|
type: e.type,
|
|
447
446
|
style: { ...this.style },
|
|
448
447
|
options: structuredClone(this.options)
|
|
449
|
-
}) : n === "default" ? this.callbacks.onSaveDefault?.(e.type, structuredClone(this.options)) : n === "reset" ? this.resetOptions() : n.startsWith(
|
|
448
|
+
}) : n === "default" ? this.callbacks.onSaveDefault?.(e.type, structuredClone(this.options)) : n === "reset" ? this.resetOptions() : n.startsWith(q) && this.applyTemplate(a(n));
|
|
450
449
|
}, this.templateBtn, (e) => {
|
|
451
450
|
let n = a(e);
|
|
452
451
|
n && t?.remove(n.name, n.type);
|
|
@@ -454,7 +453,7 @@ var W = 12, G = "t:", K = 1, q = class {
|
|
|
454
453
|
}
|
|
455
454
|
applyTemplate(e) {
|
|
456
455
|
let t = this.target;
|
|
457
|
-
!e || !t || (Object.keys(e.style).length > 0 && this.setStyle(e.style), e.options && this.setOptions(
|
|
456
|
+
!e || !t || (Object.keys(e.style).length > 0 && this.setStyle(e.style), e.options && this.setOptions(h(t.defs, e.options)), this.renderBody());
|
|
458
457
|
}
|
|
459
458
|
resetOptions() {
|
|
460
459
|
let e = this.target;
|
|
@@ -469,6 +468,6 @@ var W = 12, G = "t:", K = 1, q = class {
|
|
|
469
468
|
}
|
|
470
469
|
};
|
|
471
470
|
//#endregion
|
|
472
|
-
export {
|
|
471
|
+
export { Y as WidgetDrawingSettings };
|
|
473
472
|
|
|
474
|
-
//# sourceMappingURL=WidgetDrawingSettings-
|
|
473
|
+
//# sourceMappingURL=WidgetDrawingSettings-CJsNm1Bf.js.map
|