@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.
Files changed (70) hide show
  1. package/README.md +11 -1
  2. package/dist/appointment.d.ts +40 -0
  3. package/dist/appointment.js +175 -0
  4. package/dist/base.d.ts +408 -0
  5. package/dist/base.js +31 -0
  6. package/dist/basic.d.ts +43 -0
  7. package/dist/basic.js +222 -0
  8. package/dist/calendar.js +21 -20
  9. package/dist/cdn/appointment-CrIZi8Bp.js +1 -0
  10. package/dist/cdn/base-DTQ50VdG.js +1 -0
  11. package/dist/cdn/basic-CrEW2RKF.js +1 -0
  12. package/dist/cdn/calendar-CYRrdGIf.js +16 -0
  13. package/dist/cdn/charts-D6KM26Vp.js +1 -0
  14. package/dist/cdn/combobox-6EFI2qqN.js +1 -0
  15. package/dist/cdn/controls-BwebEIlf.js +1 -0
  16. package/dist/cdn/display-DFuMkcj5.js +1 -0
  17. package/dist/cdn/fields-DhLIhHQ8.js +1 -0
  18. package/dist/cdn/forms-BHivKDdC.js +1 -0
  19. package/dist/cdn/holidays-DgbIAdlt.js +1 -0
  20. package/dist/cdn/inputs-R7nEHfbV.js +1 -0
  21. package/dist/cdn/kashi-elements.js +1 -1
  22. package/dist/cdn/map-H3xiZd8Y.js +12 -0
  23. package/dist/cdn/{menu-DhrqyLgy.js → menu-BAUSubXk.js} +1 -1
  24. package/dist/cdn/nav-NK-v48B5.js +1 -0
  25. package/dist/cdn/overlay-CBv8grz3.js +1 -0
  26. package/dist/cdn/pickers-BHzNt_X8.js +1 -0
  27. package/dist/cdn/table-Bt9WVLoo.js +1 -0
  28. package/dist/cdn/text-D4a_hlwL.js +1 -0
  29. package/dist/cdn/time-DJ3p1wvd.js +1 -0
  30. package/dist/cdn/words-BdADG_9U.js +1 -0
  31. package/dist/cdn.d.ts +1 -0
  32. package/dist/cdn.js +4 -0
  33. package/dist/charts.js +27 -24
  34. package/dist/combobox.d.ts +6 -5
  35. package/dist/combobox.js +29 -20
  36. package/dist/controls.js +15 -15
  37. package/dist/display.js +17 -14
  38. package/dist/fields.js +3 -3
  39. package/dist/forms.d.ts +3 -3
  40. package/dist/forms.js +54 -47
  41. package/dist/index.d.ts +12 -2
  42. package/dist/index.js +7 -1
  43. package/dist/inputs.d.ts +3 -3
  44. package/dist/inputs.js +31 -30
  45. package/dist/map.js +16 -13
  46. package/dist/nav.js +18 -16
  47. package/dist/overlay.js +5 -5
  48. package/dist/pickers.d.ts +1 -1
  49. package/dist/pickers.js +39 -38
  50. package/dist/table.js +7 -7
  51. package/dist/toast.js +3 -3
  52. package/package.json +4 -4
  53. package/dist/cdn/base-Cmq7zeIG.js +0 -1
  54. package/dist/cdn/calendar-Dm3fq2bs.js +0 -16
  55. package/dist/cdn/charts-DNOWi4sJ.js +0 -1
  56. package/dist/cdn/combobox-ZGrZ5okg.js +0 -1
  57. package/dist/cdn/controls-K-OZcjg4.js +0 -1
  58. package/dist/cdn/digits-DE1YGT94.js +0 -1
  59. package/dist/cdn/display-C975tS7j.js +0 -1
  60. package/dist/cdn/fields-BUTaSN8m.js +0 -1
  61. package/dist/cdn/forms-C-effPKn.js +0 -1
  62. package/dist/cdn/inputs-BjOddAM7.js +0 -1
  63. package/dist/cdn/jalali-BiM5Kfep.js +0 -1
  64. package/dist/cdn/map-BHuusa4t.js +0 -12
  65. package/dist/cdn/nav-D_w5BV_K.js +0 -1
  66. package/dist/cdn/overlay-DX9un2xm.js +0 -1
  67. package/dist/cdn/pickers-BFLpUruK.js +0 -1
  68. package/dist/cdn/table-DPQfDMs-.js +0 -1
  69. package/dist/cdn/text-D1U32D6K.js +0 -1
  70. package/dist/cdn/words-9OdzG7y6.js +0 -1
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;
@@ -26,6 +27,8 @@ export function define(tag, ctor, display = "inline") {
26
27
  const rules = [
27
28
  BLOCK_TAGS.length && `:where(${BLOCK_TAGS.join(",")}) { display: block; }`,
28
29
  CONTENTS_TAGS.length && `:where(${CONTENTS_TAGS.join(",")}) { display: contents; }`,
30
+ // display بالا قاعدهٔ hidden مرورگر را از کار می‌اندازد؛ عنصر پنهان‌شده باید پنهان بماند
31
+ `:where(${[...BLOCK_TAGS, ...CONTENTS_TAGS].join(",")})[hidden] { display: none; }`,
29
32
  ].filter(Boolean);
30
33
  style.textContent = `@layer kashi.elements { ${rules.join(" ")} }`;
31
34
  }
@@ -62,6 +65,34 @@ export function afterParse(cb) {
62
65
  else
63
66
  cb();
64
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
+ };
65
96
  let counter = 0;
66
97
  /** شناسهٔ یکتا برای اتصال برچسب، راهنما و خطا */
67
98
  export const uid = (prefix) => `${prefix}-${(++counter).toString(36)}`;
