@dskripchenko/laravel-admin 1.1.7 → 1.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +57 -55
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.mjs
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ref as E, computed as p, defineComponent as L, openBlock as s, createElementBlock as c, createElementVNode as d, createBlock as w, unref as r, withCtx as m, Fragment as T, renderList as I, createTextVNode as C, toDisplayString as h, createCommentVNode as F, createVNode as x, renderSlot as H, resolveDynamicComponent as ue, normalizeClass as Y, createSlots as qe, h as wt, watch as
|
|
2
|
-
import { defineStore as
|
|
1
|
+
import { ref as E, computed as p, defineComponent as L, openBlock as s, createElementBlock as c, createElementVNode as d, createBlock as w, unref as r, withCtx as m, Fragment as T, renderList as I, createTextVNode as C, toDisplayString as h, createCommentVNode as F, createVNode as x, renderSlot as H, resolveDynamicComponent as ue, normalizeClass as Y, createSlots as qe, h as wt, watch as ne, onBeforeUnmount as $t, resolveComponent as lt, withModifiers as Oe, nextTick as Ie, onMounted as Re, withKeys as xt, normalizeProps as Ue, mergeProps as Ee, normalizeStyle as Fe, inject as st, provide as Ct, createApp as St, reactive as At } from "vue";
|
|
2
|
+
import { defineStore as ae, createPinia as Rt } from "pinia";
|
|
3
3
|
import { RouterLink as Ut, useRouter as le, useRoute as _e, createWebHistory as it, createRouter as Et } from "vue-router";
|
|
4
4
|
import { UidMenu as ot, UidMenuItem as De, UidMenuSeparator as Ft, UidAvatar as rt, UidSidebar as Lt, UidSidebarGroup as Pt, UidSidebarItem as Tt, UidSidebarLayout as Mt, UidCard as q, UidButton as B, UidAlert as Q, UidInput as re, UidCheckbox as Se, UidSkeleton as We, UidErrorState as Nt, UidEmptyState as It, UidTable as je, UidPagination as Bt, UidBadge as Ke, UidSelect as Ae, UidStat as xe, UidHeatmap as Vt, UidGauge as zt, UidFormField as ye, UidTextarea as qt, UidNumberInput as Dt, UidDatePicker as Ot, UidStack as Wt, UidGrid as jt, UidTabs as ut, UidTabPanel as dt, UidTab as Ce, UidDescriptionList as Kt, UidDescriptionItem as Gt, UidDrawer as Ht, UidStepper as Xt, UidFileUpload as Jt, UidProgress as Yt } from "@dskripchenko/ui";
|
|
5
5
|
import Qt from "axios";
|
|
@@ -22,7 +22,7 @@ function Ii() {
|
|
|
22
22
|
function Bi() {
|
|
23
23
|
return he !== null;
|
|
24
24
|
}
|
|
25
|
-
const Ge =
|
|
25
|
+
const Ge = ae("admin-theme", () => {
|
|
26
26
|
const e = E("light"), t = E(["light", "dark"]), n = p(() => e.value === "dark");
|
|
27
27
|
function o(u) {
|
|
28
28
|
e.value = u.theme, t.value = u.availableThemes, i(u.theme);
|
|
@@ -77,7 +77,7 @@ const Ge = ne("admin-theme", () => {
|
|
|
77
77
|
}, null, 8, tn)
|
|
78
78
|
], 8, en));
|
|
79
79
|
}
|
|
80
|
-
}), He =
|
|
80
|
+
}), He = ae("admin-locale", () => {
|
|
81
81
|
const e = E("ru"), t = E(["ru", "en"]);
|
|
82
82
|
function n(i) {
|
|
83
83
|
e.value = i.locale, t.value = i.availableLocales, l(i.locale);
|
|
@@ -148,7 +148,7 @@ const Ge = ne("admin-theme", () => {
|
|
|
148
148
|
_: 1
|
|
149
149
|
}));
|
|
150
150
|
}
|
|
151
|
-
}), Xe =
|
|
151
|
+
}), Xe = ae("admin-notifications", () => {
|
|
152
152
|
const e = E([]), t = E(0), n = E(!1), o = E("all"), a = E(null), l = p(() => t.value > 0);
|
|
153
153
|
function i(A) {
|
|
154
154
|
t.value = A.unread_notifications_count;
|
|
@@ -290,7 +290,7 @@ function Ye(e, t) {
|
|
|
290
290
|
return new Z(e, t);
|
|
291
291
|
}
|
|
292
292
|
}
|
|
293
|
-
const J =
|
|
293
|
+
const J = ae("admin-auth", () => {
|
|
294
294
|
const e = E(null), t = E([]), n = E(null), o = p(() => e.value !== null), a = p(() => n.value !== null);
|
|
295
295
|
function l(_) {
|
|
296
296
|
e.value = _.user, t.value = _.permissions;
|
|
@@ -490,7 +490,7 @@ const J = ne("admin-auth", () => {
|
|
|
490
490
|
x(un)
|
|
491
491
|
]));
|
|
492
492
|
}
|
|
493
|
-
}), vn =
|
|
493
|
+
}), vn = ae("admin-menu", () => {
|
|
494
494
|
const e = E([]), t = E(!1), n = E(null), o = E(!1), a = p(() => {
|
|
495
495
|
const v = J(), b = (S) => {
|
|
496
496
|
if (Array.isArray(S.permissions) && S.permissions.length > 0 && !v.hasAnyPermission(S.permissions))
|
|
@@ -651,7 +651,7 @@ const J = ne("admin-auth", () => {
|
|
|
651
651
|
function l() {
|
|
652
652
|
o("exit-impersonation");
|
|
653
653
|
}
|
|
654
|
-
return
|
|
654
|
+
return ne(
|
|
655
655
|
() => n.impersonation,
|
|
656
656
|
(i) => {
|
|
657
657
|
typeof document > "u" || (i !== null ? document.documentElement.setAttribute(Be, "true") : document.documentElement.removeAttribute(Be));
|
|
@@ -709,7 +709,7 @@ const J = ne("admin-auth", () => {
|
|
|
709
709
|
})) : (s(), w(l, { key: 1 }));
|
|
710
710
|
};
|
|
711
711
|
}
|
|
712
|
-
}), se =
|
|
712
|
+
}), se = ae("admin-manifest", () => {
|
|
713
713
|
const e = E(null), t = E(!1), n = E(null), o = p(() => e.value !== null), a = p(() => e.value?.version ?? null), l = p(() => e.value?.resources ?? []), i = p(() => e.value?.screens ?? []), u = p(() => e.value?.settings ?? []), f = p(() => e.value?.plugins ?? []);
|
|
714
714
|
function v(_) {
|
|
715
715
|
return l.value.find((g) => g.slug === _) ?? null;
|
|
@@ -1001,20 +1001,20 @@ const J = ne("admin-auth", () => {
|
|
|
1001
1001
|
V instanceof HTMLInputElement && (u.value[$] = V);
|
|
1002
1002
|
}
|
|
1003
1003
|
function _($, V) {
|
|
1004
|
-
const
|
|
1005
|
-
l.value[$] = D,
|
|
1004
|
+
const K = V.target, D = K.value.replace(/\D/g, "").slice(-1);
|
|
1005
|
+
l.value[$] = D, K.value = D, D && $ < l.value.length - 1 && Ie(() => u.value[$ + 1]?.focus()), S.value.length === l.value.length && P();
|
|
1006
1006
|
}
|
|
1007
1007
|
function g($, V) {
|
|
1008
1008
|
V.key === "Backspace" && !l.value[$] && $ > 0 ? Ie(() => u.value[$ - 1]?.focus()) : V.key === "ArrowLeft" && $ > 0 ? (u.value[$ - 1]?.focus(), V.preventDefault()) : V.key === "ArrowRight" && $ < l.value.length - 1 && (u.value[$ + 1]?.focus(), V.preventDefault());
|
|
1009
1009
|
}
|
|
1010
1010
|
function U($) {
|
|
1011
|
-
const
|
|
1012
|
-
if (
|
|
1011
|
+
const K = ($.clipboardData?.getData("text") ?? "").replace(/\D/g, "").slice(0, l.value.length);
|
|
1012
|
+
if (K.length !== 0) {
|
|
1013
1013
|
$.preventDefault();
|
|
1014
1014
|
for (let D = 0; D < l.value.length; D++)
|
|
1015
|
-
l.value[D] =
|
|
1015
|
+
l.value[D] = K[D] ?? "";
|
|
1016
1016
|
Ie(() => {
|
|
1017
|
-
u.value[Math.min(
|
|
1017
|
+
u.value[Math.min(K.length, l.value.length - 1)]?.focus(), K.length === l.value.length && P();
|
|
1018
1018
|
});
|
|
1019
1019
|
}
|
|
1020
1020
|
}
|
|
@@ -1074,7 +1074,7 @@ const J = ne("admin-auth", () => {
|
|
|
1074
1074
|
class: "admin-code-input",
|
|
1075
1075
|
onPaste: U
|
|
1076
1076
|
}, [
|
|
1077
|
-
(s(!0), c(T, null, I(l.value, (
|
|
1077
|
+
(s(!0), c(T, null, I(l.value, (K, D) => (s(), c("input", {
|
|
1078
1078
|
key: D,
|
|
1079
1079
|
ref_for: !0,
|
|
1080
1080
|
ref: (M) => R(D, M),
|
|
@@ -1091,7 +1091,7 @@ const J = ne("admin-auth", () => {
|
|
|
1091
1091
|
], 32)) : (s(), w(r(re), {
|
|
1092
1092
|
key: 3,
|
|
1093
1093
|
modelValue: i.value,
|
|
1094
|
-
"onUpdate:modelValue": V[0] || (V[0] = (
|
|
1094
|
+
"onUpdate:modelValue": V[0] || (V[0] = (K) => i.value = K),
|
|
1095
1095
|
type: "text",
|
|
1096
1096
|
label: "Recovery-код",
|
|
1097
1097
|
autocomplete: "one-time-code",
|
|
@@ -1159,7 +1159,7 @@ const J = ne("admin-auth", () => {
|
|
|
1159
1159
|
}
|
|
1160
1160
|
await o.push({ name: t.homeRouteName });
|
|
1161
1161
|
}
|
|
1162
|
-
return
|
|
1162
|
+
return ne(
|
|
1163
1163
|
() => n.isAuthenticated,
|
|
1164
1164
|
(i) => {
|
|
1165
1165
|
i && l();
|
|
@@ -1220,7 +1220,7 @@ const J = ne("admin-auth", () => {
|
|
|
1220
1220
|
}, 8, ["class"])
|
|
1221
1221
|
]));
|
|
1222
1222
|
}
|
|
1223
|
-
}), Qe = { page: 1, per_page: 20, total: 0, last_page: 1 }, ca =
|
|
1223
|
+
}), Qe = { page: 1, per_page: 20, total: 0, last_page: 1 }, ca = ae("admin-resource-index", () => {
|
|
1224
1224
|
const e = E(null), t = E([]), n = E({ ...Qe }), o = E(!1), a = E(null), l = E(""), i = E({}), u = E(null), f = E("asc"), v = E(/* @__PURE__ */ new Set()), b = p(() => !o.value && a.value === null && t.value.length === 0), S = p(() => v.value.size), A = p(() => v.value.size > 0), R = p(() => a.value !== null), _ = p(() => v.value.size === 0 || t.value.length === 0 ? "none" : t.value.every((z) => v.value.has(g(z))) ? "all" : "mixed");
|
|
1225
1225
|
function g(N) {
|
|
1226
1226
|
return N.id ?? N.key ?? "";
|
|
@@ -1263,7 +1263,7 @@ const J = ne("admin-auth", () => {
|
|
|
1263
1263
|
async function V(N, z) {
|
|
1264
1264
|
z == null || z === "" ? delete i.value[N] : i.value[N] = z, n.value.page = 1, await y();
|
|
1265
1265
|
}
|
|
1266
|
-
async function
|
|
1266
|
+
async function K() {
|
|
1267
1267
|
i.value = {}, n.value.page = 1, await y();
|
|
1268
1268
|
}
|
|
1269
1269
|
async function D(N, z = "asc") {
|
|
@@ -1279,7 +1279,7 @@ const J = ne("admin-auth", () => {
|
|
|
1279
1279
|
const z = new Set(v.value);
|
|
1280
1280
|
z.has(N) ? z.delete(N) : z.add(N), v.value = z;
|
|
1281
1281
|
}
|
|
1282
|
-
function
|
|
1282
|
+
function j() {
|
|
1283
1283
|
if (_.value === "all") {
|
|
1284
1284
|
v.value = /* @__PURE__ */ new Set();
|
|
1285
1285
|
return;
|
|
@@ -1288,7 +1288,7 @@ const J = ne("admin-auth", () => {
|
|
|
1288
1288
|
for (const z of t.value) N.add(g(z));
|
|
1289
1289
|
v.value = N;
|
|
1290
1290
|
}
|
|
1291
|
-
function
|
|
1291
|
+
function ee() {
|
|
1292
1292
|
v.value = /* @__PURE__ */ new Set();
|
|
1293
1293
|
}
|
|
1294
1294
|
function yt(N) {
|
|
@@ -1318,13 +1318,13 @@ const J = ne("admin-auth", () => {
|
|
|
1318
1318
|
load: y,
|
|
1319
1319
|
setSearch: $,
|
|
1320
1320
|
setFilter: V,
|
|
1321
|
-
clearFilters:
|
|
1321
|
+
clearFilters: K,
|
|
1322
1322
|
setSort: D,
|
|
1323
1323
|
toggleSort: M,
|
|
1324
1324
|
setPage: O,
|
|
1325
1325
|
toggleRow: G,
|
|
1326
|
-
toggleAllOnPage:
|
|
1327
|
-
clearSelection:
|
|
1326
|
+
toggleAllOnPage: j,
|
|
1327
|
+
clearSelection: ee,
|
|
1328
1328
|
isSelected: yt,
|
|
1329
1329
|
rowId: g
|
|
1330
1330
|
};
|
|
@@ -1377,7 +1377,7 @@ const J = ne("admin-auth", () => {
|
|
|
1377
1377
|
a.setSlug(n.slug), l.manifest === null && await l.load().catch(() => {
|
|
1378
1378
|
}), await a.load().catch(() => {
|
|
1379
1379
|
});
|
|
1380
|
-
}),
|
|
1380
|
+
}), ne(
|
|
1381
1381
|
() => n.slug,
|
|
1382
1382
|
async (P, k) => {
|
|
1383
1383
|
P !== k && (a.setSlug(P), await a.load().catch(() => {
|
|
@@ -1614,13 +1614,13 @@ const J = ne("admin-auth", () => {
|
|
|
1614
1614
|
])) : F("", !0)
|
|
1615
1615
|
]));
|
|
1616
1616
|
}
|
|
1617
|
-
}), pt =
|
|
1617
|
+
}), pt = ae("admin-resource-form", () => {
|
|
1618
1618
|
const e = E(null), t = E("create"), n = E(null), o = E({}), a = E({}), l = E({}), i = E(!1), u = E(!1), f = E(!1), v = E(null), b = p(() => t.value === "create"), S = p(() => t.value === "edit"), A = p(() => t.value === "view"), R = p(() => v.value !== null), _ = p(() => {
|
|
1619
1619
|
const M = o.value, O = a.value, G = /* @__PURE__ */ new Set([...Object.keys(M), ...Object.keys(O)]);
|
|
1620
|
-
for (const
|
|
1621
|
-
if (!Object.is(M[
|
|
1622
|
-
if (typeof M[
|
|
1623
|
-
if (JSON.stringify(M[
|
|
1620
|
+
for (const j of G)
|
|
1621
|
+
if (!Object.is(M[j], O[j]))
|
|
1622
|
+
if (typeof M[j] == "object" || typeof O[j] == "object") {
|
|
1623
|
+
if (JSON.stringify(M[j]) !== JSON.stringify(O[j])) return !0;
|
|
1624
1624
|
} else
|
|
1625
1625
|
return !0;
|
|
1626
1626
|
return !1;
|
|
@@ -1638,12 +1638,12 @@ const J = ne("admin-auth", () => {
|
|
|
1638
1638
|
async function k(M, O, G = "edit") {
|
|
1639
1639
|
e.value = M, t.value = G, n.value = O, i.value = !0, v.value = null, l.value = {};
|
|
1640
1640
|
try {
|
|
1641
|
-
const
|
|
1641
|
+
const ee = await W().get(`/${M}/read`, {
|
|
1642
1642
|
params: { id: O }
|
|
1643
1643
|
});
|
|
1644
|
-
g(o.value,
|
|
1645
|
-
} catch (
|
|
1646
|
-
throw v.value =
|
|
1644
|
+
g(o.value, ee.record), g(a.value, ee.record);
|
|
1645
|
+
} catch (j) {
|
|
1646
|
+
throw v.value = j instanceof Error ? j : new Error(String(j)), j;
|
|
1647
1647
|
} finally {
|
|
1648
1648
|
i.value = !1;
|
|
1649
1649
|
}
|
|
@@ -1660,13 +1660,15 @@ const J = ne("admin-auth", () => {
|
|
|
1660
1660
|
function V() {
|
|
1661
1661
|
l.value = {};
|
|
1662
1662
|
}
|
|
1663
|
-
async function
|
|
1663
|
+
async function K() {
|
|
1664
1664
|
if (!e.value) throw new Error("useResourceFormStore.save() before slug set");
|
|
1665
1665
|
if (u.value) throw new Error("Already saving");
|
|
1666
1666
|
u.value = !0, v.value = null, l.value = {};
|
|
1667
1667
|
try {
|
|
1668
|
-
const M = W(), O = t.value === "create" ? `/${e.value}/create` : `/${e.value}/update`, G = t.value === "create" ? o.value : { id: n.value, ...o.value },
|
|
1669
|
-
|
|
1668
|
+
const M = W(), O = t.value === "create" ? `/${e.value}/create` : `/${e.value}/update`, G = t.value === "create" ? o.value : { id: n.value, ...o.value }, j = await M.post(O, G), ee = j.record?.id ?? j.id;
|
|
1669
|
+
if (ee === void 0)
|
|
1670
|
+
throw new Error("save: backend response does not contain record.id");
|
|
1671
|
+
return n.value = ee, g(a.value, { ...o.value }), t.value = "edit", ee;
|
|
1670
1672
|
} catch (M) {
|
|
1671
1673
|
throw M instanceof Le ? l.value = { ...M.fields } : (M instanceof Z || M instanceof Error) && (v.value = M), M;
|
|
1672
1674
|
} finally {
|
|
@@ -1711,7 +1713,7 @@ const J = ne("admin-auth", () => {
|
|
|
1711
1713
|
setField: y,
|
|
1712
1714
|
setErrors: $,
|
|
1713
1715
|
clearErrors: V,
|
|
1714
|
-
save:
|
|
1716
|
+
save: K,
|
|
1715
1717
|
destroy: D
|
|
1716
1718
|
};
|
|
1717
1719
|
});
|
|
@@ -1827,7 +1829,7 @@ const ht = /* @__PURE__ */ L({
|
|
|
1827
1829
|
},
|
|
1828
1830
|
setup(e) {
|
|
1829
1831
|
const t = e, n = pt(), o = se(), a = le(), l = ct(n.state, n.errors);
|
|
1830
|
-
|
|
1832
|
+
ne(
|
|
1831
1833
|
() => n.errors,
|
|
1832
1834
|
(_) => {
|
|
1833
1835
|
l.setErrors({ ..._ });
|
|
@@ -1855,7 +1857,7 @@ const ht = /* @__PURE__ */ L({
|
|
|
1855
1857
|
o.manifest === null && await o.load().catch(() => {
|
|
1856
1858
|
}), t.id !== null && t.id !== void 0 ? await n.load(t.slug, t.id, "edit").catch(() => {
|
|
1857
1859
|
}) : n.prepareCreate(t.slug);
|
|
1858
|
-
}),
|
|
1860
|
+
}), ne(
|
|
1859
1861
|
() => [t.slug, t.id],
|
|
1860
1862
|
async ([_, g]) => {
|
|
1861
1863
|
g != null ? await n.load(_, g, "edit").catch(() => {
|
|
@@ -2150,7 +2152,7 @@ const Ya = { class: "admin-page admin-resource-view" }, Qa = { class: "admin-pag
|
|
|
2150
2152
|
o.manifest === null && await o.load().catch(() => {
|
|
2151
2153
|
}), await n.load(t.slug, t.id, "view").catch(() => {
|
|
2152
2154
|
});
|
|
2153
|
-
}),
|
|
2155
|
+
}), ne(
|
|
2154
2156
|
() => [t.slug, t.id],
|
|
2155
2157
|
async ([b, S]) => {
|
|
2156
2158
|
await n.load(b, S, "view").catch(() => {
|
|
@@ -3232,7 +3234,7 @@ const X = /* @__PURE__ */ L({
|
|
|
3232
3234
|
_: 1
|
|
3233
3235
|
}, 8, ["label", "hint", "error", "required", "disabled"]));
|
|
3234
3236
|
}
|
|
3235
|
-
}),
|
|
3237
|
+
}), te = /* @__PURE__ */ L({
|
|
3236
3238
|
__name: "SelectField",
|
|
3237
3239
|
props: {
|
|
3238
3240
|
name: {},
|
|
@@ -3517,14 +3519,14 @@ function Is() {
|
|
|
3517
3519
|
number: Ve,
|
|
3518
3520
|
slider: Ve,
|
|
3519
3521
|
rating: Ve,
|
|
3520
|
-
select:
|
|
3521
|
-
combobox:
|
|
3522
|
-
radio:
|
|
3523
|
-
tags:
|
|
3524
|
-
"morph-switcher":
|
|
3525
|
-
relation:
|
|
3526
|
-
cascader:
|
|
3527
|
-
"tree-select":
|
|
3522
|
+
select: te,
|
|
3523
|
+
combobox: te,
|
|
3524
|
+
radio: te,
|
|
3525
|
+
tags: te,
|
|
3526
|
+
"morph-switcher": te,
|
|
3527
|
+
relation: te,
|
|
3528
|
+
cascader: te,
|
|
3529
|
+
"tree-select": te,
|
|
3528
3530
|
checkbox: ze,
|
|
3529
3531
|
switcher: ze,
|
|
3530
3532
|
boolean: ze,
|
|
@@ -3706,7 +3708,7 @@ function no(e, t = {}) {
|
|
|
3706
3708
|
typeof console < "u" && console.error("[laravel-admin] manifest load failed:", S);
|
|
3707
3709
|
});
|
|
3708
3710
|
};
|
|
3709
|
-
v.isAuthenticated && b(),
|
|
3711
|
+
v.isAuthenticated && b(), ne(
|
|
3710
3712
|
() => v.user,
|
|
3711
3713
|
(S, A) => {
|
|
3712
3714
|
S && !A && b();
|
|
@@ -3773,7 +3775,7 @@ const Hs = { class: "admin-notifs__hd" }, Xs = { class: "admin-notifs__title" },
|
|
|
3773
3775
|
function l(g) {
|
|
3774
3776
|
o("update:open", g);
|
|
3775
3777
|
}
|
|
3776
|
-
|
|
3778
|
+
ne(
|
|
3777
3779
|
() => n.open,
|
|
3778
3780
|
async (g) => {
|
|
3779
3781
|
g && await a.load(a.lastFilter ?? "all", 1).catch(() => {
|
|
@@ -4059,7 +4061,7 @@ const Hs = { class: "admin-notifs__hd" }, Xs = { class: "admin-notifs__title" },
|
|
|
4059
4061
|
"model-value": b.value[V.key] ?? "",
|
|
4060
4062
|
options: P.value,
|
|
4061
4063
|
placeholder: "Не импортировать",
|
|
4062
|
-
"onUpdate:modelValue": (
|
|
4064
|
+
"onUpdate:modelValue": (K) => S(V.key, K)
|
|
4063
4065
|
}, null, 8, ["model-value", "options", "onUpdate:modelValue"])
|
|
4064
4066
|
]))), 128))
|
|
4065
4067
|
]))
|
|
@@ -4319,7 +4321,7 @@ export {
|
|
|
4319
4321
|
al as ResourceViewPage,
|
|
4320
4322
|
nt as RowsLayout,
|
|
4321
4323
|
ge as SectionLayout,
|
|
4322
|
-
|
|
4324
|
+
te as SelectField,
|
|
4323
4325
|
On as SettingsPage,
|
|
4324
4326
|
Bl as StatWidget,
|
|
4325
4327
|
Ns as TabsLayout,
|