uikit/dist/remote/AppSidebar.js
Mohamadzadeh 34959deb18
All checks were successful
Build and Deploy Next.js + Nginx Docker Image / build-and-deploy (push) Successful in 56s
Build and Deploy Next.js + Nginx Docker Image / deploy (push) Successful in 7s
fix sidebar tooltip
2026-10-04 18:04:48 +03:30

673 lines
19 KiB
JavaScript

const x = "__UIKIT_REACT_REMOTE_DEPS__", b = "uikit-app-sidebar", h = `
<svg fill="currentColor" width="16" height="16" viewBox="0 0 512 512" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
<title>ionicons-v5-i</title>
<path d="M336,376V272H191a16,16,0,0,1,0-32H336V136a56.06,56.06,0,0,0-56-56H88a56.06,56.06,0,0,0-56,56V376a56.06,56.06,0,0,0,56,56H280A56.06,56.06,0,0,0,336,376Z"/>
<path d="M425.37,272l-52.68,52.69a16,16,0,0,0,22.62,22.62l80-80a16,16,0,0,0,0-22.62l-80-80a16,16,0,0,0-22.62,22.62L425.37,240H336v32Z"/>
</svg>`, m = `
<svg width="16" height="16" viewBox="0 0 24 24" fill="currentColor" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" focusable="false">
<circle cx="5" cy="12" r="2"/>
<circle cx="12" cy="12" r="2"/>
<circle cx="19" cy="12" r="2"/>
</svg>`, w = `
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" aria-hidden="true" focusable="false">
<path d="M18 6 6 18"/>
<path d="m6 6 12 12"/>
</svg>`, g = `
:host {
box-sizing: border-box;
display: block;
width: 72px;
min-width: 72px;
max-width: 72px;
height: calc(100dvh - 110px);
min-height: calc(100dvh - 110px);
max-height: calc(100dvh - 110px);
flex: 0 0 72px;
font-family: inherit;
color: #1a202c;
direction: rtl;
}
*, *::before, *::after { box-sizing: border-box; }
.desktop-nav {
width: 100%;
height: 100%;
min-height: 0;
padding: 16px 0;
overflow-y: auto;
overflow-x: hidden;
overscroll-behavior: contain;
background: #fff;
border-left: 1px solid #e2e8f0;
scrollbar-width: thin;
scrollbar-color: #cbd5e0 transparent;
}
.desktop-nav::-webkit-scrollbar { width: 4px; }
.desktop-nav::-webkit-scrollbar-track { background: transparent; }
.desktop-nav::-webkit-scrollbar-thumb {
border-radius: 999px;
background: #cbd5e0;
}
.items {
display: flex;
flex-direction: column;
align-items: center;
gap: 6px;
width: 100%;
}
.item-wrap {
position: relative;
display: flex;
align-items: center;
justify-content: center;
width: 56px;
height: 42px;
flex: 0 0 42px;
}
.item {
appearance: none;
-webkit-appearance: none;
display: inline-flex;
align-items: center;
justify-content: center;
width: 56px;
height: 42px;
min-width: 56px;
min-height: 42px;
margin: 0;
padding: 0;
border: 0;
border-radius: 6px;
outline: 0;
background: transparent;
color: #718096;
text-decoration: none;
font: inherit;
line-height: 1;
cursor: pointer;
transition: background-color 120ms ease, box-shadow 120ms ease, opacity 120ms ease;
}
.item:hover:not([aria-disabled="true"]) { background: #edf2f7; }
.item[data-active="true"] { background: #e2e8f0; }
.item[data-active="true"]:hover { background: #e2e8f0; }
.item:focus-visible { box-shadow: 0 0 0 3px rgba(49, 130, 206, 0.45); }
.item[aria-disabled="true"] { opacity: 0.4; cursor: not-allowed; }
.icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
font-size: 16px;
color: #314E89 !important;
pointer-events: none;
}
.icon > *,
.icon svg {
display: block;
width: 16px;
height: 16px;
max-width: 16px;
max-height: 16px;
color: #314E89 !important;
}
.exit-icon svg {
width: 16px;
height: 16px;
fill: currentColor;
stroke: none;
}
.floating-tooltip {
position: fixed;
z-index: 2147483000;
display: none;
min-width: max-content;
max-width: 280px;
padding: 8px 12px;
border-radius: 6px;
background: #2d3748;
color: #fff;
font-family: inherit;
font-size: 12px;
font-weight: 700;
line-height: 1.2;
white-space: nowrap;
pointer-events: none;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.14);
}
.floating-tooltip[data-open="true"] { display: block; }
.floating-tooltip::after {
content: "";
position: absolute;
top: 16px;
left: 100%;
width: 0;
height: 0;
border-top: 6px solid transparent;
border-bottom: 6px solid transparent;
border-left: 6px solid #2d3748;
}
.mobile-nav,
.drawer-layer {
display: none;
}
@media (max-width: 61.999em) {
:host {
display: block;
width: 0;
min-width: 0;
max-width: none;
height: 0;
min-height: 0;
flex: 0 0 0;
}
.desktop-nav,
.floating-tooltip {
display: none !important;
}
.mobile-nav {
position: fixed;
inset-inline: 0;
bottom: 0;
z-index: 1200;
display: block;
background: #fff;
border-top: 1px solid #e2e8f0;
box-shadow: 0 -6px 18px rgba(0, 0, 0, 0.08);
padding-bottom: env(safe-area-inset-bottom);
}
.mobile-bar {
display: flex;
align-items: stretch;
width: 100%;
height: 56px;
padding-inline: 6px;
gap: 4px;
}
.mobile-slot {
display: flex;
flex: 1 1 0;
min-width: 0;
align-items: center;
}
.mobile-control {
appearance: none;
-webkit-appearance: none;
display: flex;
width: 100%;
min-width: 0;
height: 100%;
margin: 0;
padding: 0;
align-items: center;
justify-content: center;
border: 0;
outline: 0;
background: transparent;
color: #718096;
text-decoration: none;
font: inherit;
cursor: pointer;
}
.mobile-control[aria-disabled="true"] {
cursor: not-allowed;
}
.mobile-content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
width: 100%;
min-width: 0;
gap: 2px;
padding: 4px;
border-radius: 12px;
color: #718096;
background: transparent;
opacity: 1;
transition: background-color 150ms ease, color 150ms ease;
}
.mobile-control[data-active="true"] .mobile-content {
color: #2b6cb0;
background: #ebf8ff;
}
.mobile-control[aria-disabled="true"] .mobile-content {
opacity: 0.4;
}
.mobile-control.mobile-exit .mobile-content {
color: #c53030;
}
.mobile-icon {
display: inline-flex;
align-items: center;
justify-content: center;
width: 16px;
height: 16px;
flex: 0 0 16px;
color: #314E89 !important;
pointer-events: none;
}
.mobile-icon > *,
.mobile-icon svg {
display: block;
width: 16px;
height: 16px;
max-width: 16px;
max-height: 16px;
color: #314E89 !important;
}
.mobile-control.mobile-exit .mobile-icon,
.mobile-control.mobile-exit .mobile-icon > *,
.mobile-control.mobile-exit .mobile-icon svg,
.drawer-exit .mobile-icon,
.drawer-exit .mobile-icon > *,
.drawer-exit .mobile-icon svg {
color: #c53030 !important;
}
.mobile-label {
display: block;
width: 100%;
min-width: 0;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
color: currentColor;
font-size: 10px;
font-weight: 500;
line-height: 1.375;
text-align: center;
}
.mobile-control[data-active="true"] .mobile-label {
font-weight: 700;
}
.drawer-layer {
position: fixed;
inset: 0;
z-index: 1300;
display: none;
align-items: flex-end;
justify-content: stretch;
}
.drawer-layer[data-open="true"] {
display: flex;
}
.drawer-overlay {
position: absolute;
inset: 0;
background: rgba(0, 0, 0, 0.48);
}
.drawer-panel {
position: relative;
z-index: 1;
display: flex;
flex-direction: column;
width: 100%;
max-height: min(78dvh, 620px);
padding-bottom: env(safe-area-inset-bottom);
overflow: hidden;
border-radius: 16px 16px 0 0;
background: #fff;
box-shadow: 0 -12px 32px rgba(0, 0, 0, 0.16);
}
.drawer-header {
position: relative;
display: flex;
min-height: 52px;
padding: 14px 48px 14px 16px;
align-items: center;
border-bottom: 1px solid #e2e8f0;
color: #1a202c;
font-size: 16px;
font-weight: 700;
line-height: 1.3;
}
.drawer-close {
appearance: none;
-webkit-appearance: none;
position: absolute;
top: 10px;
inset-inline-end: 10px;
display: inline-flex;
width: 32px;
height: 32px;
padding: 0;
align-items: center;
justify-content: center;
border: 0;
border-radius: 8px;
background: transparent;
color: #4a5568;
cursor: pointer;
}
.drawer-body {
padding: 16px;
overflow-y: auto;
overscroll-behavior: contain;
}
.drawer-grid {
display: grid;
grid-template-columns: repeat(4, minmax(0, 1fr));
gap: 8px;
}
.drawer-item-wrap {
min-width: 0;
}
.drawer-item {
appearance: none;
-webkit-appearance: none;
display: flex;
width: 100%;
height: 70px;
min-width: 0;
padding: 4px;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 4px;
border: 1px solid #e2e8f0;
border-radius: 8px;
background: #fff;
color: #4a5568;
text-decoration: none;
font: inherit;
cursor: pointer;
}
.drawer-item[data-active="true"] {
border-color: #63b3ed;
background: #ebf8ff;
color: #2c5282;
}
.drawer-item[aria-disabled="true"] {
opacity: 0.4;
cursor: not-allowed;
}
.drawer-item .mobile-label {
display: -webkit-box;
overflow: hidden;
white-space: normal;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
font-size: 10px;
line-height: 1.25;
}
.drawer-item[data-active="true"] .mobile-label {
font-weight: 700;
}
.drawer-exit-section {
margin-top: 16px;
padding-top: 16px;
border-top: 1px solid #e2e8f0;
}
.drawer-exit {
appearance: none;
-webkit-appearance: none;
display: flex;
width: 100%;
min-height: 44px;
padding: 12px;
align-items: center;
justify-content: center;
gap: 8px;
border: 0;
border-radius: 12px;
background: #fff5f5;
color: #c53030;
font: inherit;
font-weight: 700;
cursor: pointer;
}
.drawer-exit[aria-disabled="true"] {
opacity: 0.4;
cursor: not-allowed;
}
}
@media (min-width: 62em) {
.mobile-nav,
.drawer-layer {
display: none !important;
}
}
@media (prefers-reduced-motion: reduce) {
.item,
.mobile-content { transition: none; }
}
`;
function v() {
return typeof window > "u" ? {} : window[x] || {};
}
function r(c, e) {
const i = document.createElement(c);
return e && (i.className = e), i;
}
function f(c, e) {
c.innerHTML = e || "";
}
class y extends HTMLElement {
constructor() {
super(), this._props = {}, this._iconRoots = [], this._shadow = this.attachShadow({ mode: "open" }), this._drawerOpen = !1, this._moreButton = null, this._shadow.addEventListener("keydown", (e) => {
e.key === "Escape" && this._drawerOpen && this.setDrawerOpen(!1);
});
}
connectedCallback() {
this.render();
}
disconnectedCallback() {
this.cleanupIconRoots();
}
set componentProps(e) {
this._props = e || {}, this.isConnected && this.render();
}
get componentProps() {
return this._props;
}
cleanupIconRoots() {
for (const e of this._iconRoots)
try {
e.unmount();
} catch {
}
this._iconRoots = [];
}
mountReactIcon(e, i) {
const { React: t, createRoot: o } = v();
if (!t || !o || !t.isValidElement?.(i)) return !1;
const n = o(e);
return n.render(i), this._iconRoots.push(n), !0;
}
renderIcon(e, i) {
const t = i?.icon;
if (!this.mountReactIcon(e, t)) {
if (typeof i?.iconSvg == "string") {
f(e, i.iconSvg);
return;
}
typeof t == "string" && t.trim().startsWith("<svg") && f(e, t);
}
}
getItemLabel(e) {
return String(e?.mobileTitle || e?.title || "");
}
hideTooltip() {
this._tooltip && (this._tooltip.dataset.open = "false");
}
showTooltip(e, i) {
if (!this._tooltip || !e || !i) return;
this._tooltip.textContent = i, this._tooltip.dataset.open = "true", this._tooltip.style.left = "0px", this._tooltip.style.top = "0px";
const t = e.getBoundingClientRect(), o = this._tooltip.getBoundingClientRect(), n = Math.max(8, t.left - o.width - 10), a = Math.max(8, Math.min(t.top, window.innerHeight - o.height - 8));
this._tooltip.style.left = `${n}px`, this._tooltip.style.top = `${a}px`;
}
bindTooltip(e, i, t) {
const o = () => this.showTooltip(i, t), n = () => this.hideTooltip();
e.addEventListener("mouseenter", o), e.addEventListener("mouseleave", n), i.addEventListener("focus", o), i.addEventListener("blur", n);
}
createItemControl(e, i, t, o) {
const n = !!e?.disabled, a = !!e?.active, l = typeof e?.onClick == "function", s = typeof e?.href == "string" && e.href.length > 0, d = r(s && !l ? "a" : "button", t);
return d.tagName === "BUTTON" ? d.type = "button" : (d.href = e.href, e.target && (d.target = e.target), e.rel && (d.rel = e.rel)), d.setAttribute("aria-label", String(e?.title || `آیتم ${i + 1}`)), d.setAttribute("aria-disabled", n ? "true" : "false"), d.dataset.active = a ? "true" : "false", a && d.setAttribute("aria-current", "page"), n && (d.tabIndex = -1), d.addEventListener("click", (p) => {
if (n) {
p.preventDefault(), p.stopPropagation();
return;
}
l && e.onClick(e, p), typeof o == "function" && o(e, p);
}), d;
}
createNavItem(e, i) {
const t = r("div", "item-wrap"), n = !!e?.disabled ? "عدم دسترسی" : String(e?.title || ""), a = this.createItemControl(e, i, "item"), l = r("span", "icon");
return a.appendChild(l), this.renderIcon(l, e), t.appendChild(a), this.bindTooltip(t, a, n), t;
}
createExitItem() {
const { onExit: e, exitDisabled: i = !1 } = this._props, t = "خروج", o = r("div", "item-wrap"), n = r("button", "item");
n.type = "button", n.setAttribute("aria-label", t), n.setAttribute("aria-disabled", i ? "true" : "false"), i && (n.tabIndex = -1), n.addEventListener("click", (l) => {
i || typeof e == "function" && e(l);
});
const a = r("span", "icon exit-icon");
return a.innerHTML = h, n.appendChild(a), o.appendChild(n), this.bindTooltip(
o,
n,
i ? "عدم دسترسی" : t
), o;
}
createMobileContent(e, i = !1) {
const t = r("span", "mobile-content"), o = r("span", `mobile-icon${i ? " exit-icon" : ""}`);
i ? o.innerHTML = h : this.renderIcon(o, e);
const n = r("span", "mobile-label");
return n.textContent = i ? "خروج" : this.getItemLabel(e), t.appendChild(o), t.appendChild(n), t;
}
createMobileItem(e, i, { drawer: t = !1 } = {}) {
const o = r("div", t ? "drawer-item-wrap" : "mobile-slot"), n = this.createItemControl(
e,
i,
t ? "drawer-item" : "mobile-control",
t ? () => this.setDrawerOpen(!1) : void 0
);
return n.appendChild(this.createMobileContent(e)), o.appendChild(n), o;
}
createMobileExit({ drawer: e = !1 } = {}) {
const { onExit: i, exitDisabled: t = !1 } = this._props, o = "خروج";
if (e) {
const l = r("div", "drawer-exit-section"), s = r("button", "drawer-exit");
s.type = "button", s.setAttribute("aria-label", o), s.setAttribute("aria-disabled", t ? "true" : "false"), t && (s.tabIndex = -1);
const d = r("span", "mobile-icon exit-icon");
d.innerHTML = h;
const p = r("span");
return p.textContent = "خروج", s.appendChild(d), s.appendChild(p), s.addEventListener("click", (u) => {
t || (this.setDrawerOpen(!1), typeof i == "function" && i(u));
}), l.appendChild(s), l;
}
const n = r("div", "mobile-slot"), a = r("button", "mobile-control mobile-exit");
return a.type = "button", a.setAttribute("aria-label", o), a.setAttribute("aria-disabled", t ? "true" : "false"), a.dataset.active = "false", t && (a.tabIndex = -1), a.appendChild(this.createMobileContent(null, !0)), a.addEventListener("click", (l) => {
t || typeof i == "function" && i(l);
}), n.appendChild(a), n;
}
createMoreButton(e) {
const i = r("div", "mobile-slot"), t = r("button", "mobile-control");
t.type = "button", t.setAttribute("aria-label", "نمایش سایر بخش‌ها"), t.setAttribute("aria-haspopup", "dialog"), t.setAttribute("aria-expanded", this._drawerOpen ? "true" : "false"), t.dataset.active = e ? "true" : "false";
const o = r("span", "mobile-content"), n = r("span", "mobile-icon");
n.innerHTML = m;
const a = r("span", "mobile-label");
return a.textContent = "بیشتر", o.appendChild(n), o.appendChild(a), t.appendChild(o), t.addEventListener("click", () => this.setDrawerOpen(!0)), i.appendChild(t), this._moreButton = t, i;
}
createDrawer(e) {
const i = r("div", "drawer-layer");
i.dataset.open = this._drawerOpen ? "true" : "false";
const t = r("div", "drawer-overlay");
t.addEventListener("click", () => this.setDrawerOpen(!1));
const o = r("section", "drawer-panel");
o.setAttribute("role", "dialog"), o.setAttribute("aria-modal", "true"), o.setAttribute("aria-label", "سایر بخش‌های سامانه");
const n = r("div", "drawer-header");
n.textContent = "سایر بخش‌های سامانه";
const a = r("button", "drawer-close");
a.type = "button", a.setAttribute("aria-label", "بستن"), a.innerHTML = w, a.addEventListener("click", () => this.setDrawerOpen(!1)), n.appendChild(a);
const l = r("div", "drawer-body"), s = r("div", "drawer-grid");
return e.forEach((d, p) => {
s.appendChild(this.createMobileItem(d, p + 4, { drawer: !0 }));
}), l.appendChild(s), this._props.showExit && l.appendChild(this.createMobileExit({ drawer: !0 })), o.appendChild(n), o.appendChild(l), i.appendChild(t), i.appendChild(o), this._drawerLayer = i, i;
}
setDrawerOpen(e) {
this._drawerOpen = !!e, this._drawerLayer && (this._drawerLayer.dataset.open = this._drawerOpen ? "true" : "false"), this._moreButton && this._moreButton.setAttribute("aria-expanded", this._drawerOpen ? "true" : "false"), !this._drawerOpen && this._moreButton && this._moreButton.focus({ preventScroll: !0 });
}
renderDesktop(e) {
const i = r("nav", "desktop-nav");
i.setAttribute("aria-label", this._props.ariaLabel || "ناوبری اصلی"), i.dir = this._props.dir === "ltr" ? "ltr" : "rtl";
const t = r("div", "items");
return e.forEach((o, n) => {
t.appendChild(this.createNavItem(o, n));
}), this._props.showExit && t.appendChild(this.createExitItem()), i.appendChild(t), i;
}
renderMobile(e) {
const i = r("nav", "mobile-nav");
i.setAttribute("aria-label", `${this._props.ariaLabel || "ناوبری اصلی"} موبایل`), i.dir = this._props.dir === "ltr" ? "ltr" : "rtl";
const t = r("div", "mobile-bar"), o = e.length > 4, n = o ? e.slice(0, 4) : e, a = o ? e.slice(4) : [];
if (n.forEach((l, s) => {
t.appendChild(this.createMobileItem(l, s));
}), o) {
const l = a.some((s) => !!s?.active);
t.appendChild(this.createMoreButton(l));
} else this._props.showExit && t.appendChild(this.createMobileExit());
return i.appendChild(t), {
mobileNav: i,
drawer: o ? this.createDrawer(a) : null
};
}
render() {
this.cleanupIconRoots(), this._shadow.replaceChildren(), this._drawerOpen = !1, this._drawerLayer = null, this._moreButton = null;
const e = document.createElement("style");
e.textContent = g, this._shadow.appendChild(e);
const i = Array.isArray(this._props.items) ? this._props.items.filter((n) => n && !n.hidden) : [];
this._shadow.appendChild(this.renderDesktop(i));
const { mobileNav: t, drawer: o } = this.renderMobile(i);
this._shadow.appendChild(t), o && this._shadow.appendChild(o), this._tooltip = r("span", "floating-tooltip"), this._tooltip.setAttribute("role", "tooltip"), this._tooltip.dataset.open = "false", this._shadow.appendChild(this._tooltip);
}
}
customElements.get(b) || customElements.define(b, y);
export {
y as AppSidebarElement
};