@iris-ui-kit/vue 0.1.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/admin.cjs CHANGED
@@ -342,6 +342,10 @@ var IrisNavMenu = vue.defineComponent({
342
342
  defaultExpandedKeys: { type: Array, default: void 0 },
343
343
  /** Icon-only rail (top-level items only). */
344
344
  collapsed: { type: Boolean, default: false },
345
+ orientation: {
346
+ type: String,
347
+ default: "vertical"
348
+ },
345
349
  ariaLabel: { type: String, default: void 0 }
346
350
  },
347
351
  emits: {
@@ -397,7 +401,7 @@ var IrisNavMenu = vue.defineComponent({
397
401
  display: "flex",
398
402
  alignItems: "center",
399
403
  gap: "10px",
400
- width: "100%",
404
+ width: props.orientation === "horizontal" && opts.depth === 0 ? "auto" : "100%",
401
405
  boxSizing: "border-box",
402
406
  border: "none",
403
407
  borderRadius: "var(--iris-radius-md, 6px)",
@@ -409,7 +413,8 @@ var IrisNavMenu = vue.defineComponent({
409
413
  textAlign: "start",
410
414
  cursor: opts.disabled ? "not-allowed" : "pointer",
411
415
  opacity: opts.disabled ? "0.5" : "1",
412
- padding: props.collapsed ? "10px" : `8px 10px 8px ${12 + opts.depth * 16}px`,
416
+ padding: props.collapsed ? "10px" : "8px 10px",
417
+ paddingInlineStart: props.collapsed ? "10px" : `${12 + opts.depth * 16}px`,
413
418
  justifyContent: props.collapsed ? "center" : "flex-start"
414
419
  };
415
420
  };
@@ -503,16 +508,40 @@ var IrisNavMenu = vue.defineComponent({
503
508
  }) : null
504
509
  ]
505
510
  );
511
+ const groupStyle = props.orientation === "horizontal" && depth === 0 ? { position: "relative" } : void 0;
506
512
  if (!branch || !open)
507
- return vue.h("div", { key: node.key, "data-iris-nav-group": branch ? "" : void 0 }, [row]);
508
- return vue.h("div", { key: node.key, "data-iris-nav-group": "", "data-open": "true" }, [
509
- row,
510
- vue.h(
513
+ return vue.h(
511
514
  "div",
512
- { "data-iris-nav-children": "", role: "group" },
513
- (node.children ?? []).map((child) => renderItem(child, depth + 1))
514
- )
515
- ]);
515
+ { key: node.key, "data-iris-nav-group": branch ? "" : void 0, style: groupStyle },
516
+ [row]
517
+ );
518
+ return vue.h(
519
+ "div",
520
+ { key: node.key, "data-iris-nav-group": "", "data-open": "true", style: groupStyle },
521
+ [
522
+ row,
523
+ vue.h(
524
+ "div",
525
+ {
526
+ "data-iris-nav-children": "",
527
+ role: "group",
528
+ style: props.orientation === "horizontal" && depth === 0 ? {
529
+ position: "absolute",
530
+ insetBlockStart: "calc(100% + 4px)",
531
+ insetInlineStart: "0",
532
+ zIndex: "60",
533
+ minWidth: "220px",
534
+ padding: "6px",
535
+ border: "1px solid var(--iris-border)",
536
+ borderRadius: "var(--iris-radius-md, 6px)",
537
+ background: "var(--iris-surface)",
538
+ boxShadow: "var(--iris-shadow-md)"
539
+ } : void 0
540
+ },
541
+ (node.children ?? []).map((child) => renderItem(child, depth + 1))
542
+ )
543
+ ]
544
+ );
516
545
  };
517
546
  const onKeydown = (e) => {
518
547
  const root = e.currentTarget;
@@ -565,11 +594,13 @@ var IrisNavMenu = vue.defineComponent({
565
594
  ...attrs,
566
595
  "data-iris-nav-menu": "",
567
596
  "data-collapsed": props.collapsed ? "true" : void 0,
597
+ "data-orientation": props.orientation,
568
598
  "aria-label": props.ariaLabel ?? t("admin.nav"),
569
599
  onKeydown,
570
600
  style: {
571
601
  display: "flex",
572
- flexDirection: "column",
602
+ flexDirection: props.orientation === "horizontal" ? "row" : "column",
603
+ alignItems: props.orientation === "horizontal" ? "center" : void 0,
573
604
  gap: "2px",
574
605
  ...attrs.style ?? {}
575
606
  }
@@ -759,6 +790,7 @@ function useTabsNav(nav) {
759
790
  closeRight: nav.closeRight,
760
791
  refresh: nav.refresh,
761
792
  setPinned: nav.setPinned,
793
+ move: nav.move,
762
794
  cacheKey: nav.cacheKey
763
795
  };
764
796
  }
@@ -1325,6 +1357,168 @@ var IrisDropdownSeparator = vue.defineComponent({
1325
1357
  });
1326
1358
  }
1327
1359
  });
