@kashi-ui/elements 0.25.0 → 1.0.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 +11 -1
- package/dist/appointment.d.ts +40 -0
- package/dist/appointment.js +175 -0
- package/dist/base.d.ts +408 -0
- package/dist/base.js +31 -0
- package/dist/basic.d.ts +43 -0
- package/dist/basic.js +222 -0
- package/dist/calendar.js +21 -20
- package/dist/cdn/appointment-CrIZi8Bp.js +1 -0
- package/dist/cdn/base-DTQ50VdG.js +1 -0
- package/dist/cdn/basic-CrEW2RKF.js +1 -0
- package/dist/cdn/calendar-CYRrdGIf.js +16 -0
- package/dist/cdn/charts-D6KM26Vp.js +1 -0
- package/dist/cdn/combobox-6EFI2qqN.js +1 -0
- package/dist/cdn/controls-BwebEIlf.js +1 -0
- package/dist/cdn/display-DFuMkcj5.js +1 -0
- package/dist/cdn/fields-DhLIhHQ8.js +1 -0
- package/dist/cdn/forms-BHivKDdC.js +1 -0
- package/dist/cdn/holidays-DgbIAdlt.js +1 -0
- package/dist/cdn/inputs-R7nEHfbV.js +1 -0
- package/dist/cdn/kashi-elements.js +1 -1
- package/dist/cdn/map-H3xiZd8Y.js +12 -0
- package/dist/cdn/{menu-DhrqyLgy.js → menu-BAUSubXk.js} +1 -1
- package/dist/cdn/nav-NK-v48B5.js +1 -0
- package/dist/cdn/overlay-CBv8grz3.js +1 -0
- package/dist/cdn/pickers-BHzNt_X8.js +1 -0
- package/dist/cdn/table-Bt9WVLoo.js +1 -0
- package/dist/cdn/text-D4a_hlwL.js +1 -0
- package/dist/cdn/time-DJ3p1wvd.js +1 -0
- package/dist/cdn/words-BdADG_9U.js +1 -0
- package/dist/cdn.d.ts +1 -0
- package/dist/cdn.js +4 -0
- package/dist/charts.js +27 -24
- package/dist/combobox.d.ts +6 -5
- package/dist/combobox.js +29 -20
- package/dist/controls.js +15 -15
- package/dist/display.js +17 -14
- package/dist/fields.js +3 -3
- package/dist/forms.d.ts +3 -3
- package/dist/forms.js +54 -47
- package/dist/index.d.ts +12 -2
- package/dist/index.js +7 -1
- package/dist/inputs.d.ts +3 -3
- package/dist/inputs.js +31 -30
- package/dist/map.js +16 -13
- package/dist/nav.js +18 -16
- package/dist/overlay.js +5 -5
- package/dist/pickers.d.ts +1 -1
- package/dist/pickers.js +39 -38
- package/dist/table.js +7 -7
- package/dist/toast.js +3 -3
- package/package.json +4 -4
- package/dist/cdn/base-Cmq7zeIG.js +0 -1
- package/dist/cdn/calendar-Dm3fq2bs.js +0 -16
- package/dist/cdn/charts-DNOWi4sJ.js +0 -1
- package/dist/cdn/combobox-ZGrZ5okg.js +0 -1
- package/dist/cdn/controls-K-OZcjg4.js +0 -1
- package/dist/cdn/digits-DE1YGT94.js +0 -1
- package/dist/cdn/display-C975tS7j.js +0 -1
- package/dist/cdn/fields-BUTaSN8m.js +0 -1
- package/dist/cdn/forms-C-effPKn.js +0 -1
- package/dist/cdn/inputs-BjOddAM7.js +0 -1
- package/dist/cdn/jalali-BiM5Kfep.js +0 -1
- package/dist/cdn/map-BHuusa4t.js +0 -12
- package/dist/cdn/nav-D_w5BV_K.js +0 -1
- package/dist/cdn/overlay-DX9un2xm.js +0 -1
- package/dist/cdn/pickers-BFLpUruK.js +0 -1
- package/dist/cdn/table-DPQfDMs-.js +0 -1
- package/dist/cdn/text-D1U32D6K.js +0 -1
- package/dist/cdn/words-9OdzG7y6.js +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{A as e,C as t,E as n,T as r,a as i,b as a,c as o,d as s,f as c,g as l,i as u,l as d,m as f,n as p,o as m,p as h,s as g,t as _,u as v,v as y,w as b,y as x}from"./base-DTQ50VdG.js";import"./calendar-CYRrdGIf.js";const S=e=>e?a(e.trim())??t(e):null,C=(e,t=0)=>new Date(e.getFullYear(),e.getMonth(),e.getDate()+t),w=(e,t)=>!e&&!t||!!e&&!!t&&e.getTime()===t.getTime(),T=[[(e,t)=>e.last7(t(7)),e=>({start:C(e,-6),end:e})],[(e,t)=>e.last30(t(30)),e=>({start:C(e,-29),end:e})],[e=>e.thisMonth,e=>{let{jy:t,jm:r}=n(e);return{start:b(t,r,1),end:e}}],[e=>e.lastMonth,e=>{let{jy:t,jm:r}=n(e),[i,a]=r===1?[t-1,12]:[t,r-1];return{start:b(i,a,1),end:C(b(t,r,1),-1)}}]];var E=class extends _{constructor(){super(...arguments),this.current={start:null,end:null},this.draft={start:null,end:null},this.valueSet=!1,this.rendered=!1,this.key=y(`kashi-range`),this.pop=null,this.onOutside=e=>{this.contains(e.target)||this.close(!1)}}connectedCallback(){!this.rendered&&!this.valueSet&&(this.current={start:S(this.getAttribute(`start`)),end:S(this.getAttribute(`end`))}),this.render()}disconnectedCallback(){this.close(!1)}attributeChangedCallback(e,t,n){this.rendered&&t!==n&&((e===`start`||e===`end`)&&(this.current={...this.current,[e]:S(n)}),this.render())}get value(){return{...this.current}}set value(e){this.valueSet=!0,this.current={start:e?.start??null,end:e?.end??null},this.rendered&&this.render()}fmt(e){return x(e,{digits:g(this),locale:s()})}text(e){return e.start&&e.end?`${this.fmt(e.start)}${h().common.range}${this.fmt(e.end)}`:null}render(){this.close(!1);let e=this.key,t=this.getAttribute(`label`)??h().dateRange.label,n=this.text(this.current),i=`<div class="k-datepicker k-daterange"><div class="k-select"><button id="${e}" type="button" class="k-select__control k-daterange__trigger" aria-haspopup="dialog" aria-expanded="false"${n?``:` data-placeholder=""`}${this.hasAttribute(`disabled`)?` disabled`:``}>${p.calendar}<span>${d(n??this.getAttribute(`placeholder`)??h().dateRange.placeholder)}</span></button></div></div>`;this.querySelector(`:scope > .k-field`)?.remove(),this.insertAdjacentHTML(`afterbegin`,v({id:e,label:t,control:i})),this.trigger=this.querySelector(`.k-daterange__trigger`),this.trigger.addEventListener(`click`,()=>this.pop?this.close():this.open()),this.rendered=!0,l(this.querySelector(`:scope > .k-field`),this.trigger,e,this.getAttribute(`error`),this.getAttribute(`hint`));let a=this.getAttribute(`name`);if(this.querySelectorAll(`:scope > input[type=hidden]`).forEach(e=>e.remove()),a)for(let[e,t]of[[`start`,this.current.start],[`end`,this.current.end]])this.insertAdjacentHTML(`beforeend`,`<input type="hidden" name="${d(`${a}_${e}`)}" value="${t?r(t):``}">`)}open(){if(this.pop||this.hasAttribute(`disabled`))return;this.draft={...this.current};let e=this.querySelector(`.k-daterange`),t=document.createElement(`div`);t.id=`${this.key}-popover`,t.className=`k-datepicker__popover k-daterange__popover`,t.setAttribute(`role`,`dialog`),t.setAttribute(`aria-label`,this.getAttribute(`label`)??h().dateRange.placeholder);let n=this.getAttribute(`presets`)===`false`?[]:T;t.innerHTML=`${n.length?`<ul class="k-daterange__presets" role="list" aria-label="${d(h().dateRange.presets)}">${n.map(([e],t)=>`<li><button type="button" class="k-daterange__preset" data-preset="${t}" aria-pressed="false">${d(e(h().dateRange,e=>f(this,e)))}</button></li>`).join(``)}</ul>`:``}<div class="k-daterange__main"><div class="k-daterange__footer"><span class="k-daterange__summary" aria-live="polite"></span><button type="button" class="k-btn k-btn--secondary k-btn--sm" data-cancel>${d(h().common.cancel)}</button><button type="button" class="k-btn k-btn--primary k-btn--sm" data-apply>${d(h().common.confirm)}</button></div></div>`;let i=document.createElement(`kashi-calendar`);for(let e of[`min`,`max`,`digits`,`holidays`]){let t=this.getAttribute(e);t!==null&&i.setAttribute(e,t)}i.range=this.draft,t.querySelector(`.k-daterange__main`).prepend(i),i.addEventListener(`kashi-change`,e=>{e.stopPropagation();let t=e.detail.date,n=this.draft;this.draft=!n.start||n.end?{start:t,end:null}:t<n.start?{start:t,end:n.start}:{start:n.start,end:t},i.range=this.draft,this.paintDraft()}),t.addEventListener(`click`,e=>{let t=e.target,a=t.closest(`[data-preset]`);if(a)this.draft=n[Number(a.dataset.preset)][1](C(/* @__PURE__ */ new Date)),i.range=this.draft,this.paintDraft();else if(t.closest(`[data-cancel]`))this.close();else if(t.closest(`[data-apply]`)&&this.draft.start&&this.draft.end){let e=!w(this.draft.start,this.current.start)||!w(this.draft.end,this.current.end);this.current={...this.draft},this.close(),this.render(),this.trigger.focus(),e&&o(this,`kashi-change`,{start:this.current.start,end:this.current.end,value:{start:r(this.current.start),end:r(this.current.end)}})}}),t.addEventListener(`keydown`,e=>{e.key===`Escape`&&(e.stopPropagation(),this.close())}),e.append(t),this.pop=t,this.trigger.setAttribute(`aria-expanded`,`true`),this.trigger.setAttribute(`aria-controls`,t.id),document.addEventListener(`pointerdown`,this.onOutside),this.paintDraft(),i.focus()}paintDraft(){let e=this.pop,t=this.draft;e.querySelector(`.k-daterange__summary`).textContent=this.text(t)??(t.start?h().dateRange.pickEnd:``),e.querySelector(`[data-apply]`).disabled=!t.start||!t.end;let n=C(/* @__PURE__ */ new Date);e.querySelectorAll(`[data-preset]`).forEach((e,r)=>{let i=T[r][1](n);e.setAttribute(`aria-pressed`,String(w(t.start,i.start)&&w(t.end,i.end)))})}close(e=!0){this.pop&&(this.pop.remove(),this.pop=null,document.removeEventListener(`pointerdown`,this.onOutside),this.trigger.setAttribute(`aria-expanded`,`false`),this.trigger.removeAttribute(`aria-controls`),e&&this.trigger.focus())}};E.observedAttributes=[`label`,`hint`,`error`,`start`,`end`,`min`,`max`,`holidays`,`digits`,`name`,`disabled`,`presets`,`placeholder`];const D=e=>`<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true" data-k-mirror=""><path d="${e?`m8 5 5 5-5 5`:`m12 5-5 5 5 5`}"/></svg>`;var O=class extends _{constructor(){super(...arguments),this.selected=null,this.year=n(/* @__PURE__ */ new Date).jy,this.focusMonth=1,this.valueSet=!1,this.rendered=!1}connectedCallback(){if(!this.rendered){this.valueSet||(this.selected=this.parse(this.getAttribute(`value`)));let e=n(/* @__PURE__ */ new Date);this.year=this.selected?.year??e.jy,this.focusMonth=this.selected?.month??(this.year===e.jy?e.jm:1)}this.render()}attributeChangedCallback(e,t,n){this.rendered&&t!==n&&(e===`value`?this.value=n??``:this.render())}parse(e){let t=(e??``).trim().match(/^(\d{4})[-/](\d{1,2})$/);return t?{year:Number(t[1]),month:Number(t[2])}:null}get value(){return this.selected?`${this.selected.year}-${String(this.selected.month).padStart(2,`0`)}`:``}set value(e){this.valueSet=!0,this.selected=this.parse(e),this.selected&&([this.year,this.focusMonth]=[this.selected.year,this.selected.month]),this.rendered&&this.render()}out(e,t){let n=e*12+t,r=this.parse(this.getAttribute(`min`)),i=this.parse(this.getAttribute(`max`));return!!r&&n<r.year*12+r.month||!!i&&n>i.year*12+i.month}render(t=!1){let r=t=>g(this)===`latin`?String(t):e(String(t)),a=n(/* @__PURE__ */ new Date),s=this.parse(this.getAttribute(`min`)),c=this.parse(this.getAttribute(`max`)),l=this.year;this.innerHTML=`<div class="k-monthpicker" role="group" aria-label="${d(this.getAttribute(`label`)??h().monthPicker.label)}"><div class="k-monthpicker__header"><button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm" data-year="-1" aria-label="${d(h().monthPicker.prevYear)}"${s&&l<=s.year?` disabled`:``}>${D(!1)}</button><span class="k-monthpicker__year" aria-live="polite">${r(l)}</span><button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm" data-year="1" aria-label="${d(h().monthPicker.nextYear)}"${c&&l>=c.year?` disabled`:``}>${D(!0)}</button></div><div class="k-monthpicker__grid">${i().months.map((e,t)=>`<button type="button" data-month="${t+1}" class="k-monthpicker__month" tabindex="${this.focusMonth===t+1?0:-1}" aria-pressed="${this.selected?.year===l&&this.selected.month===t+1}" aria-label="${e} ${r(l)}"${a.jy===l&&a.jm===t+1?` aria-current="date"`:``}${this.out(l,t+1)?` disabled`:``}>${e}</button>`).join(``)}</div></div>`;let u=this.getAttribute(`name`);u&&this.insertAdjacentHTML(`beforeend`,`<input type="hidden" name="${d(u)}" value="${this.value}">`),this.rendered=!0,this.querySelectorAll(`[data-year]`).forEach(e=>e.addEventListener(`click`,()=>{this.year+=Number(e.dataset.year),this.render()}));let f=this.querySelector(`.k-monthpicker__grid`);f.addEventListener(`click`,e=>{let t=e.target.closest(`[data-month]`);t&&!t.disabled&&(this.selected={year:this.year,month:Number(t.dataset.month)},this.focusMonth=this.selected.month,this.render(!0),o(this,`kashi-change`,{value:this.value,year:this.selected.year,month:this.selected.month}))}),f.addEventListener(`keydown`,e=>{let t=getComputedStyle(f).direction===`rtl`,n={ArrowRight:t?-1:1,ArrowLeft:t?1:-1,ArrowDown:3,ArrowUp:-3,PageUp:-12,PageDown:12},r=this.year*12+this.focusMonth-1;if(e.key in n)r+=n[e.key];else if(e.key===`Home`)r=this.year*12;else if(e.key===`End`)r=this.year*12+11;else return;e.preventDefault(),this.year=Math.floor(r/12),this.focusMonth=r%12+1,this.render(!0)}),t&&this.querySelector(`[data-month="${this.focusMonth}"]`)?.focus()}};O.observedAttributes=[`value`,`min`,`max`,`digits`,`label`,`name`];function k(t){let n=h().fileUpload.units,r=t,i=0;for(;r>=1024&&i<n.length-1;)r/=1024,i++;let a=i===0?String(r):r.toFixed(+(r<10)).replace(/\.0$/,``);return`${c()===`fa`?e(a).replace(`.`,`٫`):a} ${n[i]}`}var A=class extends _{constructor(){super(...arguments),this.items=[],this.rendered=!1,this.key=y(`kashi-upload`)}connectedCallback(){this.rendered||this.render()}attributeChangedCallback(e,t,n){this.rendered&&t!==n&&this.render()}get files(){return this.items.filter(e=>e.status!==`error`).map(e=>e.file)}get multiple(){return u(this,`multiple`,!0)}render(){let e=this.key,t=this.getAttribute(`hint`),n=this.hasAttribute(`disabled`),r=this.getAttribute(`name`),i=this.getAttribute(`accept`);this.innerHTML=`<div class="k-dropzone"${n?` data-disabled=""`:``}><span class="k-dropzone__icon" aria-hidden="true"><svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M10 13V3.5m-4 4 4-4 4 4M4 13v2.5A1.5 1.5 0 0 0 5.5 17h9a1.5 1.5 0 0 0 1.5-1.5V13"/></svg></span><p class="k-dropzone__title" style="margin: 0"><button type="button" class="k-dropzone__browse"${n?` disabled`:``}${t?` aria-describedby="${e}-hint"`:``}>${d(this.getAttribute(`label`)??h().fileUpload.browse)}</button> <span>${d(h().fileUpload.drop)}</span></p>${t?`<p class="k-dropzone__hint" id="${e}-hint" style="margin: 0">${d(t)}</p>`:``}<input type="file" tabindex="-1" aria-hidden="true"${i?` accept="${d(i)}"`:``}${this.multiple?` multiple`:``}${r?` name="${d(r)}"`:``}></div><ul class="k-file-list" role="list" hidden></ul><span class="k-sr-only" aria-live="polite"></span>`,this.rendered=!0,this.input=this.querySelector(`input[type=file]`);let a=this.querySelector(`.k-dropzone`);this.querySelector(`.k-dropzone__browse`).addEventListener(`click`,()=>this.input.click()),this.input.addEventListener(`change`,()=>{this.input.files?.length&&this.add([...this.input.files])}),a.addEventListener(`dragover`,e=>{e.preventDefault(),n||a.setAttribute(`data-dragging`,``)}),a.addEventListener(`dragleave`,e=>{a.contains(e.relatedTarget)||a.removeAttribute(`data-dragging`)}),a.addEventListener(`drop`,e=>{e.preventDefault(),a.removeAttribute(`data-dragging`),!n&&e.dataTransfer?.files.length&&this.add([...e.dataTransfer.files])}),this.querySelector(`.k-file-list`).addEventListener(`click`,e=>{let t=e.target.closest(`[data-remove]`);if(!t)return;let n=this.items.find(e=>e.id===t.dataset.remove);this.items=this.items.filter(e=>e.id!==t.dataset.remove),this.announce(h().common.removed(n?.file.name??``)),this.changed()}),this.paint()}accepts(e){let t=this.getAttribute(`accept`);return!t||t.split(`,`).map(e=>e.trim().toLowerCase()).some(t=>t.startsWith(`.`)?e.name.toLowerCase().endsWith(t):t.endsWith(`/*`)?e.type.startsWith(t.slice(0,-1)):e.type===t)}add(e){let t=this.multiple?e:e.slice(0,1),n=Number(this.getAttribute(`max-size`))||0,r=Number(this.getAttribute(`max-files`))||0,i=this.multiple?this.items.filter(e=>e.status!==`error`).length:0,a=t.map((e,t)=>{let a;this.accepts(e)?n&&e.size>n?a=h().fileUpload.tooBig(k(n)):r&&i+t>=r&&(a=h().fileUpload.tooMany(f(this,r))):a=h().fileUpload.wrongType;let o=!a&&!!this.uploader;return{id:y(`f`),file:e,status:a?`error`:o?`uploading`:`done`,progress:a||o?0:100,error:a}});this.items=this.multiple?[...this.items,...a]:a,this.announce(a.map(e=>`${e.file.name}: ${e.error??(this.uploader?h().fileUpload.uploading:h().fileUpload.done)}`).join(h().common.list)),this.changed();for(let e of a)e.status===`uploading`&&this.uploader&&this.uploader(e.file,t=>{e.progress=t,this.paint()}).then(()=>{e.status=`done`,e.progress=100,this.announce(`${e.file.name}: ${h().fileUpload.done}`),this.changed()},t=>{e.status=`error`,e.error=t instanceof Error?t.message:h().fileUpload.error,this.announce(`${e.file.name}: ${e.error}`),this.changed()})}announce(e){this.querySelector(`:scope > .k-sr-only`).textContent=e}changed(){try{let e=new DataTransfer;for(let t of this.files)e.items.add(t);this.input.files=e.files}catch{}this.paint(),o(this,`kashi-change`,{files:this.files})}paint(){let e=this.querySelector(`.k-file-list`);e.hidden=!this.items.length;let t=e=>(e.split(`.`).pop()??``).slice(0,4).toUpperCase();e.innerHTML=this.items.map(e=>`<li class="k-file" data-status="${e.status}"><span class="k-file__icon" aria-hidden="true">${d(t(e.file.name))}</span><span class="k-file__name" title="${d(e.file.name)}">${d(e.file.name)}</span><button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm k-file__remove" data-remove="${e.id}" aria-label="${d(h().common.remove(e.file.name))}"><svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3.5 5.5h13M8 5.5V4h4v1.5M5 5.5l.8 10.2a1.5 1.5 0 0 0 1.5 1.3h5.4a1.5 1.5 0 0 0 1.5-1.3L15 5.5"/></svg></button><span class="k-file__meta">${d(e.error??`${k(e.file.size)}${e.status===`uploading`?` · ${h().common.percent(f(this,Math.round(e.progress)))}`:e.status===`done`?` · ${h().fileUpload.done}`:``}`)}</span>${e.status===`uploading`?`<div role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="${Math.round(e.progress)}" aria-label="${d(h().fileUpload.uploadingFile(e.file.name))}" class="k-progress k-progress--sm"><div class="k-progress__bar" style="--k-value: ${e.progress}%"></div></div>`:``}</li>`).join(``)}};A.observedAttributes=[`accept`,`multiple`,`max-size`,`max-files`,`hint`,`name`,`disabled`,`label`];const j=/^#?([0-9a-f]{3}|[0-9a-f]{6})$/i,M=e=>{let t=e.trim().match(j);return t?`#${(t[1].length===3?[...t[1]].map(e=>e+e).join(``):t[1]).toLowerCase()}`:null},N=e=>[1,3,5].map(t=>parseInt(e.slice(t,t+2),16)),P=(e,t,n)=>`#${[e,t,n].map(e=>Math.round(Math.min(255,Math.max(0,e))).toString(16).padStart(2,`0`)).join(``)}`,F=e=>{let[t,n,r]=N(e).map(e=>e/255).map(e=>e<=.03928?e/12.92:((e+.055)/1.055)**2.4);return .2126*t+.7152*n+.0722*r},I=(e,t)=>{let[n,r]=[F(M(e)??e),F(M(t)??t)].sort((e,t)=>t-e);return(n+.05)/(r+.05)};function L(e){let[t,n,r]=N(e).map(e=>e/255),i=Math.max(t,n,r),a=i-Math.min(t,n,r),o=0;return a&&(o=i===t?(n-r)/a%6:i===n?(r-t)/a+2:(t-n)/a+4),{h:(o*60+360)%360,s:i?a/i:0,v:i}}function R({h:e,s:t,v:n}){let r=r=>{let i=(r+e/60)%6;return(n-n*t*Math.max(0,Math.min(i,4-i,1)))*255};return P(r(5),r(3),r(1))}const z=[[`firoozeh`,`#0b8077`],[`lajvard`,`#2740ed`],[`violet`,`#7c3aed`],[`anar`,`#e51d2a`],[`zafaran`,`#dd5e02`],[`peste`,`#518b25`],[`shab`,`#2a2f3d`]],B=()=>z.map(([e,t])=>[h().colorPicker.names[e],t]);var V=class extends _{constructor(){super(...arguments),this.current=`#0b8077`,this.hsv=L(`#0b8077`),this.valueSet=!1,this.rendered=!1,this.key=y(`kashi-color`),this.panel=null,this.onOutside=e=>{this.querySelector(`.k-color__anchor`)?.contains(e.target)||this.closePanel(!1)}}connectedCallback(){!this.rendered&&!this.valueSet&&this.setColor(M(this.getAttribute(`value`)??``)??`#0b8077`,!1),this.render()}disconnectedCallback(){document.removeEventListener(`pointerdown`,this.onOutside)}attributeChangedCallback(e,t,n){this.rendered&&t!==n&&(e===`value`?this.value=n??``:this.render())}get value(){return this.current}set value(e){this.valueSet=!0;let t=M(e??``);t&&this.setColor(t,!1),this.rendered&&this.paint()}setColor(e,t){if(this.current=e,!t){let t=L(e);this.hsv=t.s===0?{...t,h:this.hsv.h}:t}}swatches(){let e=this.getAttribute(`swatches`);return e===null?B():e.split(`,`).map(e=>e.trim().split(/\s+/)).filter(([e])=>M(e)).map(([e,...t])=>[t.join(` `)||e,M(e)])}render(){let e=this.key,t=this.swatches(),n=`<div class="k-color">${t.length?`<div class="k-color__swatches" role="radiogroup" aria-label="${d(h().colorPicker.swatches)}">${t.map(([t,n])=>`<label class="k-color__swatch" style="--_sw: ${n}; --_ink: ${I(n,`#ffffff`)>=3?`#fff`:`#000`}" title="${d(t)}"><input type="radio" class="k-sr-only" name="${e}-sw" value="${n}" aria-label="${d(t)}"><svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2.2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="m5 10.5 3.2 3L15 7"/></svg></label>`).join(``)}</div>`:``}<div class="k-color__row"><span class="k-color__anchor"><button type="button" class="k-color__preview" aria-label="${d(h().colorPicker.custom)}" aria-haspopup="dialog" aria-expanded="false"></button></span><div class="k-input"><input id="${e}-hex" class="k-input__control" dir="ltr" spellcheck="false" autocomplete="off"></div></div>${this.getAttribute(`show-contrast`)===`false`?``:'<p class="k-color__contrast" aria-live="polite"><span class="k-color__sample">${esc(msg().colorPicker.sample)}</span><span></span></p>'}</div>`;this.querySelector(`:scope > .k-field`)?.remove(),this.insertAdjacentHTML(`afterbegin`,v({id:`${e}-hex`,label:this.getAttribute(`label`)??h().colorPicker.label,control:n})),this.rendered=!0,this.querySelector(`.k-color__swatches`)?.addEventListener(`change`,e=>this.pick(e.target.value));let r=this.querySelector(`#${e}-hex`);r.addEventListener(`input`,()=>{let e=M(r.value);this.paintMessages(!e),e&&this.pick(e,!1)}),r.addEventListener(`blur`,()=>{M(r.value)&&(r.value=this.current)}),this.querySelector(`.k-color__preview`).addEventListener(`click`,()=>this.panel?this.closePanel():this.openPanel()),this.paint()}pick(e,t=!0,n=!1){let r=e!==this.current;this.setColor(e,n),this.paint(t),r&&o(this,`kashi-change`,{value:e})}paint(e=!0){let t=this.current,n=I(t,`#ffffff`),r=I(t,`#000000`),i=n>=r?`#ffffff`:`#000000`,a=this.querySelector(`.k-color`);a.style.setProperty(`--_sw`,t),a.style.setProperty(`--_ink`,i),this.querySelectorAll(`.k-color__swatch input`).forEach(e=>e.checked=e.value===t);let o=this.querySelector(`#${this.key}-hex`);e&&(o.value=t);let s=Math.max(n,r),c=this.querySelector(`.k-color__contrast span:last-child`);c&&(c.textContent=h().colorPicker.contrast(i===`#ffffff`?`white`:`black`,f(this,(Math.round(s*10)/10).toFixed(1)).replace(`.`,h().common.decimal),s>=4.5));let l=this.getAttribute(`name`);this.querySelectorAll(`:scope > input[type=hidden]`).forEach(e=>e.remove()),l&&this.insertAdjacentHTML(`beforeend`,`<input type="hidden" name="${d(l)}" value="${t}">`),this.panel&&this.paintPanel(),this.paintMessages(!1)}paintMessages(e){let t=this.querySelector(`#${this.key}-hex`);l(this.querySelector(`:scope > .k-field`),t,`${this.key}-hex`,e?h().colorPicker.invalid:null,this.getAttribute(`hint`))}openPanel(){let e=this.querySelector(`.k-color__anchor`),t=document.createElement(`div`);t.className=`k-color__panel`,t.setAttribute(`role`,`dialog`),t.setAttribute(`aria-label`,h().colorPicker.custom),t.innerHTML=`<div class="k-color__area" role="slider" tabindex="0" aria-label="${d(h().colorPicker.area)}"><span class="k-color__thumb"></span></div><div class="k-color__tools"><span class="k-color__current" aria-hidden="true"></span><input type="range" class="k-color__hue" min="0" max="359" aria-label="${d(h().colorPicker.hue)}"></div><div class="k-color__codes" dir="ltr">${[`R`,`G`,`B`].map((e,t)=>`<label class="k-color__code"><input class="k-color__num" inputmode="numeric" data-ch="${t}" aria-label="${d([h().colorPicker.red,h().colorPicker.green,h().colorPicker.blue][t])}"><span aria-hidden="true">${e}</span></label>`).join(``)}</div>`,e.append(t),this.panel=t;let n=t.querySelector(`.k-color__area`),r=e=>{this.hsv=e,this.pick(R(e),!0,!0)},i=e=>{let t=n.getBoundingClientRect();r({...this.hsv,s:Math.min(1,Math.max(0,(e.clientX-t.left)/t.width)),v:1-Math.min(1,Math.max(0,(e.clientY-t.top)/t.height))})};n.addEventListener(`pointerdown`,e=>{n.setPointerCapture?.(e.pointerId),i(e)}),n.addEventListener(`pointermove`,e=>e.buttons===1&&i(e)),n.addEventListener(`keydown`,e=>{let t=e.shiftKey?.1:.01,n=this.hsv,i={ArrowLeft:{s:Math.max(0,n.s-t)},ArrowRight:{s:Math.min(1,n.s+t)},ArrowUp:{v:Math.min(1,n.v+t)},ArrowDown:{v:Math.max(0,n.v-t)}};i[e.key]&&(e.preventDefault(),r({...n,...i[e.key]}))}),t.querySelector(`.k-color__hue`).addEventListener(`input`,e=>r({...this.hsv,h:Number(e.target.value)})),t.querySelectorAll(`.k-color__num`).forEach(e=>e.addEventListener(`input`,()=>{let t=N(this.current);t[Number(e.dataset.ch)]=Math.min(255,Math.max(0,Number(e.value.replace(/\D/g,``))||0)),this.pick(P(...t))})),t.addEventListener(`keydown`,e=>{e.key===`Escape`&&(e.stopPropagation(),this.closePanel())}),this.querySelector(`.k-color__preview`).setAttribute(`aria-expanded`,`true`),document.addEventListener(`pointerdown`,this.onOutside),this.paintPanel(),n.focus({preventScroll:!0})}paintPanel(){let e=this.panel,{h:t,s:n,v:r}=this.hsv,i=e=>h().common.percent(f(this,Math.round(e*100))),a=e.querySelector(`.k-color__area`);a.style.setProperty(`--_hue`,`hsl(${t} 100% 50%)`),a.setAttribute(`aria-valuenow`,String(Math.round(n*100))),a.setAttribute(`aria-valuetext`,h().colorPicker.areaValue(i(n),i(r)));let o=e.querySelector(`.k-color__thumb`);o.style.left=`${n*100}%`,o.style.top=`${(1-r)*100}%`;let s=e.querySelector(`.k-color__hue`);s.value=String(Math.round(t)),s.setAttribute(`aria-valuetext`,h().colorPicker.degrees(f(this,Math.round(t))));let c=N(this.current);e.querySelectorAll(`.k-color__num`).forEach((e,t)=>{document.activeElement!==e&&(e.value=String(c[t]))})}closePanel(e=!0){if(!this.panel)return;this.panel.remove(),this.panel=null,document.removeEventListener(`pointerdown`,this.onOutside);let t=this.querySelector(`.k-color__preview`);t.setAttribute(`aria-expanded`,`false`),e&&t.focus()}};V.observedAttributes=[`label`,`hint`,`value`,`name`,`swatches`,`show-contrast`],m(`kashi-date-range-picker`,E,`block`),m(`kashi-month-picker`,O,`block`),m(`kashi-file-upload`,A,`block`),m(`kashi-color-picker`,V,`block`);export{V as KashiColorPicker,E as KashiDateRangePicker,A as KashiFileUpload,O as KashiMonthPicker,I as contrastRatio,k as formatBytes};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{c as e,i as t,l as n,m as r,o as i,p as a,r as o,t as s,v as c}from"./base-DTQ50VdG.js";import{n as l}from"./text-D4a_hlwL.js";import{cellNumber as u}from"./controls-BwebEIlf.js";const d=e=>l(e,{digits:`latin`}).toLowerCase();var f=class extends s{constructor(){super(...arguments),this.cols=null,this.data=null,this.table=null,this.sort=null,this.query=``,this.key=c(`kashi-table`),this.getRowId=e=>String(e.id??``)}connectedCallback(){o(()=>this.isConnected&&this.setup())}attributeChangedCallback(e,t,n){this.table&&t!==n&&this.setup()}get columns(){return this.cols??[]}set columns(e){this.cols=e,this.isConnected&&this.data&&this.setup()}get rows(){return this.data??[]}set rows(e){this.data=e,this.isConnected&&this.cols&&this.setup()}get selected(){return[...this.querySelectorAll(`tbody tr[aria-selected="true"]`)].map(e=>e.dataset.id??``)}setup(){this.cols&&this.data&&this.buildFromData();let e=this.querySelector(`:scope table`);if(!e)return;let n=e.closest(`.k-table-wrap`)??this.wrap(e);n.className=`k-table-wrap${t(this,`sticky-header`)?` k-table-wrap--sticky`:``}`,e.classList.add(`k-table`),e.classList.toggle(`k-table--compact`,t(this,`compact`)),e.classList.toggle(`k-table--striped`,t(this,`striped`));let r=e.querySelector(`caption`);r&&(r.id||=`${this.key}-caption`,n.setAttribute(`aria-labelledby`,r.id)),this.table=e,this.decorateHeader(),this.decorateRows(),this.searchBox(),this.apply()}wrap(e){let t=document.createElement(`div`);return t.setAttribute(`role`,`region`),t.tabIndex=0,e.before(t),t.append(e),t}buildFromData(){let e=this.cols,t=this.getAttribute(`caption`)??``,r=(e,t)=>e.format?e.format(t[e.key],t):String(t[e.key]??``),i=`<table>${t?`<caption><span class="k-table__caption-title">${n(t)}</span></caption>`:``}<thead><tr>${e.map(e=>`<th scope="col"${e.sortable?` data-sort`:``}${e.numeric?` data-numeric`:``}>${n(e.header)}</th>`).join(``)}</tr></thead><tbody>${this.data.map(t=>`<tr data-id="${n(this.getRowId(t))}">${e.map(e=>`<td>${n(r(e,t))}</td>`).join(``)}</tr>`).join(``)}</tbody></table>`;this.querySelector(`:scope > .k-table-wrap, :scope > table`)?.remove(),this.insertAdjacentHTML(`beforeend`,i)}decorateHeader(){this.table;let n=this.headCells();n.forEach((t,n)=>{if(t.classList.contains(`k-table__check`)||(t.scope||=`col`,t.hasAttribute(`data-numeric`)&&t.classList.add(`k-table__num`),!t.hasAttribute(`data-sort`)||t.querySelector(`.k-table__sort`)))return;t.setAttribute(`aria-sort`,`none`);let r=document.createElement(`button`);r.type=`button`,r.className=`k-table__sort`,r.append(...t.childNodes),t.append(r);let i=this.dataIndex(n);r.addEventListener(`click`,()=>{this.sort=this.sort?.index===i&&this.sort.dir===`ascending`?{index:i,dir:`descending`}:{index:i,dir:`ascending`},this.apply(),e(this,`kashi-sort`,{column:i,direction:this.sort.dir})})});let r=n.map(e=>e.hasAttribute(`data-numeric`));for(let e of this.bodyRows())[...e.children].forEach((e,t)=>r[t]&&e.classList.add(`k-table__num`));let i=t(this,`selectable`),a=this.headRow(),o=a?.querySelector(`.k-table__check`);if(i&&a&&!o){let e=document.createElement(`th`);e.scope=`col`,e.className=`k-table__check`,e.innerHTML='<input type="checkbox" class="k-checkbox" aria-label="${esc(msg().table.selectAll)}">',a.prepend(e),e.querySelector(`input`).addEventListener(`change`,e=>{let t=e.target.checked;this.visibleRows().forEach(e=>this.setRow(e,t)),this.selectionChanged()})}else!i&&o&&o.remove()}headRow(){return this.table.querySelector(`:scope > thead > tr`)}headCells(){return[...this.headRow()?.children??[]]}bodyRows(){return[...this.table.querySelectorAll(`:scope > tbody > tr`)]}dataIndex(e){return this.headRow()?.querySelector(`.k-table__check`)?e-1:e}offset(){return+!!this.headRow()?.querySelector(`.k-table__check`)}decorateRows(){let e=t(this,`selectable`);this.bodyRows().forEach((t,r)=>{var i,o;(i=t.dataset).id||(i.id=String(r+1)),(o=t.dataset).order||(o.order=String(r));let s=t.querySelector(`.k-table__check`);if(e&&!s){let e=document.createElement(`td`);e.className=`k-table__check`;let r=t.children[0]?.textContent?.trim();e.innerHTML=`<input type="checkbox" class="k-checkbox" aria-label="${n(r?a().table.selectNamed(r):a().table.selectRow)}">`,t.prepend(e),t.setAttribute(`aria-selected`,`false`),e.querySelector(`input`).addEventListener(`change`,e=>{this.setRow(t,e.target.checked),this.selectionChanged()})}else!e&&s&&(s.remove(),t.removeAttribute(`aria-selected`))}),this.selectionChanged(!1)}setRow(e,t){e.setAttribute(`aria-selected`,String(t));let n=e.querySelector(`.k-table__check input`);n&&(n.checked=t)}selectionChanged(t=!0){let r=this.headRow()?.querySelector(`.k-table__check input`),i=this.visibleRows(),a=i.filter(e=>e.getAttribute(`aria-selected`)===`true`).length;r&&(r.checked=i.length>0&&a===i.length,r.indeterminate=a>0&&a<i.length);let o=this.getAttribute(`name`);if(this.querySelectorAll(`:scope > input[type=hidden]`).forEach(e=>e.remove()),o)for(let e of this.selected)this.insertAdjacentHTML(`beforeend`,`<input type="hidden" name="${n(o)}" value="${n(e)}">`);t&&e(this,`kashi-change`,{selected:this.selected})}visibleRows(){return this.bodyRows().filter(e=>!e.hidden&&!e.classList.contains(`k-table__empty`))}searchBox(){let e=this.querySelector(`:scope > .k-table-search`);if(!t(this,`searchable`))return e?.remove();if(e)return;let i=`${this.key}-search`,o=document.createElement(`div`);o.className=`k-table-search k-field`,o.style.marginBlockEnd=`var(--k-space-3)`,o.innerHTML=`<div class="k-input k-input--sm"><input id="${i}" class="k-input__control" type="search" placeholder="${n(a().table.search)}" aria-label="${n(a().table.search)}"></div><span class="k-sr-only" aria-live="polite"></span>`,this.prepend(o);let s=o.querySelector(`input`);s.addEventListener(`input`,()=>{this.query=s.value,this.apply(),o.querySelector(`.k-sr-only`).textContent=a().table.rows(r(this,this.visibleRows().length))})}apply(){let e=this.table.querySelector(`:scope > tbody`);if(!e)return;let t=this.offset(),r=this.bodyRows().filter(e=>!e.classList.contains(`k-table__empty`)),i=this.headCells();i.forEach((e,n)=>{e.hasAttribute(`aria-sort`)&&e.setAttribute(`aria-sort`,this.sort&&this.sort.index===n-t?this.sort.dir:`none`)});let o=r.sort((e,t)=>Number(e.dataset.order)-Number(t.dataset.order));if(this.sort){let{index:e,dir:n}=this.sort,r=i[e+t]?.hasAttribute(`data-numeric`),a=n=>{let i=n.children[e+t],a=i?.dataset.value??i?.textContent?.trim()??``;return r?u(a):a},s=n===`ascending`?1:-1;o=[...o].sort((e,t)=>{let n=a(e),r=a(t);return(typeof n==`number`&&typeof r==`number`?n-r:String(n).localeCompare(String(r),`fa`))*s})}let s=d(this.query.trim());for(let t of o)t.hidden=!!s&&!d(t.textContent??``).includes(s),e.append(t);if(e.querySelector(`.k-table__empty`)?.remove(),s&&!this.visibleRows().length){let t=i.length;e.insertAdjacentHTML(`beforeend`,`<tr class="k-table__empty"><td colspan="${t}"><p style="padding: 2rem; margin: 0; text-align: center">${n(a().common.noResults)}</p></td></tr>`)}this.selectionChanged(!1)}};f.observedAttributes=[`selectable`,`searchable`,`compact`,`striped`,`sticky-header`,`caption`,`name`],i(`kashi-data-table`,f,`block`);export{f as KashiDataTable};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{A as e,k as t}from"./base-DTQ50VdG.js";function n(n,{digits:r}={}){let i=n.replace(/[يى]/g,`ی`).replace(/ك/g,`ک`).replace(/ة/g,`ه`).replace(/[ً-ٰٟ]/g,``).replace(/ـ/g,``).replace(/{2,}/g,``).replace(/ * */g,``).replace(/[ \t]{2,}/g,` `).trim();return r===`fa`&&(i=e(t(i))),r===`latin`&&(i=t(i)),i}function r(t,{digits:n=!0}={}){let r={arabic:0,zwnj:0,punctuation:0,digits:0,spacing:0},i=(e,t,n,i)=>e.replace(t,(...e)=>(r[i]++,typeof n==`string`?n.replace(/\$(\d)/g,(t,n)=>e[Number(n)]??``):n(...e))),a=`[\\u0621-\\u063A\\u0641-\\u064A\\u067E\\u0686\\u0698\\u06A9\\u06AF\\u06CC]`,o=t;o=i(o,/[يى]/g,`ی`,`arabic`),o=i(o,/ك/g,`ک`,`arabic`),o=i(o,RegExp(`(^|[\\s(«])(ن?می) (?=${a})`,`g`),`$1$2`,`zwnj`),o=i(o,RegExp(`(${a}) (ها|های|هایی|هایم|هایت|هایش|تر|ترین)(?=$|[\\s.،؛؟!»)])`,`g`),`$1$2`,`zwnj`),o=i(o,RegExp(`(${a}\\s*),(?=\\s)`,`g`),`$1،`,`punctuation`),o=i(o,RegExp(`(${a}\\s*)\\?`,`g`),`$1؟`,`punctuation`),o=i(o,RegExp(`(${a}\\s*);`,`g`),`$1؛`,`punctuation`),o=i(o,/ +([،؛؟!.:])(?=\s|$)/g,`$1`,`spacing`),o=i(o,/ {2,}/g,` `,`spacing`),n&&(o=i(o,RegExp(`(${a}[\\s\\u200c]*)(\\d+)|(\\d+)(?=[\\s\\u200c]*${a})`,`g`),(t,n,r,i)=>n?n+e(r):e(i),`digits`));let s=Object.values(r).reduce((e,t)=>e+t,0);return{text:o,fixes:r,count:s}}export{n,r as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{O as e}from"./base-DTQ50VdG.js";function t(t){let n=t.trim();if(!n)return null;let r=n.split(/[:٫.،,\s]/).map(e).filter(Boolean),i,a;if(r.length>=2)[i,a]=[Number(r[0]),Number(r[1])];else{let t=e(n);t.length<=2?[i,a]=[Number(t),0]:[i,a]=[Number(t.slice(0,-2)),Number(t.slice(-2))]}return i>=0&&i<24&&a>=0&&a<60?{hours:i,minutes:a}:null}function n({hours:e,minutes:t}){return`${String(e).padStart(2,`0`)}:${String(t).padStart(2,`0`)}`}export{t as n,n as t};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const e=[``,`یک`,`دو`,`سه`,`چهار`,`پنج`,`شش`,`هفت`,`هشت`,`نه`],t=[`ده`,`یازده`,`دوازده`,`سیزده`,`چهارده`,`پانزده`,`شانزده`,`هفده`,`هجده`,`نوزده`],n=[``,``,`بیست`,`سی`,`چهل`,`پنجاه`,`شصت`,`هفتاد`,`هشتاد`,`نود`],r=[``,`صد`,`دویست`,`سیصد`,`چهارصد`,`پانصد`,`ششصد`,`هفتصد`,`هشتصد`,`نهصد`],i=[``,`هزار`,`میلیون`,`میلیارد`,`تریلیون`];function a(i){let a=[],o=Math.floor(i/100),s=i%100;return o&&a.push(r[o]),s>=10&&s<20?a.push(t[s-10]):(s>=20&&a.push(n[Math.floor(s/10)]),s%10&&a.push(e[s%10])),a.join(` و `)}const o=[``,`one`,`two`,`three`,`four`,`five`,`six`,`seven`,`eight`,`nine`,`ten`,`eleven`,`twelve`,`thirteen`,`fourteen`,`fifteen`,`sixteen`,`seventeen`,`eighteen`,`nineteen`],s=[``,``,`twenty`,`thirty`,`forty`,`fifty`,`sixty`,`seventy`,`eighty`,`ninety`],c=[``,`thousand`,`million`,`billion`,`trillion`];function l(e){let t=Math.floor(e/100),n=e%100,r=n<20?o[n]:`${s[Math.floor(n/10)]}${n%10?`-${o[n%10]}`:``}`;return[t?`${o[t]} hundred`:``,r].filter(Boolean).join(` `)}function u(e,{locale:t=`fa`}={}){let n=typeof e==`bigint`?e:BigInt(Math.trunc(e)),r=t===`en`;if(n===0n)return r?`zero`:`صفر`;let o=n<0n;if(o&&(n=-n),n>=10n**15n)throw RangeError(`عدد بزرگتر از حد پشتیبانیشده است`);let s=[];for(let e=0;n>0n;e++,n/=1000n){let t=Number(n%1000n);if(!t)continue;if(r){s.unshift([l(t),c[e]].filter(Boolean).join(` `));continue}let o=e===1&&t===1?``:a(t);s.unshift([o,i[e]].filter(Boolean).join(` `))}return r?(o?`minus `:``)+s.join(` `):(o?`منفی `:``)+s.join(` و `)}export{u as t};
|
package/dist/cdn.d.ts
CHANGED
package/dist/cdn.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
// نسخهٔ CDN با بارگذاری تنبل: هر بخش فقط وقتی یکی از تگهایش در صفحه پیدا شود دانلود میشود.
|
|
2
2
|
// صفحهای که فقط فیلد کد ملی دارد، نقشه و نمودارها را دانلود نمیکند.
|
|
3
3
|
export { toast } from "./toast.js";
|
|
4
|
+
// زبان پیش از بارگذاری عنصرها: <script type="module">import { setLocale } from ".../kashi-elements.js"; setLocale("en");</script>
|
|
5
|
+
export { setLocale } from "./base.js";
|
|
4
6
|
const MODULES = [
|
|
5
7
|
[["kashi-national-id", "kashi-legal-id", "kashi-mobile", "kashi-landline", "kashi-card-number", "kashi-iban", "kashi-postal-code", "kashi-price"], () => import("./inputs.js")],
|
|
6
8
|
[["kashi-otp"], () => import("./fields.js")],
|
|
@@ -15,6 +17,8 @@ const MODULES = [
|
|
|
15
17
|
[["kashi-multi-select", "kashi-slider", "kashi-chip-group", "kashi-password-strength", "kashi-persian-textarea", "kashi-keyboard-fix", "kashi-time-input", "kashi-plate-input", "kashi-inline-edit"], () => import("./forms.js")],
|
|
16
18
|
[["kashi-date-range-picker", "kashi-month-picker", "kashi-file-upload", "kashi-color-picker"], () => import("./pickers.js")],
|
|
17
19
|
[["kashi-bar-chart", "kashi-line-chart", "kashi-pie-chart", "kashi-bar-list", "kashi-proportion-bar", "kashi-sparkline", "kashi-activity-heatmap"], () => import("./charts.js")],
|
|
20
|
+
[["kashi-input", "kashi-textarea", "kashi-banner"], () => import("./basic.js")],
|
|
21
|
+
[["kashi-appointment-picker"], () => import("./appointment.js")],
|
|
18
22
|
[["kashi-command-palette", "kashi-context-menu", "kashi-carousel", "kashi-tree-view", "kashi-tour", "kashi-splitter", "kashi-side-nav"], () => import("./nav.js")],
|
|
19
23
|
];
|
|
20
24
|
const pending = new Set(MODULES);
|
package/dist/charts.js
CHANGED
|
@@ -1,15 +1,18 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { formatJalali, formatNumber as fmtNumber, jalaliMonthLength, toGregorian, toISODate, toJalali } from "@kashi-ui/persian";
|
|
2
|
+
import { calendarNames, define, esc, HTMLBase, lang, localeDigits, msg, uid } from "./base.js";
|
|
3
|
+
// عددها با ارقام زبان فعلی (setLocale)
|
|
4
|
+
const formatNumber = (n) => fmtNumber(n, { digits: localeDigits() });
|
|
5
|
+
const dec = (x) => formatNumber(Math.round(x * 10) / 10).replace(".", msg().common.decimal);
|
|
3
6
|
/** عدد کوتاه برای محور: ۱٬۲۰۰٬۰۰۰ ← ۱٫۲ م */
|
|
4
7
|
const compact = (n) => {
|
|
5
8
|
const a = Math.abs(n);
|
|
6
|
-
const
|
|
9
|
+
const C = msg().chart;
|
|
7
10
|
if (a >= 1e9)
|
|
8
|
-
return
|
|
11
|
+
return dec(n / 1e9) + C.billion;
|
|
9
12
|
if (a >= 1e6)
|
|
10
|
-
return
|
|
13
|
+
return dec(n / 1e6) + C.million;
|
|
11
14
|
if (a >= 1e3)
|
|
12
|
-
return
|
|
15
|
+
return dec(n / 1e3) + C.thousand;
|
|
13
16
|
return formatNumber(n);
|
|
14
17
|
};
|
|
15
18
|
/** گامهای گرد محور: ۰، ۲۵، ۵۰… */
|
|
@@ -21,7 +24,7 @@ function niceTicks(max, count = 4) {
|
|
|
21
24
|
const step = [1, 2, 2.5, 5, 10].map((m) => m * mag).find((s) => s >= raw);
|
|
22
25
|
return Array.from({ length: Math.ceil(max / step) + 1 }, (_, i) => i * step);
|
|
23
26
|
}
|
|
24
|
-
const pctOf = (v, total) =>
|
|
27
|
+
const pctOf = (v, total) => msg().common.percent(dec((v / (total || 1)) * 100));
|
|
25
28
|
const chartColor = (i) => `var(--k-chart-${i + 1})`;
|
|
26
29
|
const json = (t, fallback) => {
|
|
27
30
|
if (!t)
|
|
@@ -113,7 +116,7 @@ export class KashiBarChart extends Chart {
|
|
|
113
116
|
const top = ticks.at(-1) || 1;
|
|
114
117
|
const maxI = totals.indexOf(max);
|
|
115
118
|
const labelMax = this.getAttribute("label-max") !== "false";
|
|
116
|
-
const describe = (i) => (stacked ? `${cats[i]}: ${stacked.map((s) => `${s.name} ${f(s.values[i] ?? 0)}`).join(
|
|
119
|
+
const describe = (i) => (stacked ? `${cats[i]}: ${stacked.map((s) => `${s.name} ${f(s.values[i] ?? 0)}`).join(msg().common.list)}${msg().common.list}${msg().common.total} ${f(totals[i])}` : `${cats[i]}: ${f(totals[i])}`);
|
|
117
120
|
const height = this.getAttribute("height");
|
|
118
121
|
this.innerHTML = `<figure class="k-chart k-chart--bar" aria-labelledby="${this.key}-t" style="margin: 0${height ? `; --k-chart-height: ${esc(height)}` : ""}"><figcaption class="k-chart__head"><p class="k-chart__title" id="${this.key}-t">${esc(this.heading)}</p>${stacked && stacked.length > 1 ? `<ul class="k-chart__legend" aria-hidden="true">${stacked.map((s, i) => `<li style="--_c: ${chartColor(i)}"><span class="k-chart__key k-chart__key--box"></span>${esc(s.name)}</li>`).join("")}</ul>` : ""}</figcaption><div class="k-chart__plot"><div class="k-bars__grid" aria-hidden="true">${ticks.map((t) => `<span data-v="${esc(compact(t))}"></span>`).join("")}</div><div class="k-bars" role="list" aria-label="${esc(this.heading)}">${cats.map((label, i) => `<div class="k-bars__col" role="listitem" tabindex="0" data-i="${i}" aria-label="${esc(describe(i))}" style="--_d: ${i * 40}ms">${labelMax && i === maxI ? `<span class="k-bars__value" aria-hidden="true">${esc(f(totals[i]))}</span>` : ""}${stacked ? `<span class="k-bars__stack" style="block-size: ${(totals[i] / top) * 100}%" aria-hidden="true">${stacked.map((s, si) => `<span class="k-bars__seg" style="--_c: ${chartColor(si)}; flex-grow: ${s.values[i] ?? 0}"></span>`).join("")}</span>` : `<span class="k-bars__bar" style="block-size: ${(totals[i] / top) * 100}%" aria-hidden="true"></span>`}<span class="k-bars__label" aria-hidden="true">${esc(label)}</span></div>`).join("")}</div></div></figure>`;
|
|
119
122
|
const plot = this.querySelector(".k-chart__plot");
|
|
@@ -123,7 +126,7 @@ export class KashiBarChart extends Chart {
|
|
|
123
126
|
col.setAttribute("data-active", "");
|
|
124
127
|
const p = this.at(col.querySelector(".k-bars__bar, .k-bars__stack") ?? col, plot);
|
|
125
128
|
this.tip(plot, p.x, p.y, cats[i], stacked
|
|
126
|
-
? [...stacked.map((s, si) => ({ name: s.name, value: f(s.values[i] ?? 0), color: chartColor(si) })), { name:
|
|
129
|
+
? [...stacked.map((s, si) => ({ name: s.name, value: f(s.values[i] ?? 0), color: chartColor(si) })), { name: msg().common.total, value: f(totals[i]) }]
|
|
127
130
|
: [{ value: f(totals[i]) }]);
|
|
128
131
|
};
|
|
129
132
|
const hide = () => {
|
|
@@ -155,7 +158,7 @@ export class KashiBarList extends Chart {
|
|
|
155
158
|
const d = data[Number(row.dataset.i)];
|
|
156
159
|
row.setAttribute("data-active", "");
|
|
157
160
|
const p = this.at(row.querySelector(".k-barlist__fill"), box);
|
|
158
|
-
this.tip(box, p.x, p.y, d.label, [{ name:
|
|
161
|
+
this.tip(box, p.x, p.y, d.label, [{ name: msg().chart.value, value: f(d.value) }, { name: msg().chart.share, value: pctOf(d.value, total) }]);
|
|
159
162
|
});
|
|
160
163
|
row.addEventListener("pointerleave", () => {
|
|
161
164
|
row.removeAttribute("data-active");
|
|
@@ -182,7 +185,7 @@ export class KashiProportionBar extends Chart {
|
|
|
182
185
|
const i = Number(seg.dataset.i);
|
|
183
186
|
mark(i);
|
|
184
187
|
const p = this.at(seg, box);
|
|
185
|
-
this.tip(box, p.x, p.y, undefined, [{ name: parts[i].label, value: pctOf(parts[i].value, total), color: chartColor(i) }, { name:
|
|
188
|
+
this.tip(box, p.x, p.y, undefined, [{ name: parts[i].label, value: pctOf(parts[i].value, total), color: chartColor(i) }, { name: msg().chart.count, value: f(parts[i].value) }]);
|
|
186
189
|
});
|
|
187
190
|
seg.addEventListener("pointerleave", () => {
|
|
188
191
|
mark(null);
|
|
@@ -199,12 +202,12 @@ export class KashiPieChart extends Chart {
|
|
|
199
202
|
draw() {
|
|
200
203
|
const f = this.format;
|
|
201
204
|
const sorted = [...this.data].sort((a, b) => b.value - a.value);
|
|
202
|
-
const parts = sorted.length > 5 ? [...sorted.slice(0, 4), { label:
|
|
205
|
+
const parts = sorted.length > 5 ? [...sorted.slice(0, 4), { label: msg().common.other, value: sorted.slice(4).reduce((n, d) => n + d.value, 0) }] : sorted;
|
|
203
206
|
const total = parts.reduce((n, d) => n + d.value, 0) || 1;
|
|
204
207
|
const slot = (i) => (i < 4 ? chartColor(i) : "var(--k-text-quaternary)");
|
|
205
208
|
const donut = this.getAttribute("variant") !== "pie";
|
|
206
209
|
const size = Number(this.getAttribute("size")) || 176;
|
|
207
|
-
const totalLabel = this.getAttribute("total-label") ??
|
|
210
|
+
const totalLabel = this.getAttribute("total-label") ?? msg().common.total;
|
|
208
211
|
// هر بخش یک کمان با stroke-dasharray؛ برای pie، شعاع نصف و ضخامت برابر قطر
|
|
209
212
|
const R = 50, r = donut ? 40 : 25, w = donut ? 16 : 50;
|
|
210
213
|
const C = 2 * Math.PI * r;
|
|
@@ -232,7 +235,7 @@ export class KashiPieChart extends Chart {
|
|
|
232
235
|
if (i === null)
|
|
233
236
|
this.tip(plot, null);
|
|
234
237
|
else
|
|
235
|
-
this.tip(plot, mid(i).x, mid(i).y, undefined, [{ name: parts[i].label, value: pctOf(parts[i].value, total), color: slot(i) }, { name:
|
|
238
|
+
this.tip(plot, mid(i).x, mid(i).y, undefined, [{ name: parts[i].label, value: pctOf(parts[i].value, total), color: slot(i) }, { name: msg().chart.count, value: f(parts[i].value) }]);
|
|
236
239
|
}
|
|
237
240
|
};
|
|
238
241
|
this.querySelectorAll(".k-pie__slice, .k-pie__legend li").forEach((el) => el.addEventListener("pointerenter", () => activate(Number(el.dataset.i))));
|
|
@@ -303,7 +306,7 @@ export class KashiLineChart extends Chart {
|
|
|
303
306
|
const f = this.format;
|
|
304
307
|
const labels = this.labels;
|
|
305
308
|
const height = this.getAttribute("height");
|
|
306
|
-
this.innerHTML = `<figure class="k-chart" aria-labelledby="${this.key}-t" style="margin: 0${height ? `; --k-chart-height: ${esc(height)}` : ""}"><figcaption class="k-chart__head"><p class="k-chart__title" id="${this.key}-t">${esc(this.heading)}</p>${shown.length > 1 ? `<ul class="k-chart__legend" aria-hidden="true">${shown.map((s, i) => `<li style="--_c: ${chartColor(i)}"><span class="k-chart__key"></span>${esc(s.name)}</li>`).join("")}</ul>` : ""}</figcaption><div class="k-chart__plot" tabindex="0" role="img" aria-label="${esc(
|
|
309
|
+
this.innerHTML = `<figure class="k-chart" aria-labelledby="${this.key}-t" style="margin: 0${height ? `; --k-chart-height: ${esc(height)}` : ""}"><figcaption class="k-chart__head"><p class="k-chart__title" id="${this.key}-t">${esc(this.heading)}</p>${shown.length > 1 ? `<ul class="k-chart__legend" aria-hidden="true">${shown.map((s, i) => `<li style="--_c: ${chartColor(i)}"><span class="k-chart__key"></span>${esc(s.name)}</li>`).join("")}</ul>` : ""}</figcaption><div class="k-chart__plot" tabindex="0" role="img" aria-label="${esc(msg().chart.keyboard(this.heading))}" aria-describedby="${this.key}-live"><svg class="k-chart__svg" aria-hidden="true" direction="ltr"></svg></div><span class="k-sr-only" aria-live="polite" id="${this.key}-live"></span><table class="k-sr-only"><caption>${esc(this.heading)}</caption><thead><tr><th scope="col">${esc(msg().chart.period)}</th>${shown.map((s) => `<th scope="col">${esc(s.name)}</th>`).join("")}</tr></thead><tbody>${labels.map((l, i) => `<tr><th scope="row">${esc(l)}</th>${shown.map((s) => `<td>${esc(f(s.values[i]))}</td>`).join("")}</tr>`).join("")}</tbody></table></figure>`;
|
|
307
310
|
const plot = this.querySelector(".k-chart__plot");
|
|
308
311
|
plot.addEventListener("pointermove", (e) => this.pick(e.clientX));
|
|
309
312
|
plot.addEventListener("pointerleave", () => this.setActive(null));
|
|
@@ -367,7 +370,7 @@ export class KashiLineChart extends Chart {
|
|
|
367
370
|
this.tip(plot, null);
|
|
368
371
|
else
|
|
369
372
|
this.tip(plot, x(a), Math.min(...shown.map((s) => y(s.values[a]))) - 6, labels[a], shown.map((s, si) => ({ name: s.name, value: f(s.values[a]), color: chartColor(si) })));
|
|
370
|
-
this.querySelector(`#${this.key}-live`).textContent = a === null ? "" : `${labels[a]}: ${shown.map((s) => `${s.name} ${f(s.values[a])}`).join(
|
|
373
|
+
this.querySelector(`#${this.key}-live`).textContent = a === null ? "" : `${labels[a]}: ${shown.map((s) => `${s.name} ${f(s.values[a])}`).join(msg().common.list)}`;
|
|
371
374
|
}
|
|
372
375
|
pick(clientX) {
|
|
373
376
|
const { plot, labels, x } = this.geometry();
|
|
@@ -386,7 +389,6 @@ export class KashiLineChart extends Chart {
|
|
|
386
389
|
}
|
|
387
390
|
}
|
|
388
391
|
KashiLineChart.observedAttributes = ["label", "labels", "series", "unit", "area", "height"];
|
|
389
|
-
const WEEK = ["ش", "", "د", "", "چ", "", "ج"];
|
|
390
392
|
/** نقشهٔ فعالیت سالانه با ماههای شمسی: data='{"2026-03-21": 3, …}'، year="1405"، unit="فعالیت" */
|
|
391
393
|
export class KashiActivityHeatmap extends Chart {
|
|
392
394
|
get data() { return this.read("data", {}); }
|
|
@@ -394,7 +396,8 @@ export class KashiActivityHeatmap extends Chart {
|
|
|
394
396
|
draw() {
|
|
395
397
|
const data = this.data;
|
|
396
398
|
const year = Number(this.getAttribute("year")) || toJalali(new Date()).jy;
|
|
397
|
-
const
|
|
399
|
+
const H = msg().heatmap;
|
|
400
|
+
const unit = this.getAttribute("unit") ?? H.unit;
|
|
398
401
|
const days = [];
|
|
399
402
|
for (let m = 1; m <= 12; m++)
|
|
400
403
|
for (let d = 1; d <= jalaliMonthLength(year, m); d++) {
|
|
@@ -406,12 +409,12 @@ export class KashiActivityHeatmap extends Chart {
|
|
|
406
409
|
// شنبه سطر اول
|
|
407
410
|
const offset = (days[0].date.getDay() + 1) % 7;
|
|
408
411
|
const col = (i) => Math.floor((i + offset) / 7);
|
|
409
|
-
const months =
|
|
412
|
+
const months = calendarNames().months.map((name, m) => ({ name, col: col(days.findIndex((d) => toJalali(d.date).jm === m + 1)) }));
|
|
410
413
|
const total = days.reduce((s, d) => s + d.value, 0);
|
|
411
|
-
const monthly =
|
|
412
|
-
const yearText = formatNumber(year).replace(
|
|
413
|
-
const name = this.getAttribute("label") ??
|
|
414
|
-
this.innerHTML = `<figure class="k-heatmap" style="margin: 0"><div class="k-heatmap__scroll"><div role="img" aria-label="${esc(`${name}: ${formatNumber(total)} ${unit}`)}"><div class="k-heatmap__months" aria-hidden="true">${months.map((m) => `<span style="grid-column: ${m.col + 1}">${m.name}</span>`).join("")}</div><div class="k-heatmap__body" aria-hidden="true"><div class="k-heatmap__days">${
|
|
414
|
+
const monthly = calendarNames().months.map((name, m) => ({ name, sum: days.filter((d) => toJalali(d.date).jm === m + 1).reduce((s, d) => s + d.value, 0) }));
|
|
415
|
+
const yearText = formatNumber(year).replace(/[٬,]/g, "");
|
|
416
|
+
const name = this.getAttribute("label") ?? H.inYear(unit, yearText);
|
|
417
|
+
this.innerHTML = `<figure class="k-heatmap" style="margin: 0"><div class="k-heatmap__scroll"><div role="img" aria-label="${esc(`${name}: ${formatNumber(total)} ${unit}`)}"><div class="k-heatmap__months" aria-hidden="true">${months.map((m) => `<span style="grid-column: ${m.col + 1}">${m.name}</span>`).join("")}</div><div class="k-heatmap__body" aria-hidden="true"><div class="k-heatmap__days">${H.weekdays.map((w) => `<span>${w}</span>`).join("")}</div><div class="k-heatmap__grid">${'<span class="k-heatmap__cell" data-empty=""></span>'.repeat(offset)}${days.map((d, i) => `<span class="k-heatmap__cell" data-l="${level(d.value)}" data-i="${i}"></span>`).join("")}</div></div></div></div><figcaption class="k-heatmap__foot"><span>${esc(H.total(formatNumber(total), unit, yearText))}</span><span class="k-heatmap__scale" aria-hidden="true">${esc(H.less)} ${[0, 1, 2, 3, 4].map((l) => `<span class="k-heatmap__cell" data-l="${l}"></span>`).join("")} ${esc(H.more)}</span></figcaption><table class="k-sr-only"><caption>${esc(H.byMonth(name))}</caption><tbody>${monthly.map((m) => `<tr><th scope="row">${m.name}</th><td>${formatNumber(m.sum)}</td></tr>`).join("")}</tbody></table></figure>`;
|
|
415
418
|
const fig = this.querySelector("figure");
|
|
416
419
|
this.querySelector(".k-heatmap__grid").addEventListener("pointerover", (e) => {
|
|
417
420
|
const cell = e.target.closest("[data-i]");
|
|
@@ -421,7 +424,7 @@ export class KashiActivityHeatmap extends Chart {
|
|
|
421
424
|
cell.setAttribute("data-active", "");
|
|
422
425
|
const p = this.at(cell, fig);
|
|
423
426
|
const d = days[Number(cell.dataset.i)];
|
|
424
|
-
this.tip(fig, p.x, p.y - 2, formatJalali(d.date, { style: "full" }), [{ value: `${formatNumber(d.value)} ${unit}` }]);
|
|
427
|
+
this.tip(fig, p.x, p.y - 2, formatJalali(d.date, { style: "full", digits: localeDigits(), locale: lang() }), [{ value: `${formatNumber(d.value)} ${unit}` }]);
|
|
425
428
|
});
|
|
426
429
|
fig.addEventListener("pointerleave", () => this.tip(fig, null));
|
|
427
430
|
}
|
package/dist/combobox.d.ts
CHANGED
|
@@ -32,8 +32,8 @@ export declare class KashiCombobox extends HTMLBase {
|
|
|
32
32
|
private listbox;
|
|
33
33
|
private live;
|
|
34
34
|
/** برچسب پیشفرض وقتی label داده نشود */
|
|
35
|
-
protected defaultLabel: string | null;
|
|
36
|
-
protected defaultPlaceholder: string;
|
|
35
|
+
protected get defaultLabel(): string | null;
|
|
36
|
+
protected get defaultPlaceholder(): string;
|
|
37
37
|
connectedCallback(): void;
|
|
38
38
|
disconnectedCallback(): void;
|
|
39
39
|
attributeChangedCallback(name: string, old: string | null, next: string | null): void;
|
|
@@ -71,8 +71,8 @@ export declare class KashiCombobox extends HTMLBase {
|
|
|
71
71
|
/** انتخاب یکی از ۳۱ استان با جستجو؛ با نام مرکز استان هم پیدا میشود (مثلاً «مشهد») */
|
|
72
72
|
export declare class KashiProvinceSelect extends KashiCombobox {
|
|
73
73
|
static observedAttributes: string[];
|
|
74
|
-
protected defaultLabel: string;
|
|
75
|
-
protected defaultPlaceholder: string;
|
|
74
|
+
protected get defaultLabel(): string;
|
|
75
|
+
protected get defaultPlaceholder(): string;
|
|
76
76
|
protected source(): ComboboxOption[];
|
|
77
77
|
protected detail(): {
|
|
78
78
|
value: string;
|
|
@@ -85,7 +85,8 @@ export declare class KashiProvinceSelect extends KashiCombobox {
|
|
|
85
85
|
*/
|
|
86
86
|
export declare class KashiCitySelect extends KashiCombobox {
|
|
87
87
|
static observedAttributes: string[];
|
|
88
|
-
protected defaultLabel: string;
|
|
88
|
+
protected get defaultLabel(): string;
|
|
89
|
+
protected get defaultPlaceholder(): string;
|
|
89
90
|
private custom;
|
|
90
91
|
get province(): string | null;
|
|
91
92
|
set province(p: string | null);
|
package/dist/combobox.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { CITIES, PROVINCES, getCities, normalizePersian
|
|
2
|
-
import {
|
|
1
|
+
import { CITIES, PROVINCES, getCities, normalizePersian } from "@kashi-ui/persian";
|
|
2
|
+
import { afterParse, define, emit, esc, fieldHTML, HTMLBase, msg, num, setMessages, syncHidden, uid } from "./base.js";
|
|
3
3
|
/** متن یکدست برای جستجو: ي/ی، ك/ک، ارقام، حروف کوچک */
|
|
4
4
|
export const searchText = (s) => normalizePersian(s, { digits: "latin" }).toLowerCase();
|
|
5
5
|
/** بیشترین تعداد گزینهٔ رسمشده؛ برای فهرستهای بلند مثل ۱۲۰۰ شهر، بقیه با تایپ پیدا میشوند */
|
|
@@ -24,14 +24,18 @@ export class KashiCombobox extends HTMLBase {
|
|
|
24
24
|
this.rendered = false;
|
|
25
25
|
this.valueSet = false;
|
|
26
26
|
this.key = uid("kashi-combo");
|
|
27
|
-
/** برچسب پیشفرض وقتی label داده نشود */
|
|
28
|
-
this.defaultLabel = null;
|
|
29
|
-
this.defaultPlaceholder = "";
|
|
30
27
|
this.onOutside = (e) => {
|
|
31
28
|
if (!this.contains(e.target))
|
|
32
29
|
this.close();
|
|
33
30
|
};
|
|
34
31
|
}
|
|
32
|
+
/** برچسب پیشفرض وقتی label داده نشود */
|
|
33
|
+
get defaultLabel() {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
get defaultPlaceholder() {
|
|
37
|
+
return "";
|
|
38
|
+
}
|
|
35
39
|
connectedCallback() {
|
|
36
40
|
afterParse(() => {
|
|
37
41
|
if (!this.isConnected)
|
|
@@ -135,7 +139,7 @@ export class KashiCombobox extends HTMLBase {
|
|
|
135
139
|
const required = this.hasAttribute("required");
|
|
136
140
|
const disabled = this.hasAttribute("disabled");
|
|
137
141
|
const listId = `${id}-list`;
|
|
138
|
-
const control = `<div class="k-combobox"><div class="k-input"${disabled ? ' data-state="disabled"' : ""}><input id="${id}" class="k-input__control" type="text" role="combobox" aria-autocomplete="list" aria-expanded="false" aria-controls="${listId}" autocomplete="off" placeholder="${esc(this.getAttribute("placeholder") ?? this.defaultPlaceholder)}"${required ? " required" : ""}${disabled ? " disabled" : ""}${!label && ariaLabel ? ` aria-label="${esc(ariaLabel)}"` : ""}><button type="button" tabindex="-1" class="k-input__action k-combobox__toggle" aria-label="
|
|
142
|
+
const control = `<div class="k-combobox"><div class="k-input"${disabled ? ' data-state="disabled"' : ""}><input id="${id}" class="k-input__control" type="text" role="combobox" aria-autocomplete="list" aria-expanded="false" aria-controls="${listId}" autocomplete="off" placeholder="${esc(this.getAttribute("placeholder") ?? this.defaultPlaceholder)}"${required ? " required" : ""}${disabled ? " disabled" : ""}${!label && ariaLabel ? ` aria-label="${esc(ariaLabel)}"` : ""}><button type="button" tabindex="-1" class="k-input__action k-combobox__toggle" aria-label="${esc(msg().combobox.toggle)}"${disabled ? " disabled" : ""}>${CHEVRON}</button></div><ul id="${listId}" role="listbox" class="k-listbox" hidden style="inset-block-start: calc(100% + 6px)"${label ? ` aria-label="${esc(label)}"` : ` aria-labelledby="${id}"`}></ul><span class="k-sr-only" aria-live="polite"></span></div>`;
|
|
139
143
|
this.querySelector(":scope > .k-field")?.remove();
|
|
140
144
|
this.insertAdjacentHTML("afterbegin", fieldHTML({ id, label, required, control }));
|
|
141
145
|
this.input = this.querySelector("input.k-input__control");
|
|
@@ -249,11 +253,11 @@ export class KashiCombobox extends HTMLBase {
|
|
|
249
253
|
return `${header}<li id="${listId}-${i}" data-i="${i}" role="option" aria-selected="${on}"${o.disabled ? ' aria-disabled="true"' : ""}${i === this.active ? " data-active" : ""} class="k-option"><span class="k-option__body"><span>${mark(o.label)}</span>${o.description ? `<span class="k-option__desc">${esc(o.description)}</span>` : ""}</span>${on ? `<span class="k-option__check">${CHECK}</span>` : ""}</li>`;
|
|
250
254
|
});
|
|
251
255
|
if (!this.filtered.length)
|
|
252
|
-
items.push(`<li class="k-listbox__empty" role="presentation">${esc(this.getAttribute("empty-message") ??
|
|
256
|
+
items.push(`<li class="k-listbox__empty" role="presentation">${esc(this.getAttribute("empty-message") ?? msg().common.noResults)}</li>`);
|
|
253
257
|
if (this.filtered.length > MAX_RENDER)
|
|
254
|
-
items.push(`<li class="k-listbox__empty" role="presentation">${
|
|
258
|
+
items.push(`<li class="k-listbox__empty" role="presentation">${esc(msg().combobox.more(num(this, this.filtered.length - MAX_RENDER)))}</li>`);
|
|
255
259
|
this.listbox.innerHTML = items.join("");
|
|
256
|
-
this.live.textContent = this.typing ?
|
|
260
|
+
this.live.textContent = this.typing ? msg().common.results(num(this, this.filtered.length)) : "";
|
|
257
261
|
this.setActive(this.active);
|
|
258
262
|
}
|
|
259
263
|
setActive(i) {
|
|
@@ -319,14 +323,15 @@ export class KashiCombobox extends HTMLBase {
|
|
|
319
323
|
KashiCombobox.observedAttributes = ["label", "hint", "error", "placeholder", "required", "disabled", "name", "value", "empty-message", "aria-label"];
|
|
320
324
|
/** انتخاب یکی از ۳۱ استان با جستجو؛ با نام مرکز استان هم پیدا میشود (مثلاً «مشهد») */
|
|
321
325
|
export class KashiProvinceSelect extends KashiCombobox {
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
+
get defaultLabel() {
|
|
327
|
+
return msg().province.label;
|
|
328
|
+
}
|
|
329
|
+
get defaultPlaceholder() {
|
|
330
|
+
return msg().province.search;
|
|
326
331
|
}
|
|
327
332
|
source() {
|
|
328
333
|
const capital = this.getAttribute("show-capital") !== "false";
|
|
329
|
-
return PROVINCES.map((p) => ({ value: p.name, label: p.name, description: capital ?
|
|
334
|
+
return PROVINCES.map((p) => ({ value: p.name, label: p.name, description: capital ? msg().province.capital(p.capital) : undefined, keywords: [p.capital] }));
|
|
330
335
|
}
|
|
331
336
|
detail() {
|
|
332
337
|
return { value: this.value, province: PROVINCES.find((p) => p.name === this.value) ?? null };
|
|
@@ -343,9 +348,14 @@ const loose = (s) => searchText(s).replace(/[\s]/g, "");
|
|
|
343
348
|
export class KashiCitySelect extends KashiCombobox {
|
|
344
349
|
constructor() {
|
|
345
350
|
super(...arguments);
|
|
346
|
-
this.defaultLabel = "شهر";
|
|
347
351
|
this.custom = null;
|
|
348
352
|
}
|
|
353
|
+
get defaultLabel() {
|
|
354
|
+
return msg().city.label;
|
|
355
|
+
}
|
|
356
|
+
get defaultPlaceholder() {
|
|
357
|
+
return this.placeholderText();
|
|
358
|
+
}
|
|
349
359
|
get province() {
|
|
350
360
|
return this.getAttribute("province") || null;
|
|
351
361
|
}
|
|
@@ -367,7 +377,7 @@ export class KashiCitySelect extends KashiCombobox {
|
|
|
367
377
|
let o = city ? (list.find((x) => x.label === city && (!p || x.value.startsWith(`${p}${SEP}`))) ?? null) : null;
|
|
368
378
|
if (city && !o) {
|
|
369
379
|
this.custom = city;
|
|
370
|
-
o = { value: `custom${SEP}${city}`, label: city, description:
|
|
380
|
+
o = { value: `custom${SEP}${city}`, label: city, description: msg().city.outside };
|
|
371
381
|
}
|
|
372
382
|
this.selected = o;
|
|
373
383
|
this.query = o?.label ?? "";
|
|
@@ -403,11 +413,10 @@ export class KashiCitySelect extends KashiCombobox {
|
|
|
403
413
|
}
|
|
404
414
|
}
|
|
405
415
|
connectedCallback() {
|
|
406
|
-
this.defaultPlaceholder = this.placeholderText();
|
|
407
416
|
super.connectedCallback();
|
|
408
417
|
}
|
|
409
418
|
placeholderText() {
|
|
410
|
-
return this.province ?
|
|
419
|
+
return this.province ? msg().city.search : msg().city.hint;
|
|
411
420
|
}
|
|
412
421
|
source(query) {
|
|
413
422
|
const p = this.province;
|
|
@@ -415,10 +424,10 @@ export class KashiCitySelect extends KashiCombobox {
|
|
|
415
424
|
? getCities(p).map((c) => ({ value: `${p}${SEP}${c}`, label: c }))
|
|
416
425
|
: Object.entries(CITIES).flatMap(([prov, cities]) => cities.map((c) => ({ value: `${prov}${SEP}${c}`, label: c, description: prov })));
|
|
417
426
|
if (this.custom)
|
|
418
|
-
list.unshift({ value: `custom${SEP}${this.custom}`, label: this.custom, description:
|
|
427
|
+
list.unshift({ value: `custom${SEP}${this.custom}`, label: this.custom, description: msg().city.outside });
|
|
419
428
|
const q = query.trim();
|
|
420
429
|
if (this.getAttribute("allow-custom") !== "false" && q && q !== this.custom && !list.some((o) => loose(o.label) === loose(q)))
|
|
421
|
-
list.push({ value: `custom${SEP}${q}`, label: q, description:
|
|
430
|
+
list.push({ value: `custom${SEP}${q}`, label: q, description: msg().city.custom });
|
|
422
431
|
return list;
|
|
423
432
|
}
|
|
424
433
|
accepts(o, q) {
|
package/dist/controls.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { formatNumber, normalizePersian, onlyDigits, toEnDigits, toFaDigits } from "@kashi-ui/persian";
|
|
2
|
-
import {
|
|
2
|
+
import { bool, define, digitsOf, emit, esc, fieldHTML, HTMLBase, msg, num, setMessages, uid } from "./base.js";
|
|
3
3
|
const REMOVE = '<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true"><path d="m6 6 8 8M14 6l-8 8"/></svg>';
|
|
4
4
|
/** چند فیلد پنهان با یک name، برای ارسال چند مقدار در فرم HTML */
|
|
5
5
|
function syncHiddenList(host, name, values) {
|
|
@@ -60,7 +60,7 @@ export class KashiTagInput extends HTMLBase {
|
|
|
60
60
|
render() {
|
|
61
61
|
const id = this.key;
|
|
62
62
|
const ariaLabel = this.getAttribute("aria-label");
|
|
63
|
-
const label = this.hasAttribute("label") ? this.getAttribute("label") : ariaLabel ? null :
|
|
63
|
+
const label = this.hasAttribute("label") ? this.getAttribute("label") : ariaLabel ? null : msg().tagInput.label;
|
|
64
64
|
const control = `<div class="k-tag-input"><input id="${id}" class="k-tag-input__control"${this.hasAttribute("disabled") ? " disabled" : ""}${!label && ariaLabel ? ` aria-label="${esc(ariaLabel)}"` : ""}></div><span class="k-sr-only" aria-live="polite"></span>`;
|
|
65
65
|
this.querySelector(":scope > .k-field")?.remove();
|
|
66
66
|
this.insertAdjacentHTML("afterbegin", fieldHTML({ id, label, control }));
|
|
@@ -107,7 +107,7 @@ export class KashiTagInput extends HTMLBase {
|
|
|
107
107
|
const t = normalizePersian(r).trim();
|
|
108
108
|
if (!t)
|
|
109
109
|
continue;
|
|
110
|
-
const err = next.length >= max ?
|
|
110
|
+
const err = next.length >= max ? msg().common.max(num(this, max)) : !dup && next.includes(t) ? msg().tagInput.duplicate : this.validate?.(t);
|
|
111
111
|
if (err) {
|
|
112
112
|
this.localError = err;
|
|
113
113
|
this.commit(next, added);
|
|
@@ -115,7 +115,7 @@ export class KashiTagInput extends HTMLBase {
|
|
|
115
115
|
return;
|
|
116
116
|
}
|
|
117
117
|
next = [...next, t];
|
|
118
|
-
added =
|
|
118
|
+
added = msg().common.added(t);
|
|
119
119
|
}
|
|
120
120
|
this.localError = null;
|
|
121
121
|
this.input.value = "";
|
|
@@ -123,7 +123,7 @@ export class KashiTagInput extends HTMLBase {
|
|
|
123
123
|
}
|
|
124
124
|
removeAt(i) {
|
|
125
125
|
const t = this.tags[i];
|
|
126
|
-
this.commit(this.tags.filter((_, j) => j !== i),
|
|
126
|
+
this.commit(this.tags.filter((_, j) => j !== i), msg().common.removed(t));
|
|
127
127
|
this.input.focus();
|
|
128
128
|
}
|
|
129
129
|
commit(next, announce) {
|
|
@@ -140,7 +140,7 @@ export class KashiTagInput extends HTMLBase {
|
|
|
140
140
|
box.querySelectorAll(".k-badge").forEach((b) => b.remove());
|
|
141
141
|
const tone = this.getAttribute("tone") ?? "brand";
|
|
142
142
|
const off = this.hasAttribute("disabled");
|
|
143
|
-
const badges = this.tags.map((t, i) => `<span class="k-badge${tone !== "neutral" ? ` k-badge--${esc(tone)}` : ""}${off ? "" : " k-badge--removable"}">${esc(t)}${off ? "" : `<button type="button" class="k-badge__remove" data-i="${i}" aria-label="
|
|
143
|
+
const badges = this.tags.map((t, i) => `<span class="k-badge${tone !== "neutral" ? ` k-badge--${esc(tone)}` : ""}${off ? "" : " k-badge--removable"}">${esc(t)}${off ? "" : `<button type="button" class="k-badge__remove" data-i="${i}" aria-label="${esc(msg().common.remove(t))}">${REMOVE}</button>`}</span>`).join("");
|
|
144
144
|
this.input.insertAdjacentHTML("beforebegin", badges);
|
|
145
145
|
this.input.placeholder = this.tags.length ? "" : (this.getAttribute("placeholder") ?? "");
|
|
146
146
|
this.paintMessages();
|
|
@@ -205,15 +205,15 @@ export class KashiNumberInput extends HTMLBase {
|
|
|
205
205
|
if (n === null)
|
|
206
206
|
return "";
|
|
207
207
|
const s = this.hasAttribute("thousands") ? formatNumber(n, { digits: "latin" }) : String(n);
|
|
208
|
-
return this
|
|
208
|
+
return digitsOf(this) === "latin" ? s : toFaDigits(s).replace(/,/g, "٬");
|
|
209
209
|
}
|
|
210
210
|
render() {
|
|
211
211
|
const id = this.key;
|
|
212
212
|
const ariaLabel = this.getAttribute("aria-label");
|
|
213
|
-
const label = this.hasAttribute("label") ? this.getAttribute("label") : ariaLabel ? null :
|
|
213
|
+
const label = this.hasAttribute("label") ? this.getAttribute("label") : ariaLabel ? null : msg().numberInput.label;
|
|
214
214
|
const disabled = this.hasAttribute("disabled");
|
|
215
215
|
const unit = this.getAttribute("unit");
|
|
216
|
-
const control = `<div class="k-number"><div class="k-input"${disabled ? ' data-state="disabled"' : ""}><button type="button" class="k-number__step" data-step="-1" tabindex="-1" aria-label="
|
|
216
|
+
const control = `<div class="k-number"><div class="k-input"${disabled ? ' data-state="disabled"' : ""}><button type="button" class="k-number__step" data-step="-1" tabindex="-1" aria-label="${esc(msg().numberInput.decrement)}"${disabled ? " disabled" : ""}>${MINUS}</button><input id="${id}" class="k-input__control" type="text" inputmode="decimal" role="spinbutton" dir="ltr"${disabled ? " disabled" : ""}${!label && ariaLabel ? ` aria-label="${esc(ariaLabel)}"` : ""}>${unit ? `<span class="k-input__addon">${esc(unit)}</span>` : ""}<button type="button" class="k-number__step" data-step="1" tabindex="-1" aria-label="${esc(msg().numberInput.increment)}"${disabled ? " disabled" : ""}>${PLUS}</button></div></div>`;
|
|
217
217
|
this.querySelector(":scope > .k-field")?.remove();
|
|
218
218
|
this.insertAdjacentHTML("afterbegin", fieldHTML({ id, label, control }));
|
|
219
219
|
this.input = this.querySelector("input.k-input__control");
|
|
@@ -290,7 +290,6 @@ export class KashiNumberInput extends HTMLBase {
|
|
|
290
290
|
}
|
|
291
291
|
KashiNumberInput.observedAttributes = ["label", "hint", "error", "value", "min", "max", "step", "thousands", "digits", "unit", "disabled", "name", "aria-label"];
|
|
292
292
|
const STAR = '<svg viewBox="0 0 24 24" aria-hidden="true"><path fill="currentColor" d="M12 2.8l2.8 5.9 6.4.8-4.7 4.4 1.2 6.3L12 17.1l-5.7 3.1 1.2-6.3L2.8 9.5l6.4-.8z"/><path class="k-rating__half" fill="none" d="M12 2.8v14.3l-5.7 3.1 1.2-6.3L2.8 9.5l6.4-.8z"/></svg>';
|
|
293
|
-
const faNum = (n) => toFaDigits(String(n)).replace(".", "٫");
|
|
294
293
|
/** امتیاز ستارهای روی رادیوهای بومی؛ با readonly فقط نمایش (با نیمستاره برای امتیاز اعشاری) */
|
|
295
294
|
export class KashiRating extends HTMLBase {
|
|
296
295
|
constructor() {
|
|
@@ -322,19 +321,20 @@ export class KashiRating extends HTMLBase {
|
|
|
322
321
|
}
|
|
323
322
|
render() {
|
|
324
323
|
const max = Number(this.getAttribute("max")) || 5;
|
|
325
|
-
const label = this.getAttribute("label") ??
|
|
324
|
+
const label = this.getAttribute("label") ?? msg().rating.label;
|
|
325
|
+
const faNum = (x) => num(this, x).replace(".", msg().common.decimal);
|
|
326
326
|
const size = this.getAttribute("size");
|
|
327
327
|
const cls = `k-rating${size === "sm" || size === "lg" ? ` k-rating--${size}` : ""}`;
|
|
328
328
|
const c = this.current;
|
|
329
329
|
const stars = Array.from({ length: max }, (_, i) => i + 1);
|
|
330
330
|
const valueHtml = this.hasAttribute("show-value") ? `<span class="k-rating__value" aria-hidden="true">${faNum(c)}</span>` : "";
|
|
331
331
|
if (this.hasAttribute("readonly")) {
|
|
332
|
-
this.innerHTML = `<span class="${cls}" data-readonly="" role="img" aria-label="${esc(`${label}: ${faNum(c)
|
|
332
|
+
this.innerHTML = `<span class="${cls}" data-readonly="" role="img" aria-label="${esc(`${label}: ${msg().common.of(faNum(c), faNum(max))}`)}">${stars.map((n) => `<span class="k-rating__star"${n <= Math.floor(c) ? ' data-filled=""' : ""}${n === Math.ceil(c) && c % 1 >= 0.25 ? ' data-half=""' : ""}>${STAR}</span>`).join("")}${valueHtml}</span>`;
|
|
333
333
|
return;
|
|
334
334
|
}
|
|
335
335
|
const name = this.getAttribute("name") ?? this.key;
|
|
336
336
|
const off = this.hasAttribute("disabled");
|
|
337
|
-
this.innerHTML = `<fieldset class="${cls}"><legend class="k-sr-only">${esc(label)}</legend>${stars.map((n) => `<label class="k-rating__star"${n <= c ? ' data-filled=""' : ""}><input type="radio" class="k-sr-only" name="${esc(name)}" value="${n}"${c === n ? " checked" : ""}${off ? " disabled" : ""} aria-label="${faNum(n)
|
|
337
|
+
this.innerHTML = `<fieldset class="${cls}"><legend class="k-sr-only">${esc(label)}</legend>${stars.map((n) => `<label class="k-rating__star"${n <= c ? ' data-filled=""' : ""}><input type="radio" class="k-sr-only" name="${esc(name)}" value="${n}"${c === n ? " checked" : ""}${off ? " disabled" : ""} aria-label="${esc(msg().common.of(faNum(n), faNum(max)))}">${STAR}</label>`).join("")}${valueHtml}</fieldset>`;
|
|
338
338
|
const fs = this.querySelector("fieldset");
|
|
339
339
|
const fill = (upto) => fs.querySelectorAll(".k-rating__star").forEach((s, i) => s.toggleAttribute("data-filled", i + 1 <= upto));
|
|
340
340
|
fs.addEventListener("change", (e) => {
|
|
@@ -390,14 +390,14 @@ export class KashiPagination extends HTMLBase {
|
|
|
390
390
|
}
|
|
391
391
|
render() {
|
|
392
392
|
const page = Math.min(this.page, this.total), total = this.total;
|
|
393
|
-
const n = (v) => (this
|
|
393
|
+
const n = (v) => (digitsOf(this) === "latin" ? String(v) : toFaDigits(v));
|
|
394
394
|
const href = this.getAttribute("href");
|
|
395
395
|
const focused = this.contains(document.activeElement) ? document.activeElement.dataset.to : null;
|
|
396
396
|
const item = (to, body, cls, { current = false, disabled = false, aria = "" } = {}) => href && !disabled
|
|
397
397
|
? `<a class="${cls}" href="${esc(href.replace("{page}", String(to)))}" data-to="${to}"${current ? ' aria-current="page"' : ""}${aria ? ` aria-label="${esc(aria)}"` : ""}>${body}</a>`
|
|
398
398
|
: `<button type="button" class="${cls}" data-to="${to}"${disabled ? " disabled" : ""}${current ? ' aria-current="page"' : ""}${aria ? ` aria-label="${esc(aria)}"` : ""}>${body}</button>`;
|
|
399
399
|
const summary = this.getAttribute("summary");
|
|
400
|
-
this.innerHTML = `<nav class="k-pagination" aria-label="${esc(this.getAttribute("label") ??
|
|
400
|
+
this.innerHTML = `<nav class="k-pagination" aria-label="${esc(this.getAttribute("label") ?? msg().pagination.nav)}">${item(page - 1, `${chevron("m12 5-5 5 5 5")}${esc(msg().common.prev)}`, "k-btn k-btn--secondary k-btn--sm", { disabled: page <= 1 })}${summary ? `<span class="k-pagination__summary">${esc(summary)}</span>` : ""}<ul class="k-pagination__pages" role="list">${pageRange(page, total, Number(this.getAttribute("siblings") ?? 1)).map((p) => `<li>${p === null ? '<span class="k-pagination__ellipsis" aria-hidden="true">…</span>' : item(p, n(p), "k-pagination__page", { current: p === page, aria: msg().pagination.page(n(p)) })}</li>`).join("")}</ul>${item(page + 1, `${esc(msg().common.next)}${chevron("m8 5 5 5-5 5")}`, "k-btn k-btn--secondary k-btn--sm", { disabled: page >= total })}</nav>`;
|
|
401
401
|
this.querySelector("nav").addEventListener("click", (e) => {
|
|
402
402
|
const b = e.target.closest("button[data-to]");
|
|
403
403
|
if (!b || b.disabled)
|