@kashi-ui/elements 0.26.0 → 1.1.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 +9 -0
- package/dist/appointment.js +13 -12
- package/dist/base.d.ts +408 -0
- package/dist/base.js +29 -0
- package/dist/basic.js +8 -9
- 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-Cga7QOfs.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 +2 -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 +4 -0
- package/dist/index.js +3 -0
- 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/appointment-DkMxtSWi.js +0 -1
- package/dist/cdn/base-DfzNTdQk.js +0 -1
- package/dist/cdn/basic-B5n1okZO.js +0 -1
- package/dist/cdn/calendar-oMlnK1_D.js +0 -16
- package/dist/cdn/charts-SHKq2S4I.js +0 -1
- package/dist/cdn/combobox-DiGy7lAB.js +0 -1
- package/dist/cdn/controls-C6zwNYWs.js +0 -1
- package/dist/cdn/digits-DE1YGT94.js +0 -1
- package/dist/cdn/display-DZFW9EEX.js +0 -1
- package/dist/cdn/fields-D2hmrvVR.js +0 -1
- package/dist/cdn/forms-CeItYHFx.js +0 -1
- package/dist/cdn/holidays-BwsAEOI1.js +0 -1
- package/dist/cdn/inputs-DuP7P3ka.js +0 -1
- package/dist/cdn/jalali-BiM5Kfep.js +0 -1
- package/dist/cdn/map-w5X2fTQI.js +0 -12
- package/dist/cdn/nav-CwPZ20z-.js +0 -1
- package/dist/cdn/overlay-BDzwsBN5.js +0 -1
- package/dist/cdn/pickers-BOpaZ-7q.js +0 -1
- package/dist/cdn/table-BdF43L5q.js +0 -1
- package/dist/cdn/text-D1U32D6K.js +0 -1
- package/dist/cdn/time-DXw4vOne.js +0 -1
- package/dist/cdn/words-9OdzG7y6.js +0 -1
package/README.md
CHANGED
|
@@ -26,6 +26,15 @@ import "@kashi-ui/css";
|
|
|
26
26
|
import "@kashi-ui/elements";
|
|
27
27
|
```
|
|
28
28
|
|
|
29
|
+
## زبان انگلیسی
|
|
30
|
+
|
|
31
|
+
```ts
|
|
32
|
+
import { setLocale } from "@kashi-ui/elements";
|
|
33
|
+
setLocale("en"); // پیش از ساخته شدن عنصرها
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
راهنما: https://kashi.sepantapouya.com/docs/i18n/
|
|
37
|
+
|
|
29
38
|
## عنصرها
|
|
30
39
|
|
|
31
40
|
- **فیلدهای فارسی:** `kashi-national-id`، `kashi-legal-id`، `kashi-mobile`، `kashi-landline`، `kashi-card-number`، `kashi-iban`، `kashi-postal-code`، `kashi-price`
|
package/dist/appointment.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
const PERIODS = [["
|
|
1
|
+
import { formatJalali, formatTime, fromISODate, getIranHoliday, parseTime, toFaDigits, toISODate, toJalali } from "@kashi-ui/persian";
|
|
2
|
+
import { calendarNames, define, digitsOf, emit, esc, HTMLBase, lang, msg, uid } from "./base.js";
|
|
3
|
+
const PERIODS = [["morning", 12], ["afternoon", 17], ["evening", 24]];
|
|
4
4
|
const day = (d, add = 0) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + add);
|
|
5
5
|
const same = (a, b) => a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
|
|
6
6
|
const minutes = (t) => {
|
|
@@ -70,7 +70,7 @@ export class KashiAppointmentPicker extends HTMLBase {
|
|
|
70
70
|
const closedAttr = this.getAttribute("closed") !== "false";
|
|
71
71
|
return Array.from({ length: count }, (_, i) => {
|
|
72
72
|
const d = day(start, i);
|
|
73
|
-
const closed = this.isClosed ? this.isClosed(d) : closedAttr && !!getIranHoliday(d);
|
|
73
|
+
const closed = this.isClosed ? this.isClosed(d) : closedAttr && !!getIranHoliday(d, { locale: lang() });
|
|
74
74
|
let slots = [];
|
|
75
75
|
if (!closed) {
|
|
76
76
|
if (this.getSlots)
|
|
@@ -92,7 +92,7 @@ export class KashiAppointmentPicker extends HTMLBase {
|
|
|
92
92
|
}
|
|
93
93
|
render(focus = null) {
|
|
94
94
|
const now = new Date();
|
|
95
|
-
const fa = this
|
|
95
|
+
const fa = digitsOf(this) === "fa";
|
|
96
96
|
const n = (v) => (fa ? toFaDigits(String(v)) : String(v));
|
|
97
97
|
const digits = fa ? "fa" : "latin";
|
|
98
98
|
const list = this.list();
|
|
@@ -101,27 +101,28 @@ export class KashiAppointmentPicker extends HTMLBase {
|
|
|
101
101
|
this.active = i >= 0 ? i : Math.max(0, list.findIndex((x) => x.free > 0));
|
|
102
102
|
}
|
|
103
103
|
const cur = list[this.active];
|
|
104
|
-
const
|
|
105
|
-
const
|
|
104
|
+
const M = msg(), A = M.appointment, { months, weekdays } = calendarNames(), locale = lang();
|
|
105
|
+
const label = this.getAttribute("label") ?? A.label;
|
|
106
|
+
const wd = (d) => (same(d, now) ? M.common.today : same(d, day(now, 1)) ? M.common.tomorrow : weekdays[(d.getDay() + 1) % 7]);
|
|
106
107
|
const daysHtml = list.map((x, i) => {
|
|
107
108
|
const { jm, jd } = toJalali(x.date);
|
|
108
|
-
const status = x.closed ?
|
|
109
|
-
return `<button type="button" role="radio" data-i="${i}" class="k-appt__day" aria-checked="${i === this.active}" tabindex="${i === this.active ? 0 : -1}"${x.closed ? " disabled" : ""} aria-label="${esc(`${formatJalali(x.date, { style: "full", digits })}
|
|
109
|
+
const status = x.closed ? A.closed : x.free ? A.freeLong(n(x.free)) : A.none;
|
|
110
|
+
return `<button type="button" role="radio" data-i="${i}" class="k-appt__day" aria-checked="${i === this.active}" tabindex="${i === this.active ? 0 : -1}"${x.closed ? " disabled" : ""} aria-label="${esc(`${formatJalali(x.date, { style: "full", digits, locale })}${M.common.list}${status}`)}"><span class="k-appt__weekday" aria-hidden="true">${wd(x.date)}</span><span class="k-appt__date" aria-hidden="true">${n(jd)}</span><span class="k-appt__month" aria-hidden="true">${months[jm - 1]}</span><span class="k-appt__free" aria-hidden="true">${x.closed ? A.closed : x.free ? A.free(n(x.free)) : A.full}</span></button>`;
|
|
110
111
|
}).join("");
|
|
111
112
|
const selDay = !!this.selected && same(this.selected.date, cur.date);
|
|
112
113
|
const focusTime = selDay ? this.selected.time : cur.slots.find((s) => s.available)?.time;
|
|
113
114
|
const slotsHtml = cur.closed || !cur.free
|
|
114
|
-
? `<p class="k-appt__empty">${cur.closed ?
|
|
115
|
+
? `<p class="k-appt__empty">${cur.closed ? A.closedDay : A.noSlots}</p>`
|
|
115
116
|
: PERIODS.map(([title, until], k) => {
|
|
116
117
|
const slots = cur.slots.filter((s) => minutes(s.time) / 60 < until && minutes(s.time) / 60 >= (k ? PERIODS[k - 1][1] : 0));
|
|
117
118
|
if (!slots.length)
|
|
118
119
|
return "";
|
|
119
120
|
const gid = `${this.key}-p${k}`;
|
|
120
|
-
return `<div class="k-appt__group"><p class="k-appt__period" id="${gid}">${title}</p><div class="k-appt__times" role="radiogroup" aria-labelledby="${gid}">${slots.map((s) => `<button type="button" role="radio" class="k-appt__time" data-time="${s.time}" aria-checked="${selDay && this.selected.time === s.time}" tabindex="${s.time === focusTime ? 0 : -1}"${s.available ? "" : " disabled"} aria-label="
|
|
121
|
+
return `<div class="k-appt__group"><p class="k-appt__period" id="${gid}">${A[title]}</p><div class="k-appt__times" role="radiogroup" aria-labelledby="${gid}">${slots.map((s) => `<button type="button" role="radio" class="k-appt__time" data-time="${s.time}" aria-checked="${selDay && this.selected.time === s.time}" tabindex="${s.time === focusTime ? 0 : -1}"${s.available ? "" : " disabled"} aria-label="${esc(A.time(n(s.time)))}${s.available ? "" : esc(A.booked)}">${n(s.time)}</button>`).join("")}</div></div>`;
|
|
121
122
|
}).join("");
|
|
122
123
|
const name = this.getAttribute("name");
|
|
123
124
|
const sel = this.selected;
|
|
124
|
-
this.innerHTML = `<div class="k-appt" role="group" aria-labelledby="${this.key}-label"><p class="k-label" id="${this.key}-label" style="margin: 0">${esc(label)}</p><div class="k-appt__days" role="radiogroup" aria-label="
|
|
125
|
+
this.innerHTML = `<div class="k-appt" role="group" aria-labelledby="${this.key}-label"><p class="k-label" id="${this.key}-label" style="margin: 0">${esc(label)}</p><div class="k-appt__days" role="radiogroup" aria-label="${esc(A.day)}">${daysHtml}</div><div class="k-appt__slots">${slotsHtml}</div><p class="k-appt__summary" aria-live="polite">${sel ? `${CLOCK}<span>${esc(A.yours)} <strong>${esc(A.at(formatJalali(sel.date, { style: "full", digits, locale }), n(sel.time)))}</strong></span>` : ""}</p>${name ? `<input type="hidden" name="${esc(`${name}_date`)}" value="${sel ? toISODate(sel.date) : ""}"><input type="hidden" name="${esc(`${name}_time`)}" value="${sel?.time ?? ""}">` : ""}</div>`;
|
|
125
126
|
this.rendered = true;
|
|
126
127
|
const days = this.querySelector(".k-appt__days");
|
|
127
128
|
const times = this.querySelector(".k-appt__slots");
|
package/dist/base.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type KashiLocale, type KashiMessagesInput } from "@kashi-ui/persian";
|
|
1
2
|
/** در Node.js (رندر سمت سرور) HTMLElement وجود ندارد؛ import کردن پکیج نباید خطا بدهد */
|
|
2
3
|
export declare const HTMLBase: typeof HTMLElement;
|
|
3
4
|
/** ثبت عنصر، فقط در مرورگر و فقط یک بار (اگر پکیج دو بار بارگذاری شود خطا نمیدهد) */
|
|
@@ -7,6 +8,412 @@ export declare function define(tag: string, ctor: CustomElementConstructor, disp
|
|
|
7
8
|
* اگر اسکریپت بدون type="module" در <head> باشد، عنصر پیش از فرزندانش به صفحه وصل میشود.
|
|
8
9
|
*/
|
|
9
10
|
export declare function afterParse(cb: () => void): void;
|
|
11
|
+
type Digits = "fa" | "latin";
|
|
12
|
+
/**
|
|
13
|
+
* زبان متنهای داخلی همهٔ عنصرها: setLocale("en") برچسب دکمهها، متن صفحهخوان، پیامهای خطا، نام ماهها و ارقام را انگلیسی میکند.
|
|
14
|
+
* پیش از ساخته شدن عنصرها صدا بزنید (بالای صفحه، بعد از import). با messages هر متنی را عوض کنید.
|
|
15
|
+
*/
|
|
16
|
+
export declare function setLocale(locale: KashiLocale, { messages, digits }?: {
|
|
17
|
+
messages?: KashiMessagesInput;
|
|
18
|
+
digits?: Digits;
|
|
19
|
+
}): void;
|
|
20
|
+
/** ارقام پیشفرض زبان فعلی */
|
|
21
|
+
export declare const localeDigits: () => Digits;
|
|
22
|
+
/** فرهنگ متنهای فعلی */
|
|
23
|
+
export declare const msg: () => {
|
|
24
|
+
common: {
|
|
25
|
+
close: string;
|
|
26
|
+
loading: string;
|
|
27
|
+
optional: string;
|
|
28
|
+
remove: (item: string) => string;
|
|
29
|
+
removeShort: string;
|
|
30
|
+
clear: string;
|
|
31
|
+
clearAll: string;
|
|
32
|
+
cancel: string;
|
|
33
|
+
confirm: string;
|
|
34
|
+
save: string;
|
|
35
|
+
edit: string;
|
|
36
|
+
prev: string;
|
|
37
|
+
next: string;
|
|
38
|
+
today: string;
|
|
39
|
+
tomorrow: string;
|
|
40
|
+
noResults: string;
|
|
41
|
+
searching: string;
|
|
42
|
+
results: (n: string) => string;
|
|
43
|
+
added: (item: string) => string;
|
|
44
|
+
removed: (item: string) => string;
|
|
45
|
+
selected: (item: string) => string;
|
|
46
|
+
max: (n: string) => string;
|
|
47
|
+
total: string;
|
|
48
|
+
other: string;
|
|
49
|
+
of: (a: string, b: string) => string;
|
|
50
|
+
and: string;
|
|
51
|
+
list: string;
|
|
52
|
+
range: string;
|
|
53
|
+
percent: (n: string) => string;
|
|
54
|
+
decimal: string;
|
|
55
|
+
};
|
|
56
|
+
money: {
|
|
57
|
+
toman: string;
|
|
58
|
+
rial: string;
|
|
59
|
+
positive: string;
|
|
60
|
+
};
|
|
61
|
+
alert: {
|
|
62
|
+
close: string;
|
|
63
|
+
};
|
|
64
|
+
banner: {
|
|
65
|
+
label: string;
|
|
66
|
+
close: string;
|
|
67
|
+
};
|
|
68
|
+
avatar: {
|
|
69
|
+
online: string;
|
|
70
|
+
offline: string;
|
|
71
|
+
busy: string;
|
|
72
|
+
away: string;
|
|
73
|
+
more: (n: string) => string;
|
|
74
|
+
};
|
|
75
|
+
bankCard: {
|
|
76
|
+
card: string;
|
|
77
|
+
cardOf: (bank: string) => string;
|
|
78
|
+
bank: string;
|
|
79
|
+
endingIn: (last4: string) => string;
|
|
80
|
+
expiry: string;
|
|
81
|
+
};
|
|
82
|
+
breadcrumb: {
|
|
83
|
+
label: string;
|
|
84
|
+
expand: string;
|
|
85
|
+
};
|
|
86
|
+
calendar: {
|
|
87
|
+
label: string;
|
|
88
|
+
prevMonth: string;
|
|
89
|
+
nextMonth: string;
|
|
90
|
+
month: string;
|
|
91
|
+
year: string;
|
|
92
|
+
holiday: string;
|
|
93
|
+
};
|
|
94
|
+
carousel: {
|
|
95
|
+
slider: string;
|
|
96
|
+
slide: string;
|
|
97
|
+
slideOf: (n: string, total: string) => string;
|
|
98
|
+
slides: (label: string) => string;
|
|
99
|
+
};
|
|
100
|
+
chart: {
|
|
101
|
+
period: string;
|
|
102
|
+
value: string;
|
|
103
|
+
share: string;
|
|
104
|
+
count: string;
|
|
105
|
+
keyboard: (title: string) => string;
|
|
106
|
+
thousand: string;
|
|
107
|
+
million: string;
|
|
108
|
+
billion: string;
|
|
109
|
+
};
|
|
110
|
+
city: {
|
|
111
|
+
label: string;
|
|
112
|
+
outside: string;
|
|
113
|
+
custom: string;
|
|
114
|
+
search: string;
|
|
115
|
+
hint: string;
|
|
116
|
+
};
|
|
117
|
+
province: {
|
|
118
|
+
label: string;
|
|
119
|
+
search: string;
|
|
120
|
+
capital: (c: string) => string;
|
|
121
|
+
};
|
|
122
|
+
colorPicker: {
|
|
123
|
+
label: string;
|
|
124
|
+
custom: string;
|
|
125
|
+
area: string;
|
|
126
|
+
areaValue: (s: string, v: string) => string;
|
|
127
|
+
eyedropper: string;
|
|
128
|
+
hue: string;
|
|
129
|
+
degrees: (n: string) => string;
|
|
130
|
+
red: string;
|
|
131
|
+
green: string;
|
|
132
|
+
blue: string;
|
|
133
|
+
invalid: string;
|
|
134
|
+
swatches: string;
|
|
135
|
+
sample: string;
|
|
136
|
+
contrast: (ink: "white" | "black", ratio: string, pass: boolean) => string;
|
|
137
|
+
names: {
|
|
138
|
+
firoozeh: string;
|
|
139
|
+
lajvard: string;
|
|
140
|
+
violet: string;
|
|
141
|
+
anar: string;
|
|
142
|
+
zafaran: string;
|
|
143
|
+
peste: string;
|
|
144
|
+
shab: string;
|
|
145
|
+
};
|
|
146
|
+
};
|
|
147
|
+
combobox: {
|
|
148
|
+
toggle: string;
|
|
149
|
+
more: (n: string) => string;
|
|
150
|
+
};
|
|
151
|
+
otp: {
|
|
152
|
+
label: string;
|
|
153
|
+
};
|
|
154
|
+
command: {
|
|
155
|
+
placeholder: string;
|
|
156
|
+
empty: string;
|
|
157
|
+
title: string;
|
|
158
|
+
navigate: string;
|
|
159
|
+
select: string;
|
|
160
|
+
};
|
|
161
|
+
contextMenu: {
|
|
162
|
+
label: string;
|
|
163
|
+
hint: string;
|
|
164
|
+
};
|
|
165
|
+
copy: {
|
|
166
|
+
copy: string;
|
|
167
|
+
copied: string;
|
|
168
|
+
failed: string;
|
|
169
|
+
};
|
|
170
|
+
countdown: {
|
|
171
|
+
days: string;
|
|
172
|
+
hours: string;
|
|
173
|
+
minutes: string;
|
|
174
|
+
seconds: string;
|
|
175
|
+
left: string;
|
|
176
|
+
};
|
|
177
|
+
table: {
|
|
178
|
+
selectAll: string;
|
|
179
|
+
selectRow: string;
|
|
180
|
+
selectNamed: (row: string) => string;
|
|
181
|
+
empty: string;
|
|
182
|
+
sort: (col: string) => string;
|
|
183
|
+
search: string;
|
|
184
|
+
rows: (n: string) => string;
|
|
185
|
+
};
|
|
186
|
+
datePicker: {
|
|
187
|
+
label: string;
|
|
188
|
+
invalid: string;
|
|
189
|
+
open: string;
|
|
190
|
+
};
|
|
191
|
+
dateRange: {
|
|
192
|
+
label: string;
|
|
193
|
+
placeholder: string;
|
|
194
|
+
presets: string;
|
|
195
|
+
pickEnd: string;
|
|
196
|
+
last7: (n: string) => string;
|
|
197
|
+
last30: (n: string) => string;
|
|
198
|
+
thisMonth: string;
|
|
199
|
+
lastMonth: string;
|
|
200
|
+
};
|
|
201
|
+
monthPicker: {
|
|
202
|
+
label: string;
|
|
203
|
+
prevYear: string;
|
|
204
|
+
nextYear: string;
|
|
205
|
+
};
|
|
206
|
+
fileUpload: {
|
|
207
|
+
units: string[];
|
|
208
|
+
browse: string;
|
|
209
|
+
drop: string;
|
|
210
|
+
tooBig: (max: string) => string;
|
|
211
|
+
wrongType: string;
|
|
212
|
+
tooMany: (n: string) => string;
|
|
213
|
+
done: string;
|
|
214
|
+
uploading: string;
|
|
215
|
+
uploadingFile: (name: string) => string;
|
|
216
|
+
error: string;
|
|
217
|
+
};
|
|
218
|
+
input: {
|
|
219
|
+
clear: string;
|
|
220
|
+
show: string;
|
|
221
|
+
hide: string;
|
|
222
|
+
checking: string;
|
|
223
|
+
};
|
|
224
|
+
invalid: {
|
|
225
|
+
card: string;
|
|
226
|
+
iban: string;
|
|
227
|
+
nationalId: string;
|
|
228
|
+
legalId: string;
|
|
229
|
+
mobile: string;
|
|
230
|
+
landline: string;
|
|
231
|
+
postal: string;
|
|
232
|
+
plate: string;
|
|
233
|
+
time: string;
|
|
234
|
+
timeRange: (a: string, b: string) => string;
|
|
235
|
+
priceMin: (n: string) => string;
|
|
236
|
+
priceMax: (n: string) => string;
|
|
237
|
+
priceRange: (a: string, b: string) => string;
|
|
238
|
+
};
|
|
239
|
+
inlineEdit: {
|
|
240
|
+
empty: string;
|
|
241
|
+
failed: string;
|
|
242
|
+
};
|
|
243
|
+
iranMap: {
|
|
244
|
+
label: string;
|
|
245
|
+
tableNote: string;
|
|
246
|
+
onMap: (label: string) => string;
|
|
247
|
+
};
|
|
248
|
+
keyboardFix: {
|
|
249
|
+
before: string;
|
|
250
|
+
after: string;
|
|
251
|
+
};
|
|
252
|
+
meter: {
|
|
253
|
+
ok: string;
|
|
254
|
+
warning: string;
|
|
255
|
+
critical: string;
|
|
256
|
+
};
|
|
257
|
+
multiSelect: {
|
|
258
|
+
label: string;
|
|
259
|
+
selected: (n: string) => string;
|
|
260
|
+
clearedAll: string;
|
|
261
|
+
};
|
|
262
|
+
numberInput: {
|
|
263
|
+
label: string;
|
|
264
|
+
increment: string;
|
|
265
|
+
decrement: string;
|
|
266
|
+
};
|
|
267
|
+
pagination: {
|
|
268
|
+
nav: string;
|
|
269
|
+
page: (n: string) => string;
|
|
270
|
+
perPage: string;
|
|
271
|
+
jump: string;
|
|
272
|
+
jumpRange: (jump: string, a: string, b: string) => string;
|
|
273
|
+
};
|
|
274
|
+
password: {
|
|
275
|
+
title: string;
|
|
276
|
+
strength: (level: string) => string;
|
|
277
|
+
levels: string[];
|
|
278
|
+
persian: string;
|
|
279
|
+
length: (n: string) => string;
|
|
280
|
+
cases: string;
|
|
281
|
+
digit: string;
|
|
282
|
+
symbol: string;
|
|
283
|
+
met: string;
|
|
284
|
+
unmet: string;
|
|
285
|
+
};
|
|
286
|
+
receipt: {
|
|
287
|
+
success: string;
|
|
288
|
+
failed: string;
|
|
289
|
+
pending: string;
|
|
290
|
+
merchant: string;
|
|
291
|
+
tracking: string;
|
|
292
|
+
copyTracking: string;
|
|
293
|
+
reference: string;
|
|
294
|
+
card: string;
|
|
295
|
+
date: string;
|
|
296
|
+
at: (time: string) => string;
|
|
297
|
+
};
|
|
298
|
+
persianInput: {
|
|
299
|
+
text: string;
|
|
300
|
+
"national-id": string;
|
|
301
|
+
"legal-id": string;
|
|
302
|
+
mobile: string;
|
|
303
|
+
landline: string;
|
|
304
|
+
card: string;
|
|
305
|
+
iban: string;
|
|
306
|
+
price: string;
|
|
307
|
+
postal: string;
|
|
308
|
+
time: string;
|
|
309
|
+
plate: string;
|
|
310
|
+
};
|
|
311
|
+
textFix: {
|
|
312
|
+
fix: string;
|
|
313
|
+
clean: string;
|
|
314
|
+
count: (n: string, summary: string) => string;
|
|
315
|
+
arabic: string;
|
|
316
|
+
zwnj: string;
|
|
317
|
+
punctuation: string;
|
|
318
|
+
digits: string;
|
|
319
|
+
spacing: string;
|
|
320
|
+
};
|
|
321
|
+
plate: {
|
|
322
|
+
label: string;
|
|
323
|
+
first: string;
|
|
324
|
+
letter: string;
|
|
325
|
+
middle: string;
|
|
326
|
+
region: string;
|
|
327
|
+
iran: string;
|
|
328
|
+
};
|
|
329
|
+
rating: {
|
|
330
|
+
label: string;
|
|
331
|
+
};
|
|
332
|
+
sideNav: {
|
|
333
|
+
label: string;
|
|
334
|
+
};
|
|
335
|
+
slider: {
|
|
336
|
+
from: string;
|
|
337
|
+
to: string;
|
|
338
|
+
};
|
|
339
|
+
splitter: {
|
|
340
|
+
label: string;
|
|
341
|
+
};
|
|
342
|
+
stat: {
|
|
343
|
+
up: string;
|
|
344
|
+
down: string;
|
|
345
|
+
flat: string;
|
|
346
|
+
};
|
|
347
|
+
stepper: {
|
|
348
|
+
label: string;
|
|
349
|
+
complete: string;
|
|
350
|
+
current: string;
|
|
351
|
+
};
|
|
352
|
+
tagInput: {
|
|
353
|
+
label: string;
|
|
354
|
+
duplicate: string;
|
|
355
|
+
};
|
|
356
|
+
toast: {
|
|
357
|
+
region: string;
|
|
358
|
+
close: string;
|
|
359
|
+
};
|
|
360
|
+
tour: {
|
|
361
|
+
done: string;
|
|
362
|
+
skip: string;
|
|
363
|
+
step: (n: string, total: string) => string;
|
|
364
|
+
};
|
|
365
|
+
heatmap: {
|
|
366
|
+
unit: string;
|
|
367
|
+
weekdays: string[];
|
|
368
|
+
inYear: (unit: string, year: string) => string;
|
|
369
|
+
total: (n: string, unit: string, year: string) => string;
|
|
370
|
+
less: string;
|
|
371
|
+
more: string;
|
|
372
|
+
byMonth: (name: string) => string;
|
|
373
|
+
};
|
|
374
|
+
appointment: {
|
|
375
|
+
label: string;
|
|
376
|
+
day: string;
|
|
377
|
+
morning: string;
|
|
378
|
+
afternoon: string;
|
|
379
|
+
evening: string;
|
|
380
|
+
closed: string;
|
|
381
|
+
full: string;
|
|
382
|
+
free: (n: string) => string;
|
|
383
|
+
freeLong: (n: string) => string;
|
|
384
|
+
none: string;
|
|
385
|
+
closedDay: string;
|
|
386
|
+
noSlots: string;
|
|
387
|
+
time: (t: string) => string;
|
|
388
|
+
booked: string;
|
|
389
|
+
yours: string;
|
|
390
|
+
at: (date: string, time: string) => string;
|
|
391
|
+
};
|
|
392
|
+
address: {
|
|
393
|
+
legend: string;
|
|
394
|
+
province: string;
|
|
395
|
+
city: string;
|
|
396
|
+
street: string;
|
|
397
|
+
plaque: string;
|
|
398
|
+
unit: string;
|
|
399
|
+
postalCode: string;
|
|
400
|
+
provinceSearch: string;
|
|
401
|
+
streetHint: string;
|
|
402
|
+
};
|
|
403
|
+
};
|
|
404
|
+
/** زبان فعلی */
|
|
405
|
+
export declare const lang: () => KashiLocale;
|
|
406
|
+
/** ارقام عنصر: ویژگی digits، وگرنه پیشفرض زبان */
|
|
407
|
+
export declare const digitsOf: (el: Element) => Digits;
|
|
408
|
+
/** عدد با ارقام همان عنصر */
|
|
409
|
+
export declare const num: (el: Element, v: number | string) => string;
|
|
410
|
+
/** نام ماهها و روزهای شمسی به زبان فعلی */
|
|
411
|
+
export declare const calendarNames: () => {
|
|
412
|
+
months: readonly ["Farvardin", "Ordibehesht", "Khordad", "Tir", "Mordad", "Shahrivar", "Mehr", "Aban", "Azar", "Dey", "Bahman", "Esfand"] | readonly ["فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند"];
|
|
413
|
+
weekdays: readonly ["Saturday", "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday"] | readonly ["شنبه", "یکشنبه", "دوشنبه", "سهشنبه", "چهارشنبه", "پنجشنبه", "جمعه"];
|
|
414
|
+
weekdaysShort: readonly ["Sa", "Su", "Mo", "Tu", "We", "Th", "Fr"] | readonly ["ش", "ی", "د", "س", "چ", "پ", "ج"];
|
|
415
|
+
friday: string;
|
|
416
|
+
};
|
|
10
417
|
/** شناسهٔ یکتا برای اتصال برچسب، راهنما و خطا */
|
|
11
418
|
export declare const uid: (prefix: string) => string;
|
|
12
419
|
/** متن امن برای قرار دادن در HTML */
|
|
@@ -45,3 +452,4 @@ export declare function fieldHTML({ id, label, required, optional, control }: Fi
|
|
|
45
452
|
export declare function setMessages(field: Element, control: HTMLElement, id: string, error: string | null, hint: string | null, extra?: string | null): void;
|
|
46
453
|
/** فیلد پنهان برای ارسال مقدار خام در فرم HTML معمولی */
|
|
47
454
|
export declare function syncHidden(host: Element, name: string | null, value: string): void;
|
|
455
|
+
export {};
|
package/dist/base.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// پایهٔ مشترک وب کامپوننتها: بدون Shadow DOM، تا کلاسهای k-* از @kashi-ui/css و تم کاربر مستقیم اعمال شوند.
|
|
2
|
+
import { JALALI_MONTHS, JALALI_MONTHS_EN, WEEKDAYS, WEEKDAYS_EN, WEEKDAYS_SHORT, WEEKDAYS_SHORT_EN, faMessages, getMessages, toFaDigits, } from "@kashi-ui/persian";
|
|
2
3
|
/** در Node.js (رندر سمت سرور) HTMLElement وجود ندارد؛ import کردن پکیج نباید خطا بدهد */
|
|
3
4
|
export const HTMLBase = typeof HTMLElement === "undefined" ? class {
|
|
4
5
|
} : HTMLElement;
|
|
@@ -64,6 +65,34 @@ export function afterParse(cb) {
|
|
|
64
65
|
else
|
|
65
66
|
cb();
|
|
66
67
|
}
|
|
68
|
+
const LOCALE = { locale: "fa", messages: faMessages, digits: "fa" };
|
|
69
|
+
/**
|
|
70
|
+
* زبان متنهای داخلی همهٔ عنصرها: setLocale("en") برچسب دکمهها، متن صفحهخوان، پیامهای خطا، نام ماهها و ارقام را انگلیسی میکند.
|
|
71
|
+
* پیش از ساخته شدن عنصرها صدا بزنید (بالای صفحه، بعد از import). با messages هر متنی را عوض کنید.
|
|
72
|
+
*/
|
|
73
|
+
export function setLocale(locale, { messages, digits } = {}) {
|
|
74
|
+
LOCALE.locale = locale;
|
|
75
|
+
LOCALE.messages = getMessages(locale, messages);
|
|
76
|
+
LOCALE.digits = digits ?? (locale === "en" ? "latin" : "fa");
|
|
77
|
+
}
|
|
78
|
+
/** ارقام پیشفرض زبان فعلی */
|
|
79
|
+
export const localeDigits = () => LOCALE.digits;
|
|
80
|
+
/** فرهنگ متنهای فعلی */
|
|
81
|
+
export const msg = () => LOCALE.messages;
|
|
82
|
+
/** زبان فعلی */
|
|
83
|
+
export const lang = () => LOCALE.locale;
|
|
84
|
+
/** ارقام عنصر: ویژگی digits، وگرنه پیشفرض زبان */
|
|
85
|
+
export const digitsOf = (el) => {
|
|
86
|
+
const a = el.getAttribute("digits");
|
|
87
|
+
return a === "latin" || a === "fa" ? a : LOCALE.digits;
|
|
88
|
+
};
|
|
89
|
+
/** عدد با ارقام همان عنصر */
|
|
90
|
+
export const num = (el, v) => (digitsOf(el) === "fa" ? toFaDigits(String(v)) : String(v));
|
|
91
|
+
/** نام ماهها و روزهای شمسی به زبان فعلی */
|
|
92
|
+
export const calendarNames = () => {
|
|
93
|
+
const en = LOCALE.locale === "en";
|
|
94
|
+
return { months: en ? JALALI_MONTHS_EN : JALALI_MONTHS, weekdays: en ? WEEKDAYS_EN : WEEKDAYS, weekdaysShort: en ? WEEKDAYS_SHORT_EN : WEEKDAYS_SHORT, friday: en ? "Friday" : "جمعه" };
|
|
95
|
+
};
|
|
67
96
|
let counter = 0;
|
|
68
97
|
/** شناسهٔ یکتا برای اتصال برچسب، راهنما و خطا */
|
|
69
98
|
export const uid = (prefix) => `${prefix}-${(++counter).toString(36)}`;
|
package/dist/basic.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { HTMLBase, ICONS, afterParse, bool, define, emit, esc, fieldHTML, setMessages, uid } from "./base.js";
|
|
1
|
+
import { afterParse, bool, define, emit, esc, fieldHTML, HTMLBase, ICONS, msg, num, setMessages, uid } from "./base.js";
|
|
3
2
|
const EYE = (off) => `<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="M1.8 10S4.8 4.5 10 4.5 18.2 10 18.2 10 15.2 15.5 10 15.5 1.8 10 1.8 10Z"/><circle cx="10" cy="10" r="2.5"/>${off ? '<path d="m3 3 14 14"/>' : ""}</svg>`;
|
|
4
3
|
const X = '<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" aria-hidden="true"><path d="m6 6 8 8M14 6l-8 8"/></svg>';
|
|
5
4
|
/** ویژگیهایی که مستقیم روی input یا textarea داخلی میروند */
|
|
@@ -62,7 +61,7 @@ export class KashiInput extends HTMLBase {
|
|
|
62
61
|
const box = `<div class="k-input${this.multiline ? " k-input--textarea" : ""}${bool(this, "autoresize") ? " k-input--autoresize" : ""}${size === "sm" || size === "lg" ? ` k-input--${size}` : ""}" data-size="${size ?? "md"}"${disabled ? ' data-state="disabled"' : ""}>${control}<span class="k-input__end"></span></div>`;
|
|
63
62
|
const optional = this.getAttribute("optional");
|
|
64
63
|
this.querySelector(":scope > .k-field")?.remove();
|
|
65
|
-
this.insertAdjacentHTML("afterbegin", fieldHTML({ id, label, required: this.hasAttribute("required"), optional: optional === null ? null : optional ||
|
|
64
|
+
this.insertAdjacentHTML("afterbegin", fieldHTML({ id, label, required: this.hasAttribute("required"), optional: optional === null ? null : optional || msg().common.optional, control: box }));
|
|
66
65
|
this.control = this.querySelector(".k-input__control");
|
|
67
66
|
this.control.value = this.text;
|
|
68
67
|
this.control.addEventListener("input", () => {
|
|
@@ -97,9 +96,9 @@ export class KashiInput extends HTMLBase {
|
|
|
97
96
|
const end = this.querySelector(".k-input__end");
|
|
98
97
|
const password = !this.multiline && this.getAttribute("type") === "password" && this.getAttribute("revealable") !== "false";
|
|
99
98
|
end.innerHTML = [
|
|
100
|
-
bool(this, "loading") ? '<span class="k-input__addon"><span class="k-spinner k-spinner--sm" role="status" aria-label="
|
|
101
|
-
bool(this, "clearable") && len > 0 && !off ? `<button type="button" class="k-input__action" data-act="clear" aria-label="
|
|
102
|
-
password ? `<button type="button" class="k-input__action" data-act="reveal" aria-label="${this.revealed ?
|
|
99
|
+
bool(this, "loading") ? '<span class="k-input__addon"><span class="k-spinner k-spinner--sm" role="status" aria-label="${esc(msg().input.checking)}"></span></span>' : "",
|
|
100
|
+
bool(this, "clearable") && len > 0 && !off ? `<button type="button" class="k-input__action" data-act="clear" aria-label="${esc(msg().input.clear)}">${X}</button>` : "",
|
|
101
|
+
password ? `<button type="button" class="k-input__action" data-act="reveal" aria-label="${esc(this.revealed ? msg().input.hide : msg().input.show)}" aria-pressed="${this.revealed}">${EYE(this.revealed)}</button>` : "",
|
|
103
102
|
].join("");
|
|
104
103
|
end.style.display = end.innerHTML ? "contents" : "none";
|
|
105
104
|
const field = this.querySelector(":scope > .k-field");
|
|
@@ -114,7 +113,7 @@ export class KashiInput extends HTMLBase {
|
|
|
114
113
|
row.innerHTML = '<div class="k-field__hints"></div>';
|
|
115
114
|
field.append(row);
|
|
116
115
|
}
|
|
117
|
-
row.insertAdjacentHTML("beforeend", `<span class="k-counter" id="${countId}"${max && len > max ? ' data-over=""' : ""}>${max ? `${
|
|
116
|
+
row.insertAdjacentHTML("beforeend", `<span class="k-counter" id="${countId}"${max && len > max ? ' data-over=""' : ""}>${max ? `${num(this, len)} / ${num(this, max)}` : num(this, len)}</span>`);
|
|
118
117
|
}
|
|
119
118
|
}
|
|
120
119
|
}
|
|
@@ -195,10 +194,10 @@ export class KashiBanner extends HTMLBase {
|
|
|
195
194
|
const box = this.box;
|
|
196
195
|
const tone = this.getAttribute("tone");
|
|
197
196
|
box.className = `k-banner${tone && tone !== "neutral" ? ` k-banner--${tone}` : ""}${bool(this, "flush") ? " k-banner--flush" : ""}`;
|
|
198
|
-
box.setAttribute("aria-label", this.getAttribute("label") ??
|
|
197
|
+
box.setAttribute("aria-label", this.getAttribute("label") ?? msg().banner.label);
|
|
199
198
|
box.querySelector(".k-banner__close")?.remove();
|
|
200
199
|
if (bool(this, "dismissible")) {
|
|
201
|
-
box.insertAdjacentHTML("beforeend", `<button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm k-banner__close" aria-label="${esc(this.getAttribute("close-label") ??
|
|
200
|
+
box.insertAdjacentHTML("beforeend", `<button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm k-banner__close" aria-label="${esc(this.getAttribute("close-label") ?? msg().banner.close)}">${ICONS.close}</button>`);
|
|
202
201
|
box.querySelector(".k-banner__close").addEventListener("click", () => this.close());
|
|
203
202
|
}
|
|
204
203
|
}
|