1360
+ var SORTABLE_ITEM_ATTR = "data-iris-sortable-item";
1361
+ var IrisSortable = vue.defineComponent({
1362
+ name: "IrisSortable",
1363
+ inheritAttrs: false,
1364
+ props: {
1365
+ /** The ordered items. Used to detect which item is at which position. */
1366
+ items: {
1367
+ type: Array,
1368
+ required: true
1369
+ },
1370
+ /** Called when the user drops an item in a new position. */
1371
+ onReorder: {
1372
+ type: Function,
1373
+ default: void 0
1374
+ },
1375
+ /** Optional item key getter. Defaults to `String(index)`. */
1376
+ getKey: {
1377
+ type: Function,
1378
+ default: void 0
1379
+ },
1380
+ disabled: {
1381
+ type: Boolean,
1382
+ default: false
1383
+ },
1384
+ orientation: {
1385
+ type: String,
1386
+ default: "vertical"
1387
+ },
1388
+ class: {
1389
+ type: String,
1390
+ default: void 0
1391
+ },
1392
+ style: {
1393
+ type: Object,
1394
+ default: void 0
1395
+ }
1396
+ },
1397
+ emits: {
1398
+ reorder: (_next) => true
1399
+ },
1400
+ setup(props, { slots, attrs, emit }) {
1401
+ const containerRef = vue.ref(null);
1402
+ const sortable = core.createSortable();
1403
+ const activeKey = vue.ref(null);
1404
+ const unsub = sortable.subscribe((state) => {
1405
+ activeKey.value = state.activeId;
1406
+ });
1407
+ vue.onBeforeUnmount(unsub);
1408
+ const indexOf = (key) => {
1409
+ const container = containerRef.value;
1410
+ if (!container) return -1;
1411
+ return Array.from(
1412
+ container.querySelectorAll(`[${SORTABLE_ITEM_ATTR}]`)
1413
+ ).findIndex((el) => el.getAttribute(SORTABLE_ITEM_ATTR) === key);
1414
+ };
1415
+ const onPointerDown = (e) => {
1416
+ if (props.disabled) return;
1417
+ const target = e.target.closest(`[${SORTABLE_ITEM_ATTR}]`);
1418
+ if (!target) return;
1419
+ const container = containerRef.value;
1420
+ if (!container) return;
1421
+ const key = target.getAttribute(SORTABLE_ITEM_ATTR) ?? "";
1422
+ const index = indexOf(key);
1423
+ if (index < 0) return;
1424
+ sortable.press(key, e.clientX, e.clientY);
1425
+ };
1426
+ const onPointerMove = (e) => {
1427
+ if (!sortable.isPending() && sortable.getState().activeId === null) return;
1428
+ const items = containerRef.value?.querySelectorAll(`[${SORTABLE_ITEM_ATTR}]`);
1429
+ const rects = Array.from(items ?? []).map((el) => {
1430
+ const rect = el.getBoundingClientRect();
1431
+ return {
1432
+ id: el.getAttribute(SORTABLE_ITEM_ATTR) ?? "",
1433
+ left: rect.left,
1434
+ top: rect.top,
1435
+ width: rect.width,
1436
+ height: rect.height
1437
+ };
1438
+ });
1439
+ sortable.tryStart(e.clientX, e.clientY);
1440
+ if (sortable.getState().activeId !== null) {
1441
+ sortable.moveOver({ x: e.clientX, y: e.clientY }, rects);
1442
+ }
1443
+ };
1444
+ const onPointerUp = () => {
1445
+ const state = sortable.getState();
1446
+ if (state.activeId === null) {
1447
+ sortable.cancel();
1448
+ return;
1449
+ }
1450
+ const result = sortable.end();
1451
+ if (result.activeId && result.overId && result.activeId !== result.overId) {
1452
+ const from = indexOf(result.activeId);
1453
+ const to = indexOf(result.overId);
1454
+ if (from >= 0 && to >= 0) {
1455
+ const next = [...props.items];
1456
+ const [moved] = next.splice(from, 1);
1457
+ next.splice(to, 0, moved);
1458
+ if (props.onReorder) {
1459
+ props.onReorder(next);
1460
+ }
1461
+ emit("reorder", next);
1462
+ }
1463
+ }
1464
+ };
1465
+ const resolveKey = (item, index) => props.getKey ? props.getKey(item, index) : String(index);
1466
+ return () => {
1467
+ const children = [];
1468
+ const defaultSlots = slots.default?.();
1469
+ if (defaultSlots) {
1470
+ const itemsArray = props.items;
1471
+ defaultSlots.forEach((child, index) => {
1472
+ const item = itemsArray[index];
1473
+ const key = resolveKey(item, index);
1474
+ const isDragging = key === activeKey.value;
1475
+ children.push(
1476
+ vue.h(
1477
+ "div",
1478
+ {
1479
+ key,
1480
+ [SORTABLE_ITEM_ATTR]: key,
1481
+ "data-iris-sortable-dragging": isDragging ? "" : void 0,
1482
+ style: {
1483
+ transition: isDragging ? "none" : "transform 150ms ease",
1484
+ opacity: isDragging ? 0.4 : 1,
1485
+ position: "relative",
1486
+ zIndex: isDragging ? 100 : void 0
1487
+ }
1488
+ },
1489
+ [child]
1490
+ )
1491
+ );
1492
+ });
1493
+ }
1494
+ return vue.h(
1495
+ "div",
1496
+ {
1497
+ ...attrs,
1498
+ ref: (el) => {
1499
+ containerRef.value = el ?? null;
1500
+ },
1501
+ "data-iris-sortable": "",
1502
+ "data-state": activeKey.value ? "dragging" : "idle",
1503
+ class: props.class,
1504
+ style: {
1505
+ display: "flex",
1506
+ flexDirection: props.orientation === "horizontal" ? "row" : "column",
1507
+ gap: "var(--iris-gap-sm, 4px)",
1508
+ opacity: props.disabled ? 0.6 : 1,
1509
+ userSelect: activeKey.value ? "none" : void 0,
1510
+ ...props.style ?? {}
1511
+ },
1512
+ onPointerdown: onPointerDown,
1513
+ onPointermove: onPointerMove,
1514
+ onPointerup: onPointerUp,
1515
+ onPointerleave: onPointerUp
1516
+ },
1517
+ children
1518
+ );
1519
+ };
1520
+ }
1521
+ });
1328
1522
 
