@tradecanvas/chart 2.6.0 → 2.8.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/README.md +2 -2
- package/dist/Chart.d.ts +11 -0
- package/dist/Chart.d.ts.map +1 -1
- package/dist/{LayoutSession-D8TcwPy1.js → LayoutSession-BJLUwx9d.js} +436 -424
- package/dist/LayoutSession-BJLUwx9d.js.map +1 -0
- package/dist/{LayoutSession-DDs1N5h2.cjs → LayoutSession-DiKwrEV8.cjs} +2 -2
- package/dist/LayoutSession-DiKwrEV8.cjs.map +1 -0
- package/dist/{WidgetCommandPalette-B1jLC9oE.js → WidgetCommandPalette-CSIKnTca.js} +2 -2
- package/dist/{WidgetCommandPalette-B1jLC9oE.js.map → WidgetCommandPalette-CSIKnTca.js.map} +1 -1
- package/dist/{WidgetCommandPalette-Cx-UQ9ft.cjs → WidgetCommandPalette-CZ3GhE1O.cjs} +2 -2
- package/dist/{WidgetCommandPalette-Cx-UQ9ft.cjs.map → WidgetCommandPalette-CZ3GhE1O.cjs.map} +1 -1
- package/dist/{WidgetDrawingSettings-ezbzlGqD.js → WidgetDrawingSettings-Cc8PeqEZ.js} +2 -2
- package/dist/{WidgetDrawingSettings-ezbzlGqD.js.map → WidgetDrawingSettings-Cc8PeqEZ.js.map} +1 -1
- package/dist/{WidgetDrawingSettings-BjPR5Wyq.cjs → WidgetDrawingSettings-DutEdVyV.cjs} +2 -2
- package/dist/{WidgetDrawingSettings-BjPR5Wyq.cjs.map → WidgetDrawingSettings-DutEdVyV.cjs.map} +1 -1
- package/dist/{WidgetIndicatorPicker-eK03W3LR.js → WidgetIndicatorPicker-DNjcuBp6.js} +2 -2
- package/dist/{WidgetIndicatorPicker-eK03W3LR.js.map → WidgetIndicatorPicker-DNjcuBp6.js.map} +1 -1
- package/dist/{WidgetIndicatorPicker-DKxoB4Un.cjs → WidgetIndicatorPicker-GCesxFMn.cjs} +2 -2
- package/dist/{WidgetIndicatorPicker-DKxoB4Un.cjs.map → WidgetIndicatorPicker-GCesxFMn.cjs.map} +1 -1
- package/dist/{WidgetIndicatorSettings-Da_T6bmX.cjs → WidgetIndicatorSettings-CBHWj5z5.cjs} +2 -2
- package/dist/{WidgetIndicatorSettings-Da_T6bmX.cjs.map → WidgetIndicatorSettings-CBHWj5z5.cjs.map} +1 -1
- package/dist/{WidgetIndicatorSettings-DR8Z9RfF.js → WidgetIndicatorSettings-XhHlqyvn.js} +3 -3
- package/dist/{WidgetIndicatorSettings-DR8Z9RfF.js.map → WidgetIndicatorSettings-XhHlqyvn.js.map} +1 -1
- package/dist/{WidgetSettings-DCGCymVY.js → WidgetSettings-B1ay0W6I.js} +3 -3
- package/dist/{WidgetSettings-DCGCymVY.js.map → WidgetSettings-B1ay0W6I.js.map} +1 -1
- package/dist/{WidgetSettings-COljE3G_.cjs → WidgetSettings-CBf6hUSV.cjs} +2 -2
- package/dist/{WidgetSettings-COljE3G_.cjs.map → WidgetSettings-CBf6hUSV.cjs.map} +1 -1
- package/dist/{WidgetSymbolSearch-Dnkh_y4h.js → WidgetSymbolSearch-BlQWH3Md.js} +2 -2
- package/dist/{WidgetSymbolSearch-Dnkh_y4h.js.map → WidgetSymbolSearch-BlQWH3Md.js.map} +1 -1
- package/dist/{WidgetSymbolSearch-C_yw9mLo.cjs → WidgetSymbolSearch-CxeLjy63.cjs} +2 -2
- package/dist/{WidgetSymbolSearch-C_yw9mLo.cjs.map → WidgetSymbolSearch-CxeLjy63.cjs.map} +1 -1
- package/dist/i18n-BFGknfTa.cjs +2 -0
- package/dist/i18n-BFGknfTa.cjs.map +1 -0
- package/dist/{i18n-DWLKoOBG.js → i18n-BZdkj80c.js} +7 -1
- package/dist/i18n-BZdkj80c.js.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.js +1 -1
- package/dist/{indicatorInputWords-VWMPRfzM.js → indicatorInputWords-B8lf8reQ.js} +2 -2
- package/dist/{indicatorInputWords-VWMPRfzM.js.map → indicatorInputWords-B8lf8reQ.js.map} +1 -1
- package/dist/{indicatorInputWords-C4Mefhve.cjs → indicatorInputWords-_kxwKob4.cjs} +2 -2
- package/dist/{indicatorInputWords-C4Mefhve.cjs.map → indicatorInputWords-_kxwKob4.cjs.map} +1 -1
- package/dist/widget/WidgetObjectTree.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 +13 -10
- package/dist/widget/index.js.map +1 -1
- package/dist/widget/locales/ar.d.ts.map +1 -1
- package/dist/widget/locales/cs.d.ts.map +1 -1
- package/dist/widget/locales/da.d.ts.map +1 -1
- package/dist/widget/locales/de.d.ts.map +1 -1
- package/dist/widget/locales/el.d.ts.map +1 -1
- package/dist/widget/locales/en.d.ts +3 -0
- package/dist/widget/locales/en.d.ts.map +1 -1
- package/dist/widget/locales/es.d.ts.map +1 -1
- package/dist/widget/locales/et.d.ts.map +1 -1
- package/dist/widget/locales/fa.d.ts.map +1 -1
- package/dist/widget/locales/fr.d.ts.map +1 -1
- package/dist/widget/locales/he.d.ts.map +1 -1
- package/dist/widget/locales/hu.d.ts.map +1 -1
- package/dist/widget/locales/id.d.ts.map +1 -1
- package/dist/widget/locales/index.cjs +1 -1
- package/dist/widget/locales/index.cjs.map +1 -1
- package/dist/widget/locales/index.js +85 -1
- package/dist/widget/locales/index.js.map +1 -1
- package/dist/widget/locales/it.d.ts.map +1 -1
- package/dist/widget/locales/ja.d.ts.map +1 -1
- package/dist/widget/locales/ko.d.ts.map +1 -1
- package/dist/widget/locales/ms.d.ts.map +1 -1
- package/dist/widget/locales/nb.d.ts.map +1 -1
- package/dist/widget/locales/nl.d.ts.map +1 -1
- package/dist/widget/locales/pl.d.ts.map +1 -1
- package/dist/widget/locales/pt.d.ts.map +1 -1
- package/dist/widget/locales/ro.d.ts.map +1 -1
- package/dist/widget/locales/ru.d.ts.map +1 -1
- package/dist/widget/locales/sk.d.ts.map +1 -1
- package/dist/widget/locales/sv.d.ts.map +1 -1
- package/dist/widget/locales/th.d.ts.map +1 -1
- package/dist/widget/locales/tr.d.ts.map +1 -1
- package/dist/widget/locales/vi.d.ts.map +1 -1
- package/dist/widget/locales/zh.d.ts.map +1 -1
- package/dist/widget/locales/zhHant.d.ts.map +1 -1
- package/dist/widget/widgetConfig.d.ts.map +1 -1
- package/dist/widgetLocales-BdRQu8wS.cjs +2 -0
- package/dist/widgetLocales-BdRQu8wS.cjs.map +1 -0
- package/dist/{widgetLocales-BX7VRdl5.js → widgetLocales-Bgm5-BB5.js} +13 -1
- package/dist/widgetLocales-Bgm5-BB5.js.map +1 -0
- package/package.json +3 -3
- package/dist/LayoutSession-D8TcwPy1.js.map +0 -1
- package/dist/LayoutSession-DDs1N5h2.cjs.map +0 -1
- package/dist/i18n-DWLKoOBG.js.map +0 -1
- package/dist/i18n-fgAwciRT.cjs +0 -2
- package/dist/i18n-fgAwciRT.cjs.map +0 -1
- package/dist/widgetLocales-BX7VRdl5.js.map +0 -1
- package/dist/widgetLocales-C_XTkni5.cjs +0 -2
- package/dist/widgetLocales-C_XTkni5.cjs.map +0 -1
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
const e=require(`./widgetLocales-C_XTkni5.cjs`),t=require(`./focusTrap-DrhhmG0V.cjs`),n=require(`./settingsControls-Tn8_vJJv.cjs`),r=require(`./i18n-fgAwciRT.cjs`);let i=require(`@tradecanvas/commons`);var a=0,o=0,s=20;function c(e){let t=document.createElement(`div`);if(t.className=`tcw-settings-section`,e){let n=document.createElement(`div`);n.className=`tcw-settings-section-title`,n.textContent=e,t.appendChild(n),t.setAttribute(`role`,`group`),t.setAttribute(`aria-label`,e)}return t}function l(e){let t=document.createElement(`div`);t.className=`tcw-settings-row`;let n=document.createElement(`span`);return n.className=`tcw-settings-label`,n.textContent=e,t.appendChild(n),t}function u(e,t,r,i,o){let s=l(e),c=document.createElement(`div`);c.className=`tcw-color-picker-wrap`;let u=document.createElement(`input`);u.type=`color`,u.setAttribute(`aria-label`,e);let d=document.createElement(`span`);d.className=`tcw-color-hex`,d.id=`tcw-color-${++a}`,u.setAttribute(`aria-describedby`,d.id);let f=null,p=t=>{u.value=n.l(t??i.start?.()),d.textContent=t??o(`settings.auto`),s.classList.toggle(`tcw-color-auto`,t===null),t!==null&&i.start&&!f?(f=document.createElement(`button`),f.type=`button`,f.className=`tcw-color-auto-btn`,f.textContent=o(`settings.auto`),f.setAttribute(`aria-label`,`${e}: ${o(`settings.auto`)}`),f.addEventListener(`click`,()=>{r(null),u.focus(),p(i.read())}),c.appendChild(f)):t===null&&f&&(f.remove(),f=null)};return u.addEventListener(`input`,()=>{r(u.value),p(u.value)}),c.append(u,d),s.appendChild(c),p(t),{row:s,sync:()=>p(i.read())}}function d(e,t,n){let r=l(e),i=document.createElement(`button`);return i.type=`button`,i.className=`tcw-toggle${t?` tcw-on`:``}`,i.setAttribute(`role`,`switch`),i.setAttribute(`aria-checked`,String(t)),i.setAttribute(`aria-label`,e),i.addEventListener(`click`,()=>{let e=!i.classList.contains(`tcw-on`);i.classList.toggle(`tcw-on`,e),i.setAttribute(`aria-checked`,String(e)),n(e)}),r.appendChild(i),r}function f(e,t,n,r){let i=l(e),a=document.createElement(`select`);a.className=`tcw-settings-select`,a.setAttribute(`aria-label`,e);for(let e of n){let n=document.createElement(`option`);n.value=e.value,n.textContent=e.label,e.value===t&&(n.selected=!0),a.appendChild(n)}return n.some(e=>e.value===t)||(a.selectedIndex=-1),a.addEventListener(`change`,()=>r(a.value)),i.appendChild(a),i}function p(e,t,n,r,i=e=>String(e)){let a=l(e),o=document.createElement(`div`);o.className=`tcw-settings-range`;let s=document.createElement(`input`);s.type=`range`,s.min=String(n.min),s.max=String(n.max),s.step=String(n.step),s.value=String(t),s.setAttribute(`aria-label`,e);let c=document.createElement(`span`);return c.className=`tcw-settings-range-val`,c.textContent=i(t),s.addEventListener(`input`,()=>{let e=Number(s.value);c.textContent=i(e),r(e)}),o.append(s,c),a.appendChild(o),a}function m(e,t,n){let i=new Intl.NumberFormat(n,{maximumFractionDigits:s}).format;return e.step===`1`&&Number.isFinite(e.max)?r.r(t(`settings.numberWhole`),{min:i(Math.max(1,e.min??1)),max:i(e.max)}):r.r(t(`settings.numberAtLeast`),{min:i(e.min??0)})}function h(e,t,n,r,i,a=`en-US`){let s=document.createElement(`div`);s.className=`tcw-settings-row tcw-settings-row--number`;let c=document.createElement(`label`);c.className=`tcw-settings-label`,c.textContent=e,s.appendChild(c);let l=document.createElement(`input`);l.type=`number`,l.className=`tcw-settings-number`,l.min=`0`,l.step=n.step,Number.isFinite(n.max)&&(l.max=String(n.max)),l.placeholder=i(`settings.auto`),l.value=t===null?``:String(t),l.setAttribute(`aria-label`,e);let u=document.createElement(`div`);u.className=`tcw-settings-hint`,u.id=`tcw-number-hint-${++o}`,u.setAttribute(`role`,`status`),l.setAttribute(`aria-describedby`,u.id);let d=e=>{e?l.removeAttribute(`aria-invalid`):l.setAttribute(`aria-invalid`,`true`),u.textContent=e?``:m(n,i,a)};return l.addEventListener(`change`,()=>{if(l.value.trim()===``){d(!0),r(null);return}let e=Number(l.value),t=Number.isFinite(e)&&e>0&&e>=(n.min??0)&&e<=n.max&&(n.step!==`1`||Number.isInteger(e));d(t),t&&r(e)}),s.append(l,u),s}var g=[{id:`symbol`,icon:`chartType:candlestick`},{id:`statusLine`,icon:`type`},{id:`scales`,icon:`ruler`},{id:`appearance`,icon:`palette`},{id:`layers`,icon:`layers`},{id:`trading`,icon:`trendingUp`}],_=[1,2,3,4],v=`t:`,y={step:`any`,max:1/0,min:1e-8},b=1,x=class{callbacks;t;backdrop=null;modal=null;bodyEl=null;tabButtons=[];templateBtn=null;menu=null;currentTab=`symbol`;currentSettings=null;chartType=null;lookRows=[];returnFocus=null;uid=b++;constructor(e,t,n={},r=()=>document.body){this.available=n,this.host=r,this.callbacks=e,this.t=t}open(e,t=null,n=`symbol`){this.modal&&this.remove(),this.returnFocus=document.activeElement instanceof HTMLElement?document.activeElement:null,this.currentSettings={...e},this.chartType=t,this.currentTab=n,this.buildModal(),this.tabButtons.find(e=>e.dataset.tab===n)?.focus()}isOpen(){return this.modal!==null}follow(e){!this.modal||this.currentSettings&&S(this.currentSettings,e)||this.refresh(e)}refresh(e,t){if(!this.modal)return;this.currentSettings={...e},t!==void 0&&(this.chartType=t);let n=this.focusedControl();this.renderTabContent(),n!==null&&this.focusControl(n)}focusedControl(){let e=document.activeElement;if(!this.bodyEl||!(e instanceof HTMLElement)||!this.bodyEl.contains(e))return null;let t=this.panelControls().indexOf(e);return t<0?null:t}focusControl(e){let t=this.panelControls();(t[Math.min(e,t.length-1)]??this.tabButtons.find(e=>e.dataset.tab===this.currentTab))?.focus()}panelControls(){return this.bodyEl?[...this.bodyEl.querySelectorAll(t.t)]:[]}close(){this.finish(!0)}destroy(){this.remove()}finish(e){this.modal&&(e?this.callbacks.onClose():this.callbacks.onCancel?.(),this.remove(),this.returnFocus?.isConnected&&this.returnFocus.focus(),this.returnFocus=null)}remove(){this.menu?.destroy(),this.menu=null,this.backdrop?.remove(),this.backdrop=this.modal=this.bodyEl=this.templateBtn=null,this.tabButtons=[]}buildModal(){let e=document.createElement(`div`);e.className=`tcw-modal-backdrop`;let n=!1;e.addEventListener(`pointerdown`,t=>{n=t.target===e}),e.addEventListener(`click`,t=>{t.target===e&&n&&this.finish(!1),n=!1});let r=document.createElement(`div`);r.className=`tcw-modal tcw-set`,r.setAttribute(`role`,`dialog`),r.setAttribute(`aria-modal`,`true`),r.setAttribute(`aria-labelledby`,`tcw-set-title-${this.uid}`),r.tabIndex=-1,r.addEventListener(`keydown`,e=>{if(e.key===`Escape`){e.preventDefault(),e.stopPropagation(),this.finish(!1);return}t.n(e,r)}),this.backdrop=e,this.modal=r,r.append(this.buildHeader(),this.buildBody(),this.buildFooter()),e.appendChild(r),this.host().appendChild(e),this.markTabs(),this.renderTabContent()}buildHeader(){let e=document.createElement(`div`);e.className=`tcw-modal-header`;let n=document.createElement(`h3`);n.id=`tcw-set-title-${this.uid}`,n.textContent=this.t(`settings.title`);let r=document.createElement(`button`);return r.type=`button`,r.className=`tcw-modal-close`,r.setAttribute(`aria-label`,this.t(`common.close`)),r.innerHTML=t.i(`x`,16),r.addEventListener(`click`,()=>this.finish(!1)),e.append(n,r),e}buildBody(){let e=document.createElement(`div`);e.className=`tcw-set-body`;let n=document.createElement(`div`);n.className=`tcw-set-nav`,n.setAttribute(`role`,`tablist`),n.setAttribute(`aria-orientation`,`vertical`),n.setAttribute(`aria-label`,this.t(`settings.title`)),n.addEventListener(`keydown`,e=>this.onTabKey(e)),this.tabButtons=g.map(({id:e,icon:n})=>{let r=document.createElement(`button`);return r.type=`button`,r.className=`tcw-set-tab`,r.id=`tcw-set-tab-${this.uid}-${e}`,r.dataset.tab=e,r.setAttribute(`role`,`tab`),r.setAttribute(`aria-controls`,`tcw-set-panel-${this.uid}`),r.innerHTML=`${n.startsWith(`chartType:`)?t.r(n.slice(10),16):t.i(n,16)}<span></span>`,r.querySelector(`span`).textContent=this.t(`settings.tab.${e}`),r.addEventListener(`click`,()=>this.selectTab(e)),r}),n.append(...this.tabButtons);let r=document.createElement(`div`);return r.className=`tcw-modal-body tcw-set-panel`,r.id=`tcw-set-panel-${this.uid}`,r.setAttribute(`role`,`tabpanel`),this.bodyEl=r,e.append(n,r),e}buildFooter(){let e=document.createElement(`div`);e.className=`tcw-modal-footer`;let n=this.footerButton(`template`,`tcw-footer-menu`,()=>this.openTemplates());n.setAttribute(`aria-haspopup`,`menu`),n.setAttribute(`aria-expanded`,`false`),n.innerHTML=`<span></span>${t.i(`chevronDown`,12)}`,n.querySelector(`span`).textContent=this.t(`settings.template`),this.templateBtn=n;let r=document.createElement(`div`);return r.className=`tcw-footer-end`,r.append(this.footerButton(`cancel`,`tcw-footer-cancel`,()=>this.finish(!1),this.t(`common.cancel`)),this.footerButton(`ok`,`tcw-done-btn`,()=>this.finish(!0),this.t(`drawingSettings.ok`))),e.append(n,r),e}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}markTabs(){for(let e of this.tabButtons){let t=e.dataset.tab===this.currentTab;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.currentTab=e,this.markTabs(),this.renderTabContent(),t&&this.tabButtons.find(t=>t.dataset.tab===e)?.focus()}onTabKey(e){let t=g.findIndex(e=>e.id===this.currentTab),n=e.key===`ArrowDown`||e.key===`ArrowRight`?(t+1)%g.length:e.key===`ArrowUp`||e.key===`ArrowLeft`?(t-1+g.length)%g.length:e.key===`Home`?0:e.key===`End`?g.length-1:-1;n<0||(e.preventDefault(),this.selectTab(g[n].id,!0))}openTemplates(){let e=this.templateBtn;if(!this.modal||!e)return;if(this.menu?.isOpen()){this.menu.close();return}let t=this.callbacks.templates,i=(t?.list()??[]).map(e=>({id:`${v}${e}`,label:e,icon:`layers`,remove:r.r(this.t(`templates.delete`),{name:e})})),a=[...i,...i.length>0?[`separator`]:[],...t?[{id:`save`,label:this.t(`settings.saveTemplate`),icon:`save`}]:[],{id:`reset`,label:this.t(`settings.resetToDefaults`),icon:`reset`}];this.menu??=new n.f(this.modal,this.t(`settings.template`));let o=e.getBoundingClientRect(),s=this.modal.getBoundingClientRect();this.menu.open(a,o.left-s.left,o.top-s.top,e=>{e===`reset`?this.callbacks.onReset():e===`save`?t?.save():e.startsWith(v)&&t?.apply(e.slice(2))},e,e=>t?.remove(e.slice(2)))}renderTabContent(){if(!(!this.bodyEl||!this.currentSettings))switch(this.bodyEl.replaceChildren(),this.lookRows=[],this.currentTab){case`symbol`:this.renderSymbolTab(this.currentSettings);break;case`statusLine`:this.renderStatusLineTab(this.currentSettings);break;case`scales`:this.renderScalesTab(this.currentSettings);break;case`appearance`:this.renderAppearanceTab(this.currentSettings);break;case`layers`:this.renderLayersTab(this.currentSettings);break;case`trading`:for(let t of e.d)(!t.trading||this.available.trading!==!1)&&this.renderLookSection(t);break}}renderSymbolTab(t){this.renderChartTypeSection(),this.addSection(void 0,[d(this.t(`settings.mainSeries`),t.mainSeriesVisible,e=>this.patch({mainSeriesVisible:e})),d(this.t(`settings.extendedHours`),t.extendedHours,e=>this.patch({extendedHours:e}))]);let n=this.t(`common.show`);this.renderLookSection(e.o),this.available.volume!==!1&&this.renderLookSection(e.f,[d(n,t.volumeVisible,e=>this.patch({volumeVisible:e}))]),this.renderLookSection(e.a,[d(n,t.highLowLines,e=>this.patch({highLowLines:e}))])}renderStatusLineTab(t){let n=this.available.legend!==!1,r=n?e.u:e.u.filter(t=>!e.s.includes(t));this.addSection(void 0,[...n?[d(this.t(`settings.ohlcLegend`),t.legendVisible,e=>this.patch({legendVisible:e}))]:[],...r.map(e=>this.lookRow(e))])}renderScalesTab(t){let n=[{value:`regular`,label:this.t(`settings.scale.regular`)},{value:`logarithmic`,label:this.t(`settings.scale.logarithmic`)},{value:`percentage`,label:this.t(`settings.scale.percentage`)},{value:`indexedTo100`,label:this.t(`settings.scale.indexedTo100`)}].filter(e=>e.value!==`logarithmic`||this.available.logScale!==!1),r=this.available.exchangeZone?.(),i=e.y(t.timezone,Date.now(),this.t(`settings.timezone.local`),r===void 0?void 0:{label:this.t(`settings.timezone.exchange`),zone:r});this.addSection(void 0,[f(this.t(`settings.priceScale`),t.scaleMode,n,e=>this.patch({scaleMode:e})),d(this.t(`settings.autoScale`),t.autoScale,e=>this.patch({autoScale:e})),d(this.t(`settings.invertScale`),t.invertScale,e=>this.patch({invertScale:e})),d(this.t(`settings.leftScale`),t.leftPriceScale,e=>this.patch({leftPriceScale:e})),d(this.t(`settings.indicatorValues`),t.indicatorValueLabels,e=>this.patch({indicatorValueLabels:e})),d(this.t(`settings.alignAxisLabels`),t.alignAxisLabels,e=>this.patch({alignAxisLabels:e})),...this.available.barCountdown===!1?[]:[d(this.t(`settings.barCountdown`),t.barCountdown,e=>this.patch({barCountdown:e}))],f(this.t(`settings.timezone`),t.timezone,i,e=>this.patch({timezone:e})),f(this.t(`settings.numberLocale`),t.numberLocale,e.r(t.numberLocale),e=>this.patch({numberLocale:e}))]),this.addSection(this.t(`settings.section.axes`),e.c.map(e=>this.lookRow(e)))}renderAppearanceTab(t){let[n,r,i,...a]=e.i;this.renderLookSection(n),this.renderLookSection(r,[d(this.t(`common.show`),t.gridVisible,e=>this.patch({gridVisible:e}))]),this.renderLookSection(i,[f(this.t(`settings.crosshairMode`),t.crosshairMode,[{label:this.t(`settings.crosshair.magnet`),value:`magnet`},{label:this.t(`settings.crosshair.normal`),value:`normal`},{label:this.t(`settings.crosshair.hidden`),value:`hidden`}],e=>this.patch({crosshairMode:e})),f(this.t(`settings.crosshairCursor`),t.crosshairCursor,[{label:this.t(`drawing.cursorCross`),value:`cross`},{label:this.t(`drawing.cursorDot`),value:`dot`},{label:this.t(`drawing.cursorArrow`),value:`arrow`}],e=>this.patch({crosshairCursor:e}))]);for(let e of a)this.renderLookSection(e)}renderLayersTab(e){let t=e=>`${Math.round(e*100)}%`,n=e=>this.t(e);this.addSection(void 0,[d(n(`settings.volumeProfile`),e.volumeProfileVisible,e=>this.patch({volumeProfileVisible:e}))]),this.addSection(void 0,[d(n(`settings.marketProfile`),e.marketProfileVisible,e=>this.patch({marketProfileVisible:e})),d(n(`settings.marketProfileSplit`),e.marketProfileSplit,e=>this.patch({marketProfileSplit:e})),d(n(`settings.marketProfileLetters`),e.marketProfileLetters,e=>this.patch({marketProfileLetters:e})),p(n(`settings.marketProfileBuckets`),e.marketProfileBuckets,{min:8,max:200,step:1},e=>this.patch({marketProfileBuckets:e})),p(n(`settings.marketProfileOpacity`),e.marketProfileOpacity,{min:.05,max:1,step:.05},e=>this.patch({marketProfileOpacity:e}),t)]),this.addSection(void 0,[d(n(`settings.depthHeatmap`),e.depthHeatmapVisible,e=>this.patch({depthHeatmapVisible:e})),p(n(`settings.depthHeatmapOpacity`),e.depthHeatmapOpacity,{min:.1,max:1,step:.05},e=>this.patch({depthHeatmapOpacity:e}),t)]),this.addSection(void 0,[d(n(`settings.swingMarkers`),e.pivotMarkersVisible,e=>this.patch({pivotMarkersVisible:e})),p(n(`settings.swingStrength`),e.pivotStrength,{min:2,max:20,step:1},e=>this.patch({pivotStrength:e})),d(n(`settings.swingStructure`),e.pivotStructureLabels,e=>this.patch({pivotStructureLabels:e}))]),this.addSection(void 0,[d(n(`settings.sessionShading`),e.sessionShadingVisible,e=>this.patch({sessionShadingVisible:e})),d(n(`settings.periodLevels`),e.periodLevelsVisible,e=>this.patch({periodLevelsVisible:e})),f(n(`settings.periodLevelsBasis`),e.periodLevelsPeriod,[{value:`day`,label:n(`settings.priorDay`)},{value:`week`,label:n(`settings.priorWeek`)}],e=>this.patch({periodLevelsPeriod:e}))])}addSection(e,t){let n=c(e);return n.append(...t),this.bodyEl?.appendChild(n),n}renderLookSection(e,t=[]){this.addSection(this.t(e.title),[...t,...e.rows.map(e=>this.lookRow(e))])}lookRow(e){let t=this.t(e.label),n=()=>this.callbacks.styleValue(e.keys[0]),r=()=>{let t=e.keys.map(e=>this.callbacks.styleValue(e));return t.every(e=>e===t[0])&&t[0]!==null?String(t[0]):``},a,o=t=>{this.callbacks.onStyleChange(Object.fromEntries(e.keys.map(e=>[e,t])));for(let e of this.lookRows)e.el!==a&&e.sync()},s=e.auto?[{value:``,label:this.t(`settings.auto`)}]:[],c;switch(i.CHART_STYLE_KEYS[e.keys[0]]){case`boolean`:{a=d(t,n()===!0,o);let e=a.querySelector(`button`);c=()=>{let t=n()===!0;e.classList.toggle(`tcw-on`,t),e.setAttribute(`aria-checked`,String(t))};break}case`lineStyle`:a=f(t,r(),[...s,...this.lineStyles()],e=>o(e===``?null:T(e))),c=()=>{a.querySelector(`select`).value=r()};break;case`width`:{let e=n(),i=typeof e==`number`&&!_.includes(e)?[..._,e].sort((e,t)=>e-t):_;a=f(t,r(),[...s,...i.map(e=>({value:String(e),label:`${e}px`}))],e=>o(e===``?null:Number(e))),c=()=>{a.querySelector(`select`).value=r()};break}default:{let r=n(),i=u(t,typeof r==`string`?r:null,o,{read:()=>{let e=n();return typeof e==`string`?e:null},start:e.auto?()=>(e.auto?.from?this.callbacks.styleValue(e.auto.from):e.auto?.hint)??null:void 0},this.t);a=i.row,c=i.sync}}return this.lookRows.push({el:a,sync:c}),a}lineStyles(){return[{value:`solid`,label:this.t(`drawingSettings.lineStyle.solid`)},{value:`dashed`,label:this.t(`drawingSettings.lineStyle.dashed`)},{value:`dotted`,label:this.t(`drawingSettings.lineStyle.dotted`)}]}renderChartTypeSection(){if(!this.bodyEl||!this.currentSettings||!this.chartType)return;let t=this.chartType,n=this.currentSettings.chartTypeOptions??{},r=e.m.find(e=>e.value===t),i=c(r?e.t(r,this.t):t),a=()=>this.currentSettings?.chartTypeOptions??{},o=(e,t)=>this.patch({chartTypeOptions:{...a(),[e]:t}}),s=(e,t,n,r)=>i.appendChild(h(this.t(e),t,n,r,this.t,this.currentSettings?.numberLocale||void 0));switch(t){case`renko`:{let e=n.renko??{};s(`settings.boxSize`,typeof e.boxSize==`number`?e.boxSize:null,y,e=>o(`renko`,{...a().renko??{},boxSize:e??`atr`})),s(`settings.atrPeriod`,e.atrPeriod??null,{step:`1`,max:500},e=>o(`renko`,w(a().renko,`atrPeriod`,e)));break}case`lineBreak`:s(`settings.lineBreakLines`,n.lineBreak?.lines??null,{step:`1`,max:10},e=>o(`lineBreak`,w(a().lineBreak,`lines`,e)));break;case`kagi`:s(`settings.reversal`,n.kagi?.reversal??null,y,e=>o(`kagi`,w(a().kagi,`reversal`,e))),i.appendChild(f(this.t(`settings.reversalType`),n.kagi?.reversalType??`percent`,[{value:`percent`,label:this.t(`settings.reversalType.percent`)},{value:`price`,label:this.t(`settings.reversalType.price`)}],e=>o(`kagi`,{...a().kagi??{},reversalType:e===`price`?`price`:`percent`})));break;case`pointAndFigure`:s(`settings.boxSize`,typeof n.pointAndFigure?.boxSize==`number`?n.pointAndFigure.boxSize:null,y,e=>o(`pointAndFigure`,{...a().pointAndFigure??{},boxSize:e??`auto`})),s(`settings.reversalBoxes`,n.pointAndFigure?.reversal??null,{step:`1`,max:10},e=>o(`pointAndFigure`,w(a().pointAndFigure,`reversal`,e)));break;case`rangeBars`:s(`settings.barRange`,typeof n.rangeBars?.range==`number`?n.rangeBars.range:null,y,e=>o(`rangeBars`,{range:e??`auto`}));break;default:break}for(let n of e.p(t))i.appendChild(this.lookRow(n));this.bodyEl.appendChild(i)}patch(e){this.currentSettings&&Object.assign(this.currentSettings,e),this.callbacks.onChange(e)}};function S(e,t){return C(e,t)}function C(e,t){if(e===t)return!0;if(typeof e!=`object`||typeof t!=`object`||e===null||t===null||Array.isArray(e)!==Array.isArray(t))return!1;let n=e,r=t,i=new Set([...Object.keys(n),...Object.keys(r)].filter(e=>n[e]!==void 0||r[e]!==void 0));for(let e of i)if(!C(n[e],r[e]))return!1;return!0}function w(e,t,n){let r={...e??{}};return n===null?delete r[t]:r[t]=n,r}function T(e){return e===`dashed`||e===`dotted`?e:`solid`}exports.WidgetSettings=x;
|
|
2
|
-
//# sourceMappingURL=WidgetSettings-
|
|
1
|
+
const e=require(`./widgetLocales-BdRQu8wS.cjs`),t=require(`./focusTrap-DrhhmG0V.cjs`),n=require(`./settingsControls-Tn8_vJJv.cjs`),r=require(`./i18n-BFGknfTa.cjs`);let i=require(`@tradecanvas/commons`);var a=0,o=0,s=20;function c(e){let t=document.createElement(`div`);if(t.className=`tcw-settings-section`,e){let n=document.createElement(`div`);n.className=`tcw-settings-section-title`,n.textContent=e,t.appendChild(n),t.setAttribute(`role`,`group`),t.setAttribute(`aria-label`,e)}return t}function l(e){let t=document.createElement(`div`);t.className=`tcw-settings-row`;let n=document.createElement(`span`);return n.className=`tcw-settings-label`,n.textContent=e,t.appendChild(n),t}function u(e,t,r,i,o){let s=l(e),c=document.createElement(`div`);c.className=`tcw-color-picker-wrap`;let u=document.createElement(`input`);u.type=`color`,u.setAttribute(`aria-label`,e);let d=document.createElement(`span`);d.className=`tcw-color-hex`,d.id=`tcw-color-${++a}`,u.setAttribute(`aria-describedby`,d.id);let f=null,p=t=>{u.value=n.l(t??i.start?.()),d.textContent=t??o(`settings.auto`),s.classList.toggle(`tcw-color-auto`,t===null),t!==null&&i.start&&!f?(f=document.createElement(`button`),f.type=`button`,f.className=`tcw-color-auto-btn`,f.textContent=o(`settings.auto`),f.setAttribute(`aria-label`,`${e}: ${o(`settings.auto`)}`),f.addEventListener(`click`,()=>{r(null),u.focus(),p(i.read())}),c.appendChild(f)):t===null&&f&&(f.remove(),f=null)};return u.addEventListener(`input`,()=>{r(u.value),p(u.value)}),c.append(u,d),s.appendChild(c),p(t),{row:s,sync:()=>p(i.read())}}function d(e,t,n){let r=l(e),i=document.createElement(`button`);return i.type=`button`,i.className=`tcw-toggle${t?` tcw-on`:``}`,i.setAttribute(`role`,`switch`),i.setAttribute(`aria-checked`,String(t)),i.setAttribute(`aria-label`,e),i.addEventListener(`click`,()=>{let e=!i.classList.contains(`tcw-on`);i.classList.toggle(`tcw-on`,e),i.setAttribute(`aria-checked`,String(e)),n(e)}),r.appendChild(i),r}function f(e,t,n,r){let i=l(e),a=document.createElement(`select`);a.className=`tcw-settings-select`,a.setAttribute(`aria-label`,e);for(let e of n){let n=document.createElement(`option`);n.value=e.value,n.textContent=e.label,e.value===t&&(n.selected=!0),a.appendChild(n)}return n.some(e=>e.value===t)||(a.selectedIndex=-1),a.addEventListener(`change`,()=>r(a.value)),i.appendChild(a),i}function p(e,t,n,r,i=e=>String(e)){let a=l(e),o=document.createElement(`div`);o.className=`tcw-settings-range`;let s=document.createElement(`input`);s.type=`range`,s.min=String(n.min),s.max=String(n.max),s.step=String(n.step),s.value=String(t),s.setAttribute(`aria-label`,e);let c=document.createElement(`span`);return c.className=`tcw-settings-range-val`,c.textContent=i(t),s.addEventListener(`input`,()=>{let e=Number(s.value);c.textContent=i(e),r(e)}),o.append(s,c),a.appendChild(o),a}function m(e,t,n){let i=new Intl.NumberFormat(n,{maximumFractionDigits:s}).format;return e.step===`1`&&Number.isFinite(e.max)?r.r(t(`settings.numberWhole`),{min:i(Math.max(1,e.min??1)),max:i(e.max)}):r.r(t(`settings.numberAtLeast`),{min:i(e.min??0)})}function h(e,t,n,r,i,a=`en-US`){let s=document.createElement(`div`);s.className=`tcw-settings-row tcw-settings-row--number`;let c=document.createElement(`label`);c.className=`tcw-settings-label`,c.textContent=e,s.appendChild(c);let l=document.createElement(`input`);l.type=`number`,l.className=`tcw-settings-number`,l.min=`0`,l.step=n.step,Number.isFinite(n.max)&&(l.max=String(n.max)),l.placeholder=i(`settings.auto`),l.value=t===null?``:String(t),l.setAttribute(`aria-label`,e);let u=document.createElement(`div`);u.className=`tcw-settings-hint`,u.id=`tcw-number-hint-${++o}`,u.setAttribute(`role`,`status`),l.setAttribute(`aria-describedby`,u.id);let d=e=>{e?l.removeAttribute(`aria-invalid`):l.setAttribute(`aria-invalid`,`true`),u.textContent=e?``:m(n,i,a)};return l.addEventListener(`change`,()=>{if(l.value.trim()===``){d(!0),r(null);return}let e=Number(l.value),t=Number.isFinite(e)&&e>0&&e>=(n.min??0)&&e<=n.max&&(n.step!==`1`||Number.isInteger(e));d(t),t&&r(e)}),s.append(l,u),s}var g=[{id:`symbol`,icon:`chartType:candlestick`},{id:`statusLine`,icon:`type`},{id:`scales`,icon:`ruler`},{id:`appearance`,icon:`palette`},{id:`layers`,icon:`layers`},{id:`trading`,icon:`trendingUp`}],_=[1,2,3,4],v=`t:`,y={step:`any`,max:1/0,min:1e-8},b=1,x=class{callbacks;t;backdrop=null;modal=null;bodyEl=null;tabButtons=[];templateBtn=null;menu=null;currentTab=`symbol`;currentSettings=null;chartType=null;lookRows=[];returnFocus=null;uid=b++;constructor(e,t,n={},r=()=>document.body){this.available=n,this.host=r,this.callbacks=e,this.t=t}open(e,t=null,n=`symbol`){this.modal&&this.remove(),this.returnFocus=document.activeElement instanceof HTMLElement?document.activeElement:null,this.currentSettings={...e},this.chartType=t,this.currentTab=n,this.buildModal(),this.tabButtons.find(e=>e.dataset.tab===n)?.focus()}isOpen(){return this.modal!==null}follow(e){!this.modal||this.currentSettings&&S(this.currentSettings,e)||this.refresh(e)}refresh(e,t){if(!this.modal)return;this.currentSettings={...e},t!==void 0&&(this.chartType=t);let n=this.focusedControl();this.renderTabContent(),n!==null&&this.focusControl(n)}focusedControl(){let e=document.activeElement;if(!this.bodyEl||!(e instanceof HTMLElement)||!this.bodyEl.contains(e))return null;let t=this.panelControls().indexOf(e);return t<0?null:t}focusControl(e){let t=this.panelControls();(t[Math.min(e,t.length-1)]??this.tabButtons.find(e=>e.dataset.tab===this.currentTab))?.focus()}panelControls(){return this.bodyEl?[...this.bodyEl.querySelectorAll(t.t)]:[]}close(){this.finish(!0)}destroy(){this.remove()}finish(e){this.modal&&(e?this.callbacks.onClose():this.callbacks.onCancel?.(),this.remove(),this.returnFocus?.isConnected&&this.returnFocus.focus(),this.returnFocus=null)}remove(){this.menu?.destroy(),this.menu=null,this.backdrop?.remove(),this.backdrop=this.modal=this.bodyEl=this.templateBtn=null,this.tabButtons=[]}buildModal(){let e=document.createElement(`div`);e.className=`tcw-modal-backdrop`;let n=!1;e.addEventListener(`pointerdown`,t=>{n=t.target===e}),e.addEventListener(`click`,t=>{t.target===e&&n&&this.finish(!1),n=!1});let r=document.createElement(`div`);r.className=`tcw-modal tcw-set`,r.setAttribute(`role`,`dialog`),r.setAttribute(`aria-modal`,`true`),r.setAttribute(`aria-labelledby`,`tcw-set-title-${this.uid}`),r.tabIndex=-1,r.addEventListener(`keydown`,e=>{if(e.key===`Escape`){e.preventDefault(),e.stopPropagation(),this.finish(!1);return}t.n(e,r)}),this.backdrop=e,this.modal=r,r.append(this.buildHeader(),this.buildBody(),this.buildFooter()),e.appendChild(r),this.host().appendChild(e),this.markTabs(),this.renderTabContent()}buildHeader(){let e=document.createElement(`div`);e.className=`tcw-modal-header`;let n=document.createElement(`h3`);n.id=`tcw-set-title-${this.uid}`,n.textContent=this.t(`settings.title`);let r=document.createElement(`button`);return r.type=`button`,r.className=`tcw-modal-close`,r.setAttribute(`aria-label`,this.t(`common.close`)),r.innerHTML=t.i(`x`,16),r.addEventListener(`click`,()=>this.finish(!1)),e.append(n,r),e}buildBody(){let e=document.createElement(`div`);e.className=`tcw-set-body`;let n=document.createElement(`div`);n.className=`tcw-set-nav`,n.setAttribute(`role`,`tablist`),n.setAttribute(`aria-orientation`,`vertical`),n.setAttribute(`aria-label`,this.t(`settings.title`)),n.addEventListener(`keydown`,e=>this.onTabKey(e)),this.tabButtons=g.map(({id:e,icon:n})=>{let r=document.createElement(`button`);return r.type=`button`,r.className=`tcw-set-tab`,r.id=`tcw-set-tab-${this.uid}-${e}`,r.dataset.tab=e,r.setAttribute(`role`,`tab`),r.setAttribute(`aria-controls`,`tcw-set-panel-${this.uid}`),r.innerHTML=`${n.startsWith(`chartType:`)?t.r(n.slice(10),16):t.i(n,16)}<span></span>`,r.querySelector(`span`).textContent=this.t(`settings.tab.${e}`),r.addEventListener(`click`,()=>this.selectTab(e)),r}),n.append(...this.tabButtons);let r=document.createElement(`div`);return r.className=`tcw-modal-body tcw-set-panel`,r.id=`tcw-set-panel-${this.uid}`,r.setAttribute(`role`,`tabpanel`),this.bodyEl=r,e.append(n,r),e}buildFooter(){let e=document.createElement(`div`);e.className=`tcw-modal-footer`;let n=this.footerButton(`template`,`tcw-footer-menu`,()=>this.openTemplates());n.setAttribute(`aria-haspopup`,`menu`),n.setAttribute(`aria-expanded`,`false`),n.innerHTML=`<span></span>${t.i(`chevronDown`,12)}`,n.querySelector(`span`).textContent=this.t(`settings.template`),this.templateBtn=n;let r=document.createElement(`div`);return r.className=`tcw-footer-end`,r.append(this.footerButton(`cancel`,`tcw-footer-cancel`,()=>this.finish(!1),this.t(`common.cancel`)),this.footerButton(`ok`,`tcw-done-btn`,()=>this.finish(!0),this.t(`drawingSettings.ok`))),e.append(n,r),e}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}markTabs(){for(let e of this.tabButtons){let t=e.dataset.tab===this.currentTab;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.currentTab=e,this.markTabs(),this.renderTabContent(),t&&this.tabButtons.find(t=>t.dataset.tab===e)?.focus()}onTabKey(e){let t=g.findIndex(e=>e.id===this.currentTab),n=e.key===`ArrowDown`||e.key===`ArrowRight`?(t+1)%g.length:e.key===`ArrowUp`||e.key===`ArrowLeft`?(t-1+g.length)%g.length:e.key===`Home`?0:e.key===`End`?g.length-1:-1;n<0||(e.preventDefault(),this.selectTab(g[n].id,!0))}openTemplates(){let e=this.templateBtn;if(!this.modal||!e)return;if(this.menu?.isOpen()){this.menu.close();return}let t=this.callbacks.templates,i=(t?.list()??[]).map(e=>({id:`${v}${e}`,label:e,icon:`layers`,remove:r.r(this.t(`templates.delete`),{name:e})})),a=[...i,...i.length>0?[`separator`]:[],...t?[{id:`save`,label:this.t(`settings.saveTemplate`),icon:`save`}]:[],{id:`reset`,label:this.t(`settings.resetToDefaults`),icon:`reset`}];this.menu??=new n.f(this.modal,this.t(`settings.template`));let o=e.getBoundingClientRect(),s=this.modal.getBoundingClientRect();this.menu.open(a,o.left-s.left,o.top-s.top,e=>{e===`reset`?this.callbacks.onReset():e===`save`?t?.save():e.startsWith(v)&&t?.apply(e.slice(2))},e,e=>t?.remove(e.slice(2)))}renderTabContent(){if(!(!this.bodyEl||!this.currentSettings))switch(this.bodyEl.replaceChildren(),this.lookRows=[],this.currentTab){case`symbol`:this.renderSymbolTab(this.currentSettings);break;case`statusLine`:this.renderStatusLineTab(this.currentSettings);break;case`scales`:this.renderScalesTab(this.currentSettings);break;case`appearance`:this.renderAppearanceTab(this.currentSettings);break;case`layers`:this.renderLayersTab(this.currentSettings);break;case`trading`:for(let t of e.d)(!t.trading||this.available.trading!==!1)&&this.renderLookSection(t);break}}renderSymbolTab(t){this.renderChartTypeSection(),this.addSection(void 0,[d(this.t(`settings.mainSeries`),t.mainSeriesVisible,e=>this.patch({mainSeriesVisible:e})),d(this.t(`settings.extendedHours`),t.extendedHours,e=>this.patch({extendedHours:e}))]);let n=this.t(`common.show`);this.renderLookSection(e.o),this.available.volume!==!1&&this.renderLookSection(e.f,[d(n,t.volumeVisible,e=>this.patch({volumeVisible:e}))]),this.renderLookSection(e.a,[d(n,t.highLowLines,e=>this.patch({highLowLines:e}))])}renderStatusLineTab(t){let n=this.available.legend!==!1,r=n?e.u:e.u.filter(t=>!e.s.includes(t));this.addSection(void 0,[...n?[d(this.t(`settings.ohlcLegend`),t.legendVisible,e=>this.patch({legendVisible:e}))]:[],...r.map(e=>this.lookRow(e))])}renderScalesTab(t){let n=[{value:`regular`,label:this.t(`settings.scale.regular`)},{value:`logarithmic`,label:this.t(`settings.scale.logarithmic`)},{value:`percentage`,label:this.t(`settings.scale.percentage`)},{value:`indexedTo100`,label:this.t(`settings.scale.indexedTo100`)}].filter(e=>e.value!==`logarithmic`||this.available.logScale!==!1),r=this.available.exchangeZone?.(),i=e.y(t.timezone,Date.now(),this.t(`settings.timezone.local`),r===void 0?void 0:{label:this.t(`settings.timezone.exchange`),zone:r});this.addSection(void 0,[f(this.t(`settings.priceScale`),t.scaleMode,n,e=>this.patch({scaleMode:e})),d(this.t(`settings.autoScale`),t.autoScale,e=>this.patch({autoScale:e})),d(this.t(`settings.invertScale`),t.invertScale,e=>this.patch({invertScale:e})),d(this.t(`settings.leftScale`),t.leftPriceScale,e=>this.patch({leftPriceScale:e})),d(this.t(`settings.indicatorValues`),t.indicatorValueLabels,e=>this.patch({indicatorValueLabels:e})),d(this.t(`settings.alignAxisLabels`),t.alignAxisLabels,e=>this.patch({alignAxisLabels:e})),...this.available.barCountdown===!1?[]:[d(this.t(`settings.barCountdown`),t.barCountdown,e=>this.patch({barCountdown:e}))],f(this.t(`settings.timezone`),t.timezone,i,e=>this.patch({timezone:e})),f(this.t(`settings.numberLocale`),t.numberLocale,e.r(t.numberLocale),e=>this.patch({numberLocale:e}))]),this.addSection(this.t(`settings.section.axes`),e.c.map(e=>this.lookRow(e)))}renderAppearanceTab(t){let[n,r,i,...a]=e.i;this.renderLookSection(n),this.renderLookSection(r,[d(this.t(`common.show`),t.gridVisible,e=>this.patch({gridVisible:e}))]),this.renderLookSection(i,[f(this.t(`settings.crosshairMode`),t.crosshairMode,[{label:this.t(`settings.crosshair.magnet`),value:`magnet`},{label:this.t(`settings.crosshair.normal`),value:`normal`},{label:this.t(`settings.crosshair.hidden`),value:`hidden`}],e=>this.patch({crosshairMode:e})),f(this.t(`settings.crosshairCursor`),t.crosshairCursor,[{label:this.t(`drawing.cursorCross`),value:`cross`},{label:this.t(`drawing.cursorDot`),value:`dot`},{label:this.t(`drawing.cursorArrow`),value:`arrow`}],e=>this.patch({crosshairCursor:e}))]);for(let e of a)this.renderLookSection(e)}renderLayersTab(e){let t=e=>`${Math.round(e*100)}%`,n=e=>this.t(e);this.addSection(void 0,[d(n(`settings.volumeProfile`),e.volumeProfileVisible,e=>this.patch({volumeProfileVisible:e}))]),this.addSection(void 0,[d(n(`settings.marketProfile`),e.marketProfileVisible,e=>this.patch({marketProfileVisible:e})),d(n(`settings.marketProfileSplit`),e.marketProfileSplit,e=>this.patch({marketProfileSplit:e})),d(n(`settings.marketProfileLetters`),e.marketProfileLetters,e=>this.patch({marketProfileLetters:e})),p(n(`settings.marketProfileBuckets`),e.marketProfileBuckets,{min:8,max:200,step:1},e=>this.patch({marketProfileBuckets:e})),p(n(`settings.marketProfileOpacity`),e.marketProfileOpacity,{min:.05,max:1,step:.05},e=>this.patch({marketProfileOpacity:e}),t)]),this.addSection(void 0,[d(n(`settings.depthHeatmap`),e.depthHeatmapVisible,e=>this.patch({depthHeatmapVisible:e})),p(n(`settings.depthHeatmapOpacity`),e.depthHeatmapOpacity,{min:.1,max:1,step:.05},e=>this.patch({depthHeatmapOpacity:e}),t)]),this.addSection(void 0,[d(n(`settings.swingMarkers`),e.pivotMarkersVisible,e=>this.patch({pivotMarkersVisible:e})),p(n(`settings.swingStrength`),e.pivotStrength,{min:2,max:20,step:1},e=>this.patch({pivotStrength:e})),d(n(`settings.swingStructure`),e.pivotStructureLabels,e=>this.patch({pivotStructureLabels:e}))]),this.addSection(void 0,[d(n(`settings.sessionShading`),e.sessionShadingVisible,e=>this.patch({sessionShadingVisible:e})),d(n(`settings.periodLevels`),e.periodLevelsVisible,e=>this.patch({periodLevelsVisible:e})),f(n(`settings.periodLevelsBasis`),e.periodLevelsPeriod,[{value:`day`,label:n(`settings.priorDay`)},{value:`week`,label:n(`settings.priorWeek`)}],e=>this.patch({periodLevelsPeriod:e}))])}addSection(e,t){let n=c(e);return n.append(...t),this.bodyEl?.appendChild(n),n}renderLookSection(e,t=[]){this.addSection(this.t(e.title),[...t,...e.rows.map(e=>this.lookRow(e))])}lookRow(e){let t=this.t(e.label),n=()=>this.callbacks.styleValue(e.keys[0]),r=()=>{let t=e.keys.map(e=>this.callbacks.styleValue(e));return t.every(e=>e===t[0])&&t[0]!==null?String(t[0]):``},a,o=t=>{this.callbacks.onStyleChange(Object.fromEntries(e.keys.map(e=>[e,t])));for(let e of this.lookRows)e.el!==a&&e.sync()},s=e.auto?[{value:``,label:this.t(`settings.auto`)}]:[],c;switch(i.CHART_STYLE_KEYS[e.keys[0]]){case`boolean`:{a=d(t,n()===!0,o);let e=a.querySelector(`button`);c=()=>{let t=n()===!0;e.classList.toggle(`tcw-on`,t),e.setAttribute(`aria-checked`,String(t))};break}case`lineStyle`:a=f(t,r(),[...s,...this.lineStyles()],e=>o(e===``?null:T(e))),c=()=>{a.querySelector(`select`).value=r()};break;case`width`:{let e=n(),i=typeof e==`number`&&!_.includes(e)?[..._,e].sort((e,t)=>e-t):_;a=f(t,r(),[...s,...i.map(e=>({value:String(e),label:`${e}px`}))],e=>o(e===``?null:Number(e))),c=()=>{a.querySelector(`select`).value=r()};break}default:{let r=n(),i=u(t,typeof r==`string`?r:null,o,{read:()=>{let e=n();return typeof e==`string`?e:null},start:e.auto?()=>(e.auto?.from?this.callbacks.styleValue(e.auto.from):e.auto?.hint)??null:void 0},this.t);a=i.row,c=i.sync}}return this.lookRows.push({el:a,sync:c}),a}lineStyles(){return[{value:`solid`,label:this.t(`drawingSettings.lineStyle.solid`)},{value:`dashed`,label:this.t(`drawingSettings.lineStyle.dashed`)},{value:`dotted`,label:this.t(`drawingSettings.lineStyle.dotted`)}]}renderChartTypeSection(){if(!this.bodyEl||!this.currentSettings||!this.chartType)return;let t=this.chartType,n=this.currentSettings.chartTypeOptions??{},r=e.m.find(e=>e.value===t),i=c(r?e.t(r,this.t):t),a=()=>this.currentSettings?.chartTypeOptions??{},o=(e,t)=>this.patch({chartTypeOptions:{...a(),[e]:t}}),s=(e,t,n,r)=>i.appendChild(h(this.t(e),t,n,r,this.t,this.currentSettings?.numberLocale||void 0));switch(t){case`renko`:{let e=n.renko??{};s(`settings.boxSize`,typeof e.boxSize==`number`?e.boxSize:null,y,e=>o(`renko`,{...a().renko??{},boxSize:e??`atr`})),s(`settings.atrPeriod`,e.atrPeriod??null,{step:`1`,max:500},e=>o(`renko`,w(a().renko,`atrPeriod`,e)));break}case`lineBreak`:s(`settings.lineBreakLines`,n.lineBreak?.lines??null,{step:`1`,max:10},e=>o(`lineBreak`,w(a().lineBreak,`lines`,e)));break;case`kagi`:s(`settings.reversal`,n.kagi?.reversal??null,y,e=>o(`kagi`,w(a().kagi,`reversal`,e))),i.appendChild(f(this.t(`settings.reversalType`),n.kagi?.reversalType??`percent`,[{value:`percent`,label:this.t(`settings.reversalType.percent`)},{value:`price`,label:this.t(`settings.reversalType.price`)}],e=>o(`kagi`,{...a().kagi??{},reversalType:e===`price`?`price`:`percent`})));break;case`pointAndFigure`:s(`settings.boxSize`,typeof n.pointAndFigure?.boxSize==`number`?n.pointAndFigure.boxSize:null,y,e=>o(`pointAndFigure`,{...a().pointAndFigure??{},boxSize:e??`auto`})),s(`settings.reversalBoxes`,n.pointAndFigure?.reversal??null,{step:`1`,max:10},e=>o(`pointAndFigure`,w(a().pointAndFigure,`reversal`,e)));break;case`rangeBars`:s(`settings.barRange`,typeof n.rangeBars?.range==`number`?n.rangeBars.range:null,y,e=>o(`rangeBars`,{range:e??`auto`}));break;default:break}for(let n of e.p(t))i.appendChild(this.lookRow(n));this.bodyEl.appendChild(i)}patch(e){this.currentSettings&&Object.assign(this.currentSettings,e),this.callbacks.onChange(e)}};function S(e,t){return C(e,t)}function C(e,t){if(e===t)return!0;if(typeof e!=`object`||typeof t!=`object`||e===null||t===null||Array.isArray(e)!==Array.isArray(t))return!1;let n=e,r=t,i=new Set([...Object.keys(n),...Object.keys(r)].filter(e=>n[e]!==void 0||r[e]!==void 0));for(let e of i)if(!C(n[e],r[e]))return!1;return!0}function w(e,t,n){let r={...e??{}};return n===null?delete r[t]:r[t]=n,r}function T(e){return e===`dashed`||e===`dotted`?e:`solid`}exports.WidgetSettings=x;
|
|
2
|
+
//# sourceMappingURL=WidgetSettings-CBf6hUSV.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"WidgetSettings-COljE3G_.cjs","names":[],"sources":["../src/widget/settingsRows.ts","../src/widget/WidgetSettings.ts"],"sourcesContent":["import { toHex } from './settingsControls.js';\nimport { fill, type Translator } from './i18n.js';\n\n/**\n * The rows of the chart settings: a section, a colour, a switch, a choice,\n * a slider and a number, each with its label and calling back on change.\n */\n\n/** Ids for the colour rows' descriptions. */\nlet colorRowCount = 0;\n/** Ids for the number rows' hints. */\nlet numberRowCount = 0;\n/** The most decimals a number in a hint shows: the smallest size taken, 0.00000001, has 8. */\nconst HINT_MAX_DECIMALS = 20;\n\n/** A group of rows; a title names it to a screen reader too (rows named alike under several titles). */\nexport function settingsSection(title?: string): HTMLDivElement {\n const div = document.createElement('div');\n div.className = 'tcw-settings-section';\n if (title) {\n const heading = document.createElement('div');\n heading.className = 'tcw-settings-section-title';\n heading.textContent = title;\n div.appendChild(heading);\n div.setAttribute('role', 'group');\n div.setAttribute('aria-label', title);\n }\n return div;\n}\n\nfunction labelledRow(label: string): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n const lbl = document.createElement('span');\n lbl.className = 'tcw-settings-label';\n lbl.textContent = label;\n row.appendChild(lbl);\n return row;\n}\n\n/**\n * A colour of the look, shown again from `look.read()`. With `look.start`,\n * null is the part's own colour: shown as Auto, the picker starting from\n * `start()`, and once set a button takes it back.\n */\nexport function colorRow(\n label: string,\n value: string | null,\n onChange: (v: string | null) => void,\n look: { read: () => string | null; start?: () => string | number | boolean | null },\n t: Translator,\n): { row: HTMLDivElement; sync: () => void } {\n const row = labelledRow(label);\n const wrap = document.createElement('div');\n wrap.className = 'tcw-color-picker-wrap';\n const input = document.createElement('input');\n input.type = 'color';\n input.setAttribute('aria-label', label);\n // What the swatch can't say (Auto, a colour with transparency) is read with it.\n const hex = document.createElement('span');\n hex.className = 'tcw-color-hex';\n hex.id = `tcw-color-${++colorRowCount}`;\n input.setAttribute('aria-describedby', hex.id);\n\n let back: HTMLButtonElement | null = null;\n const show = (v: string | null) => {\n input.value = toHex(v ?? look.start?.());\n hex.textContent = v ?? t('settings.auto');\n row.classList.toggle('tcw-color-auto', v === null);\n if (v !== null && look.start && !back) {\n back = document.createElement('button');\n back.type = 'button';\n back.className = 'tcw-color-auto-btn';\n back.textContent = t('settings.auto');\n back.setAttribute('aria-label', `${label}: ${t('settings.auto')}`);\n back.addEventListener('click', () => {\n onChange(null);\n // Focus stays in the row as the button goes; the chart may still draw a colour the host set.\n input.focus();\n show(look.read());\n });\n wrap.appendChild(back);\n } else if (v === null && back) {\n back.remove();\n back = null;\n }\n };\n input.addEventListener('input', () => {\n onChange(input.value);\n show(input.value);\n });\n wrap.append(input, hex);\n row.appendChild(wrap);\n show(value);\n return { row, sync: () => show(look.read()) };\n}\n\nexport function toggleRow(label: string, value: boolean, onChange: (v: boolean) => void): HTMLDivElement {\n const row = labelledRow(label);\n const toggle = document.createElement('button');\n toggle.type = 'button';\n toggle.className = `tcw-toggle${value ? ' tcw-on' : ''}`;\n toggle.setAttribute('role', 'switch');\n toggle.setAttribute('aria-checked', String(value));\n toggle.setAttribute('aria-label', label);\n toggle.addEventListener('click', () => {\n const next = !toggle.classList.contains('tcw-on');\n toggle.classList.toggle('tcw-on', next);\n toggle.setAttribute('aria-checked', String(next));\n onChange(next);\n });\n row.appendChild(toggle);\n return row;\n}\n\nexport function selectRow(\n label: string,\n value: string,\n options: readonly { label: string; value: string }[],\n onChange: (v: string) => void,\n): HTMLDivElement {\n const row = labelledRow(label);\n const select = document.createElement('select');\n select.className = 'tcw-settings-select';\n select.setAttribute('aria-label', label);\n for (const opt of options) {\n const o = document.createElement('option');\n o.value = opt.value;\n o.textContent = opt.label;\n if (opt.value === value) o.selected = true;\n select.appendChild(o);\n }\n // A value none of the options has (two keys that differ): nothing chosen, so any pick is a change.\n if (!options.some((opt) => opt.value === value)) select.selectedIndex = -1;\n select.addEventListener('change', () => onChange(select.value));\n row.appendChild(select);\n return row;\n}\n\nexport function rangeRow(\n label: string,\n value: number,\n range: { min: number; max: number; step: number },\n onChange: (v: number) => void,\n format: (v: number) => string = (v) => String(v),\n): HTMLDivElement {\n const row = labelledRow(label);\n const wrap = document.createElement('div');\n wrap.className = 'tcw-settings-range';\n const input = document.createElement('input');\n input.type = 'range';\n input.min = String(range.min);\n input.max = String(range.max);\n input.step = String(range.step);\n input.value = String(value);\n input.setAttribute('aria-label', label);\n const out = document.createElement('span');\n out.className = 'tcw-settings-range-val';\n out.textContent = format(value);\n input.addEventListener('input', () => {\n const v = Number(input.value);\n out.textContent = format(v);\n onChange(v);\n });\n wrap.append(input, out);\n row.appendChild(wrap);\n return row;\n}\n\n/** What a number field takes. */\nexport interface NumberLimits {\n /** The field's step: '1' takes whole counts only, 'any' any number. */\n step: string;\n /** The largest number taken (Infinity: no limit). */\n max: number;\n /** The smallest number taken; without one, any number above 0. */\n min?: number;\n}\n\n/** What a number field takes, in words: the hint under it once it turned a number away. */\nfunction limitsText(limits: NumberLimits, t: Translator, locale: string): string {\n const format = new Intl.NumberFormat(locale, { maximumFractionDigits: HINT_MAX_DECIMALS }).format;\n if (limits.step === '1' && Number.isFinite(limits.max)) {\n return fill(t('settings.numberWhole'), { min: format(Math.max(1, limits.min ?? 1)), max: format(limits.max) });\n }\n return fill(t('settings.numberAtLeast'), { min: format(limits.min ?? 0) });\n}\n\n/**\n * A number field; empty means \"worked out from the data\" (shown as Auto). Only numbers above 0, and from\n * `limits.min` on, are taken; one turned away is marked invalid, and a hint under it, in `locale`, says what is.\n */\nexport function numberRow(\n label: string,\n value: number | null,\n limits: NumberLimits,\n onChange: (v: number | null) => void,\n t: Translator,\n locale = 'en-US',\n): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row tcw-settings-row--number';\n const lbl = document.createElement('label');\n lbl.className = 'tcw-settings-label';\n lbl.textContent = label;\n row.appendChild(lbl);\n const input = document.createElement('input');\n input.type = 'number';\n input.className = 'tcw-settings-number';\n // The min attribute is also where the arrows step from: at 1e-8, the up arrow turns 5 into 5.00000001 and an\n // empty field into 1e-8. It stays 0, and the smallest number taken is checked on change.\n input.min = '0';\n input.step = limits.step;\n if (Number.isFinite(limits.max)) input.max = String(limits.max);\n input.placeholder = t('settings.auto');\n input.value = value === null ? '' : String(value);\n input.setAttribute('aria-label', label);\n // Written when a number is turned away, and heard with the field: red alone says nothing to a screen reader.\n const hint = document.createElement('div');\n hint.className = 'tcw-settings-hint';\n hint.id = `tcw-number-hint-${++numberRowCount}`;\n hint.setAttribute('role', 'status');\n input.setAttribute('aria-describedby', hint.id);\n const mark = (ok: boolean) => {\n if (ok) input.removeAttribute('aria-invalid');\n else input.setAttribute('aria-invalid', 'true');\n hint.textContent = ok ? '' : limitsText(limits, t, locale);\n };\n input.addEventListener('change', () => {\n if (input.value.trim() === '') {\n mark(true);\n onChange(null);\n return;\n }\n const v = Number(input.value);\n const ok = Number.isFinite(v) && v > 0 && v >= (limits.min ?? 0) && v <= limits.max && (limits.step !== '1' || Number.isInteger(v));\n mark(ok);\n if (ok) onChange(v);\n });\n row.append(input, hint);\n return row;\n}\n","import { CHART_STYLE_KEYS, type ChartType, type ChartTypeOptions, type LineStyle } from '@tradecanvas/commons';\nimport type { ChartSettingsState, SettingsCallbacks, SettingsStylePatch } from './types.js';\nimport { CHART_TYPES } from './widgetConfig.js';\nimport {\n APPEARANCE_SECTIONS, HIGH_LOW_SECTION, LAST_PRICE_SECTION, LEGEND_ROWS, SCALE_ROWS, STATUS_LINE_ROWS, TRADING_SECTIONS, VOLUME_SECTION,\n seriesRows, type LookRow, type LookSection,\n} from './widgetSettingsLook.js';\nimport { chartTypeLabel, numberLocaleOptions } from './widgetLocales.js';\nimport { createChartTypeIcon, createIcon } from './icons.js';\nimport { timezoneOptions } from './widgetTimezones.js';\nimport { FOCUSABLE, keepTabInside } from './focusTrap.js';\nimport { WidgetContextMenu, type ContextMenuEntry } from './WidgetContextMenu.js';\nimport { colorRow, numberRow, rangeRow, selectRow, settingsSection, toggleRow, type NumberLimits } from './settingsRows.js';\nimport { fill, type MessageKey, type Translator } from './i18n.js';\n\nexport type SettingsTab = 'symbol' | 'statusLine' | 'scales' | 'appearance' | 'layers' | 'trading';\ntype Tab = SettingsTab;\n\n/** The tabs down the side, in the order a trader looks: the symbol first, the trading colours last. */\nconst TABS: readonly { id: Tab; icon: string }[] = [\n { id: 'symbol', icon: 'chartType:candlestick' },\n { id: 'statusLine', icon: 'type' },\n { id: 'scales', icon: 'ruler' },\n { id: 'appearance', icon: 'palette' },\n { id: 'layers', icon: 'layers' },\n { id: 'trading', icon: 'trendingUp' },\n];\n/** The widths a line takes in the settings, in pixels. */\nconst LINE_WIDTHS = [1, 2, 3, 4];\n/** A template's entry in the Template menu, by its name. */\nconst TEMPLATE_ID = 't:';\n/**\n * The smallest box, reversal or range the chart type's settings take: a\n * hundred-millionth, the finest price step markets commonly quote. A size\n * far under the prices is no use; the chart raises one that would make too\n * many bars anyway, but a slip like 1e-9 is turned away here.\n */\nconst MIN_TYPE_SIZE = 1e-8;\n/** A box, reversal or range: any number from MIN_TYPE_SIZE up. */\nconst SIZE_LIMITS: NumberLimits = { step: 'any', max: Infinity, min: MIN_TYPE_SIZE };\n\nlet nextSettingsId = 1;\n\n/**\n * The chart's settings: tabs down the side (Symbol, Status line, Scales,\n * Appearance, Layers, Trading), each change shown at once. Cancel (Escape,\n * the close button, a click outside) puts it all back, OK keeps it; the\n * Template menu applies, saves and deletes templates, and resets.\n */\nexport class WidgetSettings {\n private callbacks: SettingsCallbacks;\n private t: Translator;\n private backdrop: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private bodyEl: HTMLDivElement | null = null;\n private tabButtons: HTMLButtonElement[] = [];\n private templateBtn: HTMLButtonElement | null = null;\n private menu: WidgetContextMenu | null = null;\n private currentTab: Tab = 'symbol';\n private currentSettings: ChartSettingsState | null = null;\n /** The chart's type, whose settings the Symbol tab offers. */\n private chartType: ChartType | null = null;\n /** The look's rows on view, each showing the chart's value again (a change to one moves others: a wick with its body). */\n private lookRows: { el: HTMLElement; sync: () => void }[] = [];\n private returnFocus: HTMLElement | null = null;\n private readonly uid = nextSettingsId++;\n\n /**\n * `barCountdown` / `logScale` / `legend` / `volume` false leave out the\n * controls for features the chart has switched off: there they would do\n * nothing.\n */\n constructor(\n callbacks: SettingsCallbacks,\n t: Translator,\n private readonly available: {\n barCountdown?: boolean;\n logScale?: boolean;\n legend?: boolean;\n volume?: boolean;\n /** The exchange's time zone to offer (null while unknown), or undefined when there is none to offer. */\n exchangeZone?: () => string | null | undefined;\n /** false: the chart doesn't trade, so the orders' colours aren't offered. */\n trading?: boolean;\n } = {},\n /** Where the panel mounts (the widget's portal: themed, and inside it when fullscreen). */\n private readonly host: () => HTMLElement = () => document.body,\n ) {\n this.callbacks = callbacks;\n this.t = t;\n }\n\n /** Open on `tab` (the Symbol tab unless asked: the price axis's menu asks for Scales). */\n open(currentSettings: ChartSettingsState, chartType: ChartType | null = null, tab: SettingsTab = 'symbol'): void {\n if (this.modal) this.remove();\n this.returnFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n this.currentSettings = { ...currentSettings };\n this.chartType = chartType;\n this.currentTab = tab;\n this.buildModal();\n this.tabButtons.find((b) => b.dataset.tab === tab)?.focus();\n }\n\n isOpen(): boolean {\n return this.modal !== null;\n }\n\n /** Show `settings` when they differ from what the dialog shows: a change made outside it while it is open. */\n follow(settings: ChartSettingsState): void {\n if (!this.modal || (this.currentSettings && sameSettings(this.currentSettings, settings))) return;\n this.refresh(settings);\n }\n\n /** The settings as they are now (after an undo, a template), on the tab that's open; `chartType` when it changed. */\n refresh(settings: ChartSettingsState, chartType?: ChartType | null): void {\n if (!this.modal) return;\n this.currentSettings = { ...settings };\n if (chartType !== undefined) this.chartType = chartType;\n // A change from outside (a compare's bars, the host's setSettings) builds the panel again under the\n // control in focus: focus goes to the one in its place, not to the page outside the dialog.\n const focused = this.focusedControl();\n this.renderTabContent();\n if (focused !== null) this.focusControl(focused);\n }\n\n /** The place of the control in focus among the panel's, or null when focus is not in the panel. */\n private focusedControl(): number | null {\n const active = document.activeElement;\n if (!this.bodyEl || !(active instanceof HTMLElement) || !this.bodyEl.contains(active)) return null;\n const at = this.panelControls().indexOf(active);\n return at < 0 ? null : at;\n }\n\n /** Focus the panel's control at `index`, or its last when it has fewer; the tab when it has none. */\n private focusControl(index: number): void {\n const controls = this.panelControls();\n const control = controls[Math.min(index, controls.length - 1)] ?? this.tabButtons.find((b) => b.dataset.tab === this.currentTab);\n control?.focus();\n }\n\n private panelControls(): HTMLElement[] {\n return this.bodyEl ? [...this.bodyEl.querySelectorAll<HTMLElement>(FOCUSABLE)] : [];\n }\n\n /** Close, keeping what was changed (as OK does). */\n close(): void {\n this.finish(true);\n }\n\n destroy(): void {\n this.remove();\n }\n\n /** OK (`keep`) or Cancel, then closed, focus back where the dialog was opened from. */\n private finish(keep: boolean): void {\n if (!this.modal) return;\n if (keep) this.callbacks.onClose();\n else this.callbacks.onCancel?.();\n this.remove();\n if (this.returnFocus?.isConnected) this.returnFocus.focus();\n this.returnFocus = null;\n }\n\n private remove(): void {\n this.menu?.destroy();\n this.menu = null;\n this.backdrop?.remove();\n this.backdrop = this.modal = this.bodyEl = this.templateBtn = null;\n this.tabButtons = [];\n }\n\n private buildModal(): void {\n const backdrop = document.createElement('div');\n backdrop.className = 'tcw-modal-backdrop';\n // A press that starts in the dialog (a slider dragged, text selected) and ends on the backdrop doesn't cancel it.\n let pressedBackdrop = false;\n backdrop.addEventListener('pointerdown', (e) => {\n pressedBackdrop = e.target === backdrop;\n });\n backdrop.addEventListener('click', (e) => {\n if (e.target === backdrop && pressedBackdrop) this.finish(false);\n pressedBackdrop = false;\n });\n const modal = document.createElement('div');\n modal.className = 'tcw-modal tcw-set';\n modal.setAttribute('role', 'dialog');\n modal.setAttribute('aria-modal', 'true');\n modal.setAttribute('aria-labelledby', `tcw-set-title-${this.uid}`);\n modal.tabIndex = -1;\n modal.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n this.finish(false);\n return;\n }\n keepTabInside(e, modal);\n });\n this.backdrop = backdrop;\n this.modal = modal;\n modal.append(this.buildHeader(), this.buildBody(), this.buildFooter());\n backdrop.appendChild(modal);\n this.host().appendChild(backdrop);\n this.markTabs();\n this.renderTabContent();\n }\n\n private buildHeader(): HTMLDivElement {\n const header = document.createElement('div');\n header.className = 'tcw-modal-header';\n const title = document.createElement('h3');\n title.id = `tcw-set-title-${this.uid}`;\n title.textContent = this.t('settings.title');\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.finish(false));\n header.append(title, closeBtn);\n return header;\n }\n\n /** The tabs down the side, and the open one's settings beside them. */\n private buildBody(): HTMLDivElement {\n const body = document.createElement('div');\n body.className = 'tcw-set-body';\n const nav = document.createElement('div');\n nav.className = 'tcw-set-nav';\n nav.setAttribute('role', 'tablist');\n nav.setAttribute('aria-orientation', 'vertical');\n nav.setAttribute('aria-label', this.t('settings.title'));\n nav.addEventListener('keydown', (e) => this.onTabKey(e));\n this.tabButtons = TABS.map(({ id, icon }) => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'tcw-set-tab';\n btn.id = `tcw-set-tab-${this.uid}-${id}`;\n btn.dataset.tab = id;\n btn.setAttribute('role', 'tab');\n btn.setAttribute('aria-controls', `tcw-set-panel-${this.uid}`);\n const svg = icon.startsWith('chartType:') ? createChartTypeIcon(icon.slice('chartType:'.length) as ChartType, 16) : createIcon(icon, 16);\n btn.innerHTML = `${svg}<span></span>`;\n btn.querySelector('span')!.textContent = this.t(`settings.tab.${id}` as MessageKey);\n btn.addEventListener('click', () => this.selectTab(id));\n return btn;\n });\n nav.append(...this.tabButtons);\n const panel = document.createElement('div');\n panel.className = 'tcw-modal-body tcw-set-panel';\n panel.id = `tcw-set-panel-${this.uid}`;\n panel.setAttribute('role', 'tabpanel');\n this.bodyEl = panel;\n body.append(nav, panel);\n return body;\n }\n\n /** Template on the left; Cancel and OK on the right. */\n private buildFooter(): HTMLDivElement {\n const footer = document.createElement('div');\n footer.className = 'tcw-modal-footer';\n const template = this.footerButton('template', 'tcw-footer-menu', () => this.openTemplates());\n template.setAttribute('aria-haspopup', 'menu');\n template.setAttribute('aria-expanded', 'false');\n template.innerHTML = `<span></span>${createIcon('chevronDown', 12)}`;\n template.querySelector('span')!.textContent = this.t('settings.template');\n this.templateBtn = template;\n const end = document.createElement('div');\n end.className = 'tcw-footer-end';\n end.append(\n this.footerButton('cancel', 'tcw-footer-cancel', () => this.finish(false), this.t('common.cancel')),\n this.footerButton('ok', 'tcw-done-btn', () => this.finish(true), this.t('drawingSettings.ok')),\n );\n footer.append(template, end);\n return footer;\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 private markTabs(): void {\n for (const btn of this.tabButtons) {\n const on = btn.dataset.tab === this.currentTab;\n btn.classList.toggle('tcw-active', on);\n btn.setAttribute('aria-selected', String(on));\n btn.tabIndex = on ? 0 : -1;\n if (on) this.bodyEl?.setAttribute('aria-labelledby', btn.id);\n }\n }\n\n private selectTab(tab: Tab, focus = false): void {\n this.currentTab = tab;\n this.markTabs();\n this.renderTabContent();\n if (focus) this.tabButtons.find((b) => b.dataset.tab === tab)?.focus();\n }\n\n /** Through the tabs (Home, End), picking as they go: up and down, or along the row of chips on a phone. */\n private onTabKey(e: KeyboardEvent): void {\n const at = TABS.findIndex((tab) => tab.id === this.currentTab);\n const next = e.key === 'ArrowDown' || e.key === 'ArrowRight' ? (at + 1) % TABS.length\n : e.key === 'ArrowUp' || e.key === 'ArrowLeft' ? (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].id, true);\n }\n\n /** The Template menu: the saved templates (each removable), Save as template, Reset to defaults. */\n private openTemplates(): void {\n const btn = this.templateBtn;\n if (!this.modal || !btn) return;\n if (this.menu?.isOpen()) {\n this.menu.close();\n return;\n }\n const templates = this.callbacks.templates;\n const saved: ContextMenuEntry[] = (templates?.list() ?? []).map((name) => ({\n id: `${TEMPLATE_ID}${name}`, label: name, icon: 'layers', remove: fill(this.t('templates.delete'), { name }),\n }));\n const entries: ContextMenuEntry[] = [\n ...saved,\n ...(saved.length > 0 ? ['separator' as const] : []),\n ...(templates ? [{ id: 'save', label: this.t('settings.saveTemplate'), icon: 'save' }] : []),\n { id: 'reset', label: this.t('settings.resetToDefaults'), icon: 'reset' },\n ];\n this.menu ??= new WidgetContextMenu(this.modal, this.t('settings.template'));\n const at = btn.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 === 'reset') this.callbacks.onReset();\n else if (id === 'save') templates?.save();\n else if (id.startsWith(TEMPLATE_ID)) templates?.apply(id.slice(TEMPLATE_ID.length));\n }, btn, (id) => templates?.remove(id.slice(TEMPLATE_ID.length)));\n }\n\n private renderTabContent(): void {\n if (!this.bodyEl || !this.currentSettings) return;\n this.bodyEl.replaceChildren();\n this.lookRows = [];\n switch (this.currentTab) {\n case 'symbol': this.renderSymbolTab(this.currentSettings); break;\n case 'statusLine': this.renderStatusLineTab(this.currentSettings); break;\n case 'scales': this.renderScalesTab(this.currentSettings); break;\n case 'appearance': this.renderAppearanceTab(this.currentSettings); break;\n case 'layers': this.renderLayersTab(this.currentSettings); break;\n case 'trading':\n for (const section of TRADING_SECTIONS) {\n if (!section.trading || this.available.trading !== false) this.renderLookSection(section);\n }\n break;\n }\n }\n\n /** The chart type's own settings and colours, the main series, the last price, the volume, the high and low. */\n private renderSymbolTab(s: ChartSettingsState): void {\n this.renderChartTypeSection();\n this.addSection(undefined, [\n toggleRow(this.t('settings.mainSeries'), s.mainSeriesVisible, (v) => this.patch({ mainSeriesVisible: v })),\n toggleRow(this.t('settings.extendedHours'), s.extendedHours, (v) => this.patch({ extendedHours: v })),\n ]);\n // A section's own switch says \"Show\": its title names what it shows.\n const show = this.t('common.show');\n this.renderLookSection(LAST_PRICE_SECTION);\n if (this.available.volume !== false) {\n this.renderLookSection(VOLUME_SECTION, [toggleRow(show, s.volumeVisible, (v) => this.patch({ volumeVisible: v }))]);\n }\n this.renderLookSection(HIGH_LOW_SECTION, [toggleRow(show, s.highLowLines, (v) => this.patch({ highLowLines: v }))]);\n }\n\n /** The legend over the chart: shown or not, its colours; the panes' titles. */\n private renderStatusLineTab(s: ChartSettingsState): void {\n const legend = this.available.legend !== false;\n const rows = legend ? STATUS_LINE_ROWS : STATUS_LINE_ROWS.filter((row) => !LEGEND_ROWS.includes(row));\n this.addSection(undefined, [\n ...(legend ? [toggleRow(this.t('settings.ohlcLegend'), s.legendVisible, (v) => this.patch({ legendVisible: v }))] : []),\n ...rows.map((row) => this.lookRow(row)),\n ]);\n }\n\n /** The price scale's mode and behaviour, its labels, the time zone, how numbers are written, the axes' colours. */\n private renderScalesTab(s: ChartSettingsState): void {\n const scales = [\n { value: 'regular', label: this.t('settings.scale.regular') },\n { value: 'logarithmic', label: this.t('settings.scale.logarithmic') },\n { value: 'percentage', label: this.t('settings.scale.percentage') },\n { value: 'indexedTo100', label: this.t('settings.scale.indexedTo100') },\n ].filter((o) => o.value !== 'logarithmic' || this.available.logScale !== false);\n const exchangeZone = this.available.exchangeZone?.();\n const zones = timezoneOptions(s.timezone, Date.now(), this.t('settings.timezone.local'),\n exchangeZone !== undefined ? { label: this.t('settings.timezone.exchange'), zone: exchangeZone } : undefined);\n this.addSection(undefined, [\n selectRow(this.t('settings.priceScale'), s.scaleMode, scales, (v) => this.patch({ scaleMode: v as ChartSettingsState['scaleMode'] })),\n toggleRow(this.t('settings.autoScale'), s.autoScale, (v) => this.patch({ autoScale: v })),\n toggleRow(this.t('settings.invertScale'), s.invertScale, (v) => this.patch({ invertScale: v })),\n toggleRow(this.t('settings.leftScale'), s.leftPriceScale, (v) => this.patch({ leftPriceScale: v })),\n toggleRow(this.t('settings.indicatorValues'), s.indicatorValueLabels, (v) => this.patch({ indicatorValueLabels: v })),\n toggleRow(this.t('settings.alignAxisLabels'), s.alignAxisLabels, (v) => this.patch({ alignAxisLabels: v })),\n ...(this.available.barCountdown !== false\n ? [toggleRow(this.t('settings.barCountdown'), s.barCountdown, (v) => this.patch({ barCountdown: v }))]\n : []),\n selectRow(this.t('settings.timezone'), s.timezone, zones, (v) => this.patch({ timezone: v })),\n selectRow(this.t('settings.numberLocale'), s.numberLocale, numberLocaleOptions(s.numberLocale), (v) => this.patch({ numberLocale: v })),\n ]);\n this.addSection(this.t('settings.section.axes'), SCALE_ROWS.map((row) => this.lookRow(row)));\n }\n\n /** The background, the grid, the crosshair, the session breaks, the drawings' handles. */\n private renderAppearanceTab(s: ChartSettingsState): void {\n const [background, grid, crosshair, ...rest] = APPEARANCE_SECTIONS;\n this.renderLookSection(background);\n this.renderLookSection(grid, [toggleRow(this.t('common.show'), s.gridVisible, (v) => this.patch({ gridVisible: v }))]);\n this.renderLookSection(crosshair, [selectRow(this.t('settings.crosshairMode'), s.crosshairMode, [\n { label: this.t('settings.crosshair.magnet'), value: 'magnet' },\n { label: this.t('settings.crosshair.normal'), value: 'normal' },\n { label: this.t('settings.crosshair.hidden'), value: 'hidden' },\n ], (v) => this.patch({ crosshairMode: v as ChartSettingsState['crosshairMode'] })),\n selectRow(this.t('settings.crosshairCursor'), s.crosshairCursor, [\n { label: this.t('drawing.cursorCross'), value: 'cross' },\n { label: this.t('drawing.cursorDot'), value: 'dot' },\n { label: this.t('drawing.cursorArrow'), value: 'arrow' },\n ], (v) => this.patch({ crosshairCursor: v as ChartSettingsState['crosshairCursor'] }))]);\n for (const section of rest) this.renderLookSection(section);\n }\n\n /** What the chart can draw over the bars: the profiles, the depth, the swings, the sessions, the prior levels. */\n private renderLayersTab(s: ChartSettingsState): void {\n const percent = (v: number) => `${Math.round(v * 100)}%`;\n const t = (key: MessageKey) => this.t(key);\n this.addSection(undefined, [toggleRow(t('settings.volumeProfile'), s.volumeProfileVisible, (v) => this.patch({ volumeProfileVisible: v }))]);\n this.addSection(undefined, [\n toggleRow(t('settings.marketProfile'), s.marketProfileVisible, (v) => this.patch({ marketProfileVisible: v })),\n toggleRow(t('settings.marketProfileSplit'), s.marketProfileSplit, (v) => this.patch({ marketProfileSplit: v })),\n toggleRow(t('settings.marketProfileLetters'), s.marketProfileLetters, (v) => this.patch({ marketProfileLetters: v })),\n rangeRow(t('settings.marketProfileBuckets'), s.marketProfileBuckets, { min: 8, max: 200, step: 1 }, (v) => this.patch({ marketProfileBuckets: v })),\n rangeRow(t('settings.marketProfileOpacity'), s.marketProfileOpacity, { min: 0.05, max: 1, step: 0.05 }, (v) => this.patch({ marketProfileOpacity: v }), percent),\n ]);\n this.addSection(undefined, [\n toggleRow(t('settings.depthHeatmap'), s.depthHeatmapVisible, (v) => this.patch({ depthHeatmapVisible: v })),\n rangeRow(t('settings.depthHeatmapOpacity'), s.depthHeatmapOpacity, { min: 0.1, max: 1, step: 0.05 }, (v) => this.patch({ depthHeatmapOpacity: v }), percent),\n ]);\n this.addSection(undefined, [\n toggleRow(t('settings.swingMarkers'), s.pivotMarkersVisible, (v) => this.patch({ pivotMarkersVisible: v })),\n rangeRow(t('settings.swingStrength'), s.pivotStrength, { min: 2, max: 20, step: 1 }, (v) => this.patch({ pivotStrength: v })),\n toggleRow(t('settings.swingStructure'), s.pivotStructureLabels, (v) => this.patch({ pivotStructureLabels: v })),\n ]);\n this.addSection(undefined, [\n toggleRow(t('settings.sessionShading'), s.sessionShadingVisible, (v) => this.patch({ sessionShadingVisible: v })),\n toggleRow(t('settings.periodLevels'), s.periodLevelsVisible, (v) => this.patch({ periodLevelsVisible: v })),\n selectRow(t('settings.periodLevelsBasis'), s.periodLevelsPeriod, [\n { value: 'day', label: t('settings.priorDay') },\n { value: 'week', label: t('settings.priorWeek') },\n ], (v) => this.patch({ periodLevelsPeriod: v as ChartSettingsState['periodLevelsPeriod'] })),\n ]);\n }\n\n private addSection(title: string | undefined, rows: readonly HTMLElement[]): HTMLDivElement {\n const section = settingsSection(title);\n section.append(...rows);\n this.bodyEl?.appendChild(section);\n return section;\n }\n\n /** A section of the look, after `lead` (the switch it goes with, say). */\n private renderLookSection(section: LookSection, lead: readonly HTMLElement[] = []): void {\n this.addSection(this.t(section.title), [...lead, ...section.rows.map((row) => this.lookRow(row))]);\n }\n\n /** A row of the look: a colour, a switch, a dash or a width, as its key takes it, on the user's layer. */\n private lookRow(row: LookRow): HTMLDivElement {\n const label = this.t(row.label);\n const read = () => this.callbacks.styleValue(row.keys[0]);\n /** The keys' value, or '' when they differ (the host set each way apart): any pick then sets them all. */\n const shared = (): string => {\n const values = row.keys.map((key) => this.callbacks.styleValue(key));\n return values.every((v) => v === values[0]) && values[0] !== null ? String(values[0]) : '';\n };\n let el: HTMLDivElement;\n const set = (v: string | number | boolean | null) => {\n this.callbacks.onStyleChange(Object.fromEntries(row.keys.map((key) => [key, v])) as SettingsStylePatch);\n for (const other of this.lookRows) if (other.el !== el) other.sync();\n };\n const auto = row.auto ? [{ value: '', label: this.t('settings.auto') }] : [];\n let sync: () => void;\n switch (CHART_STYLE_KEYS[row.keys[0]]) {\n case 'boolean': {\n el = toggleRow(label, read() === true, set);\n const toggle = el.querySelector('button')!;\n sync = () => {\n const on = read() === true;\n toggle.classList.toggle('tcw-on', on);\n toggle.setAttribute('aria-checked', String(on));\n };\n break;\n }\n case 'lineStyle':\n el = selectRow(label, shared(), [...auto, ...this.lineStyles()], (v) => set(v === '' ? null : asLineStyle(v)));\n sync = () => { el.querySelector('select')!.value = shared(); };\n break;\n case 'width': {\n const value = read();\n const widths = typeof value === 'number' && !LINE_WIDTHS.includes(value) ? [...LINE_WIDTHS, value].sort((a, b) => a - b) : LINE_WIDTHS;\n el = selectRow(label, shared(), [...auto, ...widths.map((w) => ({ value: String(w), label: `${w}px` }))],\n (v) => set(v === '' ? null : Number(v)));\n sync = () => { el.querySelector('select')!.value = shared(); };\n break;\n }\n default: {\n const value = read();\n const colour = colorRow(label, typeof value === 'string' ? value : null, set, {\n read: () => { const v = read(); return typeof v === 'string' ? v : null; },\n start: row.auto ? () => (row.auto?.from ? this.callbacks.styleValue(row.auto.from) : row.auto?.hint) ?? null : undefined,\n }, this.t);\n el = colour.row;\n sync = colour.sync;\n }\n }\n this.lookRows.push({ el, sync });\n return el;\n }\n\n private lineStyles(): { value: string; label: string }[] {\n return [\n { value: 'solid', label: this.t('drawingSettings.lineStyle.solid') },\n { value: 'dashed', label: this.t('drawingSettings.lineStyle.dashed') },\n { value: 'dotted', label: this.t('drawingSettings.lineStyle.dotted') },\n ];\n }\n\n /** The chart's type: its settings (Renko's box, Kagi's reversal…) and its colours and widths. */\n private renderChartTypeSection(): void {\n if (!this.bodyEl || !this.currentSettings || !this.chartType) return;\n const type = this.chartType;\n const all = this.currentSettings.chartTypeOptions ?? {};\n const def = CHART_TYPES.find((c) => c.value === type);\n const section = settingsSection(def ? chartTypeLabel(def, this.t) : type);\n const own = () => this.currentSettings?.chartTypeOptions ?? {};\n /** Change one type's settings: the rest of its own stay. */\n const set = <K extends keyof ChartTypeOptions>(key: K, value: NonNullable<ChartTypeOptions[K]>) =>\n this.patch({ chartTypeOptions: { ...own(), [key]: value } });\n const number = (label: MessageKey, value: number | null, limits: NumberLimits, onChange: (v: number | null) => void) =>\n section.appendChild(numberRow(this.t(label), value, limits, onChange, this.t, this.currentSettings?.numberLocale || undefined));\n switch (type) {\n case 'renko': {\n const o = all.renko ?? {};\n number('settings.boxSize', typeof o.boxSize === 'number' ? o.boxSize : null, SIZE_LIMITS,\n (v) => set('renko', { ...(own().renko ?? {}), boxSize: v ?? 'atr' }));\n number('settings.atrPeriod', o.atrPeriod ?? null, { step: '1', max: 500 }, (v) => set('renko', withValue(own().renko, 'atrPeriod', v)));\n break;\n }\n case 'lineBreak':\n number('settings.lineBreakLines', all.lineBreak?.lines ?? null, { step: '1', max: 10 }, (v) => set('lineBreak', withValue(own().lineBreak, 'lines', v)));\n break;\n case 'kagi':\n number('settings.reversal', all.kagi?.reversal ?? null, SIZE_LIMITS, (v) => set('kagi', withValue(own().kagi, 'reversal', v)));\n section.appendChild(selectRow(this.t('settings.reversalType'), all.kagi?.reversalType ?? 'percent', [\n { value: 'percent', label: this.t('settings.reversalType.percent') },\n { value: 'price', label: this.t('settings.reversalType.price') },\n ], (v) => set('kagi', { ...(own().kagi ?? {}), reversalType: v === 'price' ? 'price' : 'percent' })));\n break;\n case 'pointAndFigure':\n number('settings.boxSize', typeof all.pointAndFigure?.boxSize === 'number' ? all.pointAndFigure.boxSize : null, SIZE_LIMITS,\n (v) => set('pointAndFigure', { ...(own().pointAndFigure ?? {}), boxSize: v ?? 'auto' }));\n number('settings.reversalBoxes', all.pointAndFigure?.reversal ?? null, { step: '1', max: 10 },\n (v) => set('pointAndFigure', withValue(own().pointAndFigure, 'reversal', v)));\n break;\n case 'rangeBars':\n number('settings.barRange', typeof all.rangeBars?.range === 'number' ? all.rangeBars.range : null, SIZE_LIMITS,\n (v) => set('rangeBars', { range: v ?? 'auto' }));\n break;\n default:\n break;\n }\n for (const row of seriesRows(type)) section.appendChild(this.lookRow(row));\n this.bodyEl.appendChild(section);\n }\n\n private patch(partial: Partial<ChartSettingsState>): void {\n if (this.currentSettings) Object.assign(this.currentSettings, partial);\n this.callbacks.onChange(partial);\n }\n}\n\n/** Whether two settings say the same, whatever order their keys were set in, at any depth. */\nfunction sameSettings(a: ChartSettingsState, b: ChartSettingsState): boolean {\n return sameValue(a, b);\n}\n\nfunction sameValue(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n const x = a as Record<string, unknown>;\n const y = b as Record<string, unknown>;\n // A key set to undefined is as one not there, as JSON has it.\n const keys = new Set([...Object.keys(x), ...Object.keys(y)].filter((k) => x[k] !== undefined || y[k] !== undefined));\n for (const key of keys) if (!sameValue(x[key], y[key])) return false;\n return true;\n}\n\n/** `settings` with `key` set to `value`, or without it (back to its default) for null. */\nfunction withValue<T extends object, K extends string>(settings: T | undefined, key: K, value: number | null): T {\n const next = { ...(settings ?? {}) } as Record<string, unknown>;\n if (value === null) delete next[key];\n else next[key] = value;\n return next as T;\n}\n\nfunction asLineStyle(v: string): LineStyle {\n return v === 'dashed' || v === 'dotted' ? v : 'solid';\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"WidgetSettings-CBf6hUSV.cjs","names":[],"sources":["../src/widget/settingsRows.ts","../src/widget/WidgetSettings.ts"],"sourcesContent":["import { toHex } from './settingsControls.js';\nimport { fill, type Translator } from './i18n.js';\n\n/**\n * The rows of the chart settings: a section, a colour, a switch, a choice,\n * a slider and a number, each with its label and calling back on change.\n */\n\n/** Ids for the colour rows' descriptions. */\nlet colorRowCount = 0;\n/** Ids for the number rows' hints. */\nlet numberRowCount = 0;\n/** The most decimals a number in a hint shows: the smallest size taken, 0.00000001, has 8. */\nconst HINT_MAX_DECIMALS = 20;\n\n/** A group of rows; a title names it to a screen reader too (rows named alike under several titles). */\nexport function settingsSection(title?: string): HTMLDivElement {\n const div = document.createElement('div');\n div.className = 'tcw-settings-section';\n if (title) {\n const heading = document.createElement('div');\n heading.className = 'tcw-settings-section-title';\n heading.textContent = title;\n div.appendChild(heading);\n div.setAttribute('role', 'group');\n div.setAttribute('aria-label', title);\n }\n return div;\n}\n\nfunction labelledRow(label: string): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row';\n const lbl = document.createElement('span');\n lbl.className = 'tcw-settings-label';\n lbl.textContent = label;\n row.appendChild(lbl);\n return row;\n}\n\n/**\n * A colour of the look, shown again from `look.read()`. With `look.start`,\n * null is the part's own colour: shown as Auto, the picker starting from\n * `start()`, and once set a button takes it back.\n */\nexport function colorRow(\n label: string,\n value: string | null,\n onChange: (v: string | null) => void,\n look: { read: () => string | null; start?: () => string | number | boolean | null },\n t: Translator,\n): { row: HTMLDivElement; sync: () => void } {\n const row = labelledRow(label);\n const wrap = document.createElement('div');\n wrap.className = 'tcw-color-picker-wrap';\n const input = document.createElement('input');\n input.type = 'color';\n input.setAttribute('aria-label', label);\n // What the swatch can't say (Auto, a colour with transparency) is read with it.\n const hex = document.createElement('span');\n hex.className = 'tcw-color-hex';\n hex.id = `tcw-color-${++colorRowCount}`;\n input.setAttribute('aria-describedby', hex.id);\n\n let back: HTMLButtonElement | null = null;\n const show = (v: string | null) => {\n input.value = toHex(v ?? look.start?.());\n hex.textContent = v ?? t('settings.auto');\n row.classList.toggle('tcw-color-auto', v === null);\n if (v !== null && look.start && !back) {\n back = document.createElement('button');\n back.type = 'button';\n back.className = 'tcw-color-auto-btn';\n back.textContent = t('settings.auto');\n back.setAttribute('aria-label', `${label}: ${t('settings.auto')}`);\n back.addEventListener('click', () => {\n onChange(null);\n // Focus stays in the row as the button goes; the chart may still draw a colour the host set.\n input.focus();\n show(look.read());\n });\n wrap.appendChild(back);\n } else if (v === null && back) {\n back.remove();\n back = null;\n }\n };\n input.addEventListener('input', () => {\n onChange(input.value);\n show(input.value);\n });\n wrap.append(input, hex);\n row.appendChild(wrap);\n show(value);\n return { row, sync: () => show(look.read()) };\n}\n\nexport function toggleRow(label: string, value: boolean, onChange: (v: boolean) => void): HTMLDivElement {\n const row = labelledRow(label);\n const toggle = document.createElement('button');\n toggle.type = 'button';\n toggle.className = `tcw-toggle${value ? ' tcw-on' : ''}`;\n toggle.setAttribute('role', 'switch');\n toggle.setAttribute('aria-checked', String(value));\n toggle.setAttribute('aria-label', label);\n toggle.addEventListener('click', () => {\n const next = !toggle.classList.contains('tcw-on');\n toggle.classList.toggle('tcw-on', next);\n toggle.setAttribute('aria-checked', String(next));\n onChange(next);\n });\n row.appendChild(toggle);\n return row;\n}\n\nexport function selectRow(\n label: string,\n value: string,\n options: readonly { label: string; value: string }[],\n onChange: (v: string) => void,\n): HTMLDivElement {\n const row = labelledRow(label);\n const select = document.createElement('select');\n select.className = 'tcw-settings-select';\n select.setAttribute('aria-label', label);\n for (const opt of options) {\n const o = document.createElement('option');\n o.value = opt.value;\n o.textContent = opt.label;\n if (opt.value === value) o.selected = true;\n select.appendChild(o);\n }\n // A value none of the options has (two keys that differ): nothing chosen, so any pick is a change.\n if (!options.some((opt) => opt.value === value)) select.selectedIndex = -1;\n select.addEventListener('change', () => onChange(select.value));\n row.appendChild(select);\n return row;\n}\n\nexport function rangeRow(\n label: string,\n value: number,\n range: { min: number; max: number; step: number },\n onChange: (v: number) => void,\n format: (v: number) => string = (v) => String(v),\n): HTMLDivElement {\n const row = labelledRow(label);\n const wrap = document.createElement('div');\n wrap.className = 'tcw-settings-range';\n const input = document.createElement('input');\n input.type = 'range';\n input.min = String(range.min);\n input.max = String(range.max);\n input.step = String(range.step);\n input.value = String(value);\n input.setAttribute('aria-label', label);\n const out = document.createElement('span');\n out.className = 'tcw-settings-range-val';\n out.textContent = format(value);\n input.addEventListener('input', () => {\n const v = Number(input.value);\n out.textContent = format(v);\n onChange(v);\n });\n wrap.append(input, out);\n row.appendChild(wrap);\n return row;\n}\n\n/** What a number field takes. */\nexport interface NumberLimits {\n /** The field's step: '1' takes whole counts only, 'any' any number. */\n step: string;\n /** The largest number taken (Infinity: no limit). */\n max: number;\n /** The smallest number taken; without one, any number above 0. */\n min?: number;\n}\n\n/** What a number field takes, in words: the hint under it once it turned a number away. */\nfunction limitsText(limits: NumberLimits, t: Translator, locale: string): string {\n const format = new Intl.NumberFormat(locale, { maximumFractionDigits: HINT_MAX_DECIMALS }).format;\n if (limits.step === '1' && Number.isFinite(limits.max)) {\n return fill(t('settings.numberWhole'), { min: format(Math.max(1, limits.min ?? 1)), max: format(limits.max) });\n }\n return fill(t('settings.numberAtLeast'), { min: format(limits.min ?? 0) });\n}\n\n/**\n * A number field; empty means \"worked out from the data\" (shown as Auto). Only numbers above 0, and from\n * `limits.min` on, are taken; one turned away is marked invalid, and a hint under it, in `locale`, says what is.\n */\nexport function numberRow(\n label: string,\n value: number | null,\n limits: NumberLimits,\n onChange: (v: number | null) => void,\n t: Translator,\n locale = 'en-US',\n): HTMLDivElement {\n const row = document.createElement('div');\n row.className = 'tcw-settings-row tcw-settings-row--number';\n const lbl = document.createElement('label');\n lbl.className = 'tcw-settings-label';\n lbl.textContent = label;\n row.appendChild(lbl);\n const input = document.createElement('input');\n input.type = 'number';\n input.className = 'tcw-settings-number';\n // The min attribute is also where the arrows step from: at 1e-8, the up arrow turns 5 into 5.00000001 and an\n // empty field into 1e-8. It stays 0, and the smallest number taken is checked on change.\n input.min = '0';\n input.step = limits.step;\n if (Number.isFinite(limits.max)) input.max = String(limits.max);\n input.placeholder = t('settings.auto');\n input.value = value === null ? '' : String(value);\n input.setAttribute('aria-label', label);\n // Written when a number is turned away, and heard with the field: red alone says nothing to a screen reader.\n const hint = document.createElement('div');\n hint.className = 'tcw-settings-hint';\n hint.id = `tcw-number-hint-${++numberRowCount}`;\n hint.setAttribute('role', 'status');\n input.setAttribute('aria-describedby', hint.id);\n const mark = (ok: boolean) => {\n if (ok) input.removeAttribute('aria-invalid');\n else input.setAttribute('aria-invalid', 'true');\n hint.textContent = ok ? '' : limitsText(limits, t, locale);\n };\n input.addEventListener('change', () => {\n if (input.value.trim() === '') {\n mark(true);\n onChange(null);\n return;\n }\n const v = Number(input.value);\n const ok = Number.isFinite(v) && v > 0 && v >= (limits.min ?? 0) && v <= limits.max && (limits.step !== '1' || Number.isInteger(v));\n mark(ok);\n if (ok) onChange(v);\n });\n row.append(input, hint);\n return row;\n}\n","import { CHART_STYLE_KEYS, type ChartType, type ChartTypeOptions, type LineStyle } from '@tradecanvas/commons';\nimport type { ChartSettingsState, SettingsCallbacks, SettingsStylePatch } from './types.js';\nimport { CHART_TYPES } from './widgetConfig.js';\nimport {\n APPEARANCE_SECTIONS, HIGH_LOW_SECTION, LAST_PRICE_SECTION, LEGEND_ROWS, SCALE_ROWS, STATUS_LINE_ROWS, TRADING_SECTIONS, VOLUME_SECTION,\n seriesRows, type LookRow, type LookSection,\n} from './widgetSettingsLook.js';\nimport { chartTypeLabel, numberLocaleOptions } from './widgetLocales.js';\nimport { createChartTypeIcon, createIcon } from './icons.js';\nimport { timezoneOptions } from './widgetTimezones.js';\nimport { FOCUSABLE, keepTabInside } from './focusTrap.js';\nimport { WidgetContextMenu, type ContextMenuEntry } from './WidgetContextMenu.js';\nimport { colorRow, numberRow, rangeRow, selectRow, settingsSection, toggleRow, type NumberLimits } from './settingsRows.js';\nimport { fill, type MessageKey, type Translator } from './i18n.js';\n\nexport type SettingsTab = 'symbol' | 'statusLine' | 'scales' | 'appearance' | 'layers' | 'trading';\ntype Tab = SettingsTab;\n\n/** The tabs down the side, in the order a trader looks: the symbol first, the trading colours last. */\nconst TABS: readonly { id: Tab; icon: string }[] = [\n { id: 'symbol', icon: 'chartType:candlestick' },\n { id: 'statusLine', icon: 'type' },\n { id: 'scales', icon: 'ruler' },\n { id: 'appearance', icon: 'palette' },\n { id: 'layers', icon: 'layers' },\n { id: 'trading', icon: 'trendingUp' },\n];\n/** The widths a line takes in the settings, in pixels. */\nconst LINE_WIDTHS = [1, 2, 3, 4];\n/** A template's entry in the Template menu, by its name. */\nconst TEMPLATE_ID = 't:';\n/**\n * The smallest box, reversal or range the chart type's settings take: a\n * hundred-millionth, the finest price step markets commonly quote. A size\n * far under the prices is no use; the chart raises one that would make too\n * many bars anyway, but a slip like 1e-9 is turned away here.\n */\nconst MIN_TYPE_SIZE = 1e-8;\n/** A box, reversal or range: any number from MIN_TYPE_SIZE up. */\nconst SIZE_LIMITS: NumberLimits = { step: 'any', max: Infinity, min: MIN_TYPE_SIZE };\n\nlet nextSettingsId = 1;\n\n/**\n * The chart's settings: tabs down the side (Symbol, Status line, Scales,\n * Appearance, Layers, Trading), each change shown at once. Cancel (Escape,\n * the close button, a click outside) puts it all back, OK keeps it; the\n * Template menu applies, saves and deletes templates, and resets.\n */\nexport class WidgetSettings {\n private callbacks: SettingsCallbacks;\n private t: Translator;\n private backdrop: HTMLDivElement | null = null;\n private modal: HTMLDivElement | null = null;\n private bodyEl: HTMLDivElement | null = null;\n private tabButtons: HTMLButtonElement[] = [];\n private templateBtn: HTMLButtonElement | null = null;\n private menu: WidgetContextMenu | null = null;\n private currentTab: Tab = 'symbol';\n private currentSettings: ChartSettingsState | null = null;\n /** The chart's type, whose settings the Symbol tab offers. */\n private chartType: ChartType | null = null;\n /** The look's rows on view, each showing the chart's value again (a change to one moves others: a wick with its body). */\n private lookRows: { el: HTMLElement; sync: () => void }[] = [];\n private returnFocus: HTMLElement | null = null;\n private readonly uid = nextSettingsId++;\n\n /**\n * `barCountdown` / `logScale` / `legend` / `volume` false leave out the\n * controls for features the chart has switched off: there they would do\n * nothing.\n */\n constructor(\n callbacks: SettingsCallbacks,\n t: Translator,\n private readonly available: {\n barCountdown?: boolean;\n logScale?: boolean;\n legend?: boolean;\n volume?: boolean;\n /** The exchange's time zone to offer (null while unknown), or undefined when there is none to offer. */\n exchangeZone?: () => string | null | undefined;\n /** false: the chart doesn't trade, so the orders' colours aren't offered. */\n trading?: boolean;\n } = {},\n /** Where the panel mounts (the widget's portal: themed, and inside it when fullscreen). */\n private readonly host: () => HTMLElement = () => document.body,\n ) {\n this.callbacks = callbacks;\n this.t = t;\n }\n\n /** Open on `tab` (the Symbol tab unless asked: the price axis's menu asks for Scales). */\n open(currentSettings: ChartSettingsState, chartType: ChartType | null = null, tab: SettingsTab = 'symbol'): void {\n if (this.modal) this.remove();\n this.returnFocus = document.activeElement instanceof HTMLElement ? document.activeElement : null;\n this.currentSettings = { ...currentSettings };\n this.chartType = chartType;\n this.currentTab = tab;\n this.buildModal();\n this.tabButtons.find((b) => b.dataset.tab === tab)?.focus();\n }\n\n isOpen(): boolean {\n return this.modal !== null;\n }\n\n /** Show `settings` when they differ from what the dialog shows: a change made outside it while it is open. */\n follow(settings: ChartSettingsState): void {\n if (!this.modal || (this.currentSettings && sameSettings(this.currentSettings, settings))) return;\n this.refresh(settings);\n }\n\n /** The settings as they are now (after an undo, a template), on the tab that's open; `chartType` when it changed. */\n refresh(settings: ChartSettingsState, chartType?: ChartType | null): void {\n if (!this.modal) return;\n this.currentSettings = { ...settings };\n if (chartType !== undefined) this.chartType = chartType;\n // A change from outside (a compare's bars, the host's setSettings) builds the panel again under the\n // control in focus: focus goes to the one in its place, not to the page outside the dialog.\n const focused = this.focusedControl();\n this.renderTabContent();\n if (focused !== null) this.focusControl(focused);\n }\n\n /** The place of the control in focus among the panel's, or null when focus is not in the panel. */\n private focusedControl(): number | null {\n const active = document.activeElement;\n if (!this.bodyEl || !(active instanceof HTMLElement) || !this.bodyEl.contains(active)) return null;\n const at = this.panelControls().indexOf(active);\n return at < 0 ? null : at;\n }\n\n /** Focus the panel's control at `index`, or its last when it has fewer; the tab when it has none. */\n private focusControl(index: number): void {\n const controls = this.panelControls();\n const control = controls[Math.min(index, controls.length - 1)] ?? this.tabButtons.find((b) => b.dataset.tab === this.currentTab);\n control?.focus();\n }\n\n private panelControls(): HTMLElement[] {\n return this.bodyEl ? [...this.bodyEl.querySelectorAll<HTMLElement>(FOCUSABLE)] : [];\n }\n\n /** Close, keeping what was changed (as OK does). */\n close(): void {\n this.finish(true);\n }\n\n destroy(): void {\n this.remove();\n }\n\n /** OK (`keep`) or Cancel, then closed, focus back where the dialog was opened from. */\n private finish(keep: boolean): void {\n if (!this.modal) return;\n if (keep) this.callbacks.onClose();\n else this.callbacks.onCancel?.();\n this.remove();\n if (this.returnFocus?.isConnected) this.returnFocus.focus();\n this.returnFocus = null;\n }\n\n private remove(): void {\n this.menu?.destroy();\n this.menu = null;\n this.backdrop?.remove();\n this.backdrop = this.modal = this.bodyEl = this.templateBtn = null;\n this.tabButtons = [];\n }\n\n private buildModal(): void {\n const backdrop = document.createElement('div');\n backdrop.className = 'tcw-modal-backdrop';\n // A press that starts in the dialog (a slider dragged, text selected) and ends on the backdrop doesn't cancel it.\n let pressedBackdrop = false;\n backdrop.addEventListener('pointerdown', (e) => {\n pressedBackdrop = e.target === backdrop;\n });\n backdrop.addEventListener('click', (e) => {\n if (e.target === backdrop && pressedBackdrop) this.finish(false);\n pressedBackdrop = false;\n });\n const modal = document.createElement('div');\n modal.className = 'tcw-modal tcw-set';\n modal.setAttribute('role', 'dialog');\n modal.setAttribute('aria-modal', 'true');\n modal.setAttribute('aria-labelledby', `tcw-set-title-${this.uid}`);\n modal.tabIndex = -1;\n modal.addEventListener('keydown', (e) => {\n if (e.key === 'Escape') {\n e.preventDefault();\n e.stopPropagation();\n this.finish(false);\n return;\n }\n keepTabInside(e, modal);\n });\n this.backdrop = backdrop;\n this.modal = modal;\n modal.append(this.buildHeader(), this.buildBody(), this.buildFooter());\n backdrop.appendChild(modal);\n this.host().appendChild(backdrop);\n this.markTabs();\n this.renderTabContent();\n }\n\n private buildHeader(): HTMLDivElement {\n const header = document.createElement('div');\n header.className = 'tcw-modal-header';\n const title = document.createElement('h3');\n title.id = `tcw-set-title-${this.uid}`;\n title.textContent = this.t('settings.title');\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.finish(false));\n header.append(title, closeBtn);\n return header;\n }\n\n /** The tabs down the side, and the open one's settings beside them. */\n private buildBody(): HTMLDivElement {\n const body = document.createElement('div');\n body.className = 'tcw-set-body';\n const nav = document.createElement('div');\n nav.className = 'tcw-set-nav';\n nav.setAttribute('role', 'tablist');\n nav.setAttribute('aria-orientation', 'vertical');\n nav.setAttribute('aria-label', this.t('settings.title'));\n nav.addEventListener('keydown', (e) => this.onTabKey(e));\n this.tabButtons = TABS.map(({ id, icon }) => {\n const btn = document.createElement('button');\n btn.type = 'button';\n btn.className = 'tcw-set-tab';\n btn.id = `tcw-set-tab-${this.uid}-${id}`;\n btn.dataset.tab = id;\n btn.setAttribute('role', 'tab');\n btn.setAttribute('aria-controls', `tcw-set-panel-${this.uid}`);\n const svg = icon.startsWith('chartType:') ? createChartTypeIcon(icon.slice('chartType:'.length) as ChartType, 16) : createIcon(icon, 16);\n btn.innerHTML = `${svg}<span></span>`;\n btn.querySelector('span')!.textContent = this.t(`settings.tab.${id}` as MessageKey);\n btn.addEventListener('click', () => this.selectTab(id));\n return btn;\n });\n nav.append(...this.tabButtons);\n const panel = document.createElement('div');\n panel.className = 'tcw-modal-body tcw-set-panel';\n panel.id = `tcw-set-panel-${this.uid}`;\n panel.setAttribute('role', 'tabpanel');\n this.bodyEl = panel;\n body.append(nav, panel);\n return body;\n }\n\n /** Template on the left; Cancel and OK on the right. */\n private buildFooter(): HTMLDivElement {\n const footer = document.createElement('div');\n footer.className = 'tcw-modal-footer';\n const template = this.footerButton('template', 'tcw-footer-menu', () => this.openTemplates());\n template.setAttribute('aria-haspopup', 'menu');\n template.setAttribute('aria-expanded', 'false');\n template.innerHTML = `<span></span>${createIcon('chevronDown', 12)}`;\n template.querySelector('span')!.textContent = this.t('settings.template');\n this.templateBtn = template;\n const end = document.createElement('div');\n end.className = 'tcw-footer-end';\n end.append(\n this.footerButton('cancel', 'tcw-footer-cancel', () => this.finish(false), this.t('common.cancel')),\n this.footerButton('ok', 'tcw-done-btn', () => this.finish(true), this.t('drawingSettings.ok')),\n );\n footer.append(template, end);\n return footer;\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 private markTabs(): void {\n for (const btn of this.tabButtons) {\n const on = btn.dataset.tab === this.currentTab;\n btn.classList.toggle('tcw-active', on);\n btn.setAttribute('aria-selected', String(on));\n btn.tabIndex = on ? 0 : -1;\n if (on) this.bodyEl?.setAttribute('aria-labelledby', btn.id);\n }\n }\n\n private selectTab(tab: Tab, focus = false): void {\n this.currentTab = tab;\n this.markTabs();\n this.renderTabContent();\n if (focus) this.tabButtons.find((b) => b.dataset.tab === tab)?.focus();\n }\n\n /** Through the tabs (Home, End), picking as they go: up and down, or along the row of chips on a phone. */\n private onTabKey(e: KeyboardEvent): void {\n const at = TABS.findIndex((tab) => tab.id === this.currentTab);\n const next = e.key === 'ArrowDown' || e.key === 'ArrowRight' ? (at + 1) % TABS.length\n : e.key === 'ArrowUp' || e.key === 'ArrowLeft' ? (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].id, true);\n }\n\n /** The Template menu: the saved templates (each removable), Save as template, Reset to defaults. */\n private openTemplates(): void {\n const btn = this.templateBtn;\n if (!this.modal || !btn) return;\n if (this.menu?.isOpen()) {\n this.menu.close();\n return;\n }\n const templates = this.callbacks.templates;\n const saved: ContextMenuEntry[] = (templates?.list() ?? []).map((name) => ({\n id: `${TEMPLATE_ID}${name}`, label: name, icon: 'layers', remove: fill(this.t('templates.delete'), { name }),\n }));\n const entries: ContextMenuEntry[] = [\n ...saved,\n ...(saved.length > 0 ? ['separator' as const] : []),\n ...(templates ? [{ id: 'save', label: this.t('settings.saveTemplate'), icon: 'save' }] : []),\n { id: 'reset', label: this.t('settings.resetToDefaults'), icon: 'reset' },\n ];\n this.menu ??= new WidgetContextMenu(this.modal, this.t('settings.template'));\n const at = btn.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 === 'reset') this.callbacks.onReset();\n else if (id === 'save') templates?.save();\n else if (id.startsWith(TEMPLATE_ID)) templates?.apply(id.slice(TEMPLATE_ID.length));\n }, btn, (id) => templates?.remove(id.slice(TEMPLATE_ID.length)));\n }\n\n private renderTabContent(): void {\n if (!this.bodyEl || !this.currentSettings) return;\n this.bodyEl.replaceChildren();\n this.lookRows = [];\n switch (this.currentTab) {\n case 'symbol': this.renderSymbolTab(this.currentSettings); break;\n case 'statusLine': this.renderStatusLineTab(this.currentSettings); break;\n case 'scales': this.renderScalesTab(this.currentSettings); break;\n case 'appearance': this.renderAppearanceTab(this.currentSettings); break;\n case 'layers': this.renderLayersTab(this.currentSettings); break;\n case 'trading':\n for (const section of TRADING_SECTIONS) {\n if (!section.trading || this.available.trading !== false) this.renderLookSection(section);\n }\n break;\n }\n }\n\n /** The chart type's own settings and colours, the main series, the last price, the volume, the high and low. */\n private renderSymbolTab(s: ChartSettingsState): void {\n this.renderChartTypeSection();\n this.addSection(undefined, [\n toggleRow(this.t('settings.mainSeries'), s.mainSeriesVisible, (v) => this.patch({ mainSeriesVisible: v })),\n toggleRow(this.t('settings.extendedHours'), s.extendedHours, (v) => this.patch({ extendedHours: v })),\n ]);\n // A section's own switch says \"Show\": its title names what it shows.\n const show = this.t('common.show');\n this.renderLookSection(LAST_PRICE_SECTION);\n if (this.available.volume !== false) {\n this.renderLookSection(VOLUME_SECTION, [toggleRow(show, s.volumeVisible, (v) => this.patch({ volumeVisible: v }))]);\n }\n this.renderLookSection(HIGH_LOW_SECTION, [toggleRow(show, s.highLowLines, (v) => this.patch({ highLowLines: v }))]);\n }\n\n /** The legend over the chart: shown or not, its colours; the panes' titles. */\n private renderStatusLineTab(s: ChartSettingsState): void {\n const legend = this.available.legend !== false;\n const rows = legend ? STATUS_LINE_ROWS : STATUS_LINE_ROWS.filter((row) => !LEGEND_ROWS.includes(row));\n this.addSection(undefined, [\n ...(legend ? [toggleRow(this.t('settings.ohlcLegend'), s.legendVisible, (v) => this.patch({ legendVisible: v }))] : []),\n ...rows.map((row) => this.lookRow(row)),\n ]);\n }\n\n /** The price scale's mode and behaviour, its labels, the time zone, how numbers are written, the axes' colours. */\n private renderScalesTab(s: ChartSettingsState): void {\n const scales = [\n { value: 'regular', label: this.t('settings.scale.regular') },\n { value: 'logarithmic', label: this.t('settings.scale.logarithmic') },\n { value: 'percentage', label: this.t('settings.scale.percentage') },\n { value: 'indexedTo100', label: this.t('settings.scale.indexedTo100') },\n ].filter((o) => o.value !== 'logarithmic' || this.available.logScale !== false);\n const exchangeZone = this.available.exchangeZone?.();\n const zones = timezoneOptions(s.timezone, Date.now(), this.t('settings.timezone.local'),\n exchangeZone !== undefined ? { label: this.t('settings.timezone.exchange'), zone: exchangeZone } : undefined);\n this.addSection(undefined, [\n selectRow(this.t('settings.priceScale'), s.scaleMode, scales, (v) => this.patch({ scaleMode: v as ChartSettingsState['scaleMode'] })),\n toggleRow(this.t('settings.autoScale'), s.autoScale, (v) => this.patch({ autoScale: v })),\n toggleRow(this.t('settings.invertScale'), s.invertScale, (v) => this.patch({ invertScale: v })),\n toggleRow(this.t('settings.leftScale'), s.leftPriceScale, (v) => this.patch({ leftPriceScale: v })),\n toggleRow(this.t('settings.indicatorValues'), s.indicatorValueLabels, (v) => this.patch({ indicatorValueLabels: v })),\n toggleRow(this.t('settings.alignAxisLabels'), s.alignAxisLabels, (v) => this.patch({ alignAxisLabels: v })),\n ...(this.available.barCountdown !== false\n ? [toggleRow(this.t('settings.barCountdown'), s.barCountdown, (v) => this.patch({ barCountdown: v }))]\n : []),\n selectRow(this.t('settings.timezone'), s.timezone, zones, (v) => this.patch({ timezone: v })),\n selectRow(this.t('settings.numberLocale'), s.numberLocale, numberLocaleOptions(s.numberLocale), (v) => this.patch({ numberLocale: v })),\n ]);\n this.addSection(this.t('settings.section.axes'), SCALE_ROWS.map((row) => this.lookRow(row)));\n }\n\n /** The background, the grid, the crosshair, the session breaks, the drawings' handles. */\n private renderAppearanceTab(s: ChartSettingsState): void {\n const [background, grid, crosshair, ...rest] = APPEARANCE_SECTIONS;\n this.renderLookSection(background);\n this.renderLookSection(grid, [toggleRow(this.t('common.show'), s.gridVisible, (v) => this.patch({ gridVisible: v }))]);\n this.renderLookSection(crosshair, [selectRow(this.t('settings.crosshairMode'), s.crosshairMode, [\n { label: this.t('settings.crosshair.magnet'), value: 'magnet' },\n { label: this.t('settings.crosshair.normal'), value: 'normal' },\n { label: this.t('settings.crosshair.hidden'), value: 'hidden' },\n ], (v) => this.patch({ crosshairMode: v as ChartSettingsState['crosshairMode'] })),\n selectRow(this.t('settings.crosshairCursor'), s.crosshairCursor, [\n { label: this.t('drawing.cursorCross'), value: 'cross' },\n { label: this.t('drawing.cursorDot'), value: 'dot' },\n { label: this.t('drawing.cursorArrow'), value: 'arrow' },\n ], (v) => this.patch({ crosshairCursor: v as ChartSettingsState['crosshairCursor'] }))]);\n for (const section of rest) this.renderLookSection(section);\n }\n\n /** What the chart can draw over the bars: the profiles, the depth, the swings, the sessions, the prior levels. */\n private renderLayersTab(s: ChartSettingsState): void {\n const percent = (v: number) => `${Math.round(v * 100)}%`;\n const t = (key: MessageKey) => this.t(key);\n this.addSection(undefined, [toggleRow(t('settings.volumeProfile'), s.volumeProfileVisible, (v) => this.patch({ volumeProfileVisible: v }))]);\n this.addSection(undefined, [\n toggleRow(t('settings.marketProfile'), s.marketProfileVisible, (v) => this.patch({ marketProfileVisible: v })),\n toggleRow(t('settings.marketProfileSplit'), s.marketProfileSplit, (v) => this.patch({ marketProfileSplit: v })),\n toggleRow(t('settings.marketProfileLetters'), s.marketProfileLetters, (v) => this.patch({ marketProfileLetters: v })),\n rangeRow(t('settings.marketProfileBuckets'), s.marketProfileBuckets, { min: 8, max: 200, step: 1 }, (v) => this.patch({ marketProfileBuckets: v })),\n rangeRow(t('settings.marketProfileOpacity'), s.marketProfileOpacity, { min: 0.05, max: 1, step: 0.05 }, (v) => this.patch({ marketProfileOpacity: v }), percent),\n ]);\n this.addSection(undefined, [\n toggleRow(t('settings.depthHeatmap'), s.depthHeatmapVisible, (v) => this.patch({ depthHeatmapVisible: v })),\n rangeRow(t('settings.depthHeatmapOpacity'), s.depthHeatmapOpacity, { min: 0.1, max: 1, step: 0.05 }, (v) => this.patch({ depthHeatmapOpacity: v }), percent),\n ]);\n this.addSection(undefined, [\n toggleRow(t('settings.swingMarkers'), s.pivotMarkersVisible, (v) => this.patch({ pivotMarkersVisible: v })),\n rangeRow(t('settings.swingStrength'), s.pivotStrength, { min: 2, max: 20, step: 1 }, (v) => this.patch({ pivotStrength: v })),\n toggleRow(t('settings.swingStructure'), s.pivotStructureLabels, (v) => this.patch({ pivotStructureLabels: v })),\n ]);\n this.addSection(undefined, [\n toggleRow(t('settings.sessionShading'), s.sessionShadingVisible, (v) => this.patch({ sessionShadingVisible: v })),\n toggleRow(t('settings.periodLevels'), s.periodLevelsVisible, (v) => this.patch({ periodLevelsVisible: v })),\n selectRow(t('settings.periodLevelsBasis'), s.periodLevelsPeriod, [\n { value: 'day', label: t('settings.priorDay') },\n { value: 'week', label: t('settings.priorWeek') },\n ], (v) => this.patch({ periodLevelsPeriod: v as ChartSettingsState['periodLevelsPeriod'] })),\n ]);\n }\n\n private addSection(title: string | undefined, rows: readonly HTMLElement[]): HTMLDivElement {\n const section = settingsSection(title);\n section.append(...rows);\n this.bodyEl?.appendChild(section);\n return section;\n }\n\n /** A section of the look, after `lead` (the switch it goes with, say). */\n private renderLookSection(section: LookSection, lead: readonly HTMLElement[] = []): void {\n this.addSection(this.t(section.title), [...lead, ...section.rows.map((row) => this.lookRow(row))]);\n }\n\n /** A row of the look: a colour, a switch, a dash or a width, as its key takes it, on the user's layer. */\n private lookRow(row: LookRow): HTMLDivElement {\n const label = this.t(row.label);\n const read = () => this.callbacks.styleValue(row.keys[0]);\n /** The keys' value, or '' when they differ (the host set each way apart): any pick then sets them all. */\n const shared = (): string => {\n const values = row.keys.map((key) => this.callbacks.styleValue(key));\n return values.every((v) => v === values[0]) && values[0] !== null ? String(values[0]) : '';\n };\n let el: HTMLDivElement;\n const set = (v: string | number | boolean | null) => {\n this.callbacks.onStyleChange(Object.fromEntries(row.keys.map((key) => [key, v])) as SettingsStylePatch);\n for (const other of this.lookRows) if (other.el !== el) other.sync();\n };\n const auto = row.auto ? [{ value: '', label: this.t('settings.auto') }] : [];\n let sync: () => void;\n switch (CHART_STYLE_KEYS[row.keys[0]]) {\n case 'boolean': {\n el = toggleRow(label, read() === true, set);\n const toggle = el.querySelector('button')!;\n sync = () => {\n const on = read() === true;\n toggle.classList.toggle('tcw-on', on);\n toggle.setAttribute('aria-checked', String(on));\n };\n break;\n }\n case 'lineStyle':\n el = selectRow(label, shared(), [...auto, ...this.lineStyles()], (v) => set(v === '' ? null : asLineStyle(v)));\n sync = () => { el.querySelector('select')!.value = shared(); };\n break;\n case 'width': {\n const value = read();\n const widths = typeof value === 'number' && !LINE_WIDTHS.includes(value) ? [...LINE_WIDTHS, value].sort((a, b) => a - b) : LINE_WIDTHS;\n el = selectRow(label, shared(), [...auto, ...widths.map((w) => ({ value: String(w), label: `${w}px` }))],\n (v) => set(v === '' ? null : Number(v)));\n sync = () => { el.querySelector('select')!.value = shared(); };\n break;\n }\n default: {\n const value = read();\n const colour = colorRow(label, typeof value === 'string' ? value : null, set, {\n read: () => { const v = read(); return typeof v === 'string' ? v : null; },\n start: row.auto ? () => (row.auto?.from ? this.callbacks.styleValue(row.auto.from) : row.auto?.hint) ?? null : undefined,\n }, this.t);\n el = colour.row;\n sync = colour.sync;\n }\n }\n this.lookRows.push({ el, sync });\n return el;\n }\n\n private lineStyles(): { value: string; label: string }[] {\n return [\n { value: 'solid', label: this.t('drawingSettings.lineStyle.solid') },\n { value: 'dashed', label: this.t('drawingSettings.lineStyle.dashed') },\n { value: 'dotted', label: this.t('drawingSettings.lineStyle.dotted') },\n ];\n }\n\n /** The chart's type: its settings (Renko's box, Kagi's reversal…) and its colours and widths. */\n private renderChartTypeSection(): void {\n if (!this.bodyEl || !this.currentSettings || !this.chartType) return;\n const type = this.chartType;\n const all = this.currentSettings.chartTypeOptions ?? {};\n const def = CHART_TYPES.find((c) => c.value === type);\n const section = settingsSection(def ? chartTypeLabel(def, this.t) : type);\n const own = () => this.currentSettings?.chartTypeOptions ?? {};\n /** Change one type's settings: the rest of its own stay. */\n const set = <K extends keyof ChartTypeOptions>(key: K, value: NonNullable<ChartTypeOptions[K]>) =>\n this.patch({ chartTypeOptions: { ...own(), [key]: value } });\n const number = (label: MessageKey, value: number | null, limits: NumberLimits, onChange: (v: number | null) => void) =>\n section.appendChild(numberRow(this.t(label), value, limits, onChange, this.t, this.currentSettings?.numberLocale || undefined));\n switch (type) {\n case 'renko': {\n const o = all.renko ?? {};\n number('settings.boxSize', typeof o.boxSize === 'number' ? o.boxSize : null, SIZE_LIMITS,\n (v) => set('renko', { ...(own().renko ?? {}), boxSize: v ?? 'atr' }));\n number('settings.atrPeriod', o.atrPeriod ?? null, { step: '1', max: 500 }, (v) => set('renko', withValue(own().renko, 'atrPeriod', v)));\n break;\n }\n case 'lineBreak':\n number('settings.lineBreakLines', all.lineBreak?.lines ?? null, { step: '1', max: 10 }, (v) => set('lineBreak', withValue(own().lineBreak, 'lines', v)));\n break;\n case 'kagi':\n number('settings.reversal', all.kagi?.reversal ?? null, SIZE_LIMITS, (v) => set('kagi', withValue(own().kagi, 'reversal', v)));\n section.appendChild(selectRow(this.t('settings.reversalType'), all.kagi?.reversalType ?? 'percent', [\n { value: 'percent', label: this.t('settings.reversalType.percent') },\n { value: 'price', label: this.t('settings.reversalType.price') },\n ], (v) => set('kagi', { ...(own().kagi ?? {}), reversalType: v === 'price' ? 'price' : 'percent' })));\n break;\n case 'pointAndFigure':\n number('settings.boxSize', typeof all.pointAndFigure?.boxSize === 'number' ? all.pointAndFigure.boxSize : null, SIZE_LIMITS,\n (v) => set('pointAndFigure', { ...(own().pointAndFigure ?? {}), boxSize: v ?? 'auto' }));\n number('settings.reversalBoxes', all.pointAndFigure?.reversal ?? null, { step: '1', max: 10 },\n (v) => set('pointAndFigure', withValue(own().pointAndFigure, 'reversal', v)));\n break;\n case 'rangeBars':\n number('settings.barRange', typeof all.rangeBars?.range === 'number' ? all.rangeBars.range : null, SIZE_LIMITS,\n (v) => set('rangeBars', { range: v ?? 'auto' }));\n break;\n default:\n break;\n }\n for (const row of seriesRows(type)) section.appendChild(this.lookRow(row));\n this.bodyEl.appendChild(section);\n }\n\n private patch(partial: Partial<ChartSettingsState>): void {\n if (this.currentSettings) Object.assign(this.currentSettings, partial);\n this.callbacks.onChange(partial);\n }\n}\n\n/** Whether two settings say the same, whatever order their keys were set in, at any depth. */\nfunction sameSettings(a: ChartSettingsState, b: ChartSettingsState): boolean {\n return sameValue(a, b);\n}\n\nfunction sameValue(a: unknown, b: unknown): boolean {\n if (a === b) return true;\n if (typeof a !== 'object' || typeof b !== 'object' || a === null || b === null) return false;\n if (Array.isArray(a) !== Array.isArray(b)) return false;\n const x = a as Record<string, unknown>;\n const y = b as Record<string, unknown>;\n // A key set to undefined is as one not there, as JSON has it.\n const keys = new Set([...Object.keys(x), ...Object.keys(y)].filter((k) => x[k] !== undefined || y[k] !== undefined));\n for (const key of keys) if (!sameValue(x[key], y[key])) return false;\n return true;\n}\n\n/** `settings` with `key` set to `value`, or without it (back to its default) for null. */\nfunction withValue<T extends object, K extends string>(settings: T | undefined, key: K, value: number | null): T {\n const next = { ...(settings ?? {}) } as Record<string, unknown>;\n if (value === null) delete next[key];\n else next[key] = value;\n return next as T;\n}\n\nfunction asLineStyle(v: string): LineStyle {\n return v === 'dashed' || v === 'dotted' ? v : 'solid';\n}\n"],"mappings":"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"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { o as e } from "./widgetFeatures-sU-9JOSB.js";
|
|
2
2
|
import { i as t, n } from "./focusTrap-Br9Zfje0.js";
|
|
3
3
|
import { a as r, c as i, d as a, i as o, l as s, o as c, s as l } from "./symbolCatalog-B_9kDAjE.js";
|
|
4
|
-
import { r as u, t as d } from "./i18n-
|
|
4
|
+
import { r as u, t as d } from "./i18n-BZdkj80c.js";
|
|
5
5
|
var f = 20, p = 1e3, m = /* @__PURE__ */ new Set(), h = {
|
|
6
6
|
stock: 1,
|
|
7
7
|
stocks: 1,
|
|
@@ -590,4 +590,4 @@ var X = class {
|
|
|
590
590
|
//#endregion
|
|
591
591
|
export { K as MAX_LISTED_ROWS, W as SYMBOL_SEARCH_DEBOUNCE_MS, X as WidgetSymbolSearch };
|
|
592
592
|
|
|
593
|
-
//# sourceMappingURL=WidgetSymbolSearch-
|
|
593
|
+
//# sourceMappingURL=WidgetSymbolSearch-BlQWH3Md.js.map
|