@kashi-ui/elements 0.24.0 → 0.26.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 +8 -3
- package/dist/appointment.d.ts +40 -0
- package/dist/appointment.js +174 -0
- package/dist/base.js +26 -0
- package/dist/basic.d.ts +43 -0
- package/dist/basic.js +223 -0
- package/dist/calendar.d.ts +13 -0
- package/dist/calendar.js +46 -1
- package/dist/cdn/appointment-DkMxtSWi.js +1 -0
- package/dist/cdn/base-DfzNTdQk.js +1 -0
- package/dist/cdn/basic-B5n1okZO.js +1 -0
- package/dist/cdn/calendar-oMlnK1_D.js +16 -0
- package/dist/cdn/charts-SHKq2S4I.js +1 -0
- package/dist/cdn/combobox-DiGy7lAB.js +1 -0
- package/dist/cdn/controls-C6zwNYWs.js +1 -0
- package/dist/cdn/digits-DE1YGT94.js +1 -0
- package/dist/cdn/display-DZFW9EEX.js +1 -0
- package/dist/cdn/fields-D2hmrvVR.js +1 -0
- package/dist/cdn/forms-CeItYHFx.js +1 -0
- package/dist/cdn/holidays-BwsAEOI1.js +1 -0
- package/dist/cdn/inputs-DuP7P3ka.js +1 -0
- package/dist/cdn/jalali-BiM5Kfep.js +1 -0
- package/dist/cdn/kashi-elements.js +1 -27
- package/dist/cdn/map-w5X2fTQI.js +12 -0
- package/dist/cdn/menu-Cga7QOfs.js +1 -0
- package/dist/cdn/nav-CwPZ20z-.js +1 -0
- package/dist/cdn/overlay-BDzwsBN5.js +1 -0
- package/dist/cdn/pickers-BOpaZ-7q.js +1 -0
- package/dist/cdn/table-BdF43L5q.js +1 -0
- package/dist/cdn/text-D1U32D6K.js +1 -0
- package/dist/cdn/time-DXw4vOne.js +1 -0
- package/dist/cdn/words-9OdzG7y6.js +1 -0
- package/dist/cdn.d.ts +3 -0
- package/dist/cdn.js +46 -0
- package/dist/charts.d.ts +106 -0
- package/dist/charts.js +436 -0
- package/dist/forms.d.ts +186 -0
- package/dist/forms.js +902 -0
- package/dist/index.d.ts +40 -2
- package/dist/index.js +13 -1
- package/dist/nav.d.ts +163 -0
- package/dist/nav.js +918 -0
- package/dist/pickers.d.ts +108 -0
- package/dist/pickers.js +655 -0
- package/package.json +4 -4
- /package/dist/cdn/{bank-logos-D670Gw0K.js → dist-D670Gw0K.js} +0 -0
package/dist/charts.js
ADDED
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
import { JALALI_MONTHS, formatJalali, formatNumber, jalaliMonthLength, toGregorian, toISODate, toJalali } from "@kashi-ui/persian";
|
|
2
|
+
import { HTMLBase, define, esc, uid } from "./base.js";
|
|
3
|
+
/** عدد کوتاه برای محور: ۱٬۲۰۰٬۰۰۰ ← ۱٫۲ م */
|
|
4
|
+
const compact = (n) => {
|
|
5
|
+
const a = Math.abs(n);
|
|
6
|
+
const fa = (x, u) => `${formatNumber(Math.round(x * 10) / 10).replace(".", "٫")}${u}`;
|
|
7
|
+
if (a >= 1e9)
|
|
8
|
+
return fa(n / 1e9, " میلیارد");
|
|
9
|
+
if (a >= 1e6)
|
|
10
|
+
return fa(n / 1e6, " م");
|
|
11
|
+
if (a >= 1e3)
|
|
12
|
+
return fa(n / 1e3, " هزار");
|
|
13
|
+
return formatNumber(n);
|
|
14
|
+
};
|
|
15
|
+
/** گامهای گرد محور: ۰، ۲۵، ۵۰… */
|
|
16
|
+
function niceTicks(max, count = 4) {
|
|
17
|
+
if (max <= 0)
|
|
18
|
+
return [0];
|
|
19
|
+
const raw = max / count;
|
|
20
|
+
const mag = 10 ** Math.floor(Math.log10(raw));
|
|
21
|
+
const step = [1, 2, 2.5, 5, 10].map((m) => m * mag).find((s) => s >= raw);
|
|
22
|
+
return Array.from({ length: Math.ceil(max / step) + 1 }, (_, i) => i * step);
|
|
23
|
+
}
|
|
24
|
+
const pctOf = (v, total) => `${formatNumber(Math.round((v / (total || 1)) * 1000) / 10).replace(".", "٫")}٪`;
|
|
25
|
+
const chartColor = (i) => `var(--k-chart-${i + 1})`;
|
|
26
|
+
const json = (t, fallback) => {
|
|
27
|
+
if (!t)
|
|
28
|
+
return fallback;
|
|
29
|
+
try {
|
|
30
|
+
return JSON.parse(t);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return fallback;
|
|
34
|
+
}
|
|
35
|
+
};
|
|
36
|
+
/** پایهٔ نمودارها: داده از ویژگیهای JSON یا JavaScript، با هر تغییر دوباره رسم میشود */
|
|
37
|
+
class Chart extends HTMLBase {
|
|
38
|
+
constructor() {
|
|
39
|
+
super(...arguments);
|
|
40
|
+
this.key = uid("kashi-chart");
|
|
41
|
+
this.props = {};
|
|
42
|
+
}
|
|
43
|
+
connectedCallback() {
|
|
44
|
+
this.draw();
|
|
45
|
+
}
|
|
46
|
+
attributeChangedCallback() {
|
|
47
|
+
if (this.isConnected)
|
|
48
|
+
this.draw();
|
|
49
|
+
}
|
|
50
|
+
/** قالب عدد در راهنما و برچسبها */
|
|
51
|
+
get format() {
|
|
52
|
+
const unit = this.getAttribute("unit");
|
|
53
|
+
return this.fmt ?? ((n) => `${formatNumber(Math.round(n))}${unit ? ` ${unit}` : ""}`);
|
|
54
|
+
}
|
|
55
|
+
set format(f) {
|
|
56
|
+
this.fmt = f;
|
|
57
|
+
if (this.isConnected)
|
|
58
|
+
this.draw();
|
|
59
|
+
}
|
|
60
|
+
/** مقدار دادهشده با JavaScript، وگرنه ویژگی JSON */
|
|
61
|
+
read(name, fallback) {
|
|
62
|
+
return this.props[name] ?? json(this.getAttribute(name), fallback);
|
|
63
|
+
}
|
|
64
|
+
write(name, v) {
|
|
65
|
+
this.props[name] = v;
|
|
66
|
+
if (this.isConnected)
|
|
67
|
+
this.draw();
|
|
68
|
+
}
|
|
69
|
+
/** عنوان نمودار با ویژگی label (نه title، که راهنمای پیشفرض مرورگر را روی کل نمودار نشان میدهد) */
|
|
70
|
+
get heading() {
|
|
71
|
+
return this.getAttribute("label") ?? "";
|
|
72
|
+
}
|
|
73
|
+
/** راهنمای شناور داخل box در نقطهٔ (x, y)؛ داخل ظرف میماند */
|
|
74
|
+
tip(box, x, y = 0, title, rows = []) {
|
|
75
|
+
let t = box.querySelector(":scope > .k-chart__tip");
|
|
76
|
+
if (x === null) {
|
|
77
|
+
t?.remove();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
if (!t) {
|
|
81
|
+
t = document.createElement("div");
|
|
82
|
+
t.className = "k-chart__tip";
|
|
83
|
+
t.setAttribute("aria-hidden", "true");
|
|
84
|
+
box.append(t);
|
|
85
|
+
}
|
|
86
|
+
const w = box.clientWidth;
|
|
87
|
+
t.style.left = `${w ? Math.min(Math.max(x, 80), w - 80) : x}px`;
|
|
88
|
+
t.style.top = `${y}px`;
|
|
89
|
+
t.innerHTML = `${title ? `<span class="k-chart__tip-title">${esc(title)}</span>` : ""}${rows.map((r) => `<span class="k-chart__tip-row"${r.color ? ` style="--_c: ${r.color}"` : ""}>${r.name !== undefined ? `<span>${r.color ? "<i></i>" : ""}${esc(r.name)}</span>` : ""}<strong>${esc(r.value)}</strong></span>`).join("")}`;
|
|
90
|
+
}
|
|
91
|
+
/** موقعیت بالای یک عنصر نسبت به ظرف */
|
|
92
|
+
at(el, box) {
|
|
93
|
+
const b = box.getBoundingClientRect(), r = el.getBoundingClientRect();
|
|
94
|
+
return { x: r.left + r.width / 2 - b.left, y: r.top - b.top };
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
/** نمودار ستونی: data='[{"label":"…","value":…}]'، یا انباشته با labels و series (تا چهار سری) */
|
|
98
|
+
export class KashiBarChart extends Chart {
|
|
99
|
+
get data() { return this.read("data", []); }
|
|
100
|
+
set data(v) { this.write("data", v); }
|
|
101
|
+
get series() { return this.read("series", []); }
|
|
102
|
+
set series(v) { this.write("series", v); }
|
|
103
|
+
get labels() { return this.read("labels", []); }
|
|
104
|
+
set labels(v) { this.write("labels", v); }
|
|
105
|
+
draw() {
|
|
106
|
+
const f = this.format;
|
|
107
|
+
const stacked = this.series.length ? this.series.slice(0, 4) : null;
|
|
108
|
+
const data = this.data;
|
|
109
|
+
const cats = stacked ? this.labels : data.map((d) => d.label);
|
|
110
|
+
const totals = cats.map((_, i) => (stacked ? stacked.reduce((n, s) => n + (s.values[i] ?? 0), 0) : data[i].value));
|
|
111
|
+
const max = Math.max(0, ...totals);
|
|
112
|
+
const ticks = niceTicks(max);
|
|
113
|
+
const top = ticks.at(-1) || 1;
|
|
114
|
+
const maxI = totals.indexOf(max);
|
|
115
|
+
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("، ")}، جمع ${f(totals[i])}` : `${cats[i]}: ${f(totals[i])}`);
|
|
117
|
+
const height = this.getAttribute("height");
|
|
118
|
+
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
|
+
const plot = this.querySelector(".k-chart__plot");
|
|
120
|
+
const show = (col) => {
|
|
121
|
+
const i = Number(col.dataset.i);
|
|
122
|
+
plot.querySelector("[data-active]")?.removeAttribute("data-active");
|
|
123
|
+
col.setAttribute("data-active", "");
|
|
124
|
+
const p = this.at(col.querySelector(".k-bars__bar, .k-bars__stack") ?? col, plot);
|
|
125
|
+
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: "جمع", value: f(totals[i]) }]
|
|
127
|
+
: [{ value: f(totals[i]) }]);
|
|
128
|
+
};
|
|
129
|
+
const hide = () => {
|
|
130
|
+
plot.querySelector("[data-active]")?.removeAttribute("data-active");
|
|
131
|
+
this.tip(plot, null);
|
|
132
|
+
};
|
|
133
|
+
plot.querySelectorAll(".k-bars__col").forEach((col) => {
|
|
134
|
+
col.addEventListener("pointerenter", () => show(col));
|
|
135
|
+
col.addEventListener("focus", () => show(col));
|
|
136
|
+
col.addEventListener("pointerleave", hide);
|
|
137
|
+
col.addEventListener("blur", hide);
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
KashiBarChart.observedAttributes = ["label", "data", "labels", "series", "unit", "label-max", "height"];
|
|
142
|
+
/** میلههای افقی برای رتبهبندی: data='[{"label":"…","value":…,"href":"…"}]' */
|
|
143
|
+
export class KashiBarList extends Chart {
|
|
144
|
+
get data() { return this.read("data", []); }
|
|
145
|
+
set data(v) { this.write("data", v); }
|
|
146
|
+
draw() {
|
|
147
|
+
const f = this.format;
|
|
148
|
+
const data = this.data;
|
|
149
|
+
const max = Math.max(1, ...data.map((d) => d.value));
|
|
150
|
+
const total = data.reduce((n, d) => n + d.value, 0);
|
|
151
|
+
this.innerHTML = `<figure class="k-chart" aria-labelledby="${this.key}-t" style="margin: 0"><figcaption class="k-chart__head"><p class="k-chart__title" id="${this.key}-t">${esc(this.heading)}</p></figcaption><ol class="k-barlist" style="position: relative">${data.map((d, i) => `<li class="k-barlist__row" data-i="${i}" style="--_d: ${i * 60}ms"><span class="k-barlist__track"><span class="k-barlist__fill" style="inline-size: ${(d.value / max) * 100}%" aria-hidden="true"></span>${d.href ? `<a class="k-barlist__label" href="${esc(d.href)}">${esc(d.label)}</a>` : `<span class="k-barlist__label">${esc(d.label)}</span>`}</span><span class="k-barlist__value">${esc(f(d.value))} <span class="k-barlist__share">${pctOf(d.value, total)}</span></span></li>`).join("")}</ol></figure>`;
|
|
152
|
+
const box = this.querySelector(".k-barlist");
|
|
153
|
+
box.querySelectorAll(".k-barlist__row").forEach((row) => {
|
|
154
|
+
row.addEventListener("pointerenter", () => {
|
|
155
|
+
const d = data[Number(row.dataset.i)];
|
|
156
|
+
row.setAttribute("data-active", "");
|
|
157
|
+
const p = this.at(row.querySelector(".k-barlist__fill"), box);
|
|
158
|
+
this.tip(box, p.x, p.y, d.label, [{ name: "مقدار", value: f(d.value) }, { name: "سهم از کل", value: pctOf(d.value, total) }]);
|
|
159
|
+
});
|
|
160
|
+
row.addEventListener("pointerleave", () => {
|
|
161
|
+
row.removeAttribute("data-active");
|
|
162
|
+
this.tip(box, null);
|
|
163
|
+
});
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
KashiBarList.observedAttributes = ["label", "data", "unit"];
|
|
168
|
+
/** سهم هر بخش از کل در یک میلهٔ افقی (تا چهار بخش): data='[{"label":"…","value":…}]' */
|
|
169
|
+
export class KashiProportionBar extends Chart {
|
|
170
|
+
get data() { return this.read("data", []); }
|
|
171
|
+
set data(v) { this.write("data", v); }
|
|
172
|
+
draw() {
|
|
173
|
+
const f = this.format;
|
|
174
|
+
const parts = this.data.slice(0, 4);
|
|
175
|
+
const total = parts.reduce((n, d) => n + d.value, 0);
|
|
176
|
+
const percent = this.getAttribute("percent") !== "false";
|
|
177
|
+
this.innerHTML = `<figure class="k-chart" aria-labelledby="${this.key}-t" style="margin: 0"><figcaption class="k-chart__head"><p class="k-chart__title" id="${this.key}-t">${esc(this.heading)}</p></figcaption><div class="k-proportion__wrap"><div class="k-proportion" aria-hidden="true">${parts.map((d, i) => `<span class="k-proportion__seg" data-i="${i}" style="--_c: ${chartColor(i)}; flex-grow: ${d.value}"></span>`).join("")}</div></div><ul class="k-proportion__legend">${parts.map((d, i) => `<li data-i="${i}" style="--_c: ${chartColor(i)}"><span class="k-chart__key k-chart__key--box" aria-hidden="true"></span><span>${esc(d.label)}</span><strong>${esc(percent ? pctOf(d.value, total) : f(d.value))}</strong>${percent ? `<span class="k-proportion__abs">${esc(f(d.value))}</span>` : ""}</li>`).join("")}</ul></figure>`;
|
|
178
|
+
const box = this.querySelector(".k-proportion__wrap");
|
|
179
|
+
const mark = (i) => this.querySelectorAll("[data-i]").forEach((el) => el.toggleAttribute("data-active", Number(el.dataset.i) === i));
|
|
180
|
+
box.querySelectorAll(".k-proportion__seg").forEach((seg) => {
|
|
181
|
+
seg.addEventListener("pointerenter", () => {
|
|
182
|
+
const i = Number(seg.dataset.i);
|
|
183
|
+
mark(i);
|
|
184
|
+
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: "تعداد", value: f(parts[i].value) }]);
|
|
186
|
+
});
|
|
187
|
+
seg.addEventListener("pointerleave", () => {
|
|
188
|
+
mark(null);
|
|
189
|
+
this.tip(box, null);
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
KashiProportionBar.observedAttributes = ["label", "data", "unit", "percent"];
|
|
195
|
+
/** نمودار دایرهای یا دونات تا پنج بخش (بقیه در «سایر»): data='[{"label":"…","value":…}]'، variant="pie" */
|
|
196
|
+
export class KashiPieChart extends Chart {
|
|
197
|
+
get data() { return this.read("data", []); }
|
|
198
|
+
set data(v) { this.write("data", v); }
|
|
199
|
+
draw() {
|
|
200
|
+
const f = this.format;
|
|
201
|
+
const sorted = [...this.data].sort((a, b) => b.value - a.value);
|
|
202
|
+
const parts = sorted.length > 5 ? [...sorted.slice(0, 4), { label: "سایر", value: sorted.slice(4).reduce((n, d) => n + d.value, 0) }] : sorted;
|
|
203
|
+
const total = parts.reduce((n, d) => n + d.value, 0) || 1;
|
|
204
|
+
const slot = (i) => (i < 4 ? chartColor(i) : "var(--k-text-quaternary)");
|
|
205
|
+
const donut = this.getAttribute("variant") !== "pie";
|
|
206
|
+
const size = Number(this.getAttribute("size")) || 176;
|
|
207
|
+
const totalLabel = this.getAttribute("total-label") ?? "جمع";
|
|
208
|
+
// هر بخش یک کمان با stroke-dasharray؛ برای pie، شعاع نصف و ضخامت برابر قطر
|
|
209
|
+
const R = 50, r = donut ? 40 : 25, w = donut ? 16 : 50;
|
|
210
|
+
const C = 2 * Math.PI * r;
|
|
211
|
+
const gap = parts.length > 1 ? (donut ? 1.6 : 0.8) : 0;
|
|
212
|
+
let acc = 0;
|
|
213
|
+
const arcs = parts.map((d) => {
|
|
214
|
+
const len = (d.value / total) * C;
|
|
215
|
+
const a = { start: acc, len };
|
|
216
|
+
acc += len;
|
|
217
|
+
return a;
|
|
218
|
+
});
|
|
219
|
+
this.innerHTML = `<figure class="k-chart k-pie" aria-labelledby="${this.key}-t" style="margin: 0"><figcaption class="k-chart__head"><p class="k-chart__title" id="${this.key}-t">${esc(this.heading)}</p></figcaption><div class="k-pie__body"><div class="k-pie__plot" style="inline-size: ${size}px; block-size: ${size}px"><svg viewBox="0 0 100 100" class="k-pie__svg" aria-hidden="true">${donut ? `<circle cx="${R}" cy="${R}" r="${r}" fill="none" stroke="var(--k-bg-tertiary)" stroke-width="${w}"></circle>` : ""}${parts.map((d, i) => `<circle class="k-pie__slice" data-i="${i}" cx="${R}" cy="${R}" r="${r}" fill="none" stroke="${slot(i)}" stroke-width="${w}" stroke-dasharray="${Math.max(0, arcs[i].len - gap)} ${C}" stroke-dashoffset="${-arcs[i].start}" transform="rotate(-90 ${R} ${R})" style="--_d: ${i * 80}ms"></circle>`).join("")}</svg>${donut ? `<div class="k-pie__center" aria-hidden="true"><strong>${esc(f(total))}</strong><span>${esc(totalLabel)}</span></div>` : ""}</div><ul class="k-pie__legend">${parts.map((d, i) => `<li data-i="${i}" style="--_c: ${slot(i)}"><span class="k-chart__key k-chart__key--box" aria-hidden="true"></span><span class="k-pie__name">${esc(d.label)}</span><strong>${pctOf(d.value, total)}</strong><span class="k-pie__abs">${esc(f(d.value))}</span></li>`).join("")}</ul></div></figure>`;
|
|
220
|
+
const plot = this.querySelector(".k-pie__plot");
|
|
221
|
+
const center = this.querySelector(".k-pie__center");
|
|
222
|
+
const mid = (i) => {
|
|
223
|
+
const ang = ((arcs[i].start + arcs[i].len / 2) / C) * 2 * Math.PI - Math.PI / 2;
|
|
224
|
+
const rr = donut ? r : r * 1.3;
|
|
225
|
+
return { x: ((R + rr * Math.cos(ang)) / (2 * R)) * size, y: ((R + rr * Math.sin(ang)) / (2 * R)) * size - 8 };
|
|
226
|
+
};
|
|
227
|
+
const activate = (i) => {
|
|
228
|
+
this.querySelectorAll("[data-i]").forEach((el) => el.toggleAttribute("data-active", Number(el.dataset.i) === i));
|
|
229
|
+
if (center)
|
|
230
|
+
center.innerHTML = i === null ? `<strong>${esc(f(total))}</strong><span>${esc(totalLabel)}</span>` : `<strong>${pctOf(parts[i].value, total)}</strong><span>${esc(parts[i].label)}</span>`;
|
|
231
|
+
if (!donut) {
|
|
232
|
+
if (i === null)
|
|
233
|
+
this.tip(plot, null);
|
|
234
|
+
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: "تعداد", value: f(parts[i].value) }]);
|
|
236
|
+
}
|
|
237
|
+
};
|
|
238
|
+
this.querySelectorAll(".k-pie__slice, .k-pie__legend li").forEach((el) => el.addEventListener("pointerenter", () => activate(Number(el.dataset.i))));
|
|
239
|
+
plot.addEventListener("pointerleave", () => activate(null));
|
|
240
|
+
this.querySelector(".k-pie__legend").addEventListener("pointerleave", () => activate(null));
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
KashiPieChart.observedAttributes = ["label", "data", "unit", "variant", "total-label", "size"];
|
|
244
|
+
/** خط روند کوچک برای کارت آمار و جدول: values="12, 18, 15, 22" */
|
|
245
|
+
export class KashiSparkline extends Chart {
|
|
246
|
+
get values() {
|
|
247
|
+
const v = this.props.values;
|
|
248
|
+
return v ?? (this.getAttribute("values") ?? "").split(/[,،\s]+/).filter(Boolean).map(Number).filter((n) => !Number.isNaN(n));
|
|
249
|
+
}
|
|
250
|
+
set values(v) { this.write("values", v); }
|
|
251
|
+
draw() {
|
|
252
|
+
const values = this.values;
|
|
253
|
+
if (!values.length) {
|
|
254
|
+
this.innerHTML = "";
|
|
255
|
+
return;
|
|
256
|
+
}
|
|
257
|
+
const hi = Math.max(...values), lo = Math.min(...values);
|
|
258
|
+
// حداقل دامنه ۲۵٪ مقدار تا تغییر کوچک، زیگزاگ بزرگ دیده نشود
|
|
259
|
+
const span = Math.max(hi - lo, Math.abs(hi) * 0.25) || 1;
|
|
260
|
+
const min = (hi + lo) / 2 - span / 2;
|
|
261
|
+
const d = values.map((v, i) => `${i ? "L" : "M"}${(i / Math.max(1, values.length - 1)) * 100},${28 - ((v - min) / span) * 24}`).join(" ");
|
|
262
|
+
const tone = this.getAttribute("tone") ?? "brand";
|
|
263
|
+
const c = tone === "neutral" ? "var(--k-text-tertiary)" : tone === "brand" ? "var(--k-text-brand)" : `var(--k-text-${tone})`;
|
|
264
|
+
const label = this.getAttribute("label");
|
|
265
|
+
this.innerHTML = `<svg class="k-sparkline" viewBox="0 0 100 30" preserveAspectRatio="none"${label ? ` role="img" aria-label="${esc(label)}"` : ' aria-hidden="true"'} style="color: ${c}">${this.getAttribute("area") !== "false" ? `<path d="${d} L100,30 L0,30 Z" fill="currentColor" opacity="0.1"></path>` : ""}<path d="${d}" fill="none" stroke="currentColor" stroke-width="2" vector-effect="non-scaling-stroke" stroke-linejoin="round" stroke-linecap="round"></path></svg>`;
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
KashiSparkline.observedAttributes = ["values", "tone", "area", "label"];
|
|
269
|
+
/**
|
|
270
|
+
* نمودار خطی تا چهار سری: labels='["فروردین", …]' و series='[{"name":"…","values":[…]}]'.
|
|
271
|
+
* راهنمای عمودی با موس و ←→ روی کیبورد؛ محور زمان در RTL از راست شروع میشود.
|
|
272
|
+
*/
|
|
273
|
+
export class KashiLineChart extends Chart {
|
|
274
|
+
constructor() {
|
|
275
|
+
super(...arguments);
|
|
276
|
+
this.ro = null;
|
|
277
|
+
this.active = null;
|
|
278
|
+
}
|
|
279
|
+
get labels() { return this.read("labels", []); }
|
|
280
|
+
set labels(v) { this.write("labels", v); }
|
|
281
|
+
get series() { return this.read("series", []); }
|
|
282
|
+
set series(v) { this.write("series", v); }
|
|
283
|
+
connectedCallback() {
|
|
284
|
+
super.connectedCallback();
|
|
285
|
+
if (typeof ResizeObserver !== "undefined" && !this.ro) {
|
|
286
|
+
let w = 0;
|
|
287
|
+
this.ro = new ResizeObserver(() => {
|
|
288
|
+
const nw = this.clientWidth;
|
|
289
|
+
if (nw && nw !== w) {
|
|
290
|
+
w = nw;
|
|
291
|
+
this.paintSvg();
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
this.ro.observe(this);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
disconnectedCallback() {
|
|
298
|
+
this.ro?.disconnect();
|
|
299
|
+
this.ro = null;
|
|
300
|
+
}
|
|
301
|
+
draw() {
|
|
302
|
+
const shown = this.series.slice(0, 4);
|
|
303
|
+
const f = this.format;
|
|
304
|
+
const labels = this.labels;
|
|
305
|
+
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(`${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">دوره</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
|
+
const plot = this.querySelector(".k-chart__plot");
|
|
308
|
+
plot.addEventListener("pointermove", (e) => this.pick(e.clientX));
|
|
309
|
+
plot.addEventListener("pointerleave", () => this.setActive(null));
|
|
310
|
+
plot.addEventListener("blur", () => this.setActive(null));
|
|
311
|
+
plot.addEventListener("keydown", (e) => {
|
|
312
|
+
const rtl = getComputedStyle(plot).direction === "rtl";
|
|
313
|
+
const n = labels.length;
|
|
314
|
+
const next = { ArrowLeft: rtl ? 1 : -1, ArrowRight: rtl ? -1 : 1 }[e.key];
|
|
315
|
+
if (next) {
|
|
316
|
+
e.preventDefault();
|
|
317
|
+
this.setActive(Math.min(n - 1, Math.max(0, (this.active ?? (next > 0 ? -1 : n)) + next)));
|
|
318
|
+
}
|
|
319
|
+
else if (e.key === "Home")
|
|
320
|
+
this.setActive(0);
|
|
321
|
+
else if (e.key === "End")
|
|
322
|
+
this.setActive(n - 1);
|
|
323
|
+
else if (e.key === "Escape")
|
|
324
|
+
this.setActive(null);
|
|
325
|
+
});
|
|
326
|
+
this.active = null;
|
|
327
|
+
this.paintSvg();
|
|
328
|
+
}
|
|
329
|
+
geometry() {
|
|
330
|
+
const plot = this.querySelector(".k-chart__plot");
|
|
331
|
+
const shown = this.series.slice(0, 4);
|
|
332
|
+
const labels = this.labels;
|
|
333
|
+
const w = plot.clientWidth || 600, h = plot.clientHeight || 220;
|
|
334
|
+
const rtl = getComputedStyle(plot).direction === "rtl";
|
|
335
|
+
const pad = { top: 12, bottom: 24, start: 52, end: shown.length > 1 ? 64 : 16 };
|
|
336
|
+
const ticks = niceTicks(Math.max(0, ...shown.flatMap((s) => s.values)));
|
|
337
|
+
const top = ticks.at(-1) || 1;
|
|
338
|
+
const innerW = Math.max(1, w - pad.start - pad.end), innerH = Math.max(1, h - pad.top - pad.bottom);
|
|
339
|
+
// محور زمان در جهت خواندن صفحه: در RTL اولین نقطه سمت راست
|
|
340
|
+
const x = (i) => {
|
|
341
|
+
const t = labels.length > 1 ? i / (labels.length - 1) : 0.5;
|
|
342
|
+
return rtl ? w - pad.start - t * innerW : pad.start + t * innerW;
|
|
343
|
+
};
|
|
344
|
+
const y = (v) => pad.top + innerH - (v / top) * innerH;
|
|
345
|
+
return { plot, shown, labels, w, h, rtl, pad, ticks, innerW, innerH, x, y };
|
|
346
|
+
}
|
|
347
|
+
paintSvg() {
|
|
348
|
+
if (!this.querySelector(".k-chart__plot"))
|
|
349
|
+
return;
|
|
350
|
+
const { plot, shown, labels, w, h, rtl, pad, ticks, innerW, innerH, x, y } = this.geometry();
|
|
351
|
+
const svg = plot.querySelector("svg");
|
|
352
|
+
const tickX = rtl ? w - pad.start + 8 : pad.start - 8;
|
|
353
|
+
const anchor = rtl ? "start" : "end";
|
|
354
|
+
const last = labels.length - 1;
|
|
355
|
+
// برچسب انتهای خطها روی هم نیفتند: دستکم ۱۴ پیکسل فاصلهٔ عمودی
|
|
356
|
+
const order = shown.map((s, i) => ({ i, y: y(s.values[last]) })).sort((a, b) => a.y - b.y);
|
|
357
|
+
for (let k = 1; k < order.length; k++)
|
|
358
|
+
if (order[k].y - order[k - 1].y < 14)
|
|
359
|
+
order[k].y = order[k - 1].y + 14;
|
|
360
|
+
const endY = Object.fromEntries(order.map((o) => [o.i, o.y]));
|
|
361
|
+
const step = Math.max(1, Math.ceil(labels.length / Math.max(2, Math.floor(innerW / 64))));
|
|
362
|
+
const fade = `${this.key}-fade`;
|
|
363
|
+
const a = this.active;
|
|
364
|
+
svg.innerHTML = `<g class="k-chart__grid">${ticks.map((t) => `<line x1="${pad.start}" x2="${w - pad.end}" y1="${y(t)}" y2="${y(t)}"${rtl ? ` transform="translate(${pad.end - pad.start} 0)"` : ""}></line>`).join("")}</g>${ticks.map((t) => `<text class="k-chart__tick" x="${tickX}" y="${y(t) + 4}" text-anchor="${anchor}">${esc(compact(t))}</text>`).join("")}${labels.map((l, i) => (i % step === 0 || i === last ? `<text class="k-chart__tick" x="${x(i)}" y="${h - 6}" text-anchor="middle">${esc(l)}</text>` : "")).join("")}<defs><linearGradient id="${fade}" x1="0" y1="0" x2="0" y2="1"><stop offset="0" style="stop-color: var(--k-chart-1); stop-opacity: 0.28"></stop><stop offset="1" style="stop-color: var(--k-chart-1); stop-opacity: 0"></stop></linearGradient></defs>${shown.length === 1 && this.getAttribute("area") !== "false" ? `<path class="k-chart__area" fill="url(#${fade})" d="M${x(0)},${y(0)} ${shown[0].values.map((v, i) => `L${x(i)},${y(v)}`).join(" ")} L${x(last)},${y(0)} Z"></path>` : ""}${a !== null ? `<line class="k-chart__cross" x1="${x(a)}" x2="${x(a)}" y1="${pad.top}" y2="${pad.top + innerH}"></line>` : ""}${shown.map((s, si) => `<g style="--_c: ${chartColor(si)}"><path class="k-chart__line" pathLength="1" d="${s.values.map((v, i) => `${i ? "L" : "M"}${x(i)},${y(v)}`).join(" ")}"></path><circle class="k-chart__dot" cx="${x(s.values.length - 1)}" cy="${y(s.values.at(-1) ?? 0)}" r="4"></circle>${shown.length > 1 ? `<text class="k-chart__end" x="${x(last) + (rtl ? -8 : 8)}" y="${endY[si] + 4}" text-anchor="${rtl ? "end" : "start"}">${esc(s.name)}</text>` : ""}${a !== null ? `<circle class="k-chart__dot" cx="${x(a)}" cy="${y(s.values[a])}" r="4.5"></circle>` : ""}</g>`).join("")}`;
|
|
365
|
+
const f = this.format;
|
|
366
|
+
if (a === null)
|
|
367
|
+
this.tip(plot, null);
|
|
368
|
+
else
|
|
369
|
+
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("، ")}`;
|
|
371
|
+
}
|
|
372
|
+
pick(clientX) {
|
|
373
|
+
const { plot, labels, x } = this.geometry();
|
|
374
|
+
const px = clientX - plot.getBoundingClientRect().left;
|
|
375
|
+
let best = 0;
|
|
376
|
+
labels.forEach((_, i) => {
|
|
377
|
+
if (Math.abs(x(i) - px) < Math.abs(x(best) - px))
|
|
378
|
+
best = i;
|
|
379
|
+
});
|
|
380
|
+
if (best !== this.active)
|
|
381
|
+
this.setActive(best);
|
|
382
|
+
}
|
|
383
|
+
setActive(i) {
|
|
384
|
+
this.active = i;
|
|
385
|
+
this.paintSvg();
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
KashiLineChart.observedAttributes = ["label", "labels", "series", "unit", "area", "height"];
|
|
389
|
+
const WEEK = ["ش", "", "د", "", "چ", "", "ج"];
|
|
390
|
+
/** نقشهٔ فعالیت سالانه با ماههای شمسی: data='{"2026-03-21": 3, …}'، year="1405"، unit="فعالیت" */
|
|
391
|
+
export class KashiActivityHeatmap extends Chart {
|
|
392
|
+
get data() { return this.read("data", {}); }
|
|
393
|
+
set data(v) { this.write("data", v); }
|
|
394
|
+
draw() {
|
|
395
|
+
const data = this.data;
|
|
396
|
+
const year = Number(this.getAttribute("year")) || toJalali(new Date()).jy;
|
|
397
|
+
const unit = this.getAttribute("unit") ?? "فعالیت";
|
|
398
|
+
const days = [];
|
|
399
|
+
for (let m = 1; m <= 12; m++)
|
|
400
|
+
for (let d = 1; d <= jalaliMonthLength(year, m); d++) {
|
|
401
|
+
const date = toGregorian(year, m, d);
|
|
402
|
+
days.push({ date, value: data[toISODate(date)] ?? 0 });
|
|
403
|
+
}
|
|
404
|
+
const max = Math.max(0, ...days.map((d) => d.value));
|
|
405
|
+
const level = (v) => (v <= 0 || max === 0 ? 0 : Math.max(1, Math.ceil((v / max) * 4)));
|
|
406
|
+
// شنبه سطر اول
|
|
407
|
+
const offset = (days[0].date.getDay() + 1) % 7;
|
|
408
|
+
const col = (i) => Math.floor((i + offset) / 7);
|
|
409
|
+
const months = JALALI_MONTHS.map((name, m) => ({ name, col: col(days.findIndex((d) => toJalali(d.date).jm === m + 1)) }));
|
|
410
|
+
const total = days.reduce((s, d) => s + d.value, 0);
|
|
411
|
+
const monthly = JALALI_MONTHS.map((name, m) => ({ name, sum: days.filter((d) => toJalali(d.date).jm === m + 1).reduce((s, d) => s + d.value, 0) }));
|
|
412
|
+
const yearText = formatNumber(year).replace(/٬/g, "");
|
|
413
|
+
const name = this.getAttribute("label") ?? `${unit} در سال ${yearText}`;
|
|
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">${WEEK.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>${formatNumber(total)} ${esc(unit)} در ${yearText}</span><span class="k-heatmap__scale" aria-hidden="true">کمتر ${[0, 1, 2, 3, 4].map((l) => `<span class="k-heatmap__cell" data-l="${l}"></span>`).join("")} بیشتر</span></figcaption><table class="k-sr-only"><caption>${esc(name)}، به تفکیک ماه</caption><tbody>${monthly.map((m) => `<tr><th scope="row">${m.name}</th><td>${formatNumber(m.sum)}</td></tr>`).join("")}</tbody></table></figure>`;
|
|
415
|
+
const fig = this.querySelector("figure");
|
|
416
|
+
this.querySelector(".k-heatmap__grid").addEventListener("pointerover", (e) => {
|
|
417
|
+
const cell = e.target.closest("[data-i]");
|
|
418
|
+
fig.querySelector(".k-heatmap__cell[data-active]")?.removeAttribute("data-active");
|
|
419
|
+
if (!cell)
|
|
420
|
+
return this.tip(fig, null);
|
|
421
|
+
cell.setAttribute("data-active", "");
|
|
422
|
+
const p = this.at(cell, fig);
|
|
423
|
+
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}` }]);
|
|
425
|
+
});
|
|
426
|
+
fig.addEventListener("pointerleave", () => this.tip(fig, null));
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
KashiActivityHeatmap.observedAttributes = ["data", "year", "unit", "label"];
|
|
430
|
+
define("kashi-bar-chart", KashiBarChart, "block");
|
|
431
|
+
define("kashi-line-chart", KashiLineChart, "block");
|
|
432
|
+
define("kashi-pie-chart", KashiPieChart, "block");
|
|
433
|
+
define("kashi-bar-list", KashiBarList, "block");
|
|
434
|
+
define("kashi-proportion-bar", KashiProportionBar, "block");
|
|
435
|
+
define("kashi-sparkline", KashiSparkline);
|
|
436
|
+
define("kashi-activity-heatmap", KashiActivityHeatmap, "block");
|
package/dist/forms.d.ts
ADDED
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { type Plate } from "@kashi-ui/persian";
|
|
2
|
+
import { HTMLBase } from "./base.js";
|
|
3
|
+
import { type ComboboxOption } from "./combobox.js";
|
|
4
|
+
/**
|
|
5
|
+
* انتخاب چندتایی با جستجو: انتخابها بهشکل برچسب، با Backspace حذف آخرین، ↑↓ و Enter برای انتخاب.
|
|
6
|
+
* گزینهها از <option> (selected برای انتخاب اولیه) یا element.options.
|
|
7
|
+
*/
|
|
8
|
+
export declare class KashiMultiSelect extends HTMLBase {
|
|
9
|
+
static observedAttributes: string[];
|
|
10
|
+
private list;
|
|
11
|
+
private chosen;
|
|
12
|
+
private query;
|
|
13
|
+
private active;
|
|
14
|
+
private isOpen;
|
|
15
|
+
private valueSet;
|
|
16
|
+
private key;
|
|
17
|
+
private input;
|
|
18
|
+
private box;
|
|
19
|
+
private listbox;
|
|
20
|
+
connectedCallback(): void;
|
|
21
|
+
disconnectedCallback(): void;
|
|
22
|
+
attributeChangedCallback(_n: string, old: string | null, next: string | null): void;
|
|
23
|
+
get options(): ComboboxOption[];
|
|
24
|
+
set options(o: ComboboxOption[]);
|
|
25
|
+
/** مقدار گزینههای انتخابشده */
|
|
26
|
+
get value(): string[];
|
|
27
|
+
set value(v: string[]);
|
|
28
|
+
private render;
|
|
29
|
+
private labelOf;
|
|
30
|
+
private filtered;
|
|
31
|
+
private get full();
|
|
32
|
+
private toggle;
|
|
33
|
+
private set;
|
|
34
|
+
private announce;
|
|
35
|
+
private open;
|
|
36
|
+
private close;
|
|
37
|
+
private onOutside;
|
|
38
|
+
private onKey;
|
|
39
|
+
private paint;
|
|
40
|
+
private paintList;
|
|
41
|
+
}
|
|
42
|
+
/** اسلایدر روی input range بومی؛ با range دو دستگیره برای بازه (min و max) */
|
|
43
|
+
export declare class KashiSlider extends HTMLBase {
|
|
44
|
+
static observedAttributes: string[];
|
|
45
|
+
private lo;
|
|
46
|
+
private hi;
|
|
47
|
+
private valueSet;
|
|
48
|
+
private rendered;
|
|
49
|
+
private key;
|
|
50
|
+
connectedCallback(): void;
|
|
51
|
+
attributeChangedCallback(name: string, old: string | null, next: string | null): void;
|
|
52
|
+
private num;
|
|
53
|
+
private get min();
|
|
54
|
+
private get max();
|
|
55
|
+
private get isRange();
|
|
56
|
+
private readValue;
|
|
57
|
+
/** عدد، یا در حالت range آرایهٔ [کمینه، بیشینه] */
|
|
58
|
+
get value(): number | [number, number];
|
|
59
|
+
set value(v: number | [number, number]);
|
|
60
|
+
private fmt;
|
|
61
|
+
private render;
|
|
62
|
+
}
|
|
63
|
+
/** گروه چیپ برای فیلتر: هر فرزند <button> (با data-value، data-count) یک چیپ است؛ با single فقط یکی */
|
|
64
|
+
export declare class KashiChipGroup extends HTMLBase {
|
|
65
|
+
static observedAttributes: string[];
|
|
66
|
+
private built;
|
|
67
|
+
connectedCallback(): void;
|
|
68
|
+
attributeChangedCallback(): void;
|
|
69
|
+
/** مقدار چیپهای روشن */
|
|
70
|
+
get value(): string[];
|
|
71
|
+
set value(v: string[]);
|
|
72
|
+
private build;
|
|
73
|
+
private sync;
|
|
74
|
+
}
|
|
75
|
+
/** قدرت رمز زیر فیلد رمز؛ با for="شناسهٔ فیلد" به آن وصل میشود و با هر تایپ بهروز میشود */
|
|
76
|
+
export declare class KashiPasswordStrength extends HTMLBase {
|
|
77
|
+
static observedAttributes: string[];
|
|
78
|
+
private target;
|
|
79
|
+
connectedCallback(): void;
|
|
80
|
+
disconnectedCallback(): void;
|
|
81
|
+
attributeChangedCallback(): void;
|
|
82
|
+
private attach;
|
|
83
|
+
private onInput;
|
|
84
|
+
/** امتیاز ۰ تا ۴ */
|
|
85
|
+
score(password: string): number;
|
|
86
|
+
private render;
|
|
87
|
+
}
|
|
88
|
+
/** پایهٔ فیلد متنی ساده با برچسب، راهنما و خطا، برای فیلدهای متنی فارسی */
|
|
89
|
+
declare abstract class TextField extends HTMLBase {
|
|
90
|
+
protected key: string;
|
|
91
|
+
protected control: HTMLInputElement | HTMLTextAreaElement;
|
|
92
|
+
protected rendered: boolean;
|
|
93
|
+
protected valueSet: boolean;
|
|
94
|
+
protected text: string;
|
|
95
|
+
protected abstract multiline: boolean;
|
|
96
|
+
protected abstract defaultLabel: string;
|
|
97
|
+
protected abstract hint(): string | null;
|
|
98
|
+
connectedCallback(): void;
|
|
99
|
+
attributeChangedCallback(name: string, old: string | null, next: string | null): void;
|
|
100
|
+
get value(): string;
|
|
101
|
+
set value(v: string);
|
|
102
|
+
focus(options?: FocusOptions): void;
|
|
103
|
+
protected render(): void;
|
|
104
|
+
/** راهنمای زیر فیلد؛ HTML ساختهشده توسط زیرکلاس */
|
|
105
|
+
protected paint(): void;
|
|
106
|
+
protected replace(next: string): void;
|
|
107
|
+
}
|
|
108
|
+
/** متن چندخطی با ویرایش نگارشی: ی و ک عربی، نیمفاصله، علامتها و ارقام را میشمارد و با یک دکمه اصلاح میکند */
|
|
109
|
+
export declare class KashiPersianTextarea extends TextField {
|
|
110
|
+
static observedAttributes: string[];
|
|
111
|
+
protected multiline: boolean;
|
|
112
|
+
protected defaultLabel: string;
|
|
113
|
+
protected render(): void;
|
|
114
|
+
private result;
|
|
115
|
+
protected hint(): string | null;
|
|
116
|
+
}
|
|
117
|
+
/** فیلد متنی که متن تایپشده با صفحهکلید انگلیسی را تشخیص میدهد و نسخهٔ فارسیاش را پیشنهاد میکند («sghl» ← «سلام») */
|
|
118
|
+
export declare class KashiKeyboardFix extends TextField {
|
|
119
|
+
static observedAttributes: string[];
|
|
120
|
+
protected multiline: boolean;
|
|
121
|
+
protected defaultLabel: string;
|
|
122
|
+
protected render(): void;
|
|
123
|
+
protected hint(): string | null;
|
|
124
|
+
}
|
|
125
|
+
/** ساعت ۲۴ساعته: ۹:۳۰، ۰۹۳۰ و ارقام فارسی را میفهمد؛ ↑↓ با گام step دقیقه */
|
|
126
|
+
export declare class KashiTimeInput extends HTMLBase {
|
|
127
|
+
static observedAttributes: string[];
|
|
128
|
+
private current;
|
|
129
|
+
private invalid;
|
|
130
|
+
private valueSet;
|
|
131
|
+
private rendered;
|
|
132
|
+
private key;
|
|
133
|
+
private input;
|
|
134
|
+
connectedCallback(): void;
|
|
135
|
+
attributeChangedCallback(name: string, old: string | null, next: string | null): void;
|
|
136
|
+
/** ساعت به شکل HH:MM، یا رشتهٔ خالی */
|
|
137
|
+
get value(): string;
|
|
138
|
+
set value(v: string);
|
|
139
|
+
private normal;
|
|
140
|
+
private show;
|
|
141
|
+
private get lo();
|
|
142
|
+
private get hi();
|
|
143
|
+
private render;
|
|
144
|
+
private commitText;
|
|
145
|
+
private commit;
|
|
146
|
+
private paint;
|
|
147
|
+
}
|
|
148
|
+
/** پلاک خودرو با چهار بخش (۱۲ ب ۳۴۵ ایران ۶۷)؛ فوکوس خودکار به بخش بعد و رنگ بر اساس نوع پلاک */
|
|
149
|
+
export declare class KashiPlateInput extends HTMLBase {
|
|
150
|
+
static observedAttributes: string[];
|
|
151
|
+
private plate;
|
|
152
|
+
private touched;
|
|
153
|
+
private valueSet;
|
|
154
|
+
private rendered;
|
|
155
|
+
private key;
|
|
156
|
+
connectedCallback(): void;
|
|
157
|
+
attributeChangedCallback(name: string, old: string | null, next: string | null): void;
|
|
158
|
+
/** «12-ب-345-67» */
|
|
159
|
+
private parse;
|
|
160
|
+
get value(): Plate;
|
|
161
|
+
set value(p: Plate);
|
|
162
|
+
get valid(): boolean;
|
|
163
|
+
private render;
|
|
164
|
+
private paint;
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* ویرایش درجا: متن با کلیک یا Enter به فیلد تبدیل میشود، Enter ثبت و Esc انصراف.
|
|
168
|
+
* رویداد kashi-save با detail.value؛ برای ذخیرهٔ سمت سرور event.detail.wait(promise) را صدا بزنید.
|
|
169
|
+
*/
|
|
170
|
+
export declare class KashiInlineEdit extends HTMLBase {
|
|
171
|
+
static observedAttributes: string[];
|
|
172
|
+
private text;
|
|
173
|
+
private editing;
|
|
174
|
+
private valueSet;
|
|
175
|
+
private rendered;
|
|
176
|
+
/** اعتبارسنجی؛ پیام خطا یا undefined */
|
|
177
|
+
validate?: (value: string) => string | undefined;
|
|
178
|
+
connectedCallback(): void;
|
|
179
|
+
attributeChangedCallback(name: string, old: string | null, next: string | null): void;
|
|
180
|
+
get value(): string;
|
|
181
|
+
set value(v: string);
|
|
182
|
+
private render;
|
|
183
|
+
private edit;
|
|
184
|
+
private commit;
|
|
185
|
+
}
|
|
186
|
+
export {};
|