@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
package/dist/inputs.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { formatCardNumber, formatIban, formatLandline, formatMobile, formatNumber, formatPostalCode, getBankByCard, getBankByIban, getLandlineProvince, getMobileOperator, isValidCardNumber, isValidIban, isValidLandline, isValidLegalId, isValidMobile, isValidNationalId, isValidPostalCode, normalizeLandline, normalizeMobile, numberToWords, onlyDigits, toFaDigits, } from "@kashi-ui/persian";
|
|
2
|
-
import {
|
|
1
|
+
import { formatCardNumber, formatIban, formatLandline, formatMobile, formatNumber, formatPostalCode, bankName, getBankByCard, getBankByIban, getLandlineProvince, getMobileOperator, operatorName, isValidCardNumber, isValidIban, isValidLandline, isValidLegalId, isValidMobile, isValidNationalId, isValidPostalCode, normalizeLandline, normalizeMobile, numberToWords, onlyDigits, toFaDigits, } from "@kashi-ui/persian";
|
|
2
|
+
import { bool, define, emit, esc, fieldHTML, HTMLBase, lang, msg, setMessages, syncHidden, uid } from "./base.js";
|
|
3
3
|
const fa = (s) => toFaDigits(s);
|
|
4
4
|
/** موقعیت مکاننما پس از n رقم در متن قالببندیشده */
|
|
5
5
|
function caretAfter(text, n) {
|
|
@@ -69,7 +69,7 @@ export class KashiDigitsInput extends HTMLBase {
|
|
|
69
69
|
}
|
|
70
70
|
get digits() {
|
|
71
71
|
const d = this.getAttribute("digits");
|
|
72
|
-
return d === "fa" || d === "latin" ? d : this.kind.digits;
|
|
72
|
+
return d === "fa" || d === "latin" ? d : lang() === "en" ? "latin" : this.kind.digits;
|
|
73
73
|
}
|
|
74
74
|
shown() {
|
|
75
75
|
const f = this.kind.format(this.raw);
|
|
@@ -79,7 +79,7 @@ export class KashiDigitsInput extends HTMLBase {
|
|
|
79
79
|
const k = this.kind;
|
|
80
80
|
const id = this.key;
|
|
81
81
|
const ariaLabel = this.getAttribute("aria-label");
|
|
82
|
-
const label = this.hasAttribute("label") ? this.getAttribute("label") : ariaLabel ? null : k.label;
|
|
82
|
+
const label = this.hasAttribute("label") ? this.getAttribute("label") : ariaLabel ? null : k.label();
|
|
83
83
|
const size = this.getAttribute("size");
|
|
84
84
|
const required = this.hasAttribute("required");
|
|
85
85
|
const disabled = this.hasAttribute("disabled");
|
|
@@ -119,7 +119,7 @@ export class KashiDigitsInput extends HTMLBase {
|
|
|
119
119
|
/** پیام خطای فعلی؛ فیلد مبلغ آن را برای محدوده بازنویسی میکند */
|
|
120
120
|
invalidText(touched) {
|
|
121
121
|
const show = this.raw.length > 0 && (touched || this.raw.length === this.kind.maxDigits) && !this.isValid();
|
|
122
|
-
return show ? (this.getAttribute("invalid-message") ?? this.kind.invalidMessage) : null;
|
|
122
|
+
return show ? (this.getAttribute("invalid-message") ?? this.kind.invalidMessage()) : null;
|
|
123
123
|
}
|
|
124
124
|
hintText() {
|
|
125
125
|
return this.getAttribute("hint");
|
|
@@ -174,11 +174,11 @@ export class KashiNationalId extends KashiDigitsInput {
|
|
|
174
174
|
constructor() {
|
|
175
175
|
super(...arguments);
|
|
176
176
|
this.kind = {
|
|
177
|
-
label:
|
|
177
|
+
label: () => msg().persianInput["national-id"],
|
|
178
178
|
maxDigits: 10,
|
|
179
179
|
format: (d) => d,
|
|
180
180
|
valid: (d) => isValidNationalId(d),
|
|
181
|
-
invalidMessage:
|
|
181
|
+
invalidMessage: () => msg().invalid.nationalId,
|
|
182
182
|
placeholder: { fa: "۰۰۰۰۰۰۰۰۰۰", latin: "0000000000" },
|
|
183
183
|
digits: "fa",
|
|
184
184
|
};
|
|
@@ -189,11 +189,11 @@ export class KashiLegalId extends KashiDigitsInput {
|
|
|
189
189
|
constructor() {
|
|
190
190
|
super(...arguments);
|
|
191
191
|
this.kind = {
|
|
192
|
-
label:
|
|
192
|
+
label: () => msg().persianInput["legal-id"],
|
|
193
193
|
maxDigits: 11,
|
|
194
194
|
format: (d) => d,
|
|
195
195
|
valid: (d) => isValidLegalId(d),
|
|
196
|
-
invalidMessage:
|
|
196
|
+
invalidMessage: () => msg().invalid.legalId,
|
|
197
197
|
placeholder: { fa: "۰۰۰۰۰۰۰۰۰۰۰", latin: "00000000000" },
|
|
198
198
|
digits: "fa",
|
|
199
199
|
};
|
|
@@ -204,12 +204,12 @@ export class KashiMobile extends KashiDigitsInput {
|
|
|
204
204
|
constructor() {
|
|
205
205
|
super(...arguments);
|
|
206
206
|
this.kind = {
|
|
207
|
-
label:
|
|
207
|
+
label: () => msg().persianInput.mobile,
|
|
208
208
|
maxDigits: 11,
|
|
209
209
|
normalize: normalizeMobile,
|
|
210
210
|
format: formatMobile,
|
|
211
211
|
valid: (d) => isValidMobile(d),
|
|
212
|
-
invalidMessage:
|
|
212
|
+
invalidMessage: () => msg().invalid.mobile,
|
|
213
213
|
placeholder: { fa: "۰۹۱۲ ۳۴۵ ۶۷۸۹", latin: "0912 345 6789" },
|
|
214
214
|
digits: "fa",
|
|
215
215
|
type: "tel",
|
|
@@ -217,7 +217,7 @@ export class KashiMobile extends KashiDigitsInput {
|
|
|
217
217
|
autocomplete: "tel-national",
|
|
218
218
|
meta: (d) => {
|
|
219
219
|
const op = getMobileOperator(d);
|
|
220
|
-
return op ? { text: op
|
|
220
|
+
return op ? { text: operatorName(op, lang()) } : null;
|
|
221
221
|
},
|
|
222
222
|
detail: (d) => ({ operator: getMobileOperator(d)?.name ?? null }),
|
|
223
223
|
};
|
|
@@ -228,12 +228,12 @@ export class KashiLandline extends KashiDigitsInput {
|
|
|
228
228
|
constructor() {
|
|
229
229
|
super(...arguments);
|
|
230
230
|
this.kind = {
|
|
231
|
-
label:
|
|
231
|
+
label: () => msg().persianInput.landline,
|
|
232
232
|
maxDigits: 11,
|
|
233
233
|
normalize: normalizeLandline,
|
|
234
234
|
format: formatLandline,
|
|
235
235
|
valid: (d) => isValidLandline(d),
|
|
236
|
-
invalidMessage:
|
|
236
|
+
invalidMessage: () => msg().invalid.landline,
|
|
237
237
|
placeholder: { fa: "۰۲۱ ۸۸۷۷ ۶۶۵۵", latin: "021 8877 6655" },
|
|
238
238
|
digits: "fa",
|
|
239
239
|
type: "tel",
|
|
@@ -252,17 +252,17 @@ export class KashiCardNumber extends KashiDigitsInput {
|
|
|
252
252
|
constructor() {
|
|
253
253
|
super(...arguments);
|
|
254
254
|
this.kind = {
|
|
255
|
-
label:
|
|
255
|
+
label: () => msg().persianInput.card,
|
|
256
256
|
maxDigits: 16,
|
|
257
257
|
format: formatCardNumber,
|
|
258
258
|
valid: (d) => isValidCardNumber(d),
|
|
259
|
-
invalidMessage:
|
|
259
|
+
invalidMessage: () => msg().invalid.card,
|
|
260
260
|
placeholder: { fa: "۰۰۰۰ ۰۰۰۰ ۰۰۰۰ ۰۰۰۰", latin: "0000 0000 0000 0000" },
|
|
261
261
|
digits: "fa",
|
|
262
262
|
autocomplete: "cc-number",
|
|
263
263
|
meta: (d) => {
|
|
264
264
|
const bank = getBankByCard(d);
|
|
265
|
-
return bank ? { text: bank
|
|
265
|
+
return bank ? { text: bankName(bank, lang()), bank } : null;
|
|
266
266
|
},
|
|
267
267
|
detail: (d) => ({ bank: getBankByCard(d)?.name ?? null }),
|
|
268
268
|
};
|
|
@@ -273,16 +273,16 @@ export class KashiIban extends KashiDigitsInput {
|
|
|
273
273
|
constructor() {
|
|
274
274
|
super(...arguments);
|
|
275
275
|
this.kind = {
|
|
276
|
-
label:
|
|
276
|
+
label: () => msg().persianInput.iban,
|
|
277
277
|
maxDigits: 24,
|
|
278
278
|
format: (d) => formatIban(d),
|
|
279
279
|
valid: (d) => isValidIban(d),
|
|
280
|
-
invalidMessage:
|
|
280
|
+
invalidMessage: () => msg().invalid.iban,
|
|
281
281
|
placeholder: { fa: "IR00 0000 0000 0000 0000 0000 00", latin: "IR00 0000 0000 0000 0000 0000 00" },
|
|
282
282
|
digits: "latin",
|
|
283
283
|
meta: (d) => {
|
|
284
284
|
const bank = getBankByIban(d);
|
|
285
|
-
return bank ? { text: bank
|
|
285
|
+
return bank ? { text: bankName(bank, lang()), bank } : null;
|
|
286
286
|
},
|
|
287
287
|
submit: (d) => (d ? `IR${d}` : ""),
|
|
288
288
|
detail: (d) => ({ bank: getBankByIban(d)?.name ?? null }),
|
|
@@ -297,11 +297,11 @@ export class KashiPostalCode extends KashiDigitsInput {
|
|
|
297
297
|
constructor() {
|
|
298
298
|
super(...arguments);
|
|
299
299
|
this.kind = {
|
|
300
|
-
label:
|
|
300
|
+
label: () => msg().persianInput.postal,
|
|
301
301
|
maxDigits: 10,
|
|
302
302
|
format: formatPostalCode,
|
|
303
303
|
valid: (d) => isValidPostalCode(d),
|
|
304
|
-
invalidMessage:
|
|
304
|
+
invalidMessage: () => msg().invalid.postal,
|
|
305
305
|
placeholder: { fa: "۱۲۳۴۵-۶۷۸۹۰", latin: "12345-67890" },
|
|
306
306
|
digits: "fa",
|
|
307
307
|
autocomplete: "postal-code",
|
|
@@ -313,16 +313,16 @@ export class KashiPrice extends KashiDigitsInput {
|
|
|
313
313
|
constructor() {
|
|
314
314
|
super(...arguments);
|
|
315
315
|
this.kind = {
|
|
316
|
-
label:
|
|
316
|
+
label: () => msg().persianInput.price,
|
|
317
317
|
maxDigits: 15,
|
|
318
318
|
normalize: (d) => d.replace(/^0+(?=\d)/, ""),
|
|
319
|
-
format: (d) => (d ? formatNumber(d, { digits: "latin" }).replace(/,/g, "٬") : ""),
|
|
319
|
+
format: (d) => (d ? formatNumber(d, { digits: "latin" }).replace(/,/g, this.digits === "fa" ? "٬" : ",") : ""),
|
|
320
320
|
valid: () => this.inRange(),
|
|
321
|
-
invalidMessage: "",
|
|
321
|
+
invalidMessage: () => "",
|
|
322
322
|
placeholder: { fa: "۰", latin: "0" },
|
|
323
323
|
digits: "fa",
|
|
324
324
|
meta: (_d, host) => {
|
|
325
|
-
const unit = host.getAttribute("unit") ??
|
|
325
|
+
const unit = host.getAttribute("unit") ?? msg().money.toman;
|
|
326
326
|
return unit ? { text: unit } : null;
|
|
327
327
|
},
|
|
328
328
|
detail: (d) => ({ value: d ? Number(d) : null }),
|
|
@@ -349,13 +349,14 @@ export class KashiPrice extends KashiDigitsInput {
|
|
|
349
349
|
if (custom)
|
|
350
350
|
return custom;
|
|
351
351
|
const min = this.num("min"), max = this.num("max");
|
|
352
|
-
const f = (n) => fa(formatNumber(n));
|
|
353
|
-
|
|
352
|
+
const f = (n) => (this.digits === "fa" ? fa(formatNumber(n)) : formatNumber(n, { digits: "latin" }));
|
|
353
|
+
const I = msg().invalid;
|
|
354
|
+
return min !== undefined && max !== undefined ? I.priceRange(f(min), f(max)) : min !== undefined ? I.priceMin(f(min)) : I.priceMax(f(max));
|
|
354
355
|
}
|
|
355
356
|
hintText() {
|
|
356
357
|
if (this.raw && bool(this, "show-words", true)) {
|
|
357
|
-
const unit = this.getAttribute("unit") ??
|
|
358
|
-
return `${numberToWords(Number(this.raw))}${unit ? ` ${unit}` : ""}`;
|
|
358
|
+
const unit = this.getAttribute("unit") ?? msg().money.toman;
|
|
359
|
+
return `${numberToWords(Number(this.raw), { locale: lang() })}${unit ? ` ${unit}` : ""}`;
|
|
359
360
|
}
|
|
360
361
|
return this.getAttribute("hint");
|
|
361
362
|
}
|
package/dist/map.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EMPTY_ADDRESS, PROVINCES, formatNumber, getCities } from "@kashi-ui/persian";
|
|
2
|
-
import {
|
|
2
|
+
import { afterParse, bool, define, digitsOf, emit, esc, HTMLBase, msg, uid } from "./base.js";
|
|
3
3
|
import { IRAN_PROVINCES, IRAN_VIEWBOX } from "./iranMapData.js";
|
|
4
4
|
// فرم نشانی از این عنصرها ساخته شده؛ با import همین فایل بهتنهایی هم ثبت شوند
|
|
5
5
|
import "./combobox.js";
|
|
@@ -83,7 +83,7 @@ export class KashiIranMap extends HTMLBase {
|
|
|
83
83
|
return this.multiple || bool(this, "selectable") || this.hasAttribute("value") || this.hasAttribute("name");
|
|
84
84
|
}
|
|
85
85
|
fmt(n) {
|
|
86
|
-
return formatNumber(n);
|
|
86
|
+
return formatNumber(n, { digits: digitsOf(this) });
|
|
87
87
|
}
|
|
88
88
|
level(n) {
|
|
89
89
|
const data = this.values;
|
|
@@ -115,7 +115,7 @@ export class KashiIranMap extends HTMLBase {
|
|
|
115
115
|
return typeof v === "number" ? `${n}: ${this.fmt(v)}${unit ? ` ${unit}` : ""}` : n;
|
|
116
116
|
}
|
|
117
117
|
render() {
|
|
118
|
-
const label = this.getAttribute("label") ??
|
|
118
|
+
const label = this.getAttribute("label") ?? msg().iranMap.label;
|
|
119
119
|
const sel = this.selectable;
|
|
120
120
|
const multi = this.multiple;
|
|
121
121
|
const data = this.values;
|
|
@@ -133,7 +133,7 @@ export class KashiIranMap extends HTMLBase {
|
|
|
133
133
|
? `<table class="k-sr-only"><caption>${esc(label)}</caption><tbody>${NAMES.filter((n) => typeof data[n] === "number").sort((a, b) => data[b] - data[a]).map((n) => `<tr><th scope="row">${esc(n)}</th><td>${this.fmt(data[n])}${unit ? ` ${esc(unit)}` : ""}</td></tr>`).join("")}</tbody></table>`
|
|
134
134
|
: "";
|
|
135
135
|
// نسبت ابعاد با aspect-ratio، نه padding درصدی: در چیدمان flex ستونی ارتفاع padding درصدی صفر حساب میشود
|
|
136
|
-
this.innerHTML = `<figure class="k-iran-map${sel ? " k-iran-map--selectable" : ""}"><div class="k-iran-map__canvas" style="block-size: auto; aspect-ratio: ${VW} / ${VH}"><svg viewBox="${IRAN_VIEWBOX}" class="k-iran-map__svg" role="${sel ? (multi ? "group" : "radiogroup") : "img"}" aria-label="${esc(sel ? label : `${label}${data ?
|
|
136
|
+
this.innerHTML = `<figure class="k-iran-map${sel ? " k-iran-map--selectable" : ""}"><div class="k-iran-map__canvas" style="block-size: auto; aspect-ratio: ${VW} / ${VH}"><svg viewBox="${IRAN_VIEWBOX}" class="k-iran-map__svg" role="${sel ? (multi ? "group" : "radiogroup") : "img"}" aria-label="${esc(sel ? label : `${label}${data ? msg().iranMap.tableNote : ""}`)}">${paths}</svg><div class="k-chart__tip" aria-hidden="true" style="display: none"></div></div>${legend}${table}</figure>`;
|
|
137
137
|
const svg = this.querySelector("svg");
|
|
138
138
|
const fig = this.querySelector("figure");
|
|
139
139
|
svg.addEventListener("pointerover", (e) => {
|
|
@@ -235,7 +235,7 @@ export class KashiIranMap extends HTMLBase {
|
|
|
235
235
|
const w = this.querySelector("figure").clientWidth || VW;
|
|
236
236
|
const v = this.values?.[n];
|
|
237
237
|
const unit = this.getAttribute("unit");
|
|
238
|
-
const row = typeof v === "number" ? `${this.fmt(v)}${unit ? ` ${unit}` : ""}` :
|
|
238
|
+
const row = typeof v === "number" ? `${this.fmt(v)}${unit ? ` ${unit}` : ""}` : msg().province.capital(CAPITAL[n]);
|
|
239
239
|
box.innerHTML = `<span class="k-chart__tip-title">${esc(n)}</span><span class="k-chart__tip-row"><strong>${esc(row)}</strong></span>`;
|
|
240
240
|
// داخل ظرف بماند و راهنمای استانهای شمالی بالای نقشه بیرون نزند
|
|
241
241
|
box.style.left = `${Math.min(Math.max((p.x / VW) * w, 80), w - 80)}px`;
|
|
@@ -244,7 +244,10 @@ export class KashiIranMap extends HTMLBase {
|
|
|
244
244
|
}
|
|
245
245
|
}
|
|
246
246
|
KashiIranMap.observedAttributes = ["data", "value", "label", "unit", "steps", "scale", "legend", "selectable", "multiple", "name"];
|
|
247
|
-
const LABELS =
|
|
247
|
+
const LABELS = () => {
|
|
248
|
+
const A = msg().address;
|
|
249
|
+
return { province: A.province, city: A.city, street: A.street, plaque: A.plaque, unit: A.unit, postalCode: A.postalCode };
|
|
250
|
+
};
|
|
248
251
|
/**
|
|
249
252
|
* فرم نشانی ایرانی: استان، شهرِ همان استان، نشانی، پلاک، واحد و کد پستی دهرقمی؛ با map نقشهٔ ایران برای انتخاب استان.
|
|
250
253
|
* با انتخاب شهر بدون استان، استان خودکار پر میشود و با عوض شدن استان، شهرِ نامربوط پاک میشود.
|
|
@@ -291,7 +294,7 @@ export class KashiAddressForm extends HTMLBase {
|
|
|
291
294
|
}
|
|
292
295
|
/** خطای هر فیلد، مثلاً از اعتبارسنجی سرور: { plaque: "پلاک را بنویسید." } */
|
|
293
296
|
set errors(e) {
|
|
294
|
-
for (const f of Object.keys(LABELS)) {
|
|
297
|
+
for (const f of Object.keys(LABELS())) {
|
|
295
298
|
const el = this.querySelector(`[data-field="${f}"]`);
|
|
296
299
|
if (!el)
|
|
297
300
|
continue;
|
|
@@ -306,7 +309,7 @@ export class KashiAddressForm extends HTMLBase {
|
|
|
306
309
|
}
|
|
307
310
|
}
|
|
308
311
|
label(f) {
|
|
309
|
-
return this.getAttribute(`label-${f === "postalCode" ? "postal-code" : f}`) ?? LABELS[f];
|
|
312
|
+
return this.getAttribute(`label-${f === "postalCode" ? "postal-code" : f}`) ?? LABELS()[f];
|
|
310
313
|
}
|
|
311
314
|
render() {
|
|
312
315
|
const a = this.address;
|
|
@@ -317,18 +320,18 @@ export class KashiAddressForm extends HTMLBase {
|
|
|
317
320
|
const map = bool(this, "map");
|
|
318
321
|
const k = this.key;
|
|
319
322
|
const reqMark = req ? '<span class="k-label__required" aria-hidden="true">*</span>' : "";
|
|
320
|
-
const legend = this.getAttribute("legend") ??
|
|
323
|
+
const legend = this.getAttribute("legend") ?? msg().address.legend;
|
|
321
324
|
this.innerHTML = `<fieldset class="k-address${map ? " k-address--map" : ""}"${this.hasAttribute("disabled") ? " disabled" : ""}>
|
|
322
325
|
${legend ? `<legend class="k-address__legend">${esc(legend)}</legend>` : ""}
|
|
323
326
|
<div class="k-address__fields">
|
|
324
|
-
<kashi-province-select class="k-address__province" data-field="province" label="${esc(this.label("province"))}" show-capital="false" placeholder="
|
|
327
|
+
<kashi-province-select class="k-address__province" data-field="province" label="${esc(this.label("province"))}" show-capital="false" placeholder="${esc(msg().address.provinceSearch)}"${n("province")}${r}></kashi-province-select>
|
|
325
328
|
<kashi-city-select class="k-address__city" data-field="city" label="${esc(this.label("city"))}"${n("city")}${r}></kashi-city-select>
|
|
326
|
-
<div class="k-field k-address__street" data-field="street"><div class="k-field__label-row"><label class="k-label" for="${k}-street">${esc(this.label("street"))}${reqMark}</label></div><div class="k-input k-input--textarea k-input--autoresize"><textarea id="${k}-street" class="k-input__control" rows="2" autocomplete="street-address" placeholder="
|
|
329
|
+
<div class="k-field k-address__street" data-field="street"><div class="k-field__label-row"><label class="k-label" for="${k}-street">${esc(this.label("street"))}${reqMark}</label></div><div class="k-input k-input--textarea k-input--autoresize"><textarea id="${k}-street" class="k-input__control" rows="2" autocomplete="street-address" placeholder="${esc(msg().address.streetHint)}"${n("street")}${r}></textarea></div></div>
|
|
327
330
|
<div class="k-field k-address__plaque" data-field="plaque"><div class="k-field__label-row"><label class="k-label" for="${k}-plaque">${esc(this.label("plaque"))}${reqMark}</label></div><div class="k-input"><input id="${k}-plaque" class="k-input__control" inputmode="numeric" autocomplete="address-line2"${n("plaque")}${r}></div></div>
|
|
328
|
-
<div class="k-field k-address__unit" data-field="unit"><div class="k-field__label-row"><label class="k-label" for="${k}-unit">${esc(this.label("unit"))}${req ?
|
|
331
|
+
<div class="k-field k-address__unit" data-field="unit"><div class="k-field__label-row"><label class="k-label" for="${k}-unit">${esc(this.label("unit"))}${req ? `<span class="k-label__optional">${esc(msg().common.optional)}</span>` : ""}</label></div><div class="k-input"><input id="${k}-unit" class="k-input__control" inputmode="numeric" autocomplete="address-line3"${n("unit")}></div></div>
|
|
329
332
|
<kashi-postal-code class="k-address__postal" data-field="postalCode" label="${esc(this.label("postalCode"))}"${n("postalCode")}${r}></kashi-postal-code>
|
|
330
333
|
</div>
|
|
331
|
-
${map ? `<kashi-iran-map class="k-address__map" selectable label="${esc(
|
|
334
|
+
${map ? `<kashi-iran-map class="k-address__map" selectable label="${esc(msg().iranMap.onMap(this.label("province")))}"></kashi-iran-map>` : ""}
|
|
332
335
|
</fieldset>`;
|
|
333
336
|
this.built = true;
|
|
334
337
|
const province = this.querySelector("kashi-province-select");
|
package/dist/nav.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { normalizePersian
|
|
2
|
-
import {
|
|
1
|
+
import { normalizePersian } from "@kashi-ui/persian";
|
|
2
|
+
import { afterParse, bool, define, emit, esc, HTMLBase, msg, num, uid } from "./base.js";
|
|
3
3
|
const search = (s) => normalizePersian(s, { digits: "latin" }).toLowerCase();
|
|
4
4
|
const items = (menu) => [...menu.querySelectorAll('[role^="menuitem"]:not([aria-disabled="true"])')];
|
|
5
5
|
const SEARCH = '<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" aria-hidden="true"><circle cx="9" cy="9" r="5.5"/><path d="m13.5 13.5 3 3"/></svg>';
|
|
@@ -68,9 +68,10 @@ export class KashiCommandPalette extends HTMLBase {
|
|
|
68
68
|
build() {
|
|
69
69
|
const d = document.createElement("dialog");
|
|
70
70
|
d.className = "k-dialog k-command";
|
|
71
|
-
const
|
|
71
|
+
const M = msg();
|
|
72
|
+
const title = this.getAttribute("label") ?? M.command.title;
|
|
72
73
|
d.setAttribute("aria-label", title);
|
|
73
|
-
d.innerHTML = `<div class="k-input"><span class="k-input__addon">${SEARCH}</span><input class="k-input__control" type="text" role="combobox" aria-expanded="true" aria-controls="${this.key}-list" aria-autocomplete="list" aria-label="${esc(title)}" placeholder="${esc(this.getAttribute("placeholder") ??
|
|
74
|
+
d.innerHTML = `<div class="k-input"><span class="k-input__addon">${SEARCH}</span><input class="k-input__control" type="text" role="combobox" aria-expanded="true" aria-controls="${this.key}-list" aria-autocomplete="list" aria-label="${esc(title)}" placeholder="${esc(this.getAttribute("placeholder") ?? M.command.placeholder)}" autocomplete="off"></div><ul id="${this.key}-list" role="listbox" aria-label="${esc(title)}" class="k-listbox k-listbox--inline k-command__list"></ul><div class="k-command__footer" aria-hidden="true"><span><kbd class="k-kbd">↑</kbd><kbd class="k-kbd">↓</kbd>${esc(M.command.navigate)}</span><span><kbd class="k-kbd">Enter</kbd>${esc(M.command.select)}</span><span><kbd class="k-kbd">Esc</kbd>${esc(M.common.close)}</span></div><span class="k-sr-only" aria-live="polite"></span>`;
|
|
74
75
|
this.append(d);
|
|
75
76
|
this.dialog = d;
|
|
76
77
|
const input = d.querySelector("input");
|
|
@@ -152,14 +153,14 @@ export class KashiCommandPalette extends HTMLBase {
|
|
|
152
153
|
last = it.group;
|
|
153
154
|
return `${header}<li id="${this.key}-list-${i}" data-i="${i}" role="option" aria-selected="${i === this.active}"${i === this.active ? " data-active" : ""} class="k-option"><span class="k-option__body"><span>${mark(it.label)}</span>${it.description ? `<span class="k-option__desc">${esc(it.description)}</span>` : ""}</span>${it.shortcut ? `<span class="k-menu__shortcut" aria-hidden="true">${esc(it.shortcut)}</span>` : ""}</li>`;
|
|
154
155
|
}).join("")
|
|
155
|
-
:
|
|
156
|
+
: `<li role="presentation" class="k-listbox__empty">${esc(msg().command.empty)}</li>`;
|
|
156
157
|
const input = d.querySelector("input");
|
|
157
158
|
if (list.length)
|
|
158
159
|
input.setAttribute("aria-activedescendant", `${this.key}-list-${this.active}`);
|
|
159
160
|
else
|
|
160
161
|
input.removeAttribute("aria-activedescendant");
|
|
161
162
|
d.querySelector(`#${this.key}-list-${this.active}`)?.scrollIntoView?.({ block: "nearest" });
|
|
162
|
-
d.querySelector(":scope > .k-sr-only").textContent = this.query ?
|
|
163
|
+
d.querySelector(":scope > .k-sr-only").textContent = this.query ? msg().common.results(num(this, list.length)) : "";
|
|
163
164
|
}
|
|
164
165
|
}
|
|
165
166
|
KashiCommandPalette.observedAttributes = ["placeholder", "label", "shortcut"];
|
|
@@ -192,7 +193,7 @@ export class KashiContextMenu extends HTMLBase {
|
|
|
192
193
|
this.setAttribute("aria-describedby", `${this.key}-hint`);
|
|
193
194
|
const menu = document.createElement("ul");
|
|
194
195
|
menu.setAttribute("role", "menu");
|
|
195
|
-
menu.setAttribute("aria-label", this.getAttribute("label") ??
|
|
196
|
+
menu.setAttribute("aria-label", this.getAttribute("label") ?? msg().contextMenu.label);
|
|
196
197
|
menu.className = "k-menu k-menu--context";
|
|
197
198
|
menu.hidden = true;
|
|
198
199
|
for (const el of [...(source?.children ?? [])]) {
|
|
@@ -221,7 +222,7 @@ export class KashiContextMenu extends HTMLBase {
|
|
|
221
222
|
menu.append(li);
|
|
222
223
|
}
|
|
223
224
|
source?.remove();
|
|
224
|
-
this.insertAdjacentHTML("beforeend", `<span id="${this.key}-hint" class="k-sr-only"
|
|
225
|
+
this.insertAdjacentHTML("beforeend", `<span id="${this.key}-hint" class="k-sr-only">${esc(msg().contextMenu.hint)}</span>`);
|
|
225
226
|
this.append(menu);
|
|
226
227
|
this.menu = menu;
|
|
227
228
|
this.addEventListener("contextmenu", (e) => {
|
|
@@ -333,11 +334,12 @@ export class KashiCarousel extends HTMLBase {
|
|
|
333
334
|
return Math.max(1, this.slides.length - this.perView + 1);
|
|
334
335
|
}
|
|
335
336
|
build() {
|
|
336
|
-
const
|
|
337
|
+
const M = msg();
|
|
338
|
+
const label = this.getAttribute("label") ?? M.carousel.slider;
|
|
337
339
|
const children = [...this.children];
|
|
338
340
|
const section = document.createElement("section");
|
|
339
341
|
section.className = "k-carousel";
|
|
340
|
-
section.setAttribute("aria-roledescription",
|
|
342
|
+
section.setAttribute("aria-roledescription", M.carousel.slider);
|
|
341
343
|
section.setAttribute("aria-label", label);
|
|
342
344
|
section.style.setProperty("--k-carousel-per-view", String(this.perView));
|
|
343
345
|
const track = document.createElement("div");
|
|
@@ -348,8 +350,8 @@ export class KashiCarousel extends HTMLBase {
|
|
|
348
350
|
const s = document.createElement("div");
|
|
349
351
|
s.className = "k-carousel__slide";
|
|
350
352
|
s.setAttribute("role", "group");
|
|
351
|
-
s.setAttribute("aria-roledescription",
|
|
352
|
-
s.setAttribute("aria-label",
|
|
353
|
+
s.setAttribute("aria-roledescription", M.carousel.slide);
|
|
354
|
+
s.setAttribute("aria-label", M.carousel.slideOf(num(this, i + 1), num(this, children.length)));
|
|
353
355
|
s.id = `${this.key}-s${i}`;
|
|
354
356
|
s.append(c);
|
|
355
357
|
track.append(s);
|
|
@@ -359,7 +361,7 @@ export class KashiCarousel extends HTMLBase {
|
|
|
359
361
|
this.track = track;
|
|
360
362
|
if (this.pages > 1) {
|
|
361
363
|
const dots = this.getAttribute("dots") !== "false";
|
|
362
|
-
section.insertAdjacentHTML("beforeend", `<div class="k-carousel__bar">${dots ? `<ul class="k-carousel__dots" aria-label="
|
|
364
|
+
section.insertAdjacentHTML("beforeend", `<div class="k-carousel__bar">${dots ? `<ul class="k-carousel__dots" aria-label="${esc(M.carousel.slides(label))}">${Array.from({ length: this.pages }, (_, i) => `<li><button type="button" class="k-carousel__dot" data-go="${i}" aria-label="${esc(M.carousel.slideOf(num(this, i + 1), num(this, this.pages)))}" aria-controls="${this.key}-s${i}"></button></li>`).join("")}</ul>` : "<span></span>"}<div class="k-carousel__nav"><button type="button" class="k-btn k-btn--secondary k-btn--icon k-btn--sm" data-step="-1" aria-label="${esc(M.common.prev)}">${ARROW(false)}</button><button type="button" class="k-btn k-btn--secondary k-btn--icon k-btn--sm" data-step="1" aria-label="${esc(M.common.next)}">${ARROW(true)}</button></div></div>`);
|
|
363
365
|
section.querySelector(".k-carousel__bar").addEventListener("click", (e) => {
|
|
364
366
|
const b = e.target.closest("button");
|
|
365
367
|
if (!b)
|
|
@@ -701,7 +703,7 @@ export class KashiTour extends HTMLBase {
|
|
|
701
703
|
});
|
|
702
704
|
document.body.append(this.card);
|
|
703
705
|
}
|
|
704
|
-
this.card.innerHTML = `<span class="k-tour__step"
|
|
706
|
+
this.card.innerHTML = `<span class="k-tour__step">${esc(msg().tour.step(num(this, this.i + 1), num(this, n)))}</span><p class="k-tour__title" id="${this.key}-t">${esc(s.title)}</p><p class="k-tour__body" id="${this.key}-b">${esc(s.content)}</p><div class="k-tour__actions"><button type="button" class="k-btn k-btn--link k-tour__skip" data-act="skip">${esc(msg().tour.skip)}</button><span class="k-tour__progress" aria-hidden="true">${this.steps.map((_, k) => `<span${k <= this.i ? ' data-on=""' : ""}></span>`).join("")}</span>${this.i > 0 ? '<button type="button" class="k-btn k-btn--secondary k-btn--sm" data-act="prev">${esc(msg().common.prev)}</button>' : ""}<button type="button" class="k-btn k-btn--primary k-btn--sm" data-act="${last ? "done" : "next"}">${esc(last ? msg().tour.done : msg().common.next)}</button></div>`;
|
|
705
707
|
const el = document.querySelector(s.target);
|
|
706
708
|
const reduce = typeof matchMedia === "function" && matchMedia("(prefers-reduced-motion: reduce)").matches;
|
|
707
709
|
el?.scrollIntoView?.({ block: "center", behavior: reduce ? "auto" : "smooth" });
|
|
@@ -819,7 +821,7 @@ export class KashiSplitter extends HTMLBase {
|
|
|
819
821
|
handle.setAttribute("aria-orientation", this.vertical ? "horizontal" : "vertical");
|
|
820
822
|
handle.setAttribute("aria-valuemin", String(this.num("min", 15)));
|
|
821
823
|
handle.setAttribute("aria-valuemax", String(this.num("max", 85)));
|
|
822
|
-
handle.setAttribute("aria-label", this.getAttribute("label") ??
|
|
824
|
+
handle.setAttribute("aria-label", this.getAttribute("label") ?? msg().splitter.label);
|
|
823
825
|
this.paint();
|
|
824
826
|
}
|
|
825
827
|
set(p, fire = true) {
|
|
@@ -838,7 +840,7 @@ export class KashiSplitter extends HTMLBase {
|
|
|
838
840
|
pane.style.blockSize = this.vertical ? `${this.current}%` : "";
|
|
839
841
|
const handle = box.querySelector(".k-splitter__handle");
|
|
840
842
|
handle.setAttribute("aria-valuenow", String(this.current));
|
|
841
|
-
handle.setAttribute("aria-valuetext",
|
|
843
|
+
handle.setAttribute("aria-valuetext", msg().common.percent(num(this, Math.round(this.current))));
|
|
842
844
|
}
|
|
843
845
|
}
|
|
844
846
|
KashiSplitter.observedAttributes = ["size", "min", "max", "orientation", "label", "height"];
|
package/dist/overlay.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { afterParse, bool, define, emit, esc, HTMLBase, ICONS, msg, uid } from "./base.js";
|
|
2
2
|
/**
|
|
3
3
|
* پنجرهٔ گفتگو روی <dialog> بومی با showModal: فوکوس داخل پنجره میماند، Esc میبندد،
|
|
4
4
|
* بقیهٔ صفحه از دسترس صفحهخوان خارج میشود و پس از بستن، فوکوس به دکمهٔ بازکننده برمیگردد.
|
|
@@ -100,7 +100,7 @@ export class KashiDialog extends HTMLBase {
|
|
|
100
100
|
d.setAttribute("aria-describedby", desc.id);
|
|
101
101
|
else
|
|
102
102
|
d.removeAttribute("aria-describedby");
|
|
103
|
-
d.querySelector(".k-dialog__close").setAttribute("aria-label", this.getAttribute("close-label") ??
|
|
103
|
+
d.querySelector(".k-dialog__close").setAttribute("aria-label", this.getAttribute("close-label") ?? msg().common.close);
|
|
104
104
|
}
|
|
105
105
|
sync() {
|
|
106
106
|
const d = this.dialog;
|
|
@@ -387,9 +387,9 @@ export class KashiCopyButton extends HTMLBase {
|
|
|
387
387
|
}, Number(this.getAttribute("timeout")) || 2000);
|
|
388
388
|
}
|
|
389
389
|
render() {
|
|
390
|
-
const copy = this.getAttribute("label") ??
|
|
391
|
-
const copied = this.getAttribute("copied-label") ??
|
|
392
|
-
const text = this.state === "copied" ? copied : this.state === "failed" ?
|
|
390
|
+
const copy = this.getAttribute("label") ?? msg().copy.copy;
|
|
391
|
+
const copied = this.getAttribute("copied-label") ?? msg().copy.copied;
|
|
392
|
+
const text = this.state === "copied" ? copied : this.state === "failed" ? msg().copy.failed : copy;
|
|
393
393
|
const iconOnly = bool(this, "icon-only");
|
|
394
394
|
const icon = this.state === "copied" ? ICONS.check : ICONS.copy;
|
|
395
395
|
const variant = this.getAttribute("variant") ?? "secondary";
|
package/dist/pickers.d.ts
CHANGED
|
@@ -48,7 +48,7 @@ export declare class KashiMonthPicker extends HTMLBase {
|
|
|
48
48
|
private out;
|
|
49
49
|
private render;
|
|
50
50
|
}
|
|
51
|
-
/** حجم فایل به
|
|
51
|
+
/** حجم فایل به زبان فعلی: «۱٫۲ مگابایت» یا «1.2 MB» */
|
|
52
52
|
export declare function formatBytes(bytes: number): string;
|
|
53
53
|
/**
|
|
54
54
|
* بارگذاری فایل با کشیدن و رها کردن، بررسی نوع و حجم و فهرست فایلها.
|