1329
1523
  // src/admin/AdminTabs.ts
1330
1524
  var IrisAdminTabs = vue.defineComponent({
@@ -1332,12 +1526,14 @@ var IrisAdminTabs = vue.defineComponent({
1332
1526
  inheritAttrs: false,
1333
1527
  props: {
1334
1528
  /** Shared tabs store (from `createTabsNav`). */
1335
- nav: { type: Object, required: true }
1529
+ nav: { type: Object, required: true },
1530
+ reorderable: { type: Boolean, default: true }
1336
1531
  },
1337
1532
  emits: {
1338
1533
  change: (_key) => true,
1339
1534
  close: (_key) => true,
1340
- refresh: (_key) => true
1535
+ refresh: (_key) => true,
1536
+ reorder: (_tabs) => true
1341
1537
  },
1342
1538
  setup(props, { emit, attrs }) {
1343
1539
  const { t: tr } = useI18n();
@@ -1354,6 +1550,10 @@ var IrisAdminTabs = vue.defineComponent({
1354
1550
  props.nav.refresh(key);
1355
1551
  emit("refresh", key);
1356
1552
  };
1553
+ const reorder = (tabs) => {
1554
+ tabs.forEach((tab, index) => props.nav.move(tab.key, index));
1555
+ emit("reorder", tabs);
1556
+ };
1357
1557
  const focusTab = (root, key) => {
1358
1558
  if (!root || !key) return;
1359
1559
  const labels = root.querySelectorAll("[data-iris-tab-label]");
@@ -1505,6 +1705,8 @@ var IrisAdminTabs = vue.defineComponent({
1505
1705
  action(tr("admin.refresh"), () => refresh(key)),
1506
1706
  action(tr("admin.close"), () => close(key)),
1507
1707
  vue.h(IrisDropdownSeparator),
1708
+ action(tr("admin.closeLeft"), () => props.nav.closeLeft(key)),
1709
+ action(tr("admin.closeRight"), () => props.nav.closeRight(key)),
1508
1710
  action(tr("admin.closeOthers"), () => props.nav.closeOthers(key)),
1509
1711
  action(tr("admin.closeAll"), () => props.nav.closeAll())
1510
1712
  ];
@@ -1536,14 +1738,28 @@ var IrisAdminTabs = vue.defineComponent({
1536
1738
  "aria-label": tr("admin.openPages"),
1537
1739
  onKeydown: onTablistKeydown,
1538
1740
  style: {
1539
- display: "flex",
1540
- alignItems: "center",
1541
- gap: "6px",
1542
1741
  overflowX: "auto",
1543
1742
  flex: "1"
1544
1743
  }
1545
1744
  },
1546
- t.tabs.value.map((tab) => chip(tab))
1745
+ [
1746
+ vue.h(
1747
+ IrisSortable,
1748
+ {
1749
+ items: t.tabs.value,
1750
+ getKey: (item) => item.key,
1751
+ onReorder: (items) => reorder(items),
1752
+ disabled: !props.reorderable,
1753
+ orientation: "horizontal",
1754
+ style: {
1755
+ alignItems: "center",
1756
+ gap: "6px",
1757
+ width: "max-content"
1758
+ }
1759
+ },
1760
+ { default: () => t.tabs.value.map((tab) => chip(tab)) }
1761
+ )
1762
+ ]
1547
1763
  ),
1548
1764
  actionsMenu()
1549
1765
  ]
@@ -1599,6 +1815,8 @@ var IrisAdminLayout = vue.defineComponent({
1599
1815
  menus: { type: Array, required: true },
1600
1816
  /** Active page key (v-model:activeKey). */
1601
1817
  activeKey: { type: String, default: void 0 },
1818
+ /** Initial active page key when `activeKey` is uncontrolled. */
1819
+ defaultActiveKey: { type: String, default: void 0 },
1602
1820
  /** Sidebar collapsed (v-model:collapsed); undefined = uncontrolled. */
1603
1821
  collapsed: { type: Boolean, default: void 0 },
1604
1822
  defaultCollapsed: { type: Boolean, default: false },
@@ -1607,7 +1825,16 @@ var IrisAdminLayout = vue.defineComponent({
1607
1825
  appTitle: { type: String, default: "Iris Admin" },
1608
1826
  /** Optional shared tabs store; when present the tab bar is rendered. */
1609
1827
  tabs: { type: Object, default: void 0 },
1828
+ showTabs: { type: Boolean, default: true },
1610
1829
  showBreadcrumb: { type: Boolean, default: true },
1830
+ stickyHeader: { type: Boolean, default: true },
1831
+ stickyTabs: { type: Boolean, default: true },
1832
+ menuAlign: { type: String, default: "start" },
1833
+ contentWidth: { type: String, default: "fluid" },
1834
+ contentHeight: {
1835
+ type: String,
1836
+ default: "viewport"
1837
+ },
1611
1838
  sidebarWidth: { type: [Number, String], default: 240 },
1612
1839
  collapsedWidth: { type: [Number, String], default: 64 }
1613
1840
  },
@@ -1626,6 +1853,7 @@ var IrisAdminLayout = vue.defineComponent({
1626
1853
  } = useAdminShell({
1627
1854
  menus: () => props.menus,
1628
1855
  activeKey: () => props.activeKey,
1856
+ defaultActiveKey: props.defaultActiveKey,
1629
1857
  tabs: props.tabs,
1630
1858
  onActiveKeyChange: (key) => emit("update:activeKey", key),
1631
1859
  onSelect: (key, node) => emit("select", key, node)
@@ -1744,11 +1972,37 @@ var IrisAdminLayout = vue.defineComponent({
1744
1972
  ) : null
1745
1973
  ]
1746
1974
  );
1747
- const renderContent = () => vue.h(
1975
+ const renderContent = (horizontal = false) => vue.h(
1748
1976
  "div",
1749
- { "data-iris-admin-content": "", style: { padding: "16px" } },
1750
- slots.default?.({ activeKey: activeKey.value }) ?? []
1977
+ {
1978
+ "data-iris-admin-content": "",
1979
+ "data-width": props.contentWidth,
1980
+ style: {
1981
+ boxSizing: "border-box",
1982
+ width: "100%",
1983
+ maxWidth: props.contentWidth === "centered" ? "72rem" : void 0,
1984
+ marginInline: props.contentWidth === "centered" ? "auto" : void 0,
1985
+ padding: "16px"
1986
+ }
1987
+ },
1988
+ [
1989
+ horizontal && props.showBreadcrumb ? vue.h(IrisAdminBreadcrumb, { trail: trail.value, hideSingle: false, onSelect }) : null,
1990
+ ...slots.default?.({ activeKey: activeKey.value }) ?? []
1991
+ ]
1751
1992
  );
1993
+ const renderTabs = () => props.tabs && props.showTabs ? vue.h(
1994
+ "div",
1995
+ {
1996
+ "data-iris-admin-tabs-region": "",
1997
+ "data-sticky": props.stickyTabs ? "true" : void 0,
1998
+ style: {
1999
+ position: props.stickyTabs && !props.stickyHeader ? "sticky" : "relative",
2000
+ top: "0",
2001
+ zIndex: "49"
2002
+ }
2003
+ },
2004
+ [vue.h(IrisAdminTabs, { nav: props.tabs })]
2005
+ ) : null;
1752
2006
  return () => {
1753
2007
  if (props.mode === "full-content") {
1754
2008
  return vue.h(
@@ -1765,6 +2019,80 @@ var IrisAdminLayout = vue.defineComponent({
1765
2019
  slots.default?.({ activeKey: activeKey.value }) ?? []
1766
2020
  );
1767
2021
  }
2022
+ if (props.mode === "horizontal") {
2023
+ const justifyContent = props.menuAlign === "center" ? "center" : props.menuAlign === "end" ? "flex-end" : "flex-start";
2024
+ return vue.h(
2025
+ "div",
2026
+ {
2027
+ ...attrs,
2028
+ "data-iris-admin-layout": "",
2029
+ "data-mode": "horizontal",
2030
+ style: {
2031
+ height: props.contentHeight === "viewport" ? "100vh" : "auto",
2032
+ minHeight: "100vh",
2033
+ ...attrs.style ?? {}
2034
+ }
2035
+ },
2036
+ [
2037
+ vue.h(
2038
+ IrisHeaderLayout,
2039
+ { sticky: props.stickyHeader },
2040
+ {
2041
+ header: () => vue.h("div", { "data-iris-admin-header": "" }, [
2042
+ vue.h(
2043
+ "div",
2044
+ {
2045
+ "data-iris-admin-headerbar": "",
2046
+ style: {
2047
+ display: "flex",
2048
+ alignItems: "center",
2049
+ gap: "12px",
2050
+ minHeight: "52px",
2051
+ padding: "0 16px",
2052
+ background: "var(--iris-background)"
2053
+ }
2054
+ },
2055
+ [
2056
+ renderLogo({ collapsed: false }),
2057
+ vue.h(
2058
+ "div",
2059
+ {
2060
+ "data-iris-admin-topnav": "",
2061
+ style: {
2062
+ display: "flex",
2063
+ flex: "1",
2064
+ minWidth: "0",
2065
+ justifyContent
2066
+ }
2067
+ },
2068
+ [
2069
+ vue.h(IrisNavMenu, {
2070
+ items: props.menus,
2071
+ activeKey: activeKey.value,
2072
+ orientation: "horizontal",
2073
+ onSelect
2074
+ })
2075
+ ]
2076
+ ),
2077
+ slots.toolbar ? vue.h(
2078
+ "div",
2079
+ {
2080
+ "data-iris-admin-toolbar": "",
2081
+ style: { display: "flex", alignItems: "center", gap: "8px" }
2082
+ },
2083
+ slots.toolbar()
2084
+ ) : null
2085
+ ]
2086
+ ),
2087
+ renderTabs()
2088
+ ]),
2089
+ default: () => renderContent(true),
2090
+ ...slots.footer ? { footer: () => slots.footer() } : {}
2091
+ }
2092
+ )
2093
+ ]
2094
+ );
2095
+ }
1768
2096
  return vue.h(
1769
2097
  IrisSidebarLayout,
1770
2098
  {
@@ -1811,12 +2139,9 @@ var IrisAdminLayout = vue.defineComponent({
1811
2139
  ),
1812
2140
  default: () => vue.h(
1813
2141
  IrisHeaderLayout,
1814
- { sticky: true },
2142
+ { sticky: props.stickyHeader },
1815
2143
  {
1816
- header: () => vue.h("div", { "data-iris-admin-header": "" }, [
1817
- renderHeaderBar(),
1818
- props.tabs ? vue.h(IrisAdminTabs, { nav: props.tabs }) : null
1819
- ]),
2144
+ header: () => vue.h("div", { "data-iris-admin-header": "" }, [renderHeaderBar(), renderTabs()]),
1820
2145
  default: () => renderContent(),
1821
2146
  ...slots.footer ? { footer: () => slots.footer() } : {}
1822
2147
  }
@@ -1826,11 +2151,37 @@ var IrisAdminLayout = vue.defineComponent({
1826
2151
  };
1827
2152
  }
1828
2153
  });
2154
+ function useAdminPreferences(preferences, hydrate = true) {
2155
+ const state = vue.ref(preferences.getState());
2156
+ const unsubscribe = preferences.subscribe((next) => {
2157
+ state.value = next;
2158
+ });
2159
+ vue.onMounted(() => {
2160
+ if (hydrate) void preferences.hydrate();
2161
+ });
2162
+ vue.onBeforeUnmount(unsubscribe);
2163
+ return {
2164
+ state: vue.computed(() => state.value),
2165
+ set: preferences.set,
2166
+ patch: preferences.patch,
2167
+ reset: preferences.reset,
2168
+ hydrate: preferences.hydrate,
2169
+ flush: preferences.flush
2170
+ };
2171
+ }
1829
2172
 
2173
+ Object.defineProperty(exports, "createAdminPreferences", {
2174
+ enumerable: true,
2175
+ get: function () { return core.createAdminPreferences; }
2176
+ });
1830
2177
  Object.defineProperty(exports, "createTabsNav", {
1831
2178
  enumerable: true,
1832
2179
  get: function () { return core.createTabsNav; }
1833
2180
  });
2181
+ Object.defineProperty(exports, "filterNavByAccess", {
2182
+ enumerable: true,
2183
+ get: function () { return core.filterNavByAccess; }
2184
+ });
1834
2185
  Object.defineProperty(exports, "findNavNode", {
1835
2186
  enumerable: true,
1836
2187
  get: function () { return core.findNavNode; }
@@ -1855,6 +2206,14 @@ Object.defineProperty(exports, "isClosable", {
1855
2206
  enumerable: true,
1856
2207
  get: function () { return core.isClosable; }
1857
2208
  });
2209
+ Object.defineProperty(exports, "localStorageAdminPreferencesStorage", {
2210
+ enumerable: true,
2211
+ get: function () { return core.localStorageAdminPreferencesStorage; }
2212
+ });
2213
+ Object.defineProperty(exports, "nodeAllowsRoles", {
2214
+ enumerable: true,
2215
+ get: function () { return core.nodeAllowsRoles; }
2216
+ });
1858
2217
  Object.defineProperty(exports, "visibleNav", {
1859
2218
  enumerable: true,
1860
2219
  get: function () { return core.visibleNav; }
@@ -1863,6 +2222,7 @@ exports.IrisAdminBreadcrumb = IrisAdminBreadcrumb;
1863
2222
  exports.IrisAdminLayout = IrisAdminLayout;
1864
2223
  exports.IrisAdminTabs = IrisAdminTabs;
1865
2224
  exports.IrisNavMenu = IrisNavMenu;
2225
+ exports.useAdminPreferences = useAdminPreferences;
1866
2226
  exports.useAdminShell = useAdminShell;
1867
2227
  exports.useTabsNav = useTabsNav;
1868
2228
  //# sourceMappingURL=admin.cjs.map