@diniz/webcomponents 1.0.7 → 1.1.3

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.
@@ -0,0 +1,1193 @@
1
+ var x = Object.defineProperty;
2
+ var y = (u, s, t) => s in u ? x(u, s, { enumerable: !0, configurable: !0, writable: !0, value: t }) : u[s] = t;
3
+ var c = (u, s, t) => y(u, typeof s != "symbol" ? s + "" : s, t);
4
+ import k from "feather-icons";
5
+ function w(u) {
6
+ let s = u;
7
+ const t = /* @__PURE__ */ new Set();
8
+ return {
9
+ get: () => s,
10
+ set: (e) => {
11
+ Object.is(s, e) || (s = e, t.forEach((a) => a(s)));
12
+ },
13
+ subscribe: (e) => (t.add(e), () => t.delete(e))
14
+ };
15
+ }
16
+ class b extends HTMLElement {
17
+ constructor() {
18
+ super();
19
+ c(this, "state");
20
+ c(this, "signalUnsubs");
21
+ this.attachShadow({ mode: "open" }), this.state = {}, this.signalUnsubs = /* @__PURE__ */ new Set();
22
+ }
23
+ useSignal(t) {
24
+ const e = w(t), a = e.subscribe(() => this.render());
25
+ return this.signalUnsubs.add(a), e;
26
+ }
27
+ setState(t) {
28
+ this.state = { ...this.state, ...t }, this.render();
29
+ }
30
+ connectedCallback() {
31
+ this.render();
32
+ }
33
+ disconnectedCallback() {
34
+ this.signalUnsubs.forEach((t) => t()), this.signalUnsubs.clear();
35
+ }
36
+ render() {
37
+ }
38
+ }
39
+ const g = ':root{--color-primary: #24ec71;--color-primary-contrast: #ffffff;--color-ink: #0f172a;--color-muted: #f1f5f9;--color-header: #f8fafc;--color-border: #e2e8f0;--color-border-strong: #cbd5f5;--color-nav-bg: #222222;--color-nav-text: #ffffff;--shadow-primary: 0 8px 18px rgba(31, 111, 235, .25);--focus-ring: #9ec5ff;--radius-pill: 999px;--radius-md: 12px;--color-page-bg: #ffffff;--color-page-text: #0f172a}body{background:var(--color-page-bg);color:var(--color-page-text);margin:0;font-family:Segoe UI,system-ui,-apple-system,sans-serif}:host([data-ui="button"]){display:inline-block}:host([data-ui="table"]){display:block}:host([data-ui="layout"]){display:block}:host([data-ui="sidebar"]){display:block}.btn{align-items:center;border:1px solid transparent;border-radius:var(--radius-pill);cursor:pointer;display:inline-flex;font-family:inherit;font-size:.95rem;font-weight:600;gap:.5rem;line-height:1;padding:.65rem 1.2rem;transition:transform .12s ease,box-shadow .12s ease,background-color .12s ease}.btn:focus-visible{outline:3px solid var(--focus-ring);outline-offset:2px}.btn:active:not(:disabled){transform:translateY(1px)}.btn:disabled{cursor:not-allowed;opacity:.6}.btn.primary{background:var(--color-primary);color:var(--color-primary-contrast);box-shadow:var(--shadow-primary)}.btn.secondary{background:var(--color-muted);color:var(--color-ink);border-color:var(--color-border-strong)}.btn.ghost{background:transparent;color:var(--color-primary);border-color:var(--color-border-strong)}.btn.danger{background:#ef4444;color:#fff;border-color:#ef4444}.btn-danger:hover{background:#6626dc;border-color:#dc2626}.btn.has-icon{line-height:1.2}.btn .btn-icon{width:18px;height:18px;flex-shrink:0}.btn .btn-icon svg{width:100%;height:100%}.btn.icon-only{padding:.65rem;aspect-ratio:1}.btn.icon-only.sm{padding:.45rem}.btn.icon-only.lg{padding:.8rem}.btn.sm .btn-icon{width:14px;height:14px}.btn.lg .btn-icon{width:22px;height:22px}.btn.sm{font-size:.85rem;padding:.45rem .9rem;box-shadow:0 4px 12px #a7124426}.btn.md{font-size:.95rem;padding:.65rem 1.2rem}.btn.lg{font-size:1.05rem;padding:.8rem 1.5rem}.table-wrap{border:1px solid var(--color-border);border-radius:var(--radius-md);overflow:hidden}table{border-collapse:collapse;width:100%}thead{background:var(--color-header)}th,td{padding:.75rem 1rem;text-align:left;border-bottom:1px solid var(--color-border);font-size:.95rem;border-right:1px solid var(--color-border)}tr:last-child td{border-bottom:none}.align-left{text-align:left}.align-center{text-align:center}.align-right{text-align:right}.actions-cell{display:flex;gap:.5rem;justify-content:center}.app-nav{padding:1rem;background:var(--color-nav-bg);color:var(--color-nav-text)}.app-link{color:var(--color-nav-text);margin-right:1rem;text-decoration:none}.signal-demo,.theme-toggle{margin-top:16px;display:flex;align-items:center;gap:12px}.data-table{margin-top:15px}.dashboard-layout{display:grid;grid-template-columns:220px minmax(0,1fr);gap:24px;padding:24px}.dashboard-sidebar{background:var(--color-muted);border:1px solid var(--color-border);border-radius:var(--radius-md);padding:18px}.sidebar-title{margin:0 0 12px;font-size:1rem}.sidebar-nav{display:flex;flex-direction:column;gap:10px}.sidebar-link{color:var(--color-ink);text-decoration:none;font-weight:600}.dashboard-main{display:flex;flex-direction:column;gap:12px}.dashboard-actions{display:flex;flex-wrap:wrap;gap:12px}@media (max-width: 900px){.dashboard-layout{grid-template-columns:1fr}}:host([data-ui="input"]){display:block}.input-wrapper{display:flex;flex-direction:column;gap:.35rem}.input-label{font-size:.9rem;font-weight:600;color:var(--color-ink)}.input-field{padding:.6rem .85rem;font-size:.95rem;font-family:inherit;border:1.5px solid var(--color-border);border-radius:6px;background:var(--color-page-bg);color:var(--color-page-text);transition:border-color .15s ease,box-shadow .15s ease;outline:none}.input-field::placeholder{color:#94a3b8}.input-field:focus{border-color:var(--color-primary);box-shadow:0 0 0 3px #24ec7126}.input-field:disabled{background:var(--color-muted);cursor:not-allowed;opacity:.7}.input-wrapper.invalid .input-field{border-color:#ef4444}.input-wrapper.invalid .input-field:focus{box-shadow:0 0 0 3px #ef444426}.input-error{font-size:.8rem;color:#ef4444;display:flex;align-items:center;gap:.25rem}.input-error.hidden{display:none}:host([data-ui="checkbox"]){display:inline-flex;align-items:center;cursor:pointer;-webkit-user-select:none;user-select:none}:host([data-ui="checkbox"][disabled]){cursor:not-allowed;opacity:.6}.checkbox-container{display:inline-flex;align-items:center;gap:.75rem}.checkbox-box{position:relative;display:inline-flex;align-items:center;justify-content:center;border:2px solid var(--color-border, #cbd5e1);border-radius:var(--radius-sm, 4px);background:#fff;transition:all .2s;flex-shrink:0;box-sizing:border-box}.checkbox-box.size-sm{min-width:16px;max-width:16px;min-height:16px;max-height:16px}.checkbox-box.size-md{min-width:18px;max-width:18px;min-height:18px;max-height:18px}.checkbox-box.size-lg{min-width:20px;max-width:20px;min-height:20px;max-height:20px}.checkbox-box:hover:not(.disabled){border-color:var(--color-primary, #24ec71)}.checkbox-box.checked,.checkbox-box.indeterminate{background:var(--color-primary, #24ec71);border-color:var(--color-primary, #24ec71)}.checkbox-box.disabled{background:var(--color-muted, #f1f5f9);cursor:not-allowed}.checkbox-icon{display:none;color:#fff;position:absolute}.checkbox-box.checked .checkbox-icon.check,.checkbox-box.indeterminate .checkbox-icon.minus{display:block}.checkbox-icon.check{width:12px;height:12px}.checkbox-icon.minus{width:10px;height:10px}.checkbox-label{font-size:.95rem;color:var(--color-ink, #0f172a);line-height:1.5}.checkbox-container.size-sm .checkbox-label{font-size:.875rem}.checkbox-container.size-lg .checkbox-label{font-size:1rem}input[type=checkbox]{position:absolute;opacity:0;pointer-events:none}.modal-backdrop{display:none;position:fixed;top:0;right:0;bottom:0;left:0;background:#00000080;-webkit-backdrop-filter:blur(4px);backdrop-filter:blur(4px);z-index:9999;animation:fadeIn .2s ease-out}.modal-backdrop.open{display:flex;align-items:center;justify-content:center;padding:1rem}.modal-content{background:var(--color-surface, white);border-radius:var(--radius-lg, 16px);box-shadow:0 20px 25px -5px #0000001a,0 10px 10px -5px #0000000a;max-height:90vh;display:flex;flex-direction:column;width:100%;animation:slideUp .2s ease-out}.modal-content.sm{max-width:400px}.modal-content.md{max-width:600px}.modal-content.lg{max-width:800px}.modal-content.xl{max-width:1200px}.modal-content.full{max-width:95vw}.modal-header{padding:1.5rem;border-bottom:1px solid var(--color-border, #e2e8f0);display:flex;align-items:center;justify-content:space-between}.modal-title{font-size:1.25rem;font-weight:600;color:var(--color-ink, #0f172a);margin:0}.modal-close{background:none;border:none;cursor:pointer;padding:.5rem;display:flex;align-items:center;justify-content:center;border-radius:var(--radius-md, 8px);color:var(--color-text-muted, #64748b);transition:all .2s}.modal-close:hover{background:var(--color-muted, #f1f5f9);color:var(--color-ink, #0f172a)}.modal-body{padding:1.5rem;overflow-y:auto;flex:1}.modal-footer{padding:1.5rem;border-top:1px solid var(--color-border, #e2e8f0);display:flex;gap:.75rem;justify-content:flex-end}@keyframes fadeIn{0%{opacity:0}to{opacity:1}}@keyframes slideUp{0%{opacity:0;transform:translateY(20px)}to{opacity:1;transform:translateY(0)}}:host([data-ui="select"]){display:block;width:90%}.select-container{position:relative;width:100%}.select-label{display:block;margin-bottom:.5rem;font-size:.875rem;font-weight:500;color:var(--color-ink, #0f172a)}.select-trigger{width:100%;padding:.625rem 1rem;background:#fff;border:1px solid var(--color-border, #e2e8f0);border-radius:var(--radius-md, 8px);display:flex;align-items:center;justify-content:space-between;cursor:pointer;transition:all .2s;font-size:.95rem;color:var(--color-ink, #0f172a)}.select-trigger:hover:not(:disabled){border-color:var(--color-primary, #24ec71)}.select-trigger:focus{outline:none;border-color:var(--color-primary, #24ec71);box-shadow:0 0 0 3px #24ec711a}.select-trigger:disabled{background:var(--color-muted, #f1f5f9);cursor:not-allowed;opacity:.6}.select-trigger.open{border-color:var(--color-primary, #24ec71)}.select-placeholder{color:var(--color-text-muted, #94a3b8);flex:1;text-align:left}.select-placeholder.has-selection{color:var(--color-ink, #0f172a)}.select-arrow{display:flex;transition:transform .2s;color:var(--color-text-muted, #64748b)}.select-arrow.open{transform:rotate(180deg)}.select-dropdown{position:absolute;top:calc(100% + .25rem);left:0;right:0;background:#fff;border:1px solid var(--color-border, #e2e8f0);border-radius:var(--radius-md, 8px);box-shadow:0 10px 15px -3px #0000001a,0 4px 6px -2px #0000000d;max-height:300px;overflow-y:auto;z-index:1000;display:none;animation:slideDown .15s ease-out}.select-dropdown.open{display:block}.select-search{width:100%;padding:.625rem 1rem;border:none;border-bottom:1px solid var(--color-border, #e2e8f0);font-size:.95rem;outline:none}.select-search:focus{background:var(--color-muted, #f1f5f9)}.select-option{padding:.625rem 1rem;cursor:pointer;transition:background .15s;color:var(--color-ink, #0f172a);font-size:.95rem}.select-option:hover:not(.disabled){background:var(--color-muted, #f1f5f9)}.select-option.selected{background:#24ec711a;color:var(--color-primary, #24ec71);font-weight:500}.select-option.disabled{opacity:.5;cursor:not-allowed}.select-empty{padding:1rem;text-align:center;color:var(--color-text-muted, #94a3b8);font-size:.875rem}@keyframes slideDown{0%{opacity:0;transform:translateY(-8px)}to{opacity:1;transform:translateY(0)}}:host([data-ui="pagination"]){display:block}.pagination-container{display:flex;align-items:center;justify-content:space-between;gap:1rem;flex-wrap:wrap}.pagination-info{font-size:.9rem;color:var(--color-ink);opacity:.7}.pagination{display:flex;align-items:center;gap:.25rem}.page-btn{min-width:2.5rem;height:2.5rem;padding:.5rem;border:1px solid var(--color-border);background:#fff;color:var(--color-ink);font-size:.9rem;font-weight:500;border-radius:6px;cursor:pointer;transition:all .2s ease;display:flex;align-items:center;justify-content:center}.page-btn:hover:not(:disabled):not(.active){background:var(--color-muted);border-color:var(--color-border-strong)}.page-btn:disabled{opacity:.4;cursor:not-allowed}.page-btn.active{background:var(--color-primary);color:var(--color-primary-contrast);border-color:var(--color-primary);font-weight:600}.page-btn.ellipsis{border:none;background:transparent;cursor:default;pointer-events:none}.nav-btn{padding:.5rem .75rem}.nav-btn svg{width:16px;height:16px}:host([data-ui="date-picker"]){display:inline-block;width:100%;max-width:300px}.date-picker-container{position:relative;display:flex;flex-direction:column;gap:.5rem}.date-input-wrapper{position:relative;display:flex;align-items:center;border:1px solid var(--color-border);border-radius:var(--radius-md);background:#fff;transition:all .2s ease}.date-input-wrapper:hover:not(.disabled){border-color:var(--color-border-strong)}.date-input-wrapper:focus-within{border-color:var(--color-primary);box-shadow:0 0 0 3px #24ec711a;outline:none}.date-input-wrapper.disabled{background:var(--color-muted);cursor:not-allowed;opacity:.6}.formatted-input{flex:1;border:none;padding:.75rem 1rem;font-size:.95rem;font-family:inherit;background:transparent;color:var(--color-ink);outline:none}.formatted-input:disabled{cursor:not-allowed;color:var(--color-ink);opacity:.7}.formatted-input::placeholder{color:#94a3b8;opacity:.7}.formatted-input.invalid{color:#dc2626}.hidden-date-input{position:absolute;opacity:0;pointer-events:none;width:0;height:0}.calendar-btn{padding:.5rem;margin-right:.5rem;border:none;background:transparent;cursor:pointer;display:flex;align-items:center;justify-content:center;color:var(--color-ink);opacity:.6;transition:all .2s ease;border-radius:6px}.calendar-btn:hover:not(:disabled){background:var(--color-muted);opacity:1}.calendar-btn:disabled{cursor:not-allowed;opacity:.3}.calendar-icon{width:20px;height:20px}.format-label{font-size:.75rem;color:var(--color-ink);opacity:.6;padding:0 .25rem;font-weight:500}';
40
+ class $ extends b {
41
+ connectedCallback() {
42
+ this.setAttribute("data-ui", "button"), super.connectedCallback();
43
+ }
44
+ static get observedAttributes() {
45
+ return ["variant", "size", "disabled", "type", "icon", "icon-position"];
46
+ }
47
+ attributeChangedCallback() {
48
+ this.render();
49
+ }
50
+ getVariant() {
51
+ const s = this.getAttribute("variant");
52
+ return s === "secondary" || s === "ghost" || s === "danger" ? s : "primary";
53
+ }
54
+ getSize() {
55
+ const s = this.getAttribute("size");
56
+ return s === "sm" || s === "lg" ? s : "md";
57
+ }
58
+ getType() {
59
+ return this.getAttribute("type") ?? "button";
60
+ }
61
+ getIcon() {
62
+ var a;
63
+ const s = this.getAttribute("icon");
64
+ if (!s) return null;
65
+ const t = s.trim();
66
+ return { html: `<span class="btn-icon">${((a = k.icons[t]) == null ? void 0 : a.toSvg()) || ""}</span>`, name: t };
67
+ }
68
+ getIconPosition() {
69
+ return this.getAttribute("icon-position") === "right" ? "right" : "left";
70
+ }
71
+ render() {
72
+ const s = this.getVariant(), t = this.getSize(), e = this.hasAttribute("disabled"), a = this.getType(), i = this.getIcon(), r = this.getIconPosition(), o = i !== null, n = i ? i.html : "", l = this.innerHTML.trim(), h = o && !l;
73
+ let p;
74
+ o && l ? p = r === "left" ? `${n}<span>${l}</span>` : `<span>${l}</span>${n}` : o ? p = n : p = l, this.shadowRoot.innerHTML = `
75
+ <style>${g}</style>
76
+ <button
77
+ part="button"
78
+ class="btn ${s} ${t}${o ? " has-icon" : ""}${h ? " icon-only" : ""}"
79
+ type="${a}"
80
+ ${e ? "disabled" : ""}
81
+ >
82
+ ${p}
83
+ </button>
84
+ `;
85
+ }
86
+ }
87
+ customElements.define("ui-button", $);
88
+ class A extends b {
89
+ constructor() {
90
+ super();
91
+ c(this, "inputEl", null);
92
+ c(this, "customValidator", null);
93
+ c(this, "validationRule", null);
94
+ this.state = {
95
+ value: "",
96
+ valid: !0,
97
+ touched: !1,
98
+ error: ""
99
+ };
100
+ }
101
+ static get observedAttributes() {
102
+ return ["type", "label", "placeholder", "required", "pattern", "minlength", "maxlength", "min", "max", "error-message", "custom-error", "disabled", "name", "validate"];
103
+ }
104
+ connectedCallback() {
105
+ this.setAttribute("data-ui", "input"), super.connectedCallback();
106
+ }
107
+ attributeChangedCallback(t, e, a) {
108
+ e !== a && t !== "value" && this.render();
109
+ }
110
+ setCustomValidator(t) {
111
+ this.customValidator = t, this.validate();
112
+ }
113
+ get value() {
114
+ return this.state.value;
115
+ }
116
+ set value(t) {
117
+ this.state.value = t, this.inputEl && this.inputEl.value !== t && (this.inputEl.value = t), this.validate();
118
+ }
119
+ get isValid() {
120
+ return this.state.valid;
121
+ }
122
+ checkValidity() {
123
+ return this.state.touched = !0, this.validate();
124
+ }
125
+ reportValidity() {
126
+ this.state.touched = !0;
127
+ const t = this.validate();
128
+ return this.updateErrorDisplay(), !t && this.inputEl && this.inputEl.focus(), t;
129
+ }
130
+ getType() {
131
+ const t = this.getAttribute("type");
132
+ return ["text", "email", "password", "number", "tel", "url"].includes(t || "") ? t : "text";
133
+ }
134
+ getLabel() {
135
+ return this.getAttribute("label") || "";
136
+ }
137
+ getPlaceholder() {
138
+ return this.getAttribute("placeholder") || "";
139
+ }
140
+ getName() {
141
+ return this.getAttribute("name") || "";
142
+ }
143
+ getErrorMessage() {
144
+ return this.state.error ? this.state.error : this.getAttribute("error-message") || this.getAttribute("custom-error") || "";
145
+ }
146
+ getCustomError() {
147
+ return this.getAttribute("custom-error") || "";
148
+ }
149
+ parseValidationRule(t) {
150
+ return t.startsWith("email:") ? { type: "emailDomain", domain: t.slice(6) } : t.startsWith("match:") ? { type: "match", selector: t.slice(6) } : t.startsWith("min:") ? { type: "minLength", length: parseInt(t.slice(4), 10) } : t.startsWith("max:") ? { type: "maxLength", length: parseInt(t.slice(4), 10) } : t.startsWith("regex:") ? { type: "regex", pattern: t.slice(6) } : null;
151
+ }
152
+ applyValidationRule(t) {
153
+ const e = this.state.value;
154
+ switch (t.type) {
155
+ case "emailDomain":
156
+ if (!e.endsWith(`@${t.domain}`))
157
+ return { valid: !1, message: `Must end with @${t.domain}` };
158
+ break;
159
+ case "match":
160
+ const a = document.querySelector(t.selector);
161
+ if (a && e !== a.value)
162
+ return { valid: !1, message: "Values do not match" };
163
+ break;
164
+ case "minLength":
165
+ if (e.length < t.length)
166
+ return { valid: !1, message: `Must be at least ${t.length} characters` };
167
+ break;
168
+ case "maxLength":
169
+ if (e.length > t.length)
170
+ return { valid: !1, message: `Must be no more than ${t.length} characters` };
171
+ break;
172
+ case "regex":
173
+ try {
174
+ if (!new RegExp(t.pattern).test(e))
175
+ return { valid: !1, message: "Invalid format" };
176
+ } catch {
177
+ return { valid: !1, message: "Invalid validation pattern" };
178
+ }
179
+ break;
180
+ }
181
+ return { valid: !0 };
182
+ }
183
+ validate() {
184
+ if (!this.inputEl) return !0;
185
+ const t = this.getAttribute("validate");
186
+ if (t && (this.validationRule || (this.validationRule = this.parseValidationRule(t)), this.validationRule)) {
187
+ const e = this.applyValidationRule(this.validationRule);
188
+ return this.state.valid = e.valid, !e.valid && e.message && (this.state.error = e.message), this.state.valid;
189
+ }
190
+ if (this.customValidator) {
191
+ const e = this.customValidator(this.state.value, this.inputEl);
192
+ this.state.valid = e.valid, !e.valid && e.message && (this.state.error = e.message);
193
+ } else {
194
+ const e = this.inputEl.checkValidity();
195
+ this.state.valid = e, !e && this.state.touched && (this.state.error = this.inputEl.validationMessage || this.getErrorMessage()), e && (this.state.error = "");
196
+ }
197
+ return this.state.valid;
198
+ }
199
+ handleInput(t) {
200
+ const e = t.target;
201
+ this.state.value = e.value, this.state.touched = !0, this.validate(), this.updateErrorDisplay();
202
+ }
203
+ handleBlur() {
204
+ this.state.touched = !0, this.validate(), this.updateErrorDisplay();
205
+ }
206
+ updateErrorDisplay() {
207
+ if (!this.inputEl) return;
208
+ const t = this.shadowRoot.querySelector(".input-error"), e = this.shadowRoot.querySelector(".input-wrapper"), a = this.getName();
209
+ e && e.classList.toggle("invalid", !this.state.valid && this.state.touched), t && (!this.state.valid && this.state.touched && this.state.error ? (t.textContent = this.state.error, t.classList.remove("hidden")) : t.classList.add("hidden")), this.inputEl.setAttribute("aria-invalid", String(!this.state.valid && this.state.touched)), a && this.inputEl.setAttribute("aria-describedby", `${a}-error`);
210
+ }
211
+ needsRender() {
212
+ return this.hasAttribute("type") || this.hasAttribute("label") || this.hasAttribute("placeholder") || this.hasAttribute("required") || this.hasAttribute("pattern") || this.hasAttribute("disabled") || this.hasAttribute("name") || this.hasAttribute("minlength") || this.hasAttribute("maxlength") || this.hasAttribute("min") || this.hasAttribute("max") || this.hasAttribute("error-message") || this.hasAttribute("custom-error") || this.hasAttribute("validate");
213
+ }
214
+ render() {
215
+ const t = this.getType(), e = this.getLabel(), a = this.getPlaceholder(), i = this.getName(), r = this.getErrorMessage(), o = this.hasAttribute("required"), n = this.getAttribute("pattern"), l = this.getAttribute("minlength"), h = this.getAttribute("maxlength"), p = this.getAttribute("min"), d = this.getAttribute("max"), m = this.hasAttribute("disabled"), f = !this.state.valid && this.state.touched, v = e !== "";
216
+ this.shadowRoot.innerHTML = `
217
+ <style>${g}</style>
218
+ <div class="input-wrapper${f ? " invalid" : ""}${m ? " disabled" : ""}">
219
+ ${v ? `<label class="input-label">${e}${o ? " *" : ""}</label>` : ""}
220
+ <input
221
+ part="input"
222
+ class="input-field"
223
+ type="${t}"
224
+ placeholder="${a}"
225
+ name="${i}"
226
+ .value="${this.state.value}"
227
+ ${o ? "required" : ""}
228
+ ${n ? `pattern="${n}"` : ""}
229
+ ${l ? `minlength="${l}"` : ""}
230
+ ${h ? `maxlength="${h}"` : ""}
231
+ ${p ? `min="${p}"` : ""}
232
+ ${d ? `max="${d}"` : ""}
233
+ ${m ? "disabled" : ""}
234
+ aria-invalid="${f}"
235
+ aria-describedby="${i}-error"
236
+ />
237
+ <span class="input-error${f && r ? "" : " hidden"}" id="${i}-error" role="alert">${r}</span>
238
+ </div>
239
+ `, this.inputEl = this.shadowRoot.querySelector(".input-field"), this.inputEl && (this.inputEl.addEventListener("input", this.handleInput.bind(this)), this.inputEl.addEventListener("blur", this.handleBlur.bind(this)));
240
+ }
241
+ }
242
+ customElements.define("ui-input", A);
243
+ class E extends b {
244
+ constructor() {
245
+ super(...arguments);
246
+ c(this, "columns", []);
247
+ c(this, "rows", []);
248
+ }
249
+ connectedCallback() {
250
+ this.setAttribute("data-ui", "table"), super.connectedCallback();
251
+ }
252
+ set data(t) {
253
+ this.columns = t.columns, this.rows = t.rows, this.render();
254
+ }
255
+ get data() {
256
+ return { columns: this.columns, rows: this.rows };
257
+ }
258
+ render() {
259
+ const t = this.columns.filter((i) => i.visible !== !1), e = t.map(
260
+ (i) => `<th class="align-${i.align ?? "left"}">${i.label}</th>`
261
+ ).join(""), a = this.rows.map(
262
+ (i, r) => `<tr data-row-index="${r}">${t.map(
263
+ (o) => o.actions ? `<td class="align-center actions-cell">
264
+ ${o.actions.edit ? `<ui-button variant="primary" class='action-btn' icon='edit' size="sm" data-action="edit" data-row-index="${r}">Edit</ui-button>` : ""}
265
+ ${o.actions.delete ? `<ui-button variant="danger" class='action-btn' icon='trash' size="sm" data-action="delete" data-row-index="${r}">Delete</ui-button>` : ""}
266
+ </td>` : `<td class="align-${o.align ?? "left"}">${String(
267
+ i[o.key] ?? ""
268
+ )}</td>`
269
+ ).join("")}</tr>`
270
+ ).join("");
271
+ this.shadowRoot.innerHTML = `
272
+ <style>${g}</style>
273
+ <div class="table-wrap">
274
+ <table>
275
+ <thead><tr>${e}</tr></thead>
276
+ <tbody>${a}</tbody>
277
+ </table>
278
+ </div>
279
+ `, this.shadowRoot.querySelectorAll(".action-btn").forEach((i) => {
280
+ i.addEventListener("click", (r) => {
281
+ const o = r.currentTarget, n = o.dataset.action, l = parseInt(o.dataset.rowIndex || "0", 10), h = n === "edit" ? "edit-action" : "delete-action";
282
+ this.dispatchEvent(new CustomEvent(h, {
283
+ bubbles: !0,
284
+ composed: !0,
285
+ detail: { row: this.rows[l], rowIndex: l }
286
+ }));
287
+ });
288
+ });
289
+ }
290
+ }
291
+ customElements.define("ui-table", E);
292
+ class C extends b {
293
+ constructor() {
294
+ super(...arguments);
295
+ c(this, "inputElement", null);
296
+ }
297
+ connectedCallback() {
298
+ this.setAttribute("data-ui", "date-picker"), super.connectedCallback(), this.attachEventListeners();
299
+ }
300
+ static get observedAttributes() {
301
+ return ["value", "format", "min", "max", "disabled", "placeholder"];
302
+ }
303
+ attributeChangedCallback() {
304
+ this.render(), this.attachEventListeners();
305
+ }
306
+ getFormat() {
307
+ const t = this.getAttribute("format");
308
+ return t === "DD/MM/YYYY" || t === "MM/DD/YYYY" || t === "DD-MM-YYYY" || t === "MM-DD-YYYY" ? t : "YYYY-MM-DD";
309
+ }
310
+ getValue() {
311
+ return this.getAttribute("value") || "";
312
+ }
313
+ getMin() {
314
+ return this.getAttribute("min") || "";
315
+ }
316
+ getMax() {
317
+ return this.getAttribute("max") || "";
318
+ }
319
+ getPlaceholder() {
320
+ return this.getAttribute("placeholder") || this.getFormat();
321
+ }
322
+ isDisabled() {
323
+ return this.hasAttribute("disabled");
324
+ }
325
+ /**
326
+ * Convert date from ISO format (YYYY-MM-DD) to specified format
327
+ */
328
+ formatDate(t, e) {
329
+ if (!t) return "";
330
+ const a = t.split("-");
331
+ if (a.length !== 3) return t;
332
+ const [i, r, o] = a;
333
+ switch (e) {
334
+ case "DD/MM/YYYY":
335
+ return `${o}/${r}/${i}`;
336
+ case "MM/DD/YYYY":
337
+ return `${r}/${o}/${i}`;
338
+ case "DD-MM-YYYY":
339
+ return `${o}-${r}-${i}`;
340
+ case "MM-DD-YYYY":
341
+ return `${r}-${o}-${i}`;
342
+ case "YYYY-MM-DD":
343
+ default:
344
+ return t;
345
+ }
346
+ }
347
+ /**
348
+ * Convert date from specified format to ISO format (YYYY-MM-DD)
349
+ */
350
+ parseDate(t, e) {
351
+ if (!t) return "";
352
+ let a, i, r, o;
353
+ switch (e) {
354
+ case "DD/MM/YYYY":
355
+ if (a = t.split("/"), a.length !== 3) return "";
356
+ [o, r, i] = a;
357
+ break;
358
+ case "MM/DD/YYYY":
359
+ if (a = t.split("/"), a.length !== 3) return "";
360
+ [r, o, i] = a;
361
+ break;
362
+ case "DD-MM-YYYY":
363
+ if (a = t.split("-"), a.length !== 3) return "";
364
+ [o, r, i] = a;
365
+ break;
366
+ case "MM-DD-YYYY":
367
+ if (a = t.split("-"), a.length !== 3) return "";
368
+ [r, o, i] = a;
369
+ break;
370
+ case "YYYY-MM-DD":
371
+ default:
372
+ return t;
373
+ }
374
+ return r = r.padStart(2, "0"), o = o.padStart(2, "0"), `${i}-${r}-${o}`;
375
+ }
376
+ attachEventListeners() {
377
+ if (!this.shadowRoot) return;
378
+ const t = this.shadowRoot.querySelector(".formatted-input"), e = this.shadowRoot.querySelector('input[type="date"]'), a = this.shadowRoot.querySelector(".calendar-btn");
379
+ if (!t || !e) return;
380
+ const i = () => {
381
+ const r = t.value, o = this.getFormat(), n = this.parseDate(r, o);
382
+ this.isValidDate(n) ? (e.value = n, t.classList.remove("invalid"), this.dispatchDateChange(n)) : r === "" ? (e.value = "", t.classList.remove("invalid"), this.dispatchDateChange("")) : t.classList.add("invalid");
383
+ };
384
+ t.addEventListener("blur", i), t.addEventListener("keydown", (r) => {
385
+ r.key === "Enter" && (i(), t.blur());
386
+ }), e.addEventListener("change", (r) => {
387
+ const n = r.target.value, l = this.getFormat(), h = this.formatDate(n, l);
388
+ t.value = h, t.classList.remove("invalid"), this.dispatchDateChange(n);
389
+ }), a && a.addEventListener("click", () => {
390
+ var r;
391
+ (r = e.showPicker) == null || r.call(e);
392
+ });
393
+ }
394
+ isValidDate(t) {
395
+ if (!t) return !1;
396
+ const e = new Date(t);
397
+ return e instanceof Date && !isNaN(e.getTime());
398
+ }
399
+ dispatchDateChange(t) {
400
+ const e = this.getFormat(), a = this.formatDate(t, e);
401
+ this.dispatchEvent(
402
+ new CustomEvent("date-change", {
403
+ detail: {
404
+ value: t,
405
+ formattedValue: a,
406
+ format: e
407
+ },
408
+ bubbles: !0,
409
+ composed: !0
410
+ })
411
+ ), this.setAttribute("value", t);
412
+ }
413
+ /**
414
+ * Get the current value in ISO format (YYYY-MM-DD)
415
+ */
416
+ getISOValue() {
417
+ return this.getValue();
418
+ }
419
+ /**
420
+ * Get the current value in the specified format
421
+ */
422
+ getFormattedValue() {
423
+ const t = this.getValue(), e = this.getFormat();
424
+ return this.formatDate(t, e);
425
+ }
426
+ /**
427
+ * Set the date value (accepts ISO format)
428
+ */
429
+ setValue(t) {
430
+ this.setAttribute("value", t);
431
+ }
432
+ /**
433
+ * Clear the date value
434
+ */
435
+ clear() {
436
+ this.setAttribute("value", "");
437
+ }
438
+ render() {
439
+ const t = this.getValue(), e = this.getFormat(), a = this.getMin(), i = this.getMax(), r = this.isDisabled(), o = this.getPlaceholder(), n = this.formatDate(t, e);
440
+ this.shadowRoot.innerHTML = `
441
+ <style>${g}</style>
442
+ <div class="date-picker-container">
443
+ <div class="date-input-wrapper ${r ? "disabled" : ""}">
444
+ <input
445
+ type="text"
446
+ class="formatted-input"
447
+ part="input"
448
+ value="${n}"
449
+ placeholder="${o}"
450
+ ${r ? "disabled" : ""}
451
+ />
452
+ <button
453
+ class="calendar-btn"
454
+ type="button"
455
+ ${r ? "disabled" : ""}
456
+ title="Open calendar"
457
+ >
458
+ <svg class="calendar-icon" fill="none" stroke="currentColor" viewBox="0 0 24 24">
459
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"/>
460
+ </svg>
461
+ </button>
462
+ <input
463
+ type="date"
464
+ class="hidden-date-input"
465
+ value="${t}"
466
+ ${a ? `min="${a}"` : ""}
467
+ ${i ? `max="${i}"` : ""}
468
+ ${r ? "disabled" : ""}
469
+ />
470
+ </div>
471
+ <div class="format-label">Format: ${e}</div>
472
+ </div>
473
+ `;
474
+ }
475
+ }
476
+ customElements.define("ui-date-picker", C);
477
+ class S extends b {
478
+ constructor() {
479
+ super(...arguments);
480
+ c(this, "_total", 0);
481
+ c(this, "_currentPage", 1);
482
+ c(this, "_pageSize", 10);
483
+ }
484
+ connectedCallback() {
485
+ this.setAttribute("data-ui", "pagination"), super.connectedCallback();
486
+ }
487
+ static get observedAttributes() {
488
+ return ["total", "current-page", "page-size"];
489
+ }
490
+ attributeChangedCallback(t, e, a) {
491
+ switch (t) {
492
+ case "total":
493
+ this._total = parseInt(a, 10) || 0;
494
+ break;
495
+ case "current-page":
496
+ this._currentPage = parseInt(a, 10) || 1;
497
+ break;
498
+ case "page-size":
499
+ this._pageSize = parseInt(a, 10) || 10;
500
+ break;
501
+ }
502
+ this.render();
503
+ }
504
+ get total() {
505
+ return this._total;
506
+ }
507
+ set total(t) {
508
+ this._total = t, this.setAttribute("total", String(t));
509
+ }
510
+ get currentPage() {
511
+ return this._currentPage;
512
+ }
513
+ set currentPage(t) {
514
+ this._currentPage = t, this.setAttribute("current-page", String(t));
515
+ }
516
+ get pageSize() {
517
+ return this._pageSize;
518
+ }
519
+ set pageSize(t) {
520
+ this._pageSize = t, this.setAttribute("page-size", String(t));
521
+ }
522
+ get totalPages() {
523
+ return Math.ceil(this._total / this._pageSize);
524
+ }
525
+ handlePageChange(t) {
526
+ t < 1 || t > this.totalPages || t === this._currentPage || (this.currentPage = t, this.dispatchEvent(
527
+ new CustomEvent("page-change", {
528
+ detail: {
529
+ page: t,
530
+ pageSize: this._pageSize,
531
+ total: this._total,
532
+ totalPages: this.totalPages
533
+ },
534
+ bubbles: !0,
535
+ composed: !0
536
+ })
537
+ ));
538
+ }
539
+ getPageNumbers() {
540
+ const t = this.totalPages, e = this._currentPage;
541
+ if (t <= 7)
542
+ return Array.from({ length: t }, (i, r) => r + 1);
543
+ const a = [];
544
+ return e <= 3 ? a.push(1, 2, 3, 4, "...", t) : e >= t - 2 ? a.push(1, "...", t - 3, t - 2, t - 1, t) : a.push(1, "...", e - 1, e, e + 1, "...", t), a;
545
+ }
546
+ render() {
547
+ const t = this.totalPages, e = this._currentPage, a = this.getPageNumbers(), i = (e - 1) * this._pageSize + 1, r = Math.min(e * this._pageSize, this._total);
548
+ this.shadowRoot.innerHTML = `
549
+ <style>${g}</style>
550
+ <div class="pagination-container">
551
+ <div class="pagination-info">
552
+ ${this._total > 0 ? `Showing ${i} to ${r} of ${this._total}` : "No results"}
553
+ </div>
554
+ ${t > 1 ? `
555
+ <nav class="pagination" role="navigation" aria-label="Pagination">
556
+ <button
557
+ class="page-btn nav-btn"
558
+ ${e === 1 ? "disabled" : ""}
559
+ data-page="prev"
560
+ aria-label="Previous page"
561
+ >
562
+ <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
563
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"/>
564
+ </svg>
565
+ </button>
566
+ ${a.map((o) => o === "..." ? '<button class="page-btn ellipsis" disabled>...</button>' : `
567
+ <button
568
+ class="page-btn ${o === e ? "active" : ""}"
569
+ data-page="${o}"
570
+ aria-label="Page ${o}"
571
+ ${o === e ? 'aria-current="page"' : ""}
572
+ >
573
+ ${o}
574
+ </button>
575
+ `).join("")}
576
+ <button
577
+ class="page-btn nav-btn"
578
+ ${e === t ? "disabled" : ""}
579
+ data-page="next"
580
+ aria-label="Next page"
581
+ >
582
+ <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
583
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"/>
584
+ </svg>
585
+ </button>
586
+ </nav>
587
+ ` : ""}
588
+ </div>
589
+ `, this.attachEventListeners();
590
+ }
591
+ attachEventListeners() {
592
+ this.shadowRoot && this.shadowRoot.addEventListener("click", (t) => {
593
+ const a = t.target.closest(".page-btn");
594
+ if (!a || a.disabled) return;
595
+ const i = a.dataset.page;
596
+ if (i === "prev")
597
+ this.handlePageChange(this._currentPage - 1);
598
+ else if (i === "next")
599
+ this.handlePageChange(this._currentPage + 1);
600
+ else if (i) {
601
+ const r = parseInt(i, 10);
602
+ isNaN(r) || this.handlePageChange(r);
603
+ }
604
+ });
605
+ }
606
+ }
607
+ customElements.define("ui-pagination", S);
608
+ class L extends b {
609
+ constructor() {
610
+ super(...arguments);
611
+ c(this, "isOpen", this.useSignal(!1));
612
+ }
613
+ connectedCallback() {
614
+ this.setAttribute("data-ui", "modal"), super.connectedCallback(), this.setupEventListeners();
615
+ }
616
+ static get observedAttributes() {
617
+ return ["open"];
618
+ }
619
+ attributeChangedCallback(t, e, a) {
620
+ t === "open" && e !== a && this.isOpen.set(a !== null);
621
+ }
622
+ setupEventListeners() {
623
+ document.addEventListener("keydown", (t) => {
624
+ t.key === "Escape" && this.isOpen.get() && !this.hasAttribute("no-close-on-escape") && this.close();
625
+ });
626
+ }
627
+ open() {
628
+ this.isOpen.set(!0), this.setAttribute("open", ""), this.dispatchEvent(new CustomEvent("modal-open", { bubbles: !0, composed: !0 })), document.body.style.overflow = "hidden";
629
+ }
630
+ close() {
631
+ this.isOpen.set(!1), this.removeAttribute("open"), this.dispatchEvent(new CustomEvent("modal-close", { bubbles: !0, composed: !0 })), document.body.style.overflow = "";
632
+ }
633
+ handleBackdropClick(t) {
634
+ t.target.classList.contains("modal-backdrop") && !this.hasAttribute("no-close-on-backdrop") && this.close();
635
+ }
636
+ render() {
637
+ const t = this.isOpen.get(), e = this.getAttribute("title") || "", a = this.getAttribute("size") || "md";
638
+ this.shadowRoot.innerHTML = `
639
+ <style>
640
+ ${g}
641
+
642
+ ::slotted([slot="footer"]) {
643
+ display: flex;
644
+ gap: 0.75rem;
645
+ width: 100%;
646
+ justify-content: flex-end;
647
+ }
648
+ </style>
649
+
650
+ <div class="modal-backdrop ${t ? "open" : ""}" part="backdrop">
651
+ <div class="modal-content ${a}" part="content" @click="${(o) => o.stopPropagation()}">
652
+ ${e ? `
653
+ <div class="modal-header" part="header">
654
+ <h2 class="modal-title">${e}</h2>
655
+ <button class="modal-close" part="close" aria-label="Close modal">
656
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
657
+ <line x1="18" y1="6" x2="6" y2="18"></line>
658
+ <line x1="6" y1="6" x2="18" y2="18"></line>
659
+ </svg>
660
+ </button>
661
+ </div>
662
+ ` : ""}
663
+
664
+ <div class="modal-body" part="body">
665
+ <slot></slot>
666
+ </div>
667
+
668
+ <div class="modal-footer" part="footer">
669
+ <slot name="footer"></slot>
670
+ </div>
671
+ </div>
672
+ </div>
673
+ `;
674
+ const i = this.shadowRoot.querySelector(".modal-backdrop"), r = this.shadowRoot.querySelector(".modal-close");
675
+ i == null || i.addEventListener("click", (o) => this.handleBackdropClick(o)), r == null || r.addEventListener("click", () => this.close());
676
+ }
677
+ }
678
+ customElements.define("ui-modal", L);
679
+ class Y extends b {
680
+ constructor() {
681
+ super(...arguments);
682
+ c(this, "isOpen", this.useSignal(!1));
683
+ c(this, "selectedValue", this.useSignal(""));
684
+ c(this, "searchTerm", this.useSignal(""));
685
+ c(this, "options", []);
686
+ }
687
+ connectedCallback() {
688
+ this.setAttribute("data-ui", "select"), super.connectedCallback(), this.parseOptions(), this.setupClickOutside();
689
+ }
690
+ static get observedAttributes() {
691
+ return ["value", "disabled", "placeholder", "options"];
692
+ }
693
+ attributeChangedCallback(t, e, a) {
694
+ t === "value" && e !== a && this.selectedValue.set(a || ""), t === "options" && e !== a && this.parseOptions(), this.render();
695
+ }
696
+ parseOptions() {
697
+ const t = this.getAttribute("options");
698
+ if (t)
699
+ try {
700
+ this.options = JSON.parse(t);
701
+ } catch (e) {
702
+ console.error("Invalid options JSON", e), this.options = [];
703
+ }
704
+ }
705
+ setupClickOutside() {
706
+ document.addEventListener("click", (t) => {
707
+ !t.composedPath().includes(this) && this.isOpen.get() && this.isOpen.set(!1);
708
+ });
709
+ }
710
+ toggleDropdown() {
711
+ this.hasAttribute("disabled") || (this.isOpen.set(!this.isOpen.get()), this.isOpen.get() || this.searchTerm.set(""));
712
+ }
713
+ selectOption(t) {
714
+ this.selectedValue.set(t), this.setAttribute("value", t), this.isOpen.set(!1), this.searchTerm.set(""), this.dispatchEvent(new CustomEvent("select-change", {
715
+ bubbles: !0,
716
+ composed: !0,
717
+ detail: {
718
+ value: t,
719
+ option: this.options.find((e) => e.value === t)
720
+ }
721
+ }));
722
+ }
723
+ handleSearch(t) {
724
+ this.searchTerm.set(t.toLowerCase());
725
+ }
726
+ getFilteredOptions() {
727
+ const t = this.searchTerm.get();
728
+ return t ? this.options.filter(
729
+ (e) => e.label.toLowerCase().includes(t) || e.value.toLowerCase().includes(t)
730
+ ) : this.options;
731
+ }
732
+ getSelectedLabel() {
733
+ const t = this.selectedValue.get(), e = this.options.find((a) => a.value === t);
734
+ return (e == null ? void 0 : e.label) || this.getAttribute("placeholder") || "Select an option";
735
+ }
736
+ render() {
737
+ const t = this.isOpen.get(), e = this.hasAttribute("disabled"), a = this.hasAttribute("searchable"), i = this.getAttribute("label") || "", r = this.getSelectedLabel(), o = this.getFilteredOptions(), n = this.selectedValue.get() !== "";
738
+ this.shadowRoot.innerHTML = `
739
+ <style>${g}</style>
740
+
741
+ <div class="select-container">
742
+ ${i ? `<label class="select-label">${i}</label>` : ""}
743
+
744
+ <div class="select-trigger ${t ? "open" : ""}" part="trigger" tabindex="0" ${e ? "disabled" : ""}>
745
+ <span class="select-placeholder ${n ? "has-selection" : ""}">${r}</span>
746
+ <span class="select-arrow ${t ? "open" : ""}">
747
+ <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
748
+ <polyline points="6 9 12 15 18 9"></polyline>
749
+ </svg>
750
+ </span>
751
+ </div>
752
+
753
+ <div class="select-dropdown ${t ? "open" : ""}" part="dropdown">
754
+ ${a ? `
755
+ <input
756
+ type="text"
757
+ class="select-search"
758
+ placeholder="Search..."
759
+ part="search"
760
+ >
761
+ ` : ""}
762
+
763
+ ${o.length > 0 ? o.map((d) => `
764
+ <div
765
+ class="select-option ${d.value === this.selectedValue.get() ? "selected" : ""} ${d.disabled ? "disabled" : ""}"
766
+ data-value="${d.value}"
767
+ part="option"
768
+ >
769
+ ${d.label}
770
+ </div>
771
+ `).join("") : `
772
+ <div class="select-empty">No options found</div>
773
+ `}
774
+ </div>
775
+ </div>
776
+ `;
777
+ const l = this.shadowRoot.querySelector(".select-trigger"), h = this.shadowRoot.querySelector(".select-search"), p = this.shadowRoot.querySelectorAll(".select-option:not(.disabled)");
778
+ l == null || l.addEventListener("click", () => this.toggleDropdown()), l == null || l.addEventListener("keydown", (d) => {
779
+ (d.key === "Enter" || d.key === " ") && (d.preventDefault(), this.toggleDropdown());
780
+ }), h == null || h.addEventListener("input", (d) => {
781
+ this.handleSearch(d.target.value);
782
+ }), h == null || h.addEventListener("click", (d) => d.stopPropagation()), p.forEach((d) => {
783
+ d.addEventListener("click", () => {
784
+ const m = d.getAttribute("data-value");
785
+ m && this.selectOption(m);
786
+ });
787
+ });
788
+ }
789
+ }
790
+ customElements.define("ui-select", Y);
791
+ class z extends b {
792
+ constructor() {
793
+ super(...arguments);
794
+ c(this, "checked", this.useSignal(!1));
795
+ c(this, "indeterminate", this.useSignal(!1));
796
+ }
797
+ connectedCallback() {
798
+ this.setAttribute("data-ui", "checkbox"), super.connectedCallback();
799
+ }
800
+ static get observedAttributes() {
801
+ return ["checked", "disabled", "indeterminate"];
802
+ }
803
+ attributeChangedCallback(t, e, a) {
804
+ t === "checked" && e !== a && this.checked.set(a !== null), t === "indeterminate" && e !== a && this.indeterminate.set(a !== null), this.render();
805
+ }
806
+ handleChange() {
807
+ if (this.hasAttribute("disabled")) return;
808
+ this.indeterminate.get() && (this.indeterminate.set(!1), this.removeAttribute("indeterminate"));
809
+ const t = !this.checked.get();
810
+ this.checked.set(t), t ? this.setAttribute("checked", "") : this.removeAttribute("checked"), this.dispatchEvent(new CustomEvent("checkbox-change", {
811
+ bubbles: !0,
812
+ composed: !0,
813
+ detail: { checked: t }
814
+ }));
815
+ }
816
+ setChecked(t) {
817
+ this.checked.set(t), t ? this.setAttribute("checked", "") : this.removeAttribute("checked"), this.indeterminate.set(!1), this.removeAttribute("indeterminate");
818
+ }
819
+ setIndeterminate(t) {
820
+ this.indeterminate.set(t), t ? this.setAttribute("indeterminate", "") : this.removeAttribute("indeterminate");
821
+ }
822
+ render() {
823
+ const t = this.checked.get(), e = this.indeterminate.get(), a = this.hasAttribute("disabled"), i = this.getAttribute("label") || "", r = this.getAttribute("size") || "md", o = {
824
+ sm: "size-sm",
825
+ md: "size-md",
826
+ lg: "size-lg"
827
+ };
828
+ this.shadowRoot.innerHTML = `
829
+ <style>${g}</style>
830
+
831
+ <label class="checkbox-container ${o[r]}">
832
+ <input
833
+ type="checkbox"
834
+ ${t ? "checked" : ""}
835
+ ${a ? "disabled" : ""}
836
+ >
837
+ <div class="checkbox-box ${o[r]} ${t ? "checked" : ""} ${e ? "indeterminate" : ""} ${a ? "disabled" : ""}" part="checkbox">
838
+ <svg class="checkbox-icon check" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
839
+ <polyline points="20 6 9 17 4 12"></polyline>
840
+ </svg>
841
+ <svg class="checkbox-icon minus" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="3">
842
+ <line x1="5" y1="12" x2="19" y2="12"></line>
843
+ </svg>
844
+ </div>
845
+ ${i ? `<span class="checkbox-label">${i}</span>` : "<slot></slot>"}
846
+ </label>
847
+ `;
848
+ const n = this.shadowRoot.querySelector(".checkbox-container");
849
+ n == null || n.addEventListener("click", (l) => {
850
+ l.preventDefault(), this.handleChange();
851
+ });
852
+ }
853
+ }
854
+ customElements.define("ui-checkbox", z);
855
+ const D = ':host{display:block}.tabs{background:var(--color-page-bg);border-radius:16px;box-shadow:0 1px 3px #0000000a,0 4px 12px #00000008;overflow:hidden;position:relative}.tablist{display:flex;position:relative;padding:8px;gap:4px;background:linear-gradient(180deg,#fafafa,#f5f5f5);border-bottom:1px solid rgba(0,0,0,.04)}.tab-indicator{position:absolute;bottom:8px;height:calc(100% - 16px);background:var(--color-page-bg);border-radius:10px;box-shadow:0 2px 8px #0000000f,0 1px 2px #0000000a;transition:transform .28s cubic-bezier(.4,0,.2,1),width .28s cubic-bezier(.4,0,.2,1);pointer-events:none;z-index:0}::slotted([slot="tab"]){-webkit-appearance:none;-moz-appearance:none;appearance:none;background:transparent;border:none;color:#64748b;cursor:pointer;font:600 13px/1 DM Sans,system-ui,-apple-system,sans-serif;letter-spacing:.02em;padding:10px 18px;position:relative;transition:color .2s ease;-webkit-user-select:none;user-select:none;white-space:nowrap;z-index:1}::slotted([slot="tab"]:hover){color:var(--color-ink)}::slotted([slot="tab"].is-active){color:var(--color-ink)}::slotted([slot="tab"]:focus-visible){outline:none}::slotted([slot="tab"]:focus-visible):after{content:"";position:absolute;top:6px;right:6px;bottom:6px;left:6px;border:2px solid var(--color-primary);border-radius:8px;pointer-events:none}.panels{padding:24px 28px;min-height:200px}::slotted([slot="panel"]){animation:fadeIn .3s ease}::slotted([slot="panel"]:not(.is-active)){display:none}@keyframes fadeIn{0%{opacity:0;transform:translateY(8px)}to{opacity:1;transform:translateY(0)}}@media (prefers-reduced-motion: reduce){.tab-indicator{transition:none}::slotted([slot="panel"]){animation:none}}';
856
+ class R extends b {
857
+ constructor() {
858
+ super(...arguments);
859
+ c(this, "activeId", null);
860
+ c(this, "indicator", null);
861
+ c(this, "handleTabClick", (t) => {
862
+ const e = t.target;
863
+ if (!e) return;
864
+ const a = e.closest('[slot="tab"][data-tab]');
865
+ if (!a) return;
866
+ t.preventDefault();
867
+ const i = a.getAttribute("data-tab");
868
+ i && this.setActive(i);
869
+ });
870
+ }
871
+ static get observedAttributes() {
872
+ return ["active"];
873
+ }
874
+ connectedCallback() {
875
+ this.setAttribute("data-ui", "tabs"), super.connectedCallback(), this.addEventListener("click", this.handleTabClick);
876
+ }
877
+ disconnectedCallback() {
878
+ this.removeEventListener("click", this.handleTabClick), super.disconnectedCallback();
879
+ }
880
+ attributeChangedCallback(t, e, a) {
881
+ t === "active" && e !== a && (this.activeId = a, this.syncTabs());
882
+ }
883
+ setActive(t) {
884
+ this.activeId !== t && (this.activeId = t, this.setAttribute("active", t), this.syncTabs(), this.dispatchEvent(new CustomEvent("tab-change", {
885
+ bubbles: !0,
886
+ composed: !0,
887
+ detail: { id: t }
888
+ })));
889
+ }
890
+ getTabs() {
891
+ var e;
892
+ const t = (e = this.shadowRoot) == null ? void 0 : e.querySelector('slot[name="tab"]');
893
+ return t ? t.assignedElements({ flatten: !0 }) : [];
894
+ }
895
+ getPanels() {
896
+ var e;
897
+ const t = (e = this.shadowRoot) == null ? void 0 : e.querySelector('slot[name="panel"]');
898
+ return t ? t.assignedElements({ flatten: !0 }) : [];
899
+ }
900
+ getActiveId(t) {
901
+ const e = this.getAttribute("active");
902
+ if (e && t.some((i) => i.getAttribute("data-tab") === e))
903
+ return e;
904
+ if (this.activeId && t.some((i) => i.getAttribute("data-tab") === this.activeId))
905
+ return this.activeId;
906
+ const a = t.find((i) => i.getAttribute("data-tab"));
907
+ return (a == null ? void 0 : a.getAttribute("data-tab")) ?? null;
908
+ }
909
+ syncTabs() {
910
+ const t = this.getTabs(), e = this.getPanels();
911
+ if (t.length === 0) return;
912
+ const a = this.getActiveId(t);
913
+ a && (this.activeId = a, this.getAttribute("active") !== a && this.setAttribute("active", a), t.forEach((i) => {
914
+ const r = i.getAttribute("data-tab");
915
+ if (!r) return;
916
+ const o = i.id || `tab-${r}`, n = r === a;
917
+ i.id = o, i.setAttribute("role", "tab"), i.setAttribute("aria-selected", String(n)), i.setAttribute("tabindex", n ? "0" : "-1"), i.classList.toggle("is-active", n);
918
+ }), e.forEach((i) => {
919
+ const r = i.getAttribute("data-tab");
920
+ if (!r) return;
921
+ const o = i.id || `panel-${r}`, n = r === a;
922
+ i.id = o, i.setAttribute("role", "tabpanel"), i.toggleAttribute("hidden", !n), i.classList.toggle("is-active", n);
923
+ const l = t.find((h) => h.getAttribute("data-tab") === r);
924
+ l && (l.setAttribute("aria-controls", o), i.setAttribute("aria-labelledby", l.id));
925
+ }), this.updateIndicator(t, a));
926
+ }
927
+ updateIndicator(t, e) {
928
+ if (!this.indicator) return;
929
+ const a = t.find((n) => n.getAttribute("data-tab") === e);
930
+ if (!a) return;
931
+ const i = this.shadowRoot.querySelector(".tablist");
932
+ if (!i) return;
933
+ a.getBoundingClientRect(), i.getBoundingClientRect();
934
+ const r = t.indexOf(a);
935
+ let o = 0;
936
+ for (let n = 0; n < r; n++)
937
+ o += t[n].offsetWidth;
938
+ this.indicator.style.transform = `translateX(${o}px)`, this.indicator.style.width = `${a.offsetWidth}px`;
939
+ }
940
+ render() {
941
+ this.shadowRoot.innerHTML = `
942
+ <style>${g}${D}</style>
943
+ <div class="tabs">
944
+ <div class="tablist" role="tablist">
945
+ <div class="tab-indicator"></div>
946
+ <slot name="tab"></slot>
947
+ </div>
948
+ <div class="panels">
949
+ <slot name="panel"></slot>
950
+ </div>
951
+ </div>
952
+ `, this.indicator = this.shadowRoot.querySelector(".tab-indicator");
953
+ const t = this.shadowRoot.querySelector('slot[name="tab"]'), e = this.shadowRoot.querySelector('slot[name="panel"]');
954
+ t == null || t.addEventListener("slotchange", () => this.syncTabs()), e == null || e.addEventListener("slotchange", () => this.syncTabs()), requestAnimationFrame(() => this.syncTabs());
955
+ }
956
+ }
957
+ customElements.define("ui-tabs", R);
958
+ const M = ':host{display:block;--card-transition: all .3s cubic-bezier(.4, 0, .2, 1)}:host([data-ui="card"]){display:block}.card{background:#fff;padding:24px;box-sizing:border-box;width:100%;position:relative;transition:var(--card-transition);overflow:hidden}.card.rounded{border-radius:16px}.card.square{border-radius:0}.card.default{border:1px solid #e5e7eb;background:#fff}.card.elevated{border:none;background:linear-gradient(to bottom,#fff,#fafbfc)}.card.bordered{border:2px solid #e5e7eb;background:#fff}.card.ghost{border:1px dashed #d1d5db;background:transparent}.card.default:hover{border-color:#d1d5db;transform:translateY(-2px)}.card.elevated:hover{transform:translateY(-4px)}.card.bordered:hover{border-color:#9ca3af;background:#fafbfc}.card.ghost:hover{border-color:#9ca3af;background:#f9fafb80}.card.elevated:before{content:"";position:absolute;top:0;right:0;bottom:0;left:0;border-radius:inherit;padding:2px;background:linear-gradient(135deg,#6366f11a,#ec48991a);-webkit-mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);mask:linear-gradient(#fff 0 0) content-box,linear-gradient(#fff 0 0);-webkit-mask-composite:xor;mask-composite:exclude;opacity:0;transition:opacity .3s ease;pointer-events:none}.card.elevated:hover:before{opacity:1}.card ::slotted(*:first-child){margin-top:0}.card ::slotted(*:last-child){margin-bottom:0}.card:focus-within{outline:2px solid #9ec5ff;outline-offset:2px}@media (max-width: 768px){.card{padding:20px}.card.rounded{border-radius:12px}}@media (max-width: 480px){.card{padding:16px}.card.rounded{border-radius:10px}}@media print{.card{border:1px solid #e5e7eb;box-shadow:none!important;page-break-inside:avoid}}';
959
+ class T extends b {
960
+ connectedCallback() {
961
+ this.setAttribute("data-ui", "card"), super.connectedCallback();
962
+ }
963
+ static get observedAttributes() {
964
+ return ["shadow", "shadow-color", "rounded", "variant", "elevation"];
965
+ }
966
+ attributeChangedCallback() {
967
+ this.render();
968
+ }
969
+ getShadow() {
970
+ return this.hasAttribute("shadow") && this.getAttribute("shadow") !== "false";
971
+ }
972
+ getShadowColor() {
973
+ return this.getAttribute("shadow-color") ?? "0, 0, 0";
974
+ }
975
+ getRounded() {
976
+ return this.getAttribute("rounded") !== "false";
977
+ }
978
+ getVariant() {
979
+ const s = this.getAttribute("variant");
980
+ return s === "elevated" || s === "bordered" || s === "ghost" ? s : "default";
981
+ }
982
+ getElevation() {
983
+ const s = this.getAttribute("elevation");
984
+ return s === "none" || s === "sm" || s === "md" || s === "lg" || s === "xl" ? s : "sm";
985
+ }
986
+ render() {
987
+ const s = this.getShadow(), t = this.getShadowColor(), e = this.getRounded(), a = this.getVariant(), i = this.getElevation();
988
+ let r = "none";
989
+ if (s)
990
+ switch (i) {
991
+ case "sm":
992
+ r = `0 1px 2px rgba(${t}, 0.05), 0 1px 3px rgba(${t}, 0.1)`;
993
+ break;
994
+ case "md":
995
+ r = `0 4px 6px rgba(${t}, 0.07), 0 2px 4px rgba(${t}, 0.06)`;
996
+ break;
997
+ case "lg":
998
+ r = `0 10px 15px rgba(${t}, 0.1), 0 4px 6px rgba(${t}, 0.05)`;
999
+ break;
1000
+ case "xl":
1001
+ r = `0 20px 25px rgba(${t}, 0.15), 0 10px 10px rgba(${t}, 0.04)`;
1002
+ break;
1003
+ default:
1004
+ r = "none";
1005
+ }
1006
+ this.shadowRoot.innerHTML = `
1007
+ <style>
1008
+ ${g}
1009
+ ${M}
1010
+
1011
+ .card.custom-shadow {
1012
+ box-shadow: ${r};
1013
+ }
1014
+
1015
+ .card.custom-shadow:hover {
1016
+ box-shadow: ${s && i !== "none" ? r.replace(/rgba\(([^)]+), ([\d.]+)\)/g, (o, n, l) => `rgba(${n}, ${Math.min(parseFloat(l) * 1.3, 0.25)})`) : "none"};
1017
+ }
1018
+ </style>
1019
+ <div class="card ${a} ${e ? "rounded" : "square"} ${s ? "custom-shadow" : "no-shadow"}">
1020
+ <slot></slot>
1021
+ </div>
1022
+ `;
1023
+ }
1024
+ }
1025
+ customElements.define("ui-card", T);
1026
+ class I {
1027
+ constructor() {
1028
+ c(this, "baseURL", "");
1029
+ c(this, "defaultHeaders", {
1030
+ "Content-Type": "application/json"
1031
+ });
1032
+ c(this, "defaultTimeout", 3e4);
1033
+ c(this, "interceptors", {
1034
+ request: {
1035
+ handlers: [],
1036
+ use: (s, t) => {
1037
+ this.interceptors.request.handlers.push({ onFulfilled: s, onRejected: t });
1038
+ }
1039
+ },
1040
+ response: {
1041
+ handlers: [],
1042
+ use: (s, t) => {
1043
+ this.interceptors.response.handlers.push({ onFulfilled: s, onRejected: t });
1044
+ }
1045
+ }
1046
+ });
1047
+ }
1048
+ /**
1049
+ * Set base URL for all requests
1050
+ */
1051
+ setBaseURL(s) {
1052
+ this.baseURL = s;
1053
+ }
1054
+ /**
1055
+ * Get currently set base URL
1056
+ */
1057
+ getBaseURL() {
1058
+ return this.baseURL;
1059
+ }
1060
+ /**
1061
+ * Set default headers for all requests
1062
+ */
1063
+ setDefaultHeaders(s) {
1064
+ this.defaultHeaders = { ...this.defaultHeaders, ...s };
1065
+ }
1066
+ /**
1067
+ * Set default timeout for all requests (in ms)
1068
+ */
1069
+ setDefaultTimeout(s) {
1070
+ this.defaultTimeout = s;
1071
+ }
1072
+ /**
1073
+ * Execute request with interceptors
1074
+ */
1075
+ async executeRequest(s, t) {
1076
+ const e = s.startsWith("http") ? s : this.baseURL + s;
1077
+ let a = {
1078
+ method: "GET",
1079
+ headers: { ...this.defaultHeaders },
1080
+ timeout: this.defaultTimeout,
1081
+ ...t
1082
+ };
1083
+ for (const o of this.interceptors.request.handlers)
1084
+ try {
1085
+ a = await o.onFulfilled(a);
1086
+ } catch (n) {
1087
+ if (o.onRejected)
1088
+ a = await o.onRejected(n);
1089
+ else
1090
+ throw n;
1091
+ }
1092
+ const i = new AbortController(), r = setTimeout(() => i.abort(), a.timeout || this.defaultTimeout);
1093
+ try {
1094
+ const o = {
1095
+ method: a.method,
1096
+ headers: a.headers,
1097
+ signal: i.signal
1098
+ };
1099
+ a.body && a.method !== "GET" && (o.body = (typeof a.body == "string", a.body));
1100
+ const n = await fetch(e, o);
1101
+ let l;
1102
+ const h = n.headers.get("content-type");
1103
+ h != null && h.includes("application/json") ? l = n.ok ? await n.json() : null : h != null && h.includes("text") ? l = await n.text() : l = await n.blob();
1104
+ let p = {
1105
+ status: n.status,
1106
+ statusText: n.statusText,
1107
+ headers: n.headers,
1108
+ data: l
1109
+ };
1110
+ if (!n.ok) {
1111
+ const d = new Error(`HTTP ${n.status}: ${n.statusText}`);
1112
+ throw d.response = p, d.config = a, d;
1113
+ }
1114
+ for (const d of this.interceptors.response.handlers)
1115
+ try {
1116
+ p = await d.onFulfilled(p);
1117
+ } catch (m) {
1118
+ if (d.onRejected)
1119
+ p = await d.onRejected(m);
1120
+ else
1121
+ throw m;
1122
+ }
1123
+ return p.data;
1124
+ } catch (o) {
1125
+ throw o instanceof Error && o.name === "AbortError" ? new Error(`Request timeout after ${a.timeout}ms`) : o;
1126
+ } finally {
1127
+ clearTimeout(r);
1128
+ }
1129
+ }
1130
+ /**
1131
+ * GET request
1132
+ */
1133
+ async get(s, t) {
1134
+ return this.executeRequest(s, { ...t, method: "GET" });
1135
+ }
1136
+ /**
1137
+ * POST request
1138
+ */
1139
+ async post(s, t, e) {
1140
+ return this.executeRequest(s, {
1141
+ ...e,
1142
+ method: "POST",
1143
+ body: typeof t == "string" || t instanceof FormData ? t : JSON.stringify(t)
1144
+ });
1145
+ }
1146
+ /**
1147
+ * PUT request
1148
+ */
1149
+ async put(s, t, e) {
1150
+ return this.executeRequest(s, {
1151
+ ...e,
1152
+ method: "PUT",
1153
+ body: typeof t == "string" || t instanceof FormData ? t : JSON.stringify(t)
1154
+ });
1155
+ }
1156
+ /**
1157
+ * PATCH request
1158
+ */
1159
+ async patch(s, t, e) {
1160
+ return this.executeRequest(s, {
1161
+ ...e,
1162
+ method: "PATCH",
1163
+ body: typeof t == "string" || t instanceof FormData ? t : JSON.stringify(t)
1164
+ });
1165
+ }
1166
+ /**
1167
+ * DELETE request
1168
+ */
1169
+ async delete(s, t) {
1170
+ return this.executeRequest(s, { ...t, method: "DELETE" });
1171
+ }
1172
+ /**
1173
+ * HEAD request
1174
+ */
1175
+ async head(s, t) {
1176
+ return this.executeRequest(s, { ...t, method: "HEAD" });
1177
+ }
1178
+ }
1179
+ const O = new I();
1180
+ export {
1181
+ I as HTTPClient,
1182
+ $ as UIButton,
1183
+ T as UICard,
1184
+ z as UICheckbox,
1185
+ C as UIDatePicker,
1186
+ A as UIInput,
1187
+ L as UIModal,
1188
+ S as UIPagination,
1189
+ Y as UISelect,
1190
+ E as UITable,
1191
+ R as UITabs,
1192
+ O as http
1193
+ };