@@ -0,0 +1,43 @@
1
+ import { HTMLBase } from "./base.js";
2
+ /**
3
+ * فیلد متنی کاشی با برچسب، راهنما و خطا؛ با clearable دکمهٔ پاک کردن، با type="password" دکمهٔ نمایش رمز،
4
+ * با show-count شمارندهٔ نویسه («۱۲ / ۱۰۰» با maxlength) و با loading اسپینر. input واقعی داخل عنصر است و با name مستقیم در فرم ارسال می‌شود.
5
+ */
6
+ export declare class KashiInput extends HTMLBase {
7
+ static observedAttributes: string[];
8
+ protected multiline: boolean;
9
+ protected key: string;
10
+ protected control: HTMLInputElement | HTMLTextAreaElement;
11
+ private text;
12
+ private revealed;
13
+ private rendered;
14
+ private valueSet;
15
+ connectedCallback(): void;
16
+ attributeChangedCallback(name: string, old: string | null, next: string | null): void;
17
+ get value(): string;
18
+ set value(v: string);
19
+ focus(options?: FocusOptions): void;
20
+ protected render(): void;
21
+ /** دکمه‌های انتهای فیلد، شمارنده و پیام‌ها */
22
+ private paint;
23
+ }
24
+ /** متن چندخطی کاشی؛ همان ویژگی‌های kashi-input به‌اضافهٔ rows و autoresize (ارتفاع خودکار) */
25
+ export declare class KashiTextarea extends KashiInput {
26
+ static observedAttributes: string[];
27
+ protected multiline: boolean;
28
+ }
29
+ /**
30
+ * نوار اطلاعیهٔ بالای صفحه با tone (brand، warning یا error) و دکمهٔ بستن (dismissible).
31
+ * عنصرهای slot="actions" کنار متن و slot="icon" پیش از آن می‌آیند؛ با remember="کلید" بستن در همین مرورگر یادش می‌ماند.
32
+ */
33
+ export declare class KashiBanner extends HTMLBase {
34
+ static observedAttributes: string[];
35
+ private box;
36
+ connectedCallback(): void;
37
+ attributeChangedCallback(): void;
38
+ private read;
39
+ private build;
40
+ private decorate;
41
+ /** بستن اطلاعیه؛ با preventDefault روی رویداد kashi-close جلوی بستن گرفته می‌شود */
42
+ close(): void;
43
+ }
package/dist/basic.js ADDED
@@ -0,0 +1,222 @@
1
+ import { afterParse, bool, define, emit, esc, fieldHTML, HTMLBase, ICONS, msg, num, setMessages, uid } from "./base.js";
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>`;
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>';
4
+ /** ویژگی‌هایی که مستقیم روی input یا textarea داخلی می‌روند */
5
+ const PASS = ["name", "placeholder", "autocomplete", "inputmode", "maxlength", "minlength", "pattern", "min", "max", "step", "dir", "spellcheck"];
6
+ /**
7
+ * فیلد متنی کاشی با برچسب، راهنما و خطا؛ با clearable دکمهٔ پاک کردن، با type="password" دکمهٔ نمایش رمز،
8
+ * با show-count شمارندهٔ نویسه («۱۲ / ۱۰۰» با maxlength) و با loading اسپینر. input واقعی داخل عنصر است و با name مستقیم در فرم ارسال می‌شود.
9
+ */
10
+ export class KashiInput extends HTMLBase {
11
+ constructor() {
12
+ super(...arguments);
13
+ this.multiline = false;
14
+ this.key = uid("kashi-input");
15
+ this.text = "";
16
+ this.revealed = false;
17
+ this.rendered = false;
18
+ this.valueSet = false;
19
+ }
20
+ connectedCallback() {
21
+ if (!this.rendered && !this.valueSet)
22
+ this.text = this.getAttribute("value") ?? "";
23
+ this.render();
24
+ }
25
+ attributeChangedCallback(name, old, next) {
26
+ if (!this.rendered || old === next)
27
+ return;
28
+ if (name === "value")
29
+ this.value = next ?? "";
30
+ else {
31
+ this.text = this.control.value;
32
+ this.render();
33
+ }
34
+ }
35
+ get value() {
36
+ return this.rendered ? this.control.value : this.text;
37
+ }
38
+ set value(v) {
39
+ this.valueSet = true;
40
+ this.text = String(v ?? "");
41
+ if (this.rendered) {
42
+ this.control.value = this.text;
43
+ this.paint();
44
+ }
45
+ }
46
+ focus(options) {
47
+ this.control?.focus(options);
48
+ }
49
+ render() {
50
+ const id = this.key;
51
+ const ariaLabel = this.getAttribute("aria-label");
52
+ const label = this.getAttribute("label");
53
+ const type = this.getAttribute("type") ?? "text";
54
+ const size = this.getAttribute("size");
55
+ const disabled = this.hasAttribute("disabled");
56
+ const attrs = PASS.map((a) => (this.hasAttribute(a) ? ` ${a}="${esc(this.getAttribute(a))}"` : "")).join("");
57
+ const flags = `${this.hasAttribute("required") ? " required" : ""}${disabled ? " disabled" : ""}${this.hasAttribute("readonly") ? " readonly" : ""}${!label && ariaLabel ? ` aria-label="${esc(ariaLabel)}"` : ""}`;
58
+ const control = this.multiline
59
+ ? `<textarea id="${id}" class="k-input__control" rows="${Number(this.getAttribute("rows")) || 4}"${attrs}${flags}></textarea>`
60
+ : `<input id="${id}" class="k-input__control" type="${esc(type === "password" && this.revealed ? "text" : type)}"${attrs}${flags}>`;
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>`;
62
+ const optional = this.getAttribute("optional");
63
+ this.querySelector(":scope > .k-field")?.remove();
64
+ this.insertAdjacentHTML("afterbegin", fieldHTML({ id, label, required: this.hasAttribute("required"), optional: optional === null ? null : optional || msg().common.optional, control: box }));
65
+ this.control = this.querySelector(".k-input__control");
66
+ this.control.value = this.text;
67
+ this.control.addEventListener("input", () => {
68
+ this.paint();
69
+ emit(this, "kashi-change", { value: this.control.value });
70
+ });
71
+ this.querySelector(".k-input__end").addEventListener("click", (e) => {
72
+ const b = e.target.closest("button");
73
+ if (!b)
74
+ return;
75
+ if (b.dataset.act === "clear") {
76
+ this.control.value = "";
77
+ this.control.dispatchEvent(new Event("input", { bubbles: true }));
78
+ this.control.focus();
79
+ emit(this, "kashi-clear", {});
80
+ }
81
+ else if (b.dataset.act === "reveal") {
82
+ this.revealed = !this.revealed;
83
+ this.control.type = this.revealed ? "text" : "password";
84
+ this.paint();
85
+ b.focus();
86
+ }
87
+ });
88
+ this.rendered = true;
89
+ this.paint();
90
+ }
91
+ /** دکمه‌های انتهای فیلد، شمارنده و پیام‌ها */
92
+ paint() {
93
+ const el = this.control;
94
+ const len = el.value.length;
95
+ const off = this.hasAttribute("disabled") || this.hasAttribute("readonly");
96
+ const end = this.querySelector(".k-input__end");
97
+ const password = !this.multiline && this.getAttribute("type") === "password" && this.getAttribute("revealable") !== "false";
98
+ end.innerHTML = [
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>` : "",
102
+ ].join("");
103
+ end.style.display = end.innerHTML ? "contents" : "none";
104
+ const field = this.querySelector(":scope > .k-field");
105
+ const countId = `${this.key}-count`;
106
+ setMessages(field, el, this.key, this.getAttribute("error"), this.getAttribute("hint"), bool(this, "show-count") ? countId : null);
107
+ if (bool(this, "show-count")) {
108
+ const max = Number(this.getAttribute("maxlength")) || 0;
109
+ let row = field.querySelector(":scope > .k-field__hint-row");
110
+ if (!row) {
111
+ row = document.createElement("div");
112
+ row.className = "k-field__hint-row";
113
+ row.innerHTML = '<div class="k-field__hints"></div>';
114
+ field.append(row);
115
+ }
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>`);
117
+ }
118
+ }
119
+ }
120
+ KashiInput.observedAttributes = ["label", "hint", "error", "type", "required", "disabled", "readonly", "clearable", "revealable", "show-count", "loading", "size", "optional", "aria-label", "value", ...PASS];
121
+ /** متن چندخطی کاشی؛ همان ویژگی‌های kashi-input به‌اضافهٔ rows و autoresize (ارتفاع خودکار) */
122
+ export class KashiTextarea extends KashiInput {
123
+ constructor() {
124
+ super(...arguments);
125
+ this.multiline = true;
126
+ }
127
+ }
128
+ KashiTextarea.observedAttributes = [...KashiInput.observedAttributes, "rows", "autoresize"];
129
+ /**
130
+ * نوار اطلاعیهٔ بالای صفحه با tone (brand، warning یا error) و دکمهٔ بستن (dismissible).
131
+ * عنصرهای slot="actions" کنار متن و slot="icon" پیش از آن می‌آیند؛ با remember="کلید" بستن در همین مرورگر یادش می‌ماند.
132
+ */
133
+ export class KashiBanner extends HTMLBase {
134
+ constructor() {
135
+ super(...arguments);
136
+ this.box = null;
137
+ }
138
+ connectedCallback() {
139
+ afterParse(() => {
140
+ if (!this.isConnected || this.box)
141
+ return;
142
+ const key = this.getAttribute("remember");
143
+ if (key && this.read(key)) {
144
+ this.hidden = true;
145
+ return;
146
+ }
147
+ this.build();
148
+ });
149
+ }
150
+ attributeChangedCallback() {
151
+ if (this.box)
152
+ this.decorate();
153
+ }
154
+ read(key) {
155
+ try {
156
+ return localStorage.getItem(`kashi-banner:${key}`) === "closed";
157
+ }
158
+ catch {
159
+ return false;
160
+ }
161
+ }
162
+ build() {
163
+ const icon = this.querySelector(":scope > [slot='icon']");
164
+ const actions = [...this.querySelectorAll(":scope > [slot='actions']")];
165
+ const rest = [...this.childNodes].filter((n) => n !== icon && !actions.includes(n));
166
+ const box = document.createElement("div");
167
+ box.setAttribute("role", "region");
168
+ if (icon) {
169
+ icon.removeAttribute("slot");
170
+ const s = document.createElement("span");
171
+ s.className = "k-banner__icon";
172
+ s.setAttribute("aria-hidden", "true");
173
+ s.append(icon);
174
+ box.append(s);
175
+ }
176
+ const text = document.createElement("p");
177
+ text.className = "k-banner__text";
178
+ text.append(...rest);
179
+ box.append(text);
180
+ if (actions.length) {
181
+ const a = document.createElement("div");
182
+ a.className = "k-banner__actions";
183
+ for (const el of actions) {
184
+ el.removeAttribute("slot");
185
+ a.append(el);
186
+ }
187
+ box.append(a);
188
+ }
189
+ this.replaceChildren(box);
190
+ this.box = box;
191
+ this.decorate();
192
+ }
193
+ decorate() {
194
+ const box = this.box;
195
+ const tone = this.getAttribute("tone");
196
+ box.className = `k-banner${tone && tone !== "neutral" ? ` k-banner--${tone}` : ""}${bool(this, "flush") ? " k-banner--flush" : ""}`;
197
+ box.setAttribute("aria-label", this.getAttribute("label") ?? msg().banner.label);
198
+ box.querySelector(".k-banner__close")?.remove();
199
+ if (bool(this, "dismissible")) {
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>`);
201
+ box.querySelector(".k-banner__close").addEventListener("click", () => this.close());
202
+ }
203
+ }
204
+ /** بستن اطلاعیه؛ با preventDefault روی رویداد kashi-close جلوی بستن گرفته می‌شود */
205
+ close() {
206
+ const ev = new CustomEvent("kashi-close", { bubbles: true, cancelable: true, detail: {} });
207
+ if (!this.dispatchEvent(ev))
208
+ return;
209
+ this.hidden = true;
210
+ const key = this.getAttribute("remember");
211
+ if (key) {
212
+ try {
213
+ localStorage.setItem(`kashi-banner:${key}`, "closed");
214
+ }
215
+ catch { /* حالت خصوصی */ }
216
+ }
217
+ }
218
+ }
219
+ KashiBanner.observedAttributes = ["tone", "flush", "label", "dismissible", "close-label"];
220
+ define("kashi-input", KashiInput, "block");
221
+ define("kashi-textarea", KashiTextarea, "block");
222
+ define("kashi-banner", KashiBanner, "block");
package/dist/calendar.js CHANGED
@@ -1,5 +1,5 @@
1
- import { JALALI_MONTHS, WEEKDAYS, WEEKDAYS_SHORT, formatJalali, fromISODate, getIranHoliday, jalaliMonthLength, jalaliWeekday, parseJalali, toFaDigits, toGregorian, toISODate, toJalali, } from "@kashi-ui/persian";
2
- import { HTMLBase, ICONS, bool, define, emit, esc, fieldHTML, setMessages, syncHidden, uid } from "./base.js";
1
+ import { formatJalali, fromISODate, getIranHoliday, jalaliMonthLength, jalaliWeekday, parseJalali, toFaDigits, toGregorian, toISODate, toJalali, } from "@kashi-ui/persian";
2
+ import { bool, calendarNames, define, digitsOf, emit, esc, fieldHTML, HTMLBase, ICONS, lang, msg, setMessages, syncHidden, uid } from "./base.js";
3
3
  const sameDay = (a, b) => !!a && !!b && a.getFullYear() === b.getFullYear() && a.getMonth() === b.getMonth() && a.getDate() === b.getDate();
4
4
  const startOfDay = (d) => new Date(d.getFullYear(), d.getMonth(), d.getDate());
5
5
  const addDays = (d, n) => new Date(d.getFullYear(), d.getMonth(), d.getDate() + n);
@@ -166,7 +166,7 @@ export class KashiCalendar extends HTMLBase {
166
166
  holiday(d) {
167
167
  if (this.holidayOf)
168
168
  return this.holidayOf(d) || null;
169
- return bool(this, "holidays") ? getIranHoliday(d) : null;
169
+ return bool(this, "holidays") ? getIranHoliday(d, { locale: lang() }) : null;
170
170
  }
171
171
  go(d, focus = true) {
172
172
  this.focused = this.clamp(d);
@@ -204,8 +204,9 @@ export class KashiCalendar extends HTMLBase {
204
204
  });
205
205
  }
206
206
  render() {
207
- const digits = this.getAttribute("digits") === "latin" ? "latin" : "fa";
207
+ const digits = digitsOf(this);
208
208
  const n = (v) => (digits === "fa" ? toFaDigits(v) : String(v));
209
+ const M = msg(), C = M.calendar, { months, weekdays, weekdaysShort, friday } = calendarNames();
209
210
  const today = startOfDay(new Date());
210
211
  const { jy, jm } = toJalali(this.focused);
211
212
  const monthStart = toGregorian(jy, jm, 1);
@@ -228,23 +229,23 @@ export class KashiCalendar extends HTMLBase {
228
229
  if (!d)
229
230
  return '<td role="gridcell"></td>';
230
231
  const h = this.holiday(d);
231
- const label = formatJalali(d, { style: "full", digits }) + (h ? `، تعطیل${h === "جمعه" ? "" : `: ${h}`}` : "");
232
- return `<td role="gridcell" data-date="${dayKey(d)}" aria-selected="${sameDay(d, this.selected)}"><button type="button" class="k-calendar__day" data-day="${dayKey(d)}" tabindex="${sameDay(d, this.focused) ? 0 : -1}" aria-label="${esc(label)}"${h && h !== "جمعه" ? ` title="${esc(h)}"` : ""}${h ? ' data-holiday=""' : ""}${sameDay(d, today) ? ' aria-current="date"' : ""}${this.disabled(d) ? ' aria-disabled="true"' : ""}>${n(toJalali(d).jd)}</button></td>`;
232
+ const label = formatJalali(d, { style: "full", digits, locale: lang() }) + (h ? `${M.common.list}${C.holiday}${h === friday ? "" : `: ${h}`}` : "");
233
+ return `<td role="gridcell" data-date="${dayKey(d)}" aria-selected="${sameDay(d, this.selected)}"><button type="button" class="k-calendar__day" data-day="${dayKey(d)}" tabindex="${sameDay(d, this.focused) ? 0 : -1}" aria-label="${esc(label)}"${h && h !== friday ? ` title="${esc(h)}"` : ""}${h ? ' data-holiday=""' : ""}${sameDay(d, today) ? ' aria-current="date"' : ""}${this.disabled(d) ? ' aria-disabled="true"' : ""}>${n(toJalali(d).jd)}</button></td>`;
233
234
  }).join("")}</tr>`);
234
235
  }
235
236
  const todayLabel = this.getAttribute("today-label");
236
- this.innerHTML = `<div class="k-calendar" role="group" aria-label="${esc(this.getAttribute("label") ?? "تقویم")}">
237
+ this.innerHTML = `<div class="k-calendar" role="group" aria-label="${esc(this.getAttribute("label") ?? C.label)}">
237
238
  <div class="k-calendar__header">
238
- <button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm" data-nav="prev" aria-label="ماه قبل"${prevOff ? " disabled" : ""}>${ICONS.prev}</button>
239
+ <button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm" data-nav="prev" aria-label="${esc(C.prevMonth)}"${prevOff ? " disabled" : ""}>${ICONS.prev}</button>
239
240
  <div class="k-calendar__selects">
240
- <select class="k-calendar__select" data-part="month" aria-label="ماه">${JALALI_MONTHS.map((m, i) => `<option value="${i + 1}"${i + 1 === jm ? " selected" : ""}>${m}</option>`).join("")}</select>
241
- <select class="k-calendar__select" data-part="year" aria-label="سال">${years.map((y) => `<option value="${y}"${y === jy ? " selected" : ""}>${n(y)}</option>`).join("")}</select>
241
+ <select class="k-calendar__select" data-part="month" aria-label="${esc(C.month)}">${months.map((m, i) => `<option value="${i + 1}"${i + 1 === jm ? " selected" : ""}>${m}</option>`).join("")}</select>
242
+ <select class="k-calendar__select" data-part="year" aria-label="${esc(C.year)}">${years.map((y) => `<option value="${y}"${y === jy ? " selected" : ""}>${n(y)}</option>`).join("")}</select>
242
243
  </div>
243
- <button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm" data-nav="next" aria-label="ماه بعد"${nextOff ? " disabled" : ""}>${ICONS.next}</button>
244
+ <button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm" data-nav="next" aria-label="${esc(C.nextMonth)}"${nextOff ? " disabled" : ""}>${ICONS.next}</button>
244
245
  </div>
245
- <h2 class="k-sr-only" id="${this.key}-title" aria-live="polite">${JALALI_MONTHS[jm - 1]} ${n(jy)}</h2>
246
+ <h2 class="k-sr-only" id="${this.key}-title" aria-live="polite">${months[jm - 1]} ${n(jy)}</h2>
246
247
  <table class="k-calendar__grid" role="grid" aria-labelledby="${this.key}-title">
247
- <thead><tr>${WEEKDAYS_SHORT.map((s, i) => `<th scope="col" abbr="${WEEKDAYS[i]}">${s}</th>`).join("")}</tr></thead>
248
+ <thead><tr>${weekdaysShort.map((s, i) => `<th scope="col" abbr="${weekdays[i]}">${s}</th>`).join("")}</tr></thead>
248
249
  <tbody>${rows.join("")}</tbody>
249
250
  </table>
250
251
  ${todayLabel ? `<div class="k-calendar__footer"><button type="button" class="k-btn k-btn--link" data-today>${esc(todayLabel)}</button></div>` : ""}
@@ -315,7 +316,7 @@ export class KashiDatePicker extends HTMLBase {
315
316
  this.input?.focus(options);
316
317
  }
317
318
  get digits() {
318
- return this.getAttribute("digits") === "latin" ? "latin" : "fa";
319
+ return digitsOf(this);
319
320
  }
320
321
  fmt(d) {
321
322
  return d ? formatJalali(d, { digits: this.digits }) : "";
@@ -323,7 +324,7 @@ export class KashiDatePicker extends HTMLBase {
323
324
  render() {
324
325
  const id = this.key;
325
326
  const ariaLabel = this.getAttribute("aria-label");
326
- const label = this.hasAttribute("label") ? this.getAttribute("label") : ariaLabel ? null : "تاریخ";
327
+ const label = this.hasAttribute("label") ? this.getAttribute("label") : ariaLabel ? null : msg().datePicker.label;
327
328
  const required = this.hasAttribute("required");
328
329
  const disabled = this.hasAttribute("disabled");
329
330
  const placeholder = this.getAttribute("placeholder") ?? (this.digits === "fa" ? "۱۴۰۳/۰۱/۰۱" : "1403/01/01");
@@ -346,9 +347,9 @@ export class KashiDatePicker extends HTMLBase {
346
347
  const text = this.fmt(this.selected);
347
348
  if (!this.invalid && this.input.value !== text)
348
349
  this.input.value = text;
349
- const open = this.getAttribute("open-label") ?? "انتخاب تاریخ از تقویم";
350
- this.toggle.setAttribute("aria-label", this.selected ? `${open}، ${formatJalali(this.selected, { style: "full", digits: this.digits })}` : open);
351
- const message = this.getAttribute("invalid-message") ?? "این تاریخ معتبر نیست؛ آن را به شکل ۱۴۰۳/۰۵/۱۲ وارد کنید.";
350
+ const open = this.getAttribute("open-label") ?? msg().datePicker.open;
351
+ this.toggle.setAttribute("aria-label", this.selected ? `${open}${msg().common.list}${formatJalali(this.selected, { style: "full", digits: this.digits, locale: lang() })}` : open);
352
+ const message = this.getAttribute("invalid-message") ?? msg().datePicker.invalid;
352
353
  this.input.setCustomValidity(this.invalid ? message : "");
353
354
  setMessages(this.querySelector(".k-field"), this.input, this.key, this.getAttribute("error") || (this.invalid ? message : null), this.getAttribute("hint"));
354
355
  syncHidden(this, this.getAttribute("name"), this.value);
@@ -385,7 +386,7 @@ export class KashiDatePicker extends HTMLBase {
385
386
  pop.className = "k-datepicker__popover";
386
387
  pop.id = `${this.key}-calendar`;
387
388
  pop.setAttribute("role", "dialog");
388
- pop.setAttribute("aria-label", this.getAttribute("open-label") ?? "انتخاب تاریخ از تقویم");
389
+ pop.setAttribute("aria-label", this.getAttribute("open-label") ?? msg().datePicker.open);
389
390
  pop.style.insetBlockStart = `${box.offsetTop + box.offsetHeight + 6}px`;
390
391
  const cal = document.createElement("kashi-calendar");
391
392
  for (const a of ["min", "max", "digits", "holidays"]) {
@@ -395,7 +396,7 @@ export class KashiDatePicker extends HTMLBase {
395
396
  }
396
397
  if (this.selected)
397
398
  cal.setAttribute("value", toISODate(this.selected));
398
- cal.setAttribute("today-label", this.getAttribute("today-label") ?? "امروز");
399
+ cal.setAttribute("today-label", this.getAttribute("today-label") ?? msg().common.today);
399
400
  cal.isDateDisabled = this.isDateDisabled;
400
401
  cal.addEventListener("kashi-change", (e) => {
401
402
  e.stopPropagation();
@@ -0,0 +1 @@
1
+ import{A as e,E as t,T as n,a as r,b as i,c as a,d as o,l as s,o as c,p as l,s as u,t as d,v as f,y as p}from"./base-DTQ50VdG.js";import{n as m,t as h}from"./time-DJ3p1wvd.js";import{t as g}from"./holidays-DgbIAdlt.js";const _=[[`morning`,12],[`afternoon`,17],[`evening`,24]],v=(e,t=0)=>new Date(e.getFullYear(),e.getMonth(),e.getDate()+t),y=(e,t)=>e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth()&&e.getDate()===t.getDate(),b=e=>{let t=m(e);return t?t.hours*60+t.minutes:0};var x=class extends d{constructor(){super(...arguments),this.selected=null,this.active=-1,this.valueSet=!1,this.rendered=!1,this.key=f(`kashi-appt`)}connectedCallback(){!this.rendered&&!this.valueSet&&(this.selected=this.parse(this.getAttribute(`value`))),this.render(),clearInterval(this.timer),this.timer=setInterval(()=>!this.contains(document.activeElement)&&this.render(),6e4)}disconnectedCallback(){clearInterval(this.timer)}attributeChangedCallback(e,t,n){this.rendered&&t!==n&&(e===`value`&&(this.selected=this.parse(n)),this.render())}parse(e){let t=(e??``).trim().match(/^(\d{4}-\d{2}-\d{2})[ T](\d{1,2}:\d{2})$/),n=t?i(t[1]):null;return n&&t?{date:n,time:h(m(t[2]))}:null}get value(){return this.selected?{...this.selected}:null}set value(e){this.valueSet=!0,this.selected=e?{date:v(e.date),time:e.time}:null,this.rendered&&this.render()}list(){let e=/* @__PURE__ */ new Date,t=i(this.getAttribute(`start`)??``)??e,r=Math.max(1,Number(this.getAttribute(`days`))||7),a={};try{a=JSON.parse(this.getAttribute(`booked`)??`{}`)}catch{}let s=this.getAttribute(`from`)??`09:00`,c=this.getAttribute(`to`)??`17:00`,l=Number(this.getAttribute(`step`))||30,u=this.getAttribute(`closed`)!==`false`;return Array.from({length:r},(r,i)=>{let d=v(t,i),f=this.isClosed?this.isClosed(d):u&&!!g(d,{locale:o()}),p=[];if(!f){if(this.getSlots)p=this.getSlots(d).map(e=>typeof e==`string`?{time:e,available:!0}:{time:e.time,available:e.available??!0});else{let e=new Set(a[n(d)]??[]);for(let t=b(s);t+l<=b(c);t+=l){let n=h({hours:Math.floor(t/60),minutes:t%60});p.push({time:n,available:!e.has(n)})}}if(y(d,e)){let t=e.getHours()*60+e.getMinutes();p=p.map(e=>b(e.time)<=t?{...e,available:!1}:e)}}return{date:d,closed:f,slots:p,free:p.filter(e=>e.available).length}})}render(i=null){let c=/* @__PURE__ */ new Date,d=u(this)===`fa`,f=t=>d?e(String(t)):String(t),m=d?`fa`:`latin`,h=this.list();if(this.active<0||this.active>=h.length){let e=this.selected?h.findIndex(e=>y(e.date,this.selected.date)):-1;this.active=e>=0?e:Math.max(0,h.findIndex(e=>e.free>0))}let g=h[this.active],x=l(),S=x.appointment,{months:C,weekdays:w}=r(),T=o(),E=this.getAttribute(`label`)??S.label,D=e=>y(e,c)?x.common.today:y(e,v(c,1))?x.common.tomorrow:w[(e.getDay()+1)%7],O=h.map((e,n)=>{let{jm:r,jd:i}=t(e.date),a=e.closed?S.closed:e.free?S.freeLong(f(e.free)):S.none;return`<button type="button" role="radio" data-i="${n}" class="k-appt__day" aria-checked="${n===this.active}" tabindex="${n===this.active?0:-1}"${e.closed?` disabled`:``} aria-label="${s(`${p(e.date,{style:`full`,digits:m,locale:T})}${x.common.list}${a}`)}"><span class="k-appt__weekday" aria-hidden="true">${D(e.date)}</span><span class="k-appt__date" aria-hidden="true">${f(i)}</span><span class="k-appt__month" aria-hidden="true">${C[r-1]}</span><span class="k-appt__free" aria-hidden="true">${e.closed?S.closed:e.free?S.free(f(e.free)):S.full}</span></button>`}).join(``),k=!!this.selected&&y(this.selected.date,g.date),A=k?this.selected.time:g.slots.find(e=>e.available)?.time,j=g.closed||!g.free?`<p class="k-appt__empty">${g.closed?S.closedDay:S.noSlots}</p>`:_.map(([e,t],n)=>{let r=g.slots.filter(e=>b(e.time)/60<t&&b(e.time)/60>=(n?_[n-1][1]:0));if(!r.length)return``;let i=`${this.key}-p${n}`;return`<div class="k-appt__group"><p class="k-appt__period" id="${i}">${S[e]}</p><div class="k-appt__times" role="radiogroup" aria-labelledby="${i}">${r.map(e=>`<button type="button" role="radio" class="k-appt__time" data-time="${e.time}" aria-checked="${k&&this.selected.time===e.time}" tabindex="${e.time===A?0:-1}"${e.available?``:` disabled`} aria-label="${s(S.time(f(e.time)))}${e.available?``:s(S.booked)}">${f(e.time)}</button>`).join(``)}</div></div>`}).join(``),M=this.getAttribute(`name`),N=this.selected;this.innerHTML=`<div class="k-appt" role="group" aria-labelledby="${this.key}-label"><p class="k-label" id="${this.key}-label" style="margin: 0">${s(E)}</p><div class="k-appt__days" role="radiogroup" aria-label="${s(S.day)}">${O}</div><div class="k-appt__slots">${j}</div><p class="k-appt__summary" aria-live="polite">${N?`<svg viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="1.7" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><circle cx="10" cy="10" r="7"/><path d="M10 6v4l2.5 2"/></svg><span>${s(S.yours)} <strong>${s(S.at(p(N.date,{style:`full`,digits:m,locale:T}),f(N.time)))}</strong></span>`:``}</p>${M?`<input type="hidden" name="${s(`${M}_date`)}" value="${N?n(N.date):``}"><input type="hidden" name="${s(`${M}_time`)}" value="${N?.time??``}">`:``}</div>`,this.rendered=!0;let P=this.querySelector(`.k-appt__days`),F=this.querySelector(`.k-appt__slots`);P.addEventListener(`click`,e=>{let t=e.target.closest(`.k-appt__day`);t&&!t.disabled&&(this.active=Number(t.dataset.i),this.render(`day`))}),F.addEventListener(`click`,e=>{let t=e.target.closest(`.k-appt__time`);t&&!t.disabled&&(this.selected={date:g.date,time:t.dataset.time},this.render(`time`),a(this,`kashi-change`,{date:n(g.date),time:this.selected.time,value:this.value}))}),P.addEventListener(`keydown`,e=>this.roving(e,P,e=>{this.active=Number(e.dataset.i),this.render(`day`)})),F.addEventListener(`keydown`,e=>this.roving(e,F)),i===`day`&&P.querySelector(`[tabindex="0"]`)?.focus(),i===`time`&&F.querySelector(`[aria-checked="true"]`)?.focus(),i===`day`&&P.querySelector(`[tabindex="0"]`)?.scrollIntoView?.({block:`nearest`,inline:`nearest`})}roving(e,t,n){let r=[...t.querySelectorAll(`[role="radio"]:not(:disabled)`)],i=r.indexOf(document.activeElement);if(i<0)return;let a=getComputedStyle(t).direction===`rtl`,o={ArrowLeft:a?1:-1,ArrowRight:a?-1:1,ArrowDown:1,ArrowUp:-1}[e.key],s=o?(i+o+r.length)%r.length:e.key===`Home`?0:e.key===`End`?r.length-1:-1;s<0||(e.preventDefault(),n?n(r[s]):r[s].focus())}};x.observedAttributes=[`start`,`days`,`from`,`to`,`step`,`booked`,`closed`,`label`,`name`,`digits`,`value`],c(`kashi-appointment-picker`,x,`block`);export{x as KashiAppointmentPicker};
@@ -0,0 +1 @@
1
+ const e=`۰۱۲۳۴۵۶۷۸۹`;function t(t){return String(t).replace(/\d/g,t=>e[Number(t)])}function n(t){return t.replace(/[۰-۹٠-٩]/g,t=>{let n=e.indexOf(t);return String(n>=0?n:`٠١٢٣٤٥٦٧٨٩`.indexOf(t))})}function r(e){return n(e).replace(/\D/g,``)}function i(e,{digits:n=`fa`}={}){let i=typeof e==`number`?e:Number(r(e));if(!Number.isFinite(i))return``;let a=new Intl.NumberFormat(`en-US`).format(i);return n===`fa`?t(a).replace(/,/g,`٬`):a}const a=[`فروردین`,`اردیبهشت`,`خرداد`,`تیر`,`مرداد`,`شهریور`,`مهر`,`آبان`,`آذر`,`دی`,`بهمن`,`اسفند`],o=[`شنبه`,`یکشنبه`,`دوشنبه`,`سه‌شنبه`,`چهارشنبه`,`پنجشنبه`,`جمعه`],s=[`ش`,`ی`,`د`,`س`,`چ`,`پ`,`ج`],c=[`Farvardin`,`Ordibehesht`,`Khordad`,`Tir`,`Mordad`,`Shahrivar`,`Mehr`,`Aban`,`Azar`,`Dey`,`Bahman`,`Esfand`],l=[`Saturday`,`Sunday`,`Monday`,`Tuesday`,`Wednesday`,`Thursday`,`Friday`],u=[`Sa`,`Su`,`Mo`,`Tu`,`We`,`Th`,`Fr`],d=[-61,9,38,199,426,686,756,818,1111,1181,1210,1635,2060,2097,2192,2262,2324,2394,2456,3178],f=(e,t)=>~~(e/t),p=(e,t)=>e-~~(e/t)*t;function m(e){let t=e+621,n=-14,r=d[0],i=0;if(e<r||e>=d[d.length-1])throw RangeError(`سال شمسی خارج از محدوده: ${e}`);for(let t=1;t<d.length;t++){let a=d[t];if(i=a-r,e<a)break;n+=f(i,33)*8+f(p(i,33),4),r=a}let a=e-r;n+=f(a,33)*8+f(p(a,33)+3,4),p(i,33)===4&&i-a===4&&(n+=1);let o=f(t,4)-f((f(t,100)+1)*3,4)-150,s=20+n-o;i-a<6&&(a=a-i+f(i+4,33)*33);let c=p(p(a+1,33)-1,4);return c===-1&&(c=4),{leap:c,gy:t,march:s}}function h(e,t,n){let r=f((e+f(t-8,6)+100100)*1461,4)+f(153*p(t+9,12)+2,5)+n-34840408;return r=r-f(f(e+100100+f(t-8,6),100)*3,4)+752,r}function g(e){let t=4*e+139361631;t=t+f(f(4*e+183187720,146097)*3,4)*4-3908;let n=f(p(t,1461),4)*5+308,r=f(p(n,153),5)+1,i=p(f(n,153),12)+1;return{gy:f(t,1461)-100100+f(8-i,6),gm:i,gd:r}}function _(e,t,n){let r=m(e);return h(r.gy,3,r.march)+(t-1)*31-f(t,7)*(t-7)+n-1}function ee(e){let{gy:t}=g(e),n=t-621,r=m(n),i=e-h(t,3,r.march);if(i>=0){if(i<=185)return{jy:n,jm:1+f(i,31),jd:p(i,31)+1};i-=186}else--n,i+=179,r.leap===1&&(i+=1);return{jy:n,jm:7+f(i,30),jd:p(i,30)+1}}function v(e){return m(e).leap===0}function y(e,t){return t<=6?31:t<=11||v(e)?30:29}function b(e,t,n){return Number.isInteger(e)&&Number.isInteger(t)&&Number.isInteger(n)&&e>=-61&&e<=3177&&t>=1&&t<=12&&n>=1&&n<=y(e,t)}function x(e){return ee(h(e.getFullYear(),e.getMonth()+1,e.getDate()))}function S(e,t,n){let{gy:r,gm:i,gd:a}=g(_(e,t,n));return new Date(r,i-1,a)}function C(e){return(e.getDay()+1)%7}function w(e,{style:n=`numeric`,locale:r=`fa`,digits:i=r===`en`?`latin`:`fa`}={}){let{jy:s,jm:u,jd:d}=x(e),f=e=>String(e).padStart(2,`0`),p=r===`en`,m;return n===`numeric`?m=`${s}/${f(u)}/${f(d)}`:(m=`${d} ${(p?c:a)[u-1]} ${s}`,n===`full`&&(m=p?`${l[C(e)]}, ${m}`:`${o[C(e)]} ${m}`)),i===`fa`?t(m):m}function T(e){let t=e=>String(e).padStart(2,`0`);return`${e.getFullYear()}-${t(e.getMonth()+1)}-${t(e.getDate())}`}function E(e){let t=e.match(/^(\d{4})-(\d{2})-(\d{2})$/);if(!t)return null;let n=new Date(Number(t[1]),Number(t[2])-1,Number(t[3]));return n.getMonth()===Number(t[2])-1?n:null}function D(e){let t=n(e.trim()).match(/^(\d{4})\s*[/\-.\s]\s*(\d{1,2})\s*[/\-.\s]\s*(\d{1,2})$/);if(!t)return null;let[r,i,a]=[Number(t[1]),Number(t[2]),Number(t[3])];return b(r,i,a)?S(r,i,a):null}const O={common:{close:`بستن`,loading:`در حال بارگذاری`,optional:`اختیاری`,remove:e=>`حذف ${e}`,removeShort:`حذف`,clear:`پاک کردن`,clearAll:`پاک کردن همه`,cancel:`انصراف`,confirm:`تأیید`,save:`ثبت`,edit:`ویرایش`,prev:`قبلی`,next:`بعدی`,today:`امروز`,tomorrow:`فردا`,noResults:`نتیجه‌ای پیدا نشد.`,searching:`در حال جستجو…`,results:e=>`${e} نتیجه`,added:e=>`${e} اضافه شد`,removed:e=>`${e} حذف شد`,selected:e=>`${e} انتخاب شد`,max:e=>`حداکثر ${e} مورد`,total:`جمع`,other:`سایر`,of:(e,t)=>`${e} از ${t}`,and:` و `,list:`، `,range:` تا `,percent:e=>`${e}٪`,decimal:`٫`},money:{toman:`تومان`,rial:`ریال`,positive:`مثبت `},alert:{close:`بستن`},banner:{label:`اطلاعیه`,close:`بستن اطلاعیه`},avatar:{online:`آنلاین`,offline:`آفلاین`,busy:`مشغول`,away:`غایب`,more:e=>`${e} نفر دیگر`},bankCard:{card:`کارت بانکی`,cardOf:e=>`کارت ${e}`,bank:`بانکی`,endingIn:e=>`مختوم به ${e}`,expiry:`انقضا`},breadcrumb:{label:`مسیر`,expand:`نمایش مسیر کامل`},calendar:{label:`تقویم`,prevMonth:`ماه قبل`,nextMonth:`ماه بعد`,month:`ماه`,year:`سال`,holiday:`تعطیل`},carousel:{slider:`اسلایدر`,slide:`اسلاید`,slideOf:(e,t)=>`${e} از ${t}`,slides:e=>`اسلایدهای ${e}`},chart:{period:`دوره`,value:`مقدار`,share:`سهم از کل`,count:`تعداد`,keyboard:e=>`${e}. با کلیدهای جهت بین نقطه‌ها حرکت کنید.`,thousand:` هزار`,million:` م`,billion:` میلیارد`},city:{label:`شهر`,outside:`خارج از فهرست`,custom:`شهر دیگر؛ همین نام ثبت شود`,search:`جستجوی شهر`,hint:`نام شهر، مثلاً کاشان`},province:{label:`استان`,search:`جستجوی استان یا شهر`,capital:e=>`مرکز: ${e}`},colorPicker:{label:`رنگ`,custom:`انتخاب رنگ دلخواه`,area:`اشباع و روشنایی`,areaValue:(e,t)=>`اشباع ${e}، روشنایی ${t}`,eyedropper:`برداشتن رنگ از صفحه`,hue:`رنگ‌مایه`,degrees:e=>`${e} درجه`,red:`قرمز`,green:`سبز`,blue:`آبی`,invalid:`کد رنگ معتبر نیست؛ مثل ‎#0fa89b‎ وارد کنید.`,swatches:`رنگ‌های پیشنهادی`,sample:`متن نمونه`,contrast:(e,t,n)=>`کنتراست با متن ${e===`white`?`سفید`:`مشکی`}: ${t} به ۱ ${n?`(AA)`:`(کمتر از AA)`}`,names:{firoozeh:`فیروزه‌ای`,lajvard:`لاجوردی`,violet:`بنفش`,anar:`اناری`,zafaran:`زعفرانی`,peste:`پسته‌ای`,shab:`شب`}},combobox:{toggle:`نمایش گزینه‌ها`,more:e=>`${e} گزینهٔ دیگر؛ برای پیدا کردن تایپ کنید.`},otp:{label:`کد تأیید`},command:{placeholder:`جستجوی دستور یا صفحه…`,empty:`دستوری پیدا نشد.`,title:`پالت فرمان`,navigate:`حرکت`,select:`انتخاب`},contextMenu:{label:`گزینه‌ها`,hint:`برای گزینه‌ها راست‌کلیک کنید یا Shift+F10 را بزنید.`},copy:{copy:`کپی`,copied:`کپی شد`,failed:`کپی نشد`},countdown:{days:`روز`,hours:`ساعت`,minutes:`دقیقه`,seconds:`ثانیه`,left:`مانده`},table:{selectAll:`انتخاب همهٔ ردیف‌ها`,selectRow:`انتخاب ردیف`,selectNamed:e=>`انتخاب ${e}`,empty:`داده‌ای وجود ندارد.`,sort:e=>`مرتب‌سازی بر اساس ${e}`,search:`جستجو در جدول`,rows:e=>`${e} ردیف`},datePicker:{label:`تاریخ`,invalid:`این تاریخ معتبر نیست؛ آن را به شکل ۱۴۰۳/۰۵/۱۲ وارد کنید.`,open:`انتخاب تاریخ از تقویم`},dateRange:{label:`بازهٔ تاریخ`,placeholder:`انتخاب بازهٔ تاریخ`,presets:`میان‌برها`,pickEnd:`حالا تاریخ پایان را انتخاب کنید.`,last7:e=>`${e} روز اخیر`,last30:e=>`${e} روز اخیر`,thisMonth:`این ماه`,lastMonth:`ماه قبل`},monthPicker:{label:`انتخاب ماه`,prevYear:`سال قبل`,nextYear:`سال بعد`},fileUpload:{units:[`بایت`,`کیلوبایت`,`مگابایت`,`گیگابایت`],browse:`انتخاب فایل`,drop:`یا فایل را اینجا رها کنید`,tooBig:e=>`حجم فایل بیشتر از ${e} است.`,wrongType:`این نوع فایل پذیرفته نیست.`,tooMany:e=>`حداکثر ${e} فایل.`,done:`بارگذاری شد`,uploading:`در حال بارگذاری`,uploadingFile:e=>`در حال بارگذاری ${e}`,error:`خطا در بارگذاری`},input:{clear:`پاک کردن`,show:`نمایش رمز`,hide:`پنهان کردن رمز`,checking:`در حال بررسی`},invalid:{card:`شماره کارت معتبر نیست.`,iban:`شماره شبا معتبر نیست.`,nationalId:`کد ملی معتبر نیست.`,legalId:`شناسهٔ ملی معتبر نیست.`,mobile:`شماره موبایل معتبر نیست.`,landline:`شمارهٔ تلفن ثابت معتبر نیست.`,postal:`کد پستی معتبر نیست.`,plate:`پلاک خودرو معتبر نیست.`,time:`ساعت معتبر نیست؛ آن را به شکل ۰۹:۳۰ وارد کنید.`,timeRange:(e,t)=>`ساعت باید بین ${e} و ${t} باشد.`,priceMin:e=>`مبلغ باید حداقل ${e} باشد.`,priceMax:e=>`مبلغ باید حداکثر ${e} باشد.`,priceRange:(e,t)=>`مبلغ باید حداقل ${e} و حداکثر ${t} باشد.`},inlineEdit:{empty:`خالی`,failed:`ذخیره نشد؛ دوباره امتحان کنید.`},iranMap:{label:`نقشهٔ استان‌های ایران`,tableNote:`؛ جدول داده در ادامه`,onMap:e=>`${e} روی نقشه`},keyboardFix:{before:`منظورتان`,after:`بود؟`},meter:{ok:`در محدودهٔ مجاز`,warning:`نزدیک به سقف`,critical:`سقف تقریباً پر شده`},multiSelect:{label:`انتخاب`,selected:e=>`${e} مورد انتخاب شده`,clearedAll:`همه حذف شد`},numberInput:{label:`تعداد`,increment:`افزایش`,decrement:`کاهش`},pagination:{nav:`صفحه‌بندی`,page:e=>`صفحهٔ ${e}`,perPage:`در هر صفحه`,jump:`برو به صفحه`,jumpRange:(e,t,n)=>`${e}، از ${t} تا ${n}`},password:{title:`قدرت رمز`,strength:e=>`قدرت رمز: ${e}`,levels:[`ضعیف`,`متوسط`,`خوب`,`قوی`],persian:`رمز حروف فارسی دارد؛ شاید صفحه‌کلید روی فارسی مانده است.`,length:e=>`حداقل ${e} نویسه`,cases:`حروف بزرگ و کوچک انگلیسی`,digit:`دست‌کم یک عدد`,symbol:`دست‌کم یک نماد، مثل ! یا @`,met:`، رعایت شده`,unmet:`، رعایت نشده`},receipt:{success:`پرداخت موفق`,failed:`پرداخت ناموفق`,pending:`در انتظار تأیید بانک`,merchant:`پذیرنده`,tracking:`کد پیگیری`,copyTracking:`کپی کد پیگیری`,reference:`شمارهٔ مرجع`,card:`کارت`,date:`تاریخ`,at:e=>`ساعت ${e}`},persianInput:{text:`متن`,"national-id":`کد ملی`,"legal-id":`شناسهٔ ملی شرکت`,mobile:`شمارهٔ موبایل`,landline:`تلفن ثابت`,card:`شمارهٔ کارت`,iban:`شمارهٔ شبا`,price:`مبلغ`,postal:`کد پستی`,time:`ساعت`,plate:`پلاک خودرو`},textFix:{fix:`اصلاح نگارش`,clean:`نگارش متن درست است.`,count:(e,t)=>`${e} مورد قابل اصلاح: ${t}`,arabic:`حرف عربی`,zwnj:`نیم‌فاصله`,punctuation:`علامت`,digits:`رقم`,spacing:`فاصله`},plate:{label:`پلاک خودرو`,first:`دو رقم اول پلاک`,letter:`حرف پلاک`,middle:`سه رقم پلاک`,region:`کد استان`,iran:`ایران`},rating:{label:`امتیاز`},sideNav:{label:`اصلی`},slider:{from:`حداقل`,to:`حداکثر`},splitter:{label:`تغییر اندازهٔ پنل‌ها`},stat:{up:`افزایش`,down:`کاهش`,flat:`بدون تغییر`},stepper:{label:`مراحل`,complete:`انجام شده`,current:`مرحلهٔ فعلی`},tagInput:{label:`برچسب‌ها`,duplicate:`این مورد قبلاً اضافه شده است.`},toast:{region:`اعلان‌ها`,close:`بستن اعلان`},tour:{done:`تمام`,skip:`رد کردن`,step:(e,t)=>`مرحلهٔ ${e} از ${t}`},heatmap:{unit:`فعالیت`,weekdays:[`ش`,``,`د`,``,`چ`,``,`ج`],inYear:(e,t)=>`${e} در سال ${t}`,total:(e,t,n)=>`${e} ${t} در ${n}`,less:`کمتر`,more:`بیشتر`,byMonth:e=>`${e}، به تفکیک ماه`},appointment:{label:`انتخاب نوبت`,day:`روز`,morning:`صبح`,afternoon:`بعدازظهر`,evening:`عصر`,closed:`تعطیل`,full:`پر`,free:e=>`${e} نوبت`,freeLong:e=>`${e} نوبت خالی`,none:`نوبت خالی ندارد`,closedDay:`این روز تعطیل است.`,noSlots:`نوبت خالی برای این روز نمانده است؛ روز دیگری را انتخاب کنید.`,time:e=>`ساعت ${e}`,booked:`، پر`,yours:`نوبت شما:`,at:(e,t)=>`${e}، ساعت ${t}`},address:{legend:`نشانی`,province:`استان`,city:`شهر`,street:`نشانی`,plaque:`پلاک`,unit:`واحد`,postalCode:`کد پستی`,provinceSearch:`جستجوی استان`,streetHint:`خیابان، کوچه، نام ساختمان`}},k={common:{close:`Close`,loading:`Loading`,optional:`Optional`,remove:e=>`Remove ${e}`,removeShort:`Remove`,clear:`Clear`,clearAll:`Clear all`,cancel:`Cancel`,confirm:`Apply`,save:`Save`,edit:`Edit`,prev:`Previous`,next:`Next`,today:`Today`,tomorrow:`Tomorrow`,noResults:`No results found.`,searching:`Searching…`,results:e=>`${e} ${e===`1`?`result`:`results`}`,added:e=>`${e} added`,removed:e=>`${e} removed`,selected:e=>`${e} selected`,max:e=>`Up to ${e} items`,total:`Total`,other:`Other`,of:(e,t)=>`${e} of ${t}`,and:` and `,list:`, `,range:` – `,percent:e=>`${e}%`,decimal:`.`},money:{toman:`Toman`,rial:`Rial`,positive:`plus `},alert:{close:`Close`},banner:{label:`Announcement`,close:`Dismiss announcement`},avatar:{online:`Online`,offline:`Offline`,busy:`Busy`,away:`Away`,more:e=>`${e} more`},bankCard:{card:`Bank card`,cardOf:e=>`${e} card`,bank:`Bank`,endingIn:e=>`ending in ${e}`,expiry:`Expires`},breadcrumb:{label:`Breadcrumb`,expand:`Show full path`},calendar:{label:`Calendar`,prevMonth:`Previous month`,nextMonth:`Next month`,month:`Month`,year:`Year`,holiday:`Holiday`},carousel:{slider:`carousel`,slide:`slide`,slideOf:(e,t)=>`${e} of ${t}`,slides:e=>`${e} slides`},chart:{period:`Period`,value:`Value`,share:`Share of total`,count:`Count`,keyboard:e=>`${e}. Use the arrow keys to move between points.`,thousand:`K`,million:`M`,billion:`B`},city:{label:`City`,outside:`Not in the list`,custom:`Other city; use this name`,search:`Search cities`,hint:`City name, e.g. Kashan`},province:{label:`Province`,search:`Search provinces or cities`,capital:e=>`Capital: ${e}`},colorPicker:{label:`Color`,custom:`Pick a custom color`,area:`Saturation and brightness`,areaValue:(e,t)=>`Saturation ${e}, brightness ${t}`,eyedropper:`Pick a color from the screen`,hue:`Hue`,degrees:e=>`${e} degrees`,red:`Red`,green:`Green`,blue:`Blue`,invalid:`Invalid color code; enter one like #0fa89b.`,swatches:`Suggested colors`,sample:`Sample text`,contrast:(e,t,n)=>`Contrast with ${e} text: ${t}:1 ${n?`(AA)`:`(below AA)`}`,names:{firoozeh:`Turquoise`,lajvard:`Lapis`,violet:`Violet`,anar:`Pomegranate`,zafaran:`Saffron`,peste:`Pistachio`,shab:`Night`}},combobox:{toggle:`Show options`,more:e=>`${e} more; type to find them.`},otp:{label:`Verification code`},command:{placeholder:`Search commands or pages…`,empty:`No commands found.`,title:`Command palette`,navigate:`Navigate`,select:`Select`},contextMenu:{label:`Options`,hint:`Right-click or press Shift+F10 for options.`},copy:{copy:`Copy`,copied:`Copied`,failed:`Copy failed`},countdown:{days:`days`,hours:`hours`,minutes:`minutes`,seconds:`seconds`,left:`left`},table:{selectAll:`Select all rows`,selectRow:`Select row`,selectNamed:e=>`Select ${e}`,empty:`No data.`,sort:e=>`Sort by ${e}`,search:`Search the table`,rows:e=>`${e} ${e===`1`?`row`:`rows`}`},datePicker:{label:`Date`,invalid:`Invalid date; enter it like 1403/05/12.`,open:`Choose a date from the calendar`},dateRange:{label:`Date range`,placeholder:`Select a date range`,presets:`Shortcuts`,pickEnd:`Now choose the end date.`,last7:e=>`Last ${e} days`,last30:e=>`Last ${e} days`,thisMonth:`This month`,lastMonth:`Last month`},monthPicker:{label:`Choose a month`,prevYear:`Previous year`,nextYear:`Next year`},fileUpload:{units:[`B`,`KB`,`MB`,`GB`],browse:`Choose file`,drop:`or drop a file here`,tooBig:e=>`File is larger than ${e}.`,wrongType:`This file type isn't accepted.`,tooMany:e=>`Up to ${e} files.`,done:`Uploaded`,uploading:`Uploading`,uploadingFile:e=>`Uploading ${e}`,error:`Upload failed`},input:{clear:`Clear`,show:`Show password`,hide:`Hide password`,checking:`Checking`},invalid:{card:`Invalid card number.`,iban:`Invalid IBAN.`,nationalId:`Invalid national ID.`,legalId:`Invalid company ID.`,mobile:`Invalid mobile number.`,landline:`Invalid phone number.`,postal:`Invalid postal code.`,plate:`Invalid license plate.`,time:`Invalid time; enter it like 09:30.`,timeRange:(e,t)=>`Time must be between ${e} and ${t}.`,priceMin:e=>`Amount must be at least ${e}.`,priceMax:e=>`Amount must be at most ${e}.`,priceRange:(e,t)=>`Amount must be between ${e} and ${t}.`},inlineEdit:{empty:`Empty`,failed:`Couldn't save; try again.`},iranMap:{label:`Map of Iran's provinces`,tableNote:`; data table follows`,onMap:e=>`${e} on the map`},keyboardFix:{before:`Did you mean`,after:`?`},meter:{ok:`Within limit`,warning:`Close to the limit`,critical:`Almost full`},multiSelect:{label:`Select`,selected:e=>`${e} selected`,clearedAll:`All removed`},numberInput:{label:`Quantity`,increment:`Increase`,decrement:`Decrease`},pagination:{nav:`Pagination`,page:e=>`Page ${e}`,perPage:`Per page`,jump:`Go to page`,jumpRange:(e,t,n)=>`${e}, ${t} to ${n}`},password:{title:`Password strength`,strength:e=>`Password strength: ${e}`,levels:[`Weak`,`Fair`,`Good`,`Strong`],persian:`Your password has Persian letters; the keyboard may still be on Persian.`,length:e=>`At least ${e} characters`,cases:`Upper and lower case letters`,digit:`At least one number`,symbol:`At least one symbol, like ! or @`,met:`, met`,unmet:`, not met`},receipt:{success:`Payment successful`,failed:`Payment failed`,pending:`Awaiting bank confirmation`,merchant:`Merchant`,tracking:`Tracking code`,copyTracking:`Copy tracking code`,reference:`Reference number`,card:`Card`,date:`Date`,at:e=>`at ${e}`},persianInput:{text:`Text`,"national-id":`National ID`,"legal-id":`Company ID`,mobile:`Mobile number`,landline:`Phone number`,card:`Card number`,iban:`IBAN`,price:`Amount`,postal:`Postal code`,time:`Time`,plate:`License plate`},textFix:{fix:`Fix writing`,clean:`The text looks right.`,count:(e,t)=>`${e} fixable: ${t}`,arabic:`Arabic letters`,zwnj:`half-spaces`,punctuation:`punctuation`,digits:`digits`,spacing:`spacing`},plate:{label:`License plate`,first:`First two digits`,letter:`Plate letter`,middle:`Three digits`,region:`Region code`,iran:`ایران`},rating:{label:`Rating`},sideNav:{label:`Main`},slider:{from:`Minimum`,to:`Maximum`},splitter:{label:`Resize panels`},stat:{up:`Up`,down:`Down`,flat:`No change`},stepper:{label:`Steps`,complete:`completed`,current:`current step`},tagInput:{label:`Tags`,duplicate:`This item has already been added.`},toast:{region:`Notifications`,close:`Dismiss notification`},tour:{done:`Done`,skip:`Skip`,step:(e,t)=>`Step ${e} of ${t}`},heatmap:{unit:`activities`,weekdays:[`Sa`,``,`Mo`,``,`We`,``,`Fr`],inYear:(e,t)=>`${e} in ${t}`,total:(e,t,n)=>`${e} ${t} in ${n}`,less:`Less`,more:`More`,byMonth:e=>`${e}, by month`},appointment:{label:`Book an appointment`,day:`Day`,morning:`Morning`,afternoon:`Afternoon`,evening:`Evening`,closed:`Closed`,full:`Full`,free:e=>`${e} open`,freeLong:e=>`${e} open slots`,none:`No open slots`,closedDay:`Closed on this day.`,noSlots:`No open slots left for this day; choose another day.`,time:e=>`${e}`,booked:`, booked`,yours:`Your appointment:`,at:(e,t)=>`${e} at ${t}`},address:{legend:`Address`,province:`Province`,city:`City`,street:`Street address`,plaque:`No.`,unit:`Unit`,postalCode:`Postal code`,provinceSearch:`Search provinces`,streetHint:`Street, alley, building name`}};function A(e=`fa`,t){let n=e===`en`?k:O;return t?M(n,t):n}const j=e=>typeof e==`object`&&!!e&&!Array.isArray(e);function M(e,t){let n={...e};for(let[r,i]of Object.entries(t))i!==void 0&&(n[r]=j(i)&&j(e[r])?M(e[r],i):i);return n}const N=typeof HTMLElement>`u`?class{}:HTMLElement,P=[],F=[];let I=null;function L(e,t,n=`inline`){if(typeof customElements>`u`||customElements.get(e)||(n===`block`&&P.push(e),n===`contents`&&F.push(e),R(t),customElements.define(e,t),typeof document>`u`))return;I||(I=document.createElement(`style`),I.dataset.kashiElements=``,document.head.prepend(I));let r=[P.length&&`:where(${P.join(`,`)}) { display: block; }`,F.length&&`:where(${F.join(`,`)}) { display: contents; }`,`:where(${[...P,...F].join(`,`)})[hidden] { display: none; }`].filter(Boolean);I.textContent=`@layer kashi.elements { ${r.join(` `)} }`}function R(e){let t=/* @__PURE__ */ new Set;for(let n=e.prototype;n&&n!==N.prototype;n=Object.getPrototypeOf(n))for(let[e,r]of Object.entries(Object.getOwnPropertyDescriptors(n)))r.set&&t.add(e);let n=e.prototype.connectedCallback;e.prototype.connectedCallback=function(){for(let e of t){if(!Object.prototype.hasOwnProperty.call(this,e))continue;let t=this[e];delete this[e],this[e]=t}n?.call(this)}}function z(e){typeof document<`u`&&document.readyState===`loading`?document.addEventListener(`DOMContentLoaded`,e,{once:!0}):e()}const B={locale:`fa`,messages:O,digits:`fa`};function V(e,{messages:t,digits:n}={}){B.locale=e,B.messages=A(e,t),B.digits=n??(e===`en`?`latin`:`fa`)}const H=()=>B.digits,U=()=>B.messages,W=()=>B.locale,G=e=>{let t=e.getAttribute(`digits`);return t===`latin`||t===`fa`?t:B.digits},K=(e,n)=>G(e)===`fa`?t(String(n)):String(n),q=()=>{let e=B.locale===`en`;return{months:e?c:a,weekdays:e?l:o,weekdaysShort:e?u:s,friday:e?`Friday`:`جمعه`}};let J=0;const Y=e=>`${e}-${(++J).toString(36)}`,X={"&":`&amp;`,"<":`&lt;`,">":`&gt;`,'"':`&quot;`,"'":`&#39;`},Z=e=>String(e??``).replace(/[&<>"']/g,e=>X[e]),Q=(e,t,n=!1)=>{let r=e.getAttribute(t);return r===null?n:r!==`false`};function te(e,t,n){e.dispatchEvent(new CustomEvent(t,{detail:n,bubbles:!0,composed:!0}))}const $=(e,t=1.7,n=!1)=>`<svg${n?` data-k-mirror=""`:``} viewBox="0 0 20 20" fill="none" stroke="currentColor" stroke-width="${t}" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">${e}</svg>`,ne={close:$(`<path d="m5 5 10 10M15 5 5 15"/>`),info:$(`<circle cx="10" cy="10" r="7.5"/><path d="M10 13.5V9.5M10 6.5h.01"/>`),success:$(`<circle cx="10" cy="10" r="7.5"/><path d="m6.75 10 2.25 2.25 4.25-4.5"/>`),warning:$(`<path d="M8.6 3.4 2.4 14a1.6 1.6 0 0 0 1.4 2.4h12.4a1.6 1.6 0 0 0 1.4-2.4L11.4 3.4a1.6 1.6 0 0 0-2.8 0Z"/><path d="M10 7.5v3.25M10 13.5h.01"/>`),error:$(`<circle cx="10" cy="10" r="7.5"/><path d="M10 6.5v4M10 13.5h.01"/>`),copy:$(`<rect x="7" y="7" width="10" height="10" rx="2"/><path d="M13 7V5a2 2 0 0 0-2-2H5a2 2 0 0 0-2 2v6a2 2 0 0 0 2 2h2"/>`),check:$(`<path d="m5 10.5 3.2 3L15 7"/>`,2),calendar:$(`<rect x="3" y="4.5" width="14" height="12.5" rx="2"/><path d="M3 8.5h14M7 3v3M13 3v3"/>`),prev:$(`<path d="m12 5-5 5 5 5"/>`,1.7,!0),next:$(`<path d="m8 5 5 5-5 5"/>`,1.7,!0)};function re({id:e,label:t,required:n,optional:r,control:i}){return`<div class="k-field">${t?`<div class="k-field__label-row"><label class="k-label" for="${e}">${Z(t)}${n?`<span class="k-label__required" aria-hidden="true">*</span>`:``}${r?`<span class="k-label__optional">${Z(r)}</span>`:``}</label></div>`:``}${i}</div>`}function ie(e,t,n,r,i,a){if(e.querySelector(`:scope > .k-field__hint-row`)?.remove(),r?e.setAttribute(`data-invalid`,``):e.removeAttribute(`data-invalid`),r||i){let t=document.createElement(`div`);t.className=`k-field__hint-row`,t.innerHTML=`<div class="k-field__hints">${r?`<p class="k-hint k-hint--error" id="${n}-error">${Z(r)}</p>`:``}${i?`<p class="k-hint" id="${n}-hint">${Z(i)}</p>`:``}</div>`,e.append(t)}let o=[a,r?`${n}-error`:null,i?`${n}-hint`:null].filter(Boolean).join(` `);o?t.setAttribute(`aria-describedby`,o):t.removeAttribute(`aria-describedby`),r?t.setAttribute(`aria-invalid`,`true`):t.removeAttribute(`aria-invalid`);let s=t.closest(`.k-input, .k-select, .k-otp`);s?.classList.contains(`k-input`)&&(r?s.setAttribute(`data-state`,`invalid`):s.getAttribute(`data-state`)===`invalid`&&s.removeAttribute(`data-state`))}function ae(e,t,n){let r=e.querySelector(`:scope > input[type=hidden][data-kashi-value]`);t?(r||(r=document.createElement(`input`),r.type=`hidden`,r.dataset.kashiValue=``,e.append(r)),r.name=t,r.value=n):r?.remove()}export{t as A,D as C,i as D,x as E,r as O,C as S,T,ae as _,q as a,E as b,te as c,W as d,H as f,ie as g,V as h,Q as i,n as k,Z as l,K as m,ne as n,L as o,U as p,z as r,G as s,N as t,re as u,Y as v,S as w,y as x,w as y};
@@ -0,0 +1 @@
1
+ import{c as e,g as t,i as n,l as r,m as i,n as a,o,p as s,r as c,t as l,u,v as d}from"./base-DTQ50VdG.js";const f=e=>`<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"/>${e?`<path d="m3 3 14 14"/>`:``}</svg>`,p=[`name`,`placeholder`,`autocomplete`,`inputmode`,`maxlength`,`minlength`,`pattern`,`min`,`max`,`step`,`dir`,`spellcheck`];var m=class extends l{constructor(){super(...arguments),this.multiline=!1,this.key=d(`kashi-input`),this.text=``,this.revealed=!1,this.rendered=!1,this.valueSet=!1}connectedCallback(){!this.rendered&&!this.valueSet&&(this.text=this.getAttribute(`value`)??``),this.render()}attributeChangedCallback(e,t,n){this.rendered&&t!==n&&(e===`value`?this.value=n??``:(this.text=this.control.value,this.render()))}get value(){return this.rendered?this.control.value:this.text}set value(e){this.valueSet=!0,this.text=String(e??``),this.rendered&&(this.control.value=this.text,this.paint())}focus(e){this.control?.focus(e)}render(){let t=this.key,i=this.getAttribute(`aria-label`),a=this.getAttribute(`label`),o=this.getAttribute(`type`)??`text`,c=this.getAttribute(`size`),l=this.hasAttribute(`disabled`),d=p.map(e=>this.hasAttribute(e)?` ${e}="${r(this.getAttribute(e))}"`:``).join(``),f=`${this.hasAttribute(`required`)?` required`:``}${l?` disabled`:``}${this.hasAttribute(`readonly`)?` readonly`:``}${!a&&i?` aria-label="${r(i)}"`:``}`,m=this.multiline?`<textarea id="${t}" class="k-input__control" rows="${Number(this.getAttribute(`rows`))||4}"${d}${f}></textarea>`:`<input id="${t}" class="k-input__control" type="${r(o===`password`&&this.revealed?`text`:o)}"${d}${f}>`,h=`<div class="k-input${this.multiline?` k-input--textarea`:``}${n(this,`autoresize`)?` k-input--autoresize`:``}${c===`sm`||c===`lg`?` k-input--${c}`:``}" data-size="${c??`md`}"${l?` data-state="disabled"`:``}>${m}<span class="k-input__end"></span></div>`,g=this.getAttribute(`optional`);this.querySelector(`:scope > .k-field`)?.remove(),this.insertAdjacentHTML(`afterbegin`,u({id:t,label:a,required:this.hasAttribute(`required`),optional:g===null?null:g||s().common.optional,control:h})),this.control=this.querySelector(`.k-input__control`),this.control.value=this.text,this.control.addEventListener(`input`,()=>{this.paint(),e(this,`kashi-change`,{value:this.control.value})}),this.querySelector(`.k-input__end`).addEventListener(`click`,t=>{let n=t.target.closest(`button`);n&&(n.dataset.act===`clear`?(this.control.value=``,this.control.dispatchEvent(new Event(`input`,{bubbles:!0})),this.control.focus(),e(this,`kashi-clear`,{})):n.dataset.act===`reveal`&&(this.revealed=!this.revealed,this.control.type=this.revealed?`text`:`password`,this.paint(),n.focus()))}),this.rendered=!0,this.paint()}paint(){let e=this.control,a=e.value.length,o=this.hasAttribute(`disabled`)||this.hasAttribute(`readonly`),c=this.querySelector(`.k-input__end`),l=!this.multiline&&this.getAttribute(`type`)===`password`&&this.getAttribute(`revealable`)!==`false`;c.innerHTML=[n(this,`loading`)?'<span class="k-input__addon"><span class="k-spinner k-spinner--sm" role="status" aria-label="${esc(msg().input.checking)}"></span></span>':``,n(this,`clearable`)&&a>0&&!o?`<button type="button" class="k-input__action" data-act="clear" aria-label="${r(s().input.clear)}"><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></button>`:``,l?`<button type="button" class="k-input__action" data-act="reveal" aria-label="${r(this.revealed?s().input.hide:s().input.show)}" aria-pressed="${this.revealed}">${f(this.revealed)}</button>`:``].join(``),c.style.display=c.innerHTML?`contents`:`none`;let u=this.querySelector(`:scope > .k-field`),d=`${this.key}-count`;if(t(u,e,this.key,this.getAttribute(`error`),this.getAttribute(`hint`),n(this,`show-count`)?d:null),n(this,`show-count`)){let e=Number(this.getAttribute(`maxlength`))||0,t=u.querySelector(`:scope > .k-field__hint-row`);t||(t=document.createElement(`div`),t.className=`k-field__hint-row`,t.innerHTML=`<div class="k-field__hints"></div>`,u.append(t)),t.insertAdjacentHTML(`beforeend`,`<span class="k-counter" id="${d}"${e&&a>e?` data-over=""`:``}>${e?`${i(this,a)} / ${i(this,e)}`:i(this,a)}</span>`)}}};m.observedAttributes=[`label`,`hint`,`error`,`type`,`required`,`disabled`,`readonly`,`clearable`,`revealable`,`show-count`,`loading`,`size`,`optional`,`aria-label`,`value`,...p];var h=class extends m{constructor(){super(...arguments),this.multiline=!0}};h.observedAttributes=[...m.observedAttributes,`rows`,`autoresize`];var g=class extends l{constructor(){super(...arguments),this.box=null}connectedCallback(){c(()=>{if(!this.isConnected||this.box)return;let e=this.getAttribute(`remember`);e&&this.read(e)?this.hidden=!0:this.build()})}attributeChangedCallback(){this.box&&this.decorate()}read(e){try{return localStorage.getItem(`kashi-banner:${e}`)===`closed`}catch{return!1}}build(){let e=this.querySelector(`:scope > [slot='icon']`),t=[...this.querySelectorAll(`:scope > [slot='actions']`)],n=[...this.childNodes].filter(n=>n!==e&&!t.includes(n)),r=document.createElement(`div`);if(r.setAttribute(`role`,`region`),e){e.removeAttribute(`slot`);let t=document.createElement(`span`);t.className=`k-banner__icon`,t.setAttribute(`aria-hidden`,`true`),t.append(e),r.append(t)}let i=document.createElement(`p`);if(i.className=`k-banner__text`,i.append(...n),r.append(i),t.length){let e=document.createElement(`div`);e.className=`k-banner__actions`;for(let n of t)n.removeAttribute(`slot`),e.append(n);r.append(e)}this.replaceChildren(r),this.box=r,this.decorate()}decorate(){let e=this.box,t=this.getAttribute(`tone`);e.className=`k-banner${t&&t!==`neutral`?` k-banner--${t}`:``}${n(this,`flush`)?` k-banner--flush`:``}`,e.setAttribute(`aria-label`,this.getAttribute(`label`)??s().banner.label),e.querySelector(`.k-banner__close`)?.remove(),n(this,`dismissible`)&&(e.insertAdjacentHTML(`beforeend`,`<button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm k-banner__close" aria-label="${r(this.getAttribute(`close-label`)??s().banner.close)}">${a.close}</button>`),e.querySelector(`.k-banner__close`).addEventListener(`click`,()=>this.close()))}close(){let e=new CustomEvent(`kashi-close`,{bubbles:!0,cancelable:!0,detail:{}});if(!this.dispatchEvent(e))return;this.hidden=!0;let t=this.getAttribute(`remember`);if(t)try{localStorage.setItem(`kashi-banner:${t}`,`closed`)}catch{}}};g.observedAttributes=[`tone`,`flush`,`label`,`dismissible`,`close-label`],o(`kashi-input`,m,`block`),o(`kashi-textarea`,h,`block`),o(`kashi-banner`,g,`block`);export{g as KashiBanner,m as KashiInput,h as KashiTextarea};
@@ -0,0 +1,16 @@
1
+ import{A as e,C as t,E as n,S as r,T as i,_ as a,a as o,b as s,c,d as l,g as u,i as d,l as f,n as p,o as m,p as h,s as g,t as _,u as v,v as y,w as b,x,y as S}from"./base-DTQ50VdG.js";import{t as C}from"./holidays-DgbIAdlt.js";const w=(e,t)=>!!e&&!!t&&e.getFullYear()===t.getFullYear()&&e.getMonth()===t.getMonth()&&e.getDate()===t.getDate(),T=e=>new Date(e.getFullYear(),e.getMonth(),e.getDate()),E=(e,t)=>new Date(e.getFullYear(),e.getMonth(),e.getDate()+t),D=e=>`${e.getFullYear()}-${e.getMonth()+1}-${e.getDate()}`;function O(e,t){let{jy:r,jm:i,jd:a}=n(e),o=r*12+(i-1)+t,s=Math.floor(o/12),c=o-s*12+1;return b(s,c,Math.min(a,x(s,c)))}const k=e=>e?s(e.trim())??t(e):null;var A=class extends _{constructor(){super(...arguments),this.rangeValue=null,this.hover=null,this.selected=null,this.valueSet=!1,this.focused=T(/* @__PURE__ */ new Date),this.refocus=!1,this.rendered=!1,this.key=y(`kashi-cal`),this.onClick=e=>{let t=e.target.closest(`button`);if(!t||!this.contains(t))return;let n=t.dataset.nav;if(n)this.go(O(this.focused,n===`prev`?-1:1),!1);else if(t.dataset.today!==void 0){let e=/* @__PURE__ */ new Date;this.pick(new Date(e.getFullYear(),e.getMonth(),e.getDate()))}else if(t.dataset.day){let[e,n,r]=t.dataset.day.split(`-`).map(Number);this.pick(new Date(e,n-1,r))}},this.onSelect=e=>{let t=e.target;if(!t.matches?.(`.k-calendar__select`))return;e.stopPropagation();let{jy:r,jm:i,jd:a}=n(this.focused),o=t.dataset.part===`year`?Number(t.value):r,s=t.dataset.part===`month`?Number(t.value):i;this.go(b(o,s,Math.min(a,x(o,s))),!1),this.querySelector(`.k-calendar__select[data-part="${t.dataset.part}"]`)?.focus()},this.onKey=e=>{if(!e.target.classList?.contains(`k-calendar__day`))return;let t=getComputedStyle(this).direction===`rtl`,n=this.focused,i=r(n),a={ArrowLeft:()=>E(n,t?1:-1),ArrowRight:()=>E(n,t?-1:1),ArrowUp:()=>E(n,-7),ArrowDown:()=>E(n,7),Home:()=>E(n,-i),End:()=>E(n,6-i),PageUp:()=>O(n,e.shiftKey?-12:-1),PageDown:()=>O(n,e.shiftKey?12:1)};a[e.key]&&(e.preventDefault(),this.go(a[e.key]()))}}get range(){return this.rangeValue}set range(e){this.rangeValue=e,e?.start&&(this.focused=this.clamp(T(e.start))),this.rendered&&this.render()}connectedCallback(){if(!this.rendered){this.valueSet||(this.selected=k(this.getAttribute(`value`))),this.focused=this.clamp(T(this.selected??/* @__PURE__ */ new Date)),this.addEventListener(`click`,this.onClick),this.addEventListener(`keydown`,this.onKey),this.addEventListener(`change`,this.onSelect);let e=e=>{let t=e.target.closest?.(`.k-calendar__day`)?.dataset.day;if(!this.rangeValue?.start||this.rangeValue.end||!t)return;let[n,r,i]=t.split(`-`).map(Number);this.hover=new Date(n,r-1,i),this.paintRange()};this.addEventListener(`pointerover`,e),this.addEventListener(`focusin`,e)}this.rendered=!0,this.render()}attributeChangedCallback(e,t,n){this.rendered&&t!==n&&(e===`value`&&(this.selected=k(n),this.selected&&(this.focused=T(this.selected))),this.render())}get value(){return this.selected?i(this.selected):``}set value(e){this.valueSet=!0,this.selected=k(e??``),this.selected&&(this.focused=T(this.selected)),this.rendered&&this.render()}get date(){return this.selected}set date(e){this.value=e?i(e):``}focus(){this.querySelector(`.k-calendar__day[tabindex="0"]`)?.focus()}get min(){return k(this.getAttribute(`min`))}get max(){return k(this.getAttribute(`max`))}clamp(e){let t=this.min,n=this.max;return t&&e<t?T(t):n&&e>n?T(n):e}disabled(e){let t=this.min,n=this.max;return!!t&&e<t||!!n&&e>n||!!this.isDateDisabled?.(e)}holiday(e){return this.holidayOf?this.holidayOf(e)||null:d(this,`holidays`)?C(e,{locale:l()}):null}go(e,t=!0){this.focused=this.clamp(e),this.refocus=t,this.render()}pick(e){this.disabled(e)||(this.selected=e,this.focused=e,this.refocus=!0,this.render(),a(this,this.getAttribute(`name`),this.value),c(this,`kashi-change`,{value:this.value,date:e}))}paintRange(){let e=this.rangeValue;if(!e)return;let t=e.start?T(e.start):null,n=e.end?T(e.end):null,r=t&&!n&&this.hover?this.hover:null,[i,a]=t&&(n||r)?[t,n??r].sort((e,t)=>+e-t):[t,t];this.querySelectorAll(`td[data-date]`).forEach(e=>{let[t,r,o]=e.dataset.date.split(`-`).map(Number),s=new Date(t,r-1,o),c=!!i&&!!a&&s>=i&&s<=a;e.setAttribute(`aria-selected`,String(c)),e.toggleAttribute(`data-in-range`,c&&!!n),e.toggleAttribute(`data-preview`,c&&!n),e.toggleAttribute(`data-range-start`,!!i&&w(s,i)),e.toggleAttribute(`data-range-end`,!!a&&w(s,a))})}render(){let t=g(this),i=n=>t===`fa`?e(n):String(n),s=h(),c=s.calendar,{months:u,weekdays:d,weekdaysShort:m,friday:_}=o(),v=T(/* @__PURE__ */ new Date),{jy:y,jm:C}=n(this.focused),O=b(y,C,1),k=x(y,C),A=[...Array(r(O)).fill(null),...Array.from({length:k},(e,t)=>E(O,t))];for(;A.length%7;)A.push(null);let j=this.min,M=this.max,N=j?n(j).jy:n(v).jy-100,P=M?n(M).jy:n(v).jy+20,F=Array.from({length:Math.max(0,P-N+1)},(e,t)=>N+t);F.includes(y)||F.push(y),F.sort((e,t)=>e-t);let I=!!j&&O<=T(j),L=!!M&&b(y,C,k)>=T(M),R=[];for(let e=0;e<A.length;e+=7)R.push(`<tr>${A.slice(e,e+7).map(e=>{if(!e)return`<td role="gridcell"></td>`;let r=this.holiday(e),a=S(e,{style:`full`,digits:t,locale:l()})+(r?`${s.common.list}${c.holiday}${r===_?``:`: ${r}`}`:``);return`<td role="gridcell" data-date="${D(e)}" aria-selected="${w(e,this.selected)}"><button type="button" class="k-calendar__day" data-day="${D(e)}" tabindex="${w(e,this.focused)?0:-1}" aria-label="${f(a)}"${r&&r!==_?` title="${f(r)}"`:``}${r?` data-holiday=""`:``}${w(e,v)?` aria-current="date"`:``}${this.disabled(e)?` aria-disabled="true"`:``}>${i(n(e).jd)}</button></td>`}).join(``)}</tr>`);let z=this.getAttribute(`today-label`);this.innerHTML=`<div class="k-calendar" role="group" aria-label="${f(this.getAttribute(`label`)??c.label)}">
2
+ <div class="k-calendar__header">
3
+ <button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm" data-nav="prev" aria-label="${f(c.prevMonth)}"${I?` disabled`:``}>${p.prev}</button>
4
+ <div class="k-calendar__selects">
5
+ <select class="k-calendar__select" data-part="month" aria-label="${f(c.month)}">${u.map((e,t)=>`<option value="${t+1}"${t+1===C?` selected`:``}>${e}</option>`).join(``)}</select>
6
+ <select class="k-calendar__select" data-part="year" aria-label="${f(c.year)}">${F.map(e=>`<option value="${e}"${e===y?` selected`:``}>${i(e)}</option>`).join(``)}</select>
7
+ </div>
8
+ <button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm" data-nav="next" aria-label="${f(c.nextMonth)}"${L?` disabled`:``}>${p.next}</button>
9
+ </div>
10
+ <h2 class="k-sr-only" id="${this.key}-title" aria-live="polite">${u[C-1]} ${i(y)}</h2>
11
+ <table class="k-calendar__grid" role="grid" aria-labelledby="${this.key}-title">
12
+ <thead><tr>${m.map((e,t)=>`<th scope="col" abbr="${d[t]}">${e}</th>`).join(``)}</tr></thead>
13
+ <tbody>${R.join(``)}</tbody>
14
+ </table>
15
+ ${z?`<div class="k-calendar__footer"><button type="button" class="k-btn k-btn--link" data-today>${f(z)}</button></div>`:``}
16
+ </div>`,a(this,this.getAttribute(`name`),this.value),this.paintRange(),this.refocus&&(this.refocus=!1,this.querySelector(`[data-day="${D(this.focused)}"]`)?.focus())}};A.observedAttributes=[`value`,`min`,`max`,`digits`,`holidays`,`label`,`today-label`,`name`];var j=class extends _{constructor(){super(...arguments),this.selected=null,this.valueSet=!1,this.invalid=!1,this.rendered=!1,this.key=y(`kashi-date`),this.pop=null,this.onOutside=e=>{this.contains(e.target)||this.close(!1)}}connectedCallback(){!this.rendered&&!this.valueSet&&(this.selected=k(this.getAttribute(`value`))),this.render()}disconnectedCallback(){this.close(!1)}attributeChangedCallback(e,t,n){this.rendered&&t!==n&&(e===`value`?(this.selected=k(n),this.invalid=!1,this.paint()):this.render())}get value(){return this.selected?i(this.selected):``}set value(e){this.valueSet=!0,this.selected=k(e??``),this.invalid=!1,this.rendered&&this.paint()}get date(){return this.selected}set date(e){this.value=e?i(e):``}focus(e){this.input?.focus(e)}get digits(){return g(this)}fmt(e){return e?S(e,{digits:this.digits}):``}render(){let e=this.key,t=this.getAttribute(`aria-label`),n=this.hasAttribute(`label`)?this.getAttribute(`label`):t?null:h().datePicker.label,r=this.hasAttribute(`required`),i=this.hasAttribute(`disabled`),a=this.getAttribute(`placeholder`)??(this.digits===`fa`?`۱۴۰۳/۰۱/۰۱`:`1403/01/01`);this.close(!1),this.querySelector(`:scope > .k-datepicker`)?.remove();let o=`<div class="k-input"${i?` data-state="disabled"`:``}><input id="${e}" class="k-input__control" type="text" dir="ltr" autocomplete="off" placeholder="${f(a)}"${r?` required`:``}${i?` disabled`:``}${!n&&t?` aria-label="${f(t)}"`:``}><span class="k-input__addon"><button type="button" class="k-btn k-btn--tertiary k-btn--icon k-btn--sm k-datepicker__toggle" aria-haspopup="dialog" aria-expanded="false"${i?` disabled`:``}>${p.calendar}</button></span></div>`;this.insertAdjacentHTML(`afterbegin`,`<div class="k-datepicker">${v({id:e,label:n,required:r,control:o})}</div>`),this.input=this.querySelector(`input.k-input__control`),this.toggle=this.querySelector(`.k-datepicker__toggle`),this.input.addEventListener(`blur`,()=>this.commitText()),this.input.addEventListener(`keydown`,e=>{e.key===`Enter`&&this.commitText()}),this.toggle.addEventListener(`click`,()=>this.pop?this.close():this.open()),this.rendered=!0,this.paint()}paint(){let e=this.fmt(this.selected);!this.invalid&&this.input.value!==e&&(this.input.value=e);let t=this.getAttribute(`open-label`)??h().datePicker.open;this.toggle.setAttribute(`aria-label`,this.selected?`${t}${h().common.list}${S(this.selected,{style:`full`,digits:this.digits,locale:l()})}`:t);let n=this.getAttribute(`invalid-message`)??h().datePicker.invalid;this.input.setCustomValidity(this.invalid?n:``),u(this.querySelector(`.k-field`),this.input,this.key,this.getAttribute(`error`)||(this.invalid?n:null),this.getAttribute(`hint`)),a(this,this.getAttribute(`name`),this.value)}commitText(){let e=this.input.value.trim();if(!e)return this.commit(null);let n=t(e),r=k(this.getAttribute(`min`)),i=k(this.getAttribute(`max`));n&&!(r&&n<r)&&!(i&&n>i)&&!this.isDateDisabled?.(n)?this.commit(n):(this.invalid=!0,this.paint())}commit(e){let t=!w(e,this.selected)||e===null!=(this.selected===null);this.selected=e,this.invalid=!1,this.input.value=this.fmt(e),this.paint(),t&&c(this,`kashi-change`,{value:this.value,date:e})}open(){if(this.pop||this.hasAttribute(`disabled`))return;let e=this.querySelector(`.k-datepicker`),t=this.querySelector(`.k-input`),n=document.createElement(`div`);n.className=`k-datepicker__popover`,n.id=`${this.key}-calendar`,n.setAttribute(`role`,`dialog`),n.setAttribute(`aria-label`,this.getAttribute(`open-label`)??h().datePicker.open),n.style.insetBlockStart=`${t.offsetTop+t.offsetHeight+6}px`;let r=document.createElement(`kashi-calendar`);for(let e of[`min`,`max`,`digits`,`holidays`]){let t=this.getAttribute(e);t!==null&&r.setAttribute(e,t)}this.selected&&r.setAttribute(`value`,i(this.selected)),r.setAttribute(`today-label`,this.getAttribute(`today-label`)??h().common.today),r.isDateDisabled=this.isDateDisabled,r.addEventListener(`kashi-change`,e=>{e.stopPropagation(),this.commit(e.detail.date),this.close()}),n.addEventListener(`keydown`,e=>{e.key===`Escape`&&(e.stopPropagation(),this.close())}),n.addEventListener(`focusout`,e=>{let t=e.relatedTarget;t&&!this.contains(t)&&this.close(!1)}),n.append(r),e.append(n),this.pop=n,this.toggle.setAttribute(`aria-expanded`,`true`),this.toggle.setAttribute(`aria-controls`,n.id),document.addEventListener(`pointerdown`,this.onOutside),r.focus()}close(e=!0){this.pop&&(this.pop.remove(),this.pop=null,document.removeEventListener(`pointerdown`,this.onOutside),this.toggle.setAttribute(`aria-expanded`,`false`),this.toggle.removeAttribute(`aria-controls`),e&&this.toggle.focus())}};j.observedAttributes=[`label`,`hint`,`error`,`required`,`disabled`,`value`,`min`,`max`,`digits`,`holidays`,`name`,`placeholder`,`invalid-message`,`aria-label`],m(`kashi-calendar`,A,`block`),m(`kashi-date-picker`,j,`block`);export{A as KashiCalendar,j as KashiDatePicker};