@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/index.cjs CHANGED
@@ -1,9 +1,9 @@
1
1
  'use strict';
2
2
 
3
3
  var vue = require('vue');
4
+ var core = require('@iris-ui-kit/core');
4
5
  var theme = require('@iris-ui-kit/theme');
5
6
  var skins = require('@iris-ui-kit/skins');
6
- var core = require('@iris-ui-kit/core');
7
7
  var icons = require('@iris-ui-kit/icons');
8
8
  var dom = require('@floating-ui/dom');
9
9
  var undo = require('@iris-ui-kit/core/undo');
@@ -20,6 +20,41 @@ function useStoreSelector(store2, selector, equals) {
20
20
  vue.onScopeDispose(store2.subscribeWith(selector, (v) => slice.value = v, equals));
21
21
  return slice;
22
22
  }
23
+ function useReconnectingSource(connect, handlers, options) {
24
+ const status = vue.ref("idle");
25
+ const handlersRef = { current: handlers };
26
+ handlersRef.current = handlers;
27
+ const source = core.createReconnectingSource(
28
+ connect,
29
+ {
30
+ onMessage: (data) => handlersRef.current.onMessage?.(data),
31
+ onOpen: () => handlersRef.current.onOpen?.(),
32
+ onError: (err) => handlersRef.current.onError?.(err),
33
+ onClose: () => handlersRef.current.onClose?.(),
34
+ onStatus: (s) => {
35
+ status.value = s;
36
+ }
37
+ },
38
+ options
39
+ );
40
+ source.open();
41
+ vue.onUnmounted(() => source.close());
42
+ return status;
43
+ }
44
+ function useResilientFetcher(options) {
45
+ const rf = core.createResilientFetcher(options);
46
+ vue.onUnmounted(() => {
47
+ rf.cache.clear();
48
+ });
49
+ return rf;
50
+ }
51
+ function useDisposableScope() {
52
+ const scope = vue.ref(core.createDisposableScope());
53
+ vue.onUnmounted(() => {
54
+ scope.value.destroy();
55
+ });
56
+ return scope;
57
+ }
23
58
  var IrisThemeKey = /* @__PURE__ */ Symbol("IrisTheme");
24
59
  var ThemeProvider = vue.defineComponent({
25
60
  name: "IrisThemeProvider",
@@ -812,6 +847,10 @@ var IrisNavMenu = vue.defineComponent({
812
847
  defaultExpandedKeys: { type: Array, default: void 0 },
813
848
  /** Icon-only rail (top-level items only). */
814
849
  collapsed: { type: Boolean, default: false },
850
+ orientation: {
851
+ type: String,
852
+ default: "vertical"
853
+ },
815
854
  ariaLabel: { type: String, default: void 0 }
816
855
  },
817
856
  emits: {
@@ -867,7 +906,7 @@ var IrisNavMenu = vue.defineComponent({
867
906
  display: "flex",
868
907
  alignItems: "center",
869
908
  gap: "10px",
870
- width: "100%",
909
+ width: props.orientation === "horizontal" && opts.depth === 0 ? "auto" : "100%",
871
910
  boxSizing: "border-box",
872
911
  border: "none",
873
912
  borderRadius: "var(--iris-radius-md, 6px)",
@@ -879,7 +918,8 @@ var IrisNavMenu = vue.defineComponent({
879
918
  textAlign: "start",
880
919
  cursor: opts.disabled ? "not-allowed" : "pointer",
881
920
  opacity: opts.disabled ? "0.5" : "1",
882
- padding: props.collapsed ? "10px" : `8px 10px 8px ${12 + opts.depth * 16}px`,
921
+ padding: props.collapsed ? "10px" : "8px 10px",
922
+ paddingInlineStart: props.collapsed ? "10px" : `${12 + opts.depth * 16}px`,
883
923
  justifyContent: props.collapsed ? "center" : "flex-start"
884
924
  };
885
925
  };
@@ -973,16 +1013,40 @@ var IrisNavMenu = vue.defineComponent({
973
1013
  }) : null
974
1014
  ]
975
1015
  );
1016
+ const groupStyle = props.orientation === "horizontal" && depth === 0 ? { position: "relative" } : void 0;
976
1017
  if (!branch || !open)
977
- return vue.h("div", { key: node.key, "data-iris-nav-group": branch ? "" : void 0 }, [row]);
978
- return vue.h("div", { key: node.key, "data-iris-nav-group": "", "data-open": "true" }, [
979
- row,
980
- vue.h(
1018
+ return vue.h(
981
1019
  "div",
982
- { "data-iris-nav-children": "", role: "group" },
983
- (node.children ?? []).map((child) => renderItem(child, depth + 1))
984
- )
985
- ]);
1020
+ { key: node.key, "data-iris-nav-group": branch ? "" : void 0, style: groupStyle },
1021
+ [row]
1022
+ );
1023
+ return vue.h(
1024
+ "div",
1025
+ { key: node.key, "data-iris-nav-group": "", "data-open": "true", style: groupStyle },
1026
+ [
1027
+ row,
1028
+ vue.h(
1029
+ "div",
1030
+ {
1031
+ "data-iris-nav-children": "",
1032
+ role: "group",
1033
+ style: props.orientation === "horizontal" && depth === 0 ? {
1034
+ position: "absolute",
1035
+ insetBlockStart: "calc(100% + 4px)",
1036
+ insetInlineStart: "0",
1037
+ zIndex: "60",
1038
+ minWidth: "220px",
1039
+ padding: "6px",
1040
+ border: "1px solid var(--iris-border)",
1041
+ borderRadius: "var(--iris-radius-md, 6px)",
1042
+ background: "var(--iris-surface)",
1043
+ boxShadow: "var(--iris-shadow-md)"
1044
+ } : void 0
1045
+ },
1046
+ (node.children ?? []).map((child) => renderItem(child, depth + 1))
1047
+ )
1048
+ ]
1049
+ );
986
1050
  };
987
1051
  const onKeydown = (e) => {
988
1052
  const root = e.currentTarget;
@@ -1035,11 +1099,13 @@ var IrisNavMenu = vue.defineComponent({
1035
1099
  ...attrs,
1036
1100
  "data-iris-nav-menu": "",
1037
1101
  "data-collapsed": props.collapsed ? "true" : void 0,
1102
+ "data-orientation": props.orientation,
1038
1103
  "aria-label": props.ariaLabel ?? t("admin.nav"),
1039
1104
  onKeydown,
1040
1105
  style: {
1041
1106
  display: "flex",
1042
- flexDirection: "column",
1107
+ flexDirection: props.orientation === "horizontal" ? "row" : "column",
1108
+ alignItems: props.orientation === "horizontal" ? "center" : void 0,
1043
1109
  gap: "2px",
1044
1110
  ...attrs.style ?? {}
1045
1111
  }
@@ -1229,6 +1295,7 @@ function useTabsNav(nav) {
1229
1295
  closeRight: nav.closeRight,
1230
1296
  refresh: nav.refresh,
1231
1297
  setPinned: nav.setPinned,
1298
+ move: nav.move,
1232
1299
  cacheKey: nav.cacheKey
1233
1300
  };
1234
1301
  }
@@ -1785,6 +1852,168 @@ var IrisDropdownSeparator = vue.defineComponent({
1785
1852
  });
1786
1853
  }
1787
1854
  });
1855
+ var SORTABLE_ITEM_ATTR = "data-iris-sortable-item";
1856
+ var IrisSortable = vue.defineComponent({
1857
+ name: "IrisSortable",
1858
+ inheritAttrs: false,
1859
+ props: {
1860
+ /** The ordered items. Used to detect which item is at which position. */
1861
+ items: {
1862
+ type: Array,
1863
+ required: true
1864
+ },
1865
+ /** Called when the user drops an item in a new position. */
1866
+ onReorder: {
1867
+ type: Function,
1868
+ default: void 0
1869
+ },
1870
+ /** Optional item key getter. Defaults to `String(index)`. */
1871
+ getKey: {
1872
+ type: Function,
1873
+ default: void 0
1874
+ },
1875
+ disabled: {
1876
+ type: Boolean,
1877
+ default: false
1878
+ },
1879
+ orientation: {
1880
+ type: String,
1881
+ default: "vertical"
1882
+ },
1883
+ class: {
1884
+ type: String,
1885
+ default: void 0
1886
+ },
1887
+ style: {
1888
+ type: Object,
1889
+ default: void 0
1890
+ }
1891
+ },
1892
+ emits: {
1893
+ reorder: (_next) => true
1894
+ },
1895
+ setup(props, { slots, attrs, emit }) {
1896
+ const containerRef = vue.ref(null);
1897
+ const sortable = core.createSortable();
1898
+ const activeKey = vue.ref(null);
1899
+ const unsub = sortable.subscribe((state) => {
1900
+ activeKey.value = state.activeId;
1901
+ });
1902
+ vue.onBeforeUnmount(unsub);
1903
+ const indexOf = (key) => {
1904
+ const container = containerRef.value;
1905
+ if (!container) return -1;
1906
+ return Array.from(
1907
+ container.querySelectorAll(`[${SORTABLE_ITEM_ATTR}]`)
1908
+ ).findIndex((el) => el.getAttribute(SORTABLE_ITEM_ATTR) === key);
1909
+ };
1910
+ const onPointerDown = (e) => {
1911
+ if (props.disabled) return;
1912
+ const target = e.target.closest(`[${SORTABLE_ITEM_ATTR}]`);
1913
+ if (!target) return;
1914
+ const container = containerRef.value;
1915
+ if (!container) return;
1916
+ const key = target.getAttribute(SORTABLE_ITEM_ATTR) ?? "";
1917
+ const index = indexOf(key);
1918
+ if (index < 0) return;
1919
+ sortable.press(key, e.clientX, e.clientY);
1920
+ };
1921
+ const onPointerMove = (e) => {
1922
+ if (!sortable.isPending() && sortable.getState().activeId === null) return;
1923
+ const items = containerRef.value?.querySelectorAll(`[${SORTABLE_ITEM_ATTR}]`);
1924
+ const rects = Array.from(items ?? []).map((el) => {
1925
+ const rect = el.getBoundingClientRect();
1926
+ return {
1927
+ id: el.getAttribute(SORTABLE_ITEM_ATTR) ?? "",
1928
+ left: rect.left,
1929
+ top: rect.top,
1930
+ width: rect.width,
1931
+ height: rect.height
1932
+ };
1933
+ });
1934
+ sortable.tryStart(e.clientX, e.clientY);
1935
+ if (sortable.getState().activeId !== null) {
1936
+ sortable.moveOver({ x: e.clientX, y: e.clientY }, rects);
1937
+ }
1938
+ };
1939
+ const onPointerUp = () => {
1940
+ const state = sortable.getState();
1941
+ if (state.activeId === null) {
1942
+ sortable.cancel();
1943
+ return;
1944
+ }
1945
+ const result = sortable.end();
1946
+ if (result.activeId && result.overId && result.activeId !== result.overId) {
1947
+ const from = indexOf(result.activeId);
1948
+ const to = indexOf(result.overId);
1949
+ if (from >= 0 && to >= 0) {
1950
+ const next = [...props.items];
1951
+ const [moved] = next.splice(from, 1);
1952
+ next.splice(to, 0, moved);
1953
+ if (props.onReorder) {
1954
+ props.onReorder(next);
1955
+ }
1956
+ emit("reorder", next);
1957
+ }
1958
+ }
1959
+ };
1960
+ const resolveKey = (item, index) => props.getKey ? props.getKey(item, index) : String(index);
1961
+ return () => {
1962
+ const children = [];
1963
+ const defaultSlots = slots.default?.();
1964
+ if (defaultSlots) {
1965
+ const itemsArray = props.items;
1966
+ defaultSlots.forEach((child, index) => {
1967
+ const item = itemsArray[index];
1968
+ const key = resolveKey(item, index);
1969
+ const isDragging = key === activeKey.value;
1970
+ children.push(
1971
+ vue.h(
1972
+ "div",
1973
+ {
1974
+ key,
1975
+ [SORTABLE_ITEM_ATTR]: key,
1976
+ "data-iris-sortable-dragging": isDragging ? "" : void 0,
1977
+ style: {
1978
+ transition: isDragging ? "none" : "transform 150ms ease",
1979
+ opacity: isDragging ? 0.4 : 1,
1980
+ position: "relative",
1981
+ zIndex: isDragging ? 100 : void 0
1982
+ }
1983
+ },
1984
+ [child]
1985
+ )
1986
+ );
1987
+ });
1988
+ }
1989
+ return vue.h(
1990
+ "div",
1991
+ {
1992
+ ...attrs,
1993
+ ref: (el) => {
1994
+ containerRef.value = el ?? null;
1995
+ },
1996
+ "data-iris-sortable": "",
1997
+ "data-state": activeKey.value ? "dragging" : "idle",
1998
+ class: props.class,
1999
+ style: {
2000
+ display: "flex",
2001
+ flexDirection: props.orientation === "horizontal" ? "row" : "column",
2002
+ gap: "var(--iris-gap-sm, 4px)",
2003
+ opacity: props.disabled ? 0.6 : 1,
2004
+ userSelect: activeKey.value ? "none" : void 0,
2005
+ ...props.style ?? {}
2006
+ },
2007
+ onPointerdown: onPointerDown,
2008
+ onPointermove: onPointerMove,
2009
+ onPointerup: onPointerUp,
2010
+ onPointerleave: onPointerUp
2011
+ },
2012
+ children
2013
+ );
2014
+ };
2015
+ }
2016
+ });
1788
2017
 
1789
2018
  // src/admin/AdminTabs.ts
1790
2019
  var IrisAdminTabs = vue.defineComponent({
@@ -1792,12 +2021,14 @@ var IrisAdminTabs = vue.defineComponent({
1792
2021
  inheritAttrs: false,
1793
2022
  props: {
1794
2023
  /** Shared tabs store (from `createTabsNav`). */
1795
- nav: { type: Object, required: true }
2024
+ nav: { type: Object, required: true },
2025
+ reorderable: { type: Boolean, default: true }
1796
2026
  },
1797
2027
  emits: {
1798
2028
  change: (_key) => true,
1799
2029
  close: (_key) => true,
1800
- refresh: (_key) => true
2030
+ refresh: (_key) => true,
2031
+ reorder: (_tabs) => true
1801
2032
  },
1802
2033
  setup(props, { emit, attrs }) {
1803
2034
  const { t: tr } = useI18n();
@@ -1814,6 +2045,10 @@ var IrisAdminTabs = vue.defineComponent({
1814
2045
  props.nav.refresh(key);
1815
2046
  emit("refresh", key);
1816
2047
  };
2048
+ const reorder = (tabs) => {
2049
+ tabs.forEach((tab, index) => props.nav.move(tab.key, index));
2050
+ emit("reorder", tabs);
2051
+ };
1817
2052
  const focusTab = (root, key) => {
1818
2053
  if (!root || !key) return;
1819
2054
  const labels = root.querySelectorAll("[data-iris-tab-label]");
@@ -1965,6 +2200,8 @@ var IrisAdminTabs = vue.defineComponent({
1965
2200
  action(tr("admin.refresh"), () => refresh(key)),
1966
2201
  action(tr("admin.close"), () => close(key)),
1967
2202
  vue.h(IrisDropdownSeparator),
2203
+ action(tr("admin.closeLeft"), () => props.nav.closeLeft(key)),
2204
+ action(tr("admin.closeRight"), () => props.nav.closeRight(key)),
1968
2205
  action(tr("admin.closeOthers"), () => props.nav.closeOthers(key)),
1969
2206
  action(tr("admin.closeAll"), () => props.nav.closeAll())
1970
2207
  ];
@@ -1996,14 +2233,28 @@ var IrisAdminTabs = vue.defineComponent({
1996
2233
  "aria-label": tr("admin.openPages"),
1997
2234
  onKeydown: onTablistKeydown,
1998
2235
  style: {
1999
- display: "flex",
2000
- alignItems: "center",
2001
- gap: "6px",
2002
2236
  overflowX: "auto",
2003
2237
  flex: "1"
2004
2238
  }
2005
2239
  },
2006
- t.tabs.value.map((tab) => chip(tab))
2240
+ [
2241
+ vue.h(
2242
+ IrisSortable,
2243
+ {
2244
+ items: t.tabs.value,
2245
+ getKey: (item) => item.key,
2246
+ onReorder: (items) => reorder(items),
2247
+ disabled: !props.reorderable,
2248
+ orientation: "horizontal",
2249
+ style: {
2250
+ alignItems: "center",
2251
+ gap: "6px",
2252
+ width: "max-content"
2253
+ }
2254
+ },
2255
+ { default: () => t.tabs.value.map((tab) => chip(tab)) }
2256
+ )
2257
+ ]
2007
2258
  ),
2008
2259
  actionsMenu()
2009
2260
  ]
@@ -2052,6 +2303,8 @@ var IrisAdminLayout = vue.defineComponent({
2052
2303
  menus: { type: Array, required: true },
2053
2304
  /** Active page key (v-model:activeKey). */
2054
2305
  activeKey: { type: String, default: void 0 },
2306
+ /** Initial active page key when `activeKey` is uncontrolled. */
2307
+ defaultActiveKey: { type: String, default: void 0 },
2055
2308
  /** Sidebar collapsed (v-model:collapsed); undefined = uncontrolled. */
2056
2309
  collapsed: { type: Boolean, default: void 0 },
2057
2310
  defaultCollapsed: { type: Boolean, default: false },
@@ -2060,7 +2313,16 @@ var IrisAdminLayout = vue.defineComponent({
2060
2313
  appTitle: { type: String, default: "Iris Admin" },
2061
2314
  /** Optional shared tabs store; when present the tab bar is rendered. */
2062
2315
  tabs: { type: Object, default: void 0 },
2316
+ showTabs: { type: Boolean, default: true },
2063
2317
  showBreadcrumb: { type: Boolean, default: true },
2318
+ stickyHeader: { type: Boolean, default: true },
2319
+ stickyTabs: { type: Boolean, default: true },
2320
+ menuAlign: { type: String, default: "start" },
2321
+ contentWidth: { type: String, default: "fluid" },
2322
+ contentHeight: {
2323
+ type: String,
2324
+ default: "viewport"
2325
+ },
2064
2326
  sidebarWidth: { type: [Number, String], default: 240 },
2065
2327
  collapsedWidth: { type: [Number, String], default: 64 }
2066
2328
  },
@@ -2079,6 +2341,7 @@ var IrisAdminLayout = vue.defineComponent({
2079
2341
  } = useAdminShell({
2080
2342
  menus: () => props.menus,
2081
2343
  activeKey: () => props.activeKey,
2344
+ defaultActiveKey: props.defaultActiveKey,
2082
2345
  tabs: props.tabs,
2083
2346
  onActiveKeyChange: (key) => emit("update:activeKey", key),
2084
2347
  onSelect: (key, node) => emit("select", key, node)
@@ -2197,11 +2460,37 @@ var IrisAdminLayout = vue.defineComponent({
2197
2460
  ) : null
2198
2461
  ]
2199
2462
  );
2200
- const renderContent = () => vue.h(
2463
+ const renderContent = (horizontal = false) => vue.h(
2201
2464
  "div",
2202
- { "data-iris-admin-content": "", style: { padding: "16px" } },
2203
- slots.default?.({ activeKey: activeKey.value }) ?? []
2465
+ {
2466
+ "data-iris-admin-content": "",
2467
+ "data-width": props.contentWidth,
2468
+ style: {
2469
+ boxSizing: "border-box",
2470
+ width: "100%",
2471
+ maxWidth: props.contentWidth === "centered" ? "72rem" : void 0,
2472
+ marginInline: props.contentWidth === "centered" ? "auto" : void 0,
2473
+ padding: "16px"
2474
+ }
2475
+ },
2476
+ [
2477
+ horizontal && props.showBreadcrumb ? vue.h(IrisAdminBreadcrumb, { trail: trail.value, hideSingle: false, onSelect }) : null,
2478
+ ...slots.default?.({ activeKey: activeKey.value }) ?? []
2479
+ ]
2204
2480
  );
2481
+ const renderTabs = () => props.tabs && props.showTabs ? vue.h(
2482
+ "div",
2483
+ {
2484
+ "data-iris-admin-tabs-region": "",
2485
+ "data-sticky": props.stickyTabs ? "true" : void 0,
2486
+ style: {
2487
+ position: props.stickyTabs && !props.stickyHeader ? "sticky" : "relative",
2488
+ top: "0",
2489
+ zIndex: "49"
2490
+ }
2491
+ },
2492
+ [vue.h(IrisAdminTabs, { nav: props.tabs })]
2493
+ ) : null;
2205
2494
  return () => {
2206
2495
  if (props.mode === "full-content") {
2207
2496
  return vue.h(
@@ -2218,33 +2507,107 @@ var IrisAdminLayout = vue.defineComponent({
2218
2507
  slots.default?.({ activeKey: activeKey.value }) ?? []
2219
2508
  );
2220
2509
  }
2221
- return vue.h(
2222
- IrisSidebarLayout,
2223
- {
2224
- ...attrs,
2225
- collapsed: collapsed.value,
2226
- width: props.sidebarWidth,
2227
- collapsedWidth: props.collapsedWidth,
2228
- "onUpdate:collapsed": setCollapsed,
2229
- "data-iris-admin-layout": "",
2230
- "data-mode": "sidebar",
2231
- style: {
2232
- height: "100vh",
2233
- ...attrs.style ?? {}
2234
- }
2235
- },
2236
- {
2237
- sidebar: (state) => vue.h(
2238
- "div",
2239
- {
2240
- "data-iris-admin-sidebar": "",
2241
- style: {
2242
- display: "flex",
2243
- flexDirection: "column",
2244
- height: "100%",
2245
- borderInlineEnd: "1px solid var(--iris-border)",
2246
- background: "var(--iris-surface)"
2247
- }
2510
+ if (props.mode === "horizontal") {
2511
+ const justifyContent = props.menuAlign === "center" ? "center" : props.menuAlign === "end" ? "flex-end" : "flex-start";
2512
+ return vue.h(
2513
+ "div",
2514
+ {
2515
+ ...attrs,
2516
+ "data-iris-admin-layout": "",
2517
+ "data-mode": "horizontal",
2518
+ style: {
2519
+ height: props.contentHeight === "viewport" ? "100vh" : "auto",
2520
+ minHeight: "100vh",
2521
+ ...attrs.style ?? {}
2522
+ }
2523
+ },
2524
+ [
2525
+ vue.h(
2526
+ IrisHeaderLayout,
2527
+ { sticky: props.stickyHeader },
2528
+ {
2529
+ header: () => vue.h("div", { "data-iris-admin-header": "" }, [
2530
+ vue.h(
2531
+ "div",
2532
+ {
2533
+ "data-iris-admin-headerbar": "",
2534
+ style: {
2535
+ display: "flex",
2536
+ alignItems: "center",
2537
+ gap: "12px",
2538
+ minHeight: "52px",
2539
+ padding: "0 16px",
2540
+ background: "var(--iris-background)"
2541
+ }
2542
+ },
2543
+ [
2544
+ renderLogo({ collapsed: false }),
2545
+ vue.h(
2546
+ "div",
2547
+ {
2548
+ "data-iris-admin-topnav": "",
2549
+ style: {
2550
+ display: "flex",
2551
+ flex: "1",
2552
+ minWidth: "0",
2553
+ justifyContent
2554
+ }
2555
+ },
2556
+ [
2557
+ vue.h(IrisNavMenu, {
2558
+ items: props.menus,
2559
+ activeKey: activeKey.value,
2560
+ orientation: "horizontal",
2561
+ onSelect
2562
+ })
2563
+ ]
2564
+ ),
2565
+ slots.toolbar ? vue.h(
2566
+ "div",
2567
+ {
2568
+ "data-iris-admin-toolbar": "",
2569
+ style: { display: "flex", alignItems: "center", gap: "8px" }
2570
+ },
2571
+ slots.toolbar()
2572
+ ) : null
2573
+ ]
2574
+ ),
2575
+ renderTabs()
2576
+ ]),
2577
+ default: () => renderContent(true),
2578
+ ...slots.footer ? { footer: () => slots.footer() } : {}
2579
+ }
2580
+ )
2581
+ ]
2582
+ );
2583
+ }
2584
+ return vue.h(
2585
+ IrisSidebarLayout,
2586
+ {
2587
+ ...attrs,
2588
+ collapsed: collapsed.value,
2589
+ width: props.sidebarWidth,
2590
+ collapsedWidth: props.collapsedWidth,
2591
+ "onUpdate:collapsed": setCollapsed,
2592
+ "data-iris-admin-layout": "",
2593
+ "data-mode": "sidebar",
2594
+ style: {
2595
+ height: "100vh",
2596
+ ...attrs.style ?? {}
2597
+ }
2598
+ },
2599
+ {
2600
+ sidebar: (state) => vue.h(
2601
+ "div",
2602
+ {
2603
+ "data-iris-admin-sidebar": "",
2604
+ style: {
2605
+ display: "flex",
2606
+ flexDirection: "column",
2607
+ height: "100%",
2608
+ borderInlineEnd: "1px solid var(--iris-border)",
2609
+ background: "var(--iris-surface)"
2610
+ }
2248
2611
  },
2249
2612
  [
2250
2613
  renderLogo(state),
@@ -2264,12 +2627,9 @@ var IrisAdminLayout = vue.defineComponent({
2264
2627
  ),
2265
2628
  default: () => vue.h(
2266
2629
  IrisHeaderLayout,
2267
- { sticky: true },
2630
+ { sticky: props.stickyHeader },
2268
2631
  {
2269
- header: () => vue.h("div", { "data-iris-admin-header": "" }, [
2270
- renderHeaderBar(),
2271
- props.tabs ? vue.h(IrisAdminTabs, { nav: props.tabs }) : null
2272
- ]),
2632
+ header: () => vue.h("div", { "data-iris-admin-header": "" }, [renderHeaderBar(), renderTabs()]),
2273
2633
  default: () => renderContent(),
2274
2634
  ...slots.footer ? { footer: () => slots.footer() } : {}
2275
2635
  }
@@ -2279,6 +2639,24 @@ var IrisAdminLayout = vue.defineComponent({
2279
2639
  };
2280
2640
  }
2281
2641
  });
2642
+ function useAdminPreferences(preferences, hydrate = true) {
2643
+ const state = vue.ref(preferences.getState());
2644
+ const unsubscribe = preferences.subscribe((next) => {
2645
+ state.value = next;
2646
+ });
2647
+ vue.onMounted(() => {
2648
+ if (hydrate) void preferences.hydrate();
2649
+ });
2650
+ vue.onBeforeUnmount(unsubscribe);
2651
+ return {
2652
+ state: vue.computed(() => state.value),
2653
+ set: preferences.set,
2654
+ patch: preferences.patch,
2655
+ reset: preferences.reset,
2656
+ hydrate: preferences.hydrate,
2657
+ flush: preferences.flush
2658
+ };
2659
+ }
2282
2660
  function useUndoStack(options) {
2283
2661
  const stack = undo.createUndoStack(options);
2284
2662
  const state = vue.shallowRef({
@@ -5663,6 +6041,7 @@ var IrisSelect = vue.defineComponent({
5663
6041
  props: {
5664
6042
  items: { type: Array, required: true },
5665
6043
  modelValue: { type: null },
6044
+ defaultValue: { type: null, default: void 0 },
5666
6045
  placeholder: { type: String, default: void 0 },
5667
6046
  size: { type: String, default: "md" },
5668
6047
  disabled: { type: Boolean, default: false },
@@ -5679,13 +6058,17 @@ var IrisSelect = vue.defineComponent({
5679
6058
  }
5680
6059
  },
5681
6060
  emits: {
5682
- "update:modelValue": (_value) => true
6061
+ "update:modelValue": (_value) => true,
6062
+ valueChange: (_value) => true
5683
6063
  },
5684
6064
  setup(props, { slots, attrs, emit }) {
5685
6065
  const { t } = useI18n();
5686
6066
  const open = vue.ref(false);
6067
+ const internalValue = vue.ref(props.defaultValue);
6068
+ const controlled = vue.computed(() => props.modelValue !== void 0);
6069
+ const currentValue = vue.computed(() => controlled.value ? props.modelValue : internalValue.value);
5687
6070
  const selectedItem = vue.computed(
5688
- () => props.items.find((item) => item.value === props.modelValue) ?? null
6071
+ () => props.items.find((item) => item.value === currentValue.value) ?? null
5689
6072
  );
5690
6073
  const triggerLabel = vue.computed(() => {
5691
6074
  const item = selectedItem.value;
@@ -5693,7 +6076,9 @@ var IrisSelect = vue.defineComponent({
5693
6076
  return item.label ?? String(item.value);
5694
6077
  });
5695
6078
  const onSelect = (item) => {
6079
+ if (!controlled.value) internalValue.value = item.value;
5696
6080
  emit("update:modelValue", item.value);
6081
+ emit("valueChange", item.value);
5697
6082
  open.value = false;
5698
6083
  };
5699
6084
  const sizeStyles = vue.computed(() => {
@@ -5759,7 +6144,7 @@ var IrisSelect = vue.defineComponent({
5759
6144
  default: () => [
5760
6145
  vue.h(IrisPopoverTrigger, { asChild: true }, () => [
5761
6146
  slots.trigger ? slots.trigger({
5762
- value: props.modelValue,
6147
+ value: currentValue.value,
5763
6148
  label: triggerLabel.value,
5764
6149
  open: open.value
5765
6150
  }) : vue.h(
@@ -5796,8 +6181,7 @@ var IrisSelect = vue.defineComponent({
5796
6181
  },
5797
6182
  () => vue.h(IrisList, {
5798
6183
  items: props.items,
5799
- modelValue: props.modelValue,
5800
- "onUpdate:modelValue": (v) => emit("update:modelValue", v),
6184
+ modelValue: currentValue.value,
5801
6185
  onSelect,
5802
6186
  ariaLabel: t("select.options")
5803
6187
  })
@@ -6257,8 +6641,8 @@ var IrisSkeleton = vue.defineComponent({
6257
6641
  vue.onMounted(installSkeletonStyles);
6258
6642
  const style = vue.computed(() => {
6259
6643
  const w = props.width !== void 0 ? toCss(props.width) : defaultWidth(props.shape);
6260
- const h122 = props.height !== void 0 ? toCss(props.height) : defaultHeight(props.shape, props.width);
6261
- return { width: w, height: h122 };
6644
+ const h123 = props.height !== void 0 ? toCss(props.height) : defaultHeight(props.shape, props.width);
6645
+ return { width: w, height: h123 };
6262
6646
  });
6263
6647
  return () => vue.h("div", {
6264
6648
  ...attrs,
@@ -8722,10 +9106,91 @@ var IrisVirtualScroll = vue.defineComponent({
8722
9106
  };
8723
9107
  }
8724
9108
  });
9109
+
9110
+ // src/primitives/table/controlProps.ts
9111
+ var tableControlProps = {
9112
+ selectable: {
9113
+ type: String,
9114
+ default: "none"
9115
+ },
9116
+ selection: {
9117
+ type: Array,
9118
+ default: void 0
9119
+ },
9120
+ defaultSelection: {
9121
+ type: Array,
9122
+ default: void 0
9123
+ },
9124
+ sort: {
9125
+ type: Object,
9126
+ default: void 0
9127
+ },
9128
+ defaultSort: {
9129
+ type: Object,
9130
+ default: void 0
9131
+ }
9132
+ };
8725
9133
  function getCellValue(row, column) {
8726
9134
  const key = column.dataIndex ?? column.key;
8727
9135
  return row[key];
8728
9136
  }
9137
+
9138
+ // src/primitives/table/useTableSort.ts
9139
+ function useTableSort(data, options) {
9140
+ const sortProp = vue.computed(() => options.sort === void 0 ? void 0 : vue.toValue(options.sort));
9141
+ const internalSortValue = vue.ref(options.defaultSort ?? null);
9142
+ const sortState = vue.computed({
9143
+ get: () => sortProp.value === void 0 ? internalSortValue.value : sortProp.value ?? null,
9144
+ set: (val) => {
9145
+ if (sortProp.value === void 0) internalSortValue.value = val;
9146
+ options.onSortChange?.(val);
9147
+ }
9148
+ });
9149
+ const sortComparator = vue.computed(() => {
9150
+ const s = sortState.value;
9151
+ if (!s) return null;
9152
+ const col = vue.toValue(options.leafColumns).find((c) => c.key === s.key);
9153
+ if (!col) return null;
9154
+ const dir = s.direction === "asc" ? 1 : -1;
9155
+ const sorter = col.sorter ?? ((a, b) => core.compareValues(getCellValue(a, col), getCellValue(b, col)));
9156
+ return (a, b) => sorter(a, b) * dir;
9157
+ });
9158
+ const sortedData = vue.computed(() => {
9159
+ const compare = sortComparator.value;
9160
+ if (!compare) return data.value;
9161
+ return [...data.value].sort(compare);
9162
+ });
9163
+ function setSort(next) {
9164
+ if (sortProp.value === void 0) internalSortValue.value = next;
9165
+ options.onSortChange?.(next);
9166
+ }
9167
+ function cycleSort(col) {
9168
+ if (!col.sortable) return;
9169
+ const s = sortState.value;
9170
+ if (!s || s.key !== col.key) {
9171
+ setSort({ key: col.key, direction: "asc" });
9172
+ return;
9173
+ }
9174
+ if (s.direction === "asc") {
9175
+ setSort({ key: col.key, direction: "desc" });
9176
+ return;
9177
+ }
9178
+ setSort(null);
9179
+ }
9180
+ return {
9181
+ sortState,
9182
+ cycleSort,
9183
+ setSort,
9184
+ sortComparator,
9185
+ sortedData
9186
+ };
9187
+ }
9188
+
9189
+ // src/primitives/table/Table.ts
9190
+ function getCellValue2(row, column) {
9191
+ const key = column.dataIndex ?? column.key;
9192
+ return row[key];
9193
+ }
8729
9194
  var SELECTION_COL_WIDTH = 40;
8730
9195
  var EXPAND_COL_WIDTH = 40;
8731
9196
  var DEFAULT_COL_WIDTH = 140;
@@ -8752,18 +9217,7 @@ var IrisTable = vue.defineComponent({
8752
9217
  required: true
8753
9218
  },
8754
9219
  rowKey: { type: String, default: "id" },
8755
- selectable: {
8756
- type: String,
8757
- default: "none"
8758
- },
8759
- selection: {
8760
- type: Array,
8761
- default: void 0
8762
- },
8763
- sort: {
8764
- type: Object,
8765
- default: void 0
8766
- },
9220
+ ...tableControlProps,
8767
9221
  striped: { type: Boolean, default: false },
8768
9222
  bordered: { type: Boolean, default: true },
8769
9223
  /** Enable per-column resize handles. Combine with `v-model:columnWidths` for persistence. */
@@ -8847,31 +9301,23 @@ var IrisTable = vue.defineComponent({
8847
9301
  () => grouped.value ? core.flattenLeafColumns(props.columns) : props.columns
8848
9302
  );
8849
9303
  const headerMatrix = vue.computed(() => grouped.value ? core.buildHeaderMatrix(props.columns) : null);
8850
- const internalSortValue = vue.ref(null);
8851
- const internalSort = vue.computed({
8852
- get: () => props.sort === void 0 ? internalSortValue.value : props.sort,
8853
- set: (value) => {
8854
- if (props.sort === void 0) internalSortValue.value = value;
8855
- emit("update:sort", value);
9304
+ const {
9305
+ sortState: internalSort,
9306
+ cycleSort,
9307
+ sortComparator,
9308
+ sortedData: sortedRows
9309
+ } = useTableSort(
9310
+ vue.computed(() => props.data ?? []),
9311
+ {
9312
+ leafColumns,
9313
+ sort: vue.computed(() => props.sort),
9314
+ defaultSort: props.defaultSort,
9315
+ onSortChange: (next) => emit("update:sort", next)
8856
9316
  }
8857
- });
8858
- const sortComparator = vue.computed(() => {
8859
- const state = internalSort.value;
8860
- if (!state) return null;
8861
- const column = leafColumns.value.find((c) => c.key === state.key);
8862
- if (!column) return null;
8863
- const dir = state.direction === "asc" ? 1 : -1;
8864
- const sorter = column.sorter ?? ((a, b) => core.compareValues(getCellValue(a, column), getCellValue(b, column)));
8865
- return (a, b) => sorter(a, b) * dir;
8866
- });
8867
- const sortedRows = vue.computed(() => {
8868
- const compare = sortComparator.value;
8869
- if (!compare) return props.data ?? [];
8870
- return [...props.data ?? []].sort(compare);
8871
- });
9317
+ );
8872
9318
  const selControlled = vue.computed(() => props.selection !== void 0);
8873
9319
  const selectionModel = core.createSelectionModel({
8874
- defaultSelected: props.selection ?? [],
9320
+ defaultSelected: props.selection ?? props.defaultSelection ?? [],
8875
9321
  onChange: (keys) => emit("update:selection", keys)
8876
9322
  });
8877
9323
  const selectedKeys = vue.shallowRef(selectionModel.get());
@@ -8953,14 +9399,14 @@ var IrisTable = vue.defineComponent({
8953
9399
  const beginEdit = (row, column, rowIdent) => {
8954
9400
  if (!column.editable) return;
8955
9401
  editingCellId.value = cellId(rowIdent, column.key);
8956
- const current = getCellValue(row, column);
9402
+ const current = getCellValue2(row, column);
8957
9403
  editingDraft.value = current == null ? "" : String(current);
8958
9404
  editError.value = null;
8959
9405
  void vue.nextTick(() => editorInputRef.value?.focus());
8960
9406
  };
8961
9407
  const commitEdit = (row, column, rowIndex) => {
8962
9408
  if (editingCellId.value === null) return;
8963
- const oldValue = getCellValue(row, column);
9409
+ const oldValue = getCellValue2(row, column);
8964
9410
  const draft = editingDraft.value;
8965
9411
  const newValue = column.editor === "number" ? draft === "" || Number.isNaN(Number(draft)) ? oldValue : Number(draft) : draft;
8966
9412
  if (column.validate) {
@@ -9001,17 +9447,7 @@ var IrisTable = vue.defineComponent({
9001
9447
  emit("update:columnWidths", next);
9002
9448
  };
9003
9449
  const onHeaderClick = (column) => {
9004
- if (!column.sortable) return;
9005
- const current = internalSort.value;
9006
- let next;
9007
- if (!current || current.key !== column.key) {
9008
- next = { key: column.key, direction: "asc" };
9009
- } else if (current.direction === "asc") {
9010
- next = { key: column.key, direction: "desc" };
9011
- } else {
9012
- next = null;
9013
- }
9014
- internalSort.value = next;
9450
+ cycleSort(column);
9015
9451
  };
9016
9452
  const sortIndicator = (col) => {
9017
9453
  if (!col.sortable) return null;
@@ -9585,7 +10021,7 @@ var IrisTable = vue.defineComponent({
9585
10021
  )
9586
10022
  ] : input;
9587
10023
  } else {
9588
- content = cellSlot?.({ row, index, value: getCellValue(row, col) }) ?? String(getCellValue(row, col) ?? "");
10024
+ content = cellSlot?.({ row, index, value: getCellValue2(row, col) }) ?? String(getCellValue2(row, col) ?? "");
9589
10025
  }
9590
10026
  const treeIndent = treeMeta && ci === 0 ? vue.h(
9591
10027
  "span",
@@ -9831,7 +10267,7 @@ var IrisTable = vue.defineComponent({
9831
10267
  if (visibleColSet.value && !visibleColSet.value.has(ci)) continue;
9832
10268
  const align = col.align ?? "left";
9833
10269
  const op = col.summary;
9834
- const value = op ? core.aggregate(bodyData.value, (r) => getCellValue(r, col), op) : null;
10270
+ const value = op ? core.aggregate(bodyData.value, (r) => getCellValue2(r, col), op) : null;
9835
10271
  const summaryContent = op != null && value != null ? col.renderSummary ? col.renderSummary(value, bodyData.value) : String(value) : "";
9836
10272
  summaryCells.push(
9837
10273
  vue.h(
@@ -9910,45 +10346,23 @@ var IrisTable = vue.defineComponent({
9910
10346
  };
9911
10347
  }
9912
10348
  });
9913
- var FORMULA_LEAD = /^[=+\-@\t\r]/;
9914
- function neutralizeFormula(text) {
9915
- return FORMULA_LEAD.test(text) ? `'${text}` : text;
9916
- }
9917
- function csvCell(value) {
9918
- if (value == null) return "";
9919
- const isNumber = typeof value === "number" && Number.isFinite(value);
9920
- const s = isNumber ? String(value) : neutralizeFormula(String(value));
9921
- if (/[",\r\n]/.test(s)) {
9922
- return `"${s.replace(/"/g, '""')}"`;
9923
- }
9924
- return s;
9925
- }
9926
10349
  function exportCsv(rows, columns) {
9927
- const header = columns.map((c) => csvCell(c.title)).join(",");
9928
- const body = rows.map(
9929
- (row) => columns.map((col) => {
9930
- const key = col.dataIndex ?? col.key;
9931
- return csvCell(row[key]);
9932
- }).join(",")
9933
- ).join("\n");
9934
- return body.length > 0 ? `${header}
9935
- ${body}` : header;
10350
+ return core.toCsv(
10351
+ rows,
10352
+ columns.map((column) => ({
10353
+ key: column.key,
10354
+ title: column.title,
10355
+ dataIndex: typeof column.dataIndex === "string" ? column.dataIndex : void 0
10356
+ }))
10357
+ );
9936
10358
  }
9937
10359
  async function downloadCsv(filename, csv) {
9938
10360
  const BOM = String.fromCharCode(65279);
9939
- const content = BOM + csv;
9940
- if (await core.saveFile({ filename, content, mimeType: "text/csv;charset=utf-8;" })) return;
9941
- if (typeof document === "undefined") return;
9942
- const blob = new Blob([content], { type: "text/csv;charset=utf-8;" });
9943
- const url = URL.createObjectURL(blob);
9944
- const anchor = document.createElement("a");
9945
- anchor.href = url;
9946
- anchor.download = filename;
9947
- anchor.style.display = "none";
9948
- document.body.appendChild(anchor);
9949
- anchor.click();
9950
- document.body.removeChild(anchor);
9951
- setTimeout(() => URL.revokeObjectURL(url), 0);
10361
+ await core.downloadFile({
10362
+ filename,
10363
+ content: BOM + csv,
10364
+ mimeType: "text/csv;charset=utf-8;"
10365
+ });
9952
10366
  }
9953
10367
  function exportExcel(rows, columns, options) {
9954
10368
  return core.toSpreadsheetXml(
@@ -9962,20 +10376,11 @@ function exportExcel(rows, columns, options) {
9962
10376
  );
9963
10377
  }
9964
10378
  async function downloadExcel(filename, xml) {
9965
- if (await core.saveFile({ filename, content: xml, mimeType: "application/vnd.ms-excel" })) {
9966
- return;
9967
- }
9968
- if (typeof document === "undefined") return;
9969
- const blob = new Blob([xml], { type: "application/vnd.ms-excel" });
9970
- const url = URL.createObjectURL(blob);
9971
- const anchor = document.createElement("a");
9972
- anchor.href = url;
9973
- anchor.download = filename;
9974
- anchor.style.display = "none";
9975
- document.body.appendChild(anchor);
9976
- anchor.click();
9977
- document.body.removeChild(anchor);
9978
- setTimeout(() => URL.revokeObjectURL(url), 0);
10379
+ await core.downloadFile({
10380
+ filename,
10381
+ content: xml,
10382
+ mimeType: "application/vnd.ms-excel;charset=utf-8"
10383
+ });
9979
10384
  }
9980
10385
 
9981
10386
  // src/primitives/tabs/context.ts
@@ -16367,12 +16772,12 @@ function defaultFilter(query, item) {
16367
16772
  if (!q) return 0;
16368
16773
  const haystacks = [item.label, ...item.keywords ?? []].map((s) => s.toLowerCase());
16369
16774
  let best = null;
16370
- for (const h122 of haystacks) {
16775
+ for (const h123 of haystacks) {
16371
16776
  let qi = 0;
16372
16777
  let lastIdx = -1;
16373
16778
  let score = 0;
16374
- for (let i = 0; i < h122.length && qi < q.length; i += 1) {
16375
- if (h122[i] === q[qi]) {
16779
+ for (let i = 0; i < h123.length && qi < q.length; i += 1) {
16780
+ if (h123[i] === q[qi]) {
16376
16781
  score += lastIdx === -1 ? i : i - lastIdx - 1;
16377
16782
  lastIdx = i;
16378
16783
  qi += 1;
@@ -16738,8 +17143,8 @@ var IrisTimePicker = vue.defineComponent({
16738
17143
  if (props.format === "24h") {
16739
17144
  return { h: value.value.hours, m: value.value.minutes };
16740
17145
  }
16741
- const h122 = value.value.hours % 12 === 0 ? 12 : value.value.hours % 12;
16742
- return { h: h122, m: value.value.minutes };
17146
+ const h123 = value.value.hours % 12 === 0 ? 12 : value.value.hours % 12;
17147
+ return { h: h123, m: value.value.minutes };
16743
17148
  });
16744
17149
  const emitNew = (next) => {
16745
17150
  emit("update:modelValue", next);
@@ -16755,16 +17160,16 @@ var IrisTimePicker = vue.defineComponent({
16755
17160
  };
16756
17161
  const toggleMeridiem = () => {
16757
17162
  const isPM = meridiem.value === "PM";
16758
- const h122 = value.value.hours % 12;
16759
- const newH24 = isPM ? h122 : h122 + 12;
17163
+ const h123 = value.value.hours % 12;
17164
+ const newH24 = isPM ? h123 : h123 + 12;
16760
17165
  emitNew({ hours: newH24, minutes: value.value.minutes });
16761
17166
  };
16762
17167
  const onHoursInput = (e) => {
16763
17168
  const v = parseInt(e.target.value || "0", 10);
16764
17169
  if (Number.isNaN(v)) return;
16765
17170
  if (props.format === "12h") {
16766
- const h122 = clamp5(v, 1, 12);
16767
- const wrap = h122 === 12 ? 0 : h122;
17171
+ const h123 = clamp5(v, 1, 12);
17172
+ const wrap = h123 === 12 ? 0 : h123;
16768
17173
  const newH24 = meridiem.value === "PM" ? wrap + 12 : wrap;
16769
17174
  setHours24(newH24);
16770
17175
  } else {
@@ -17947,164 +18352,6 @@ var IrisClickOutside = vue.defineComponent({
17947
18352
  );
17948
18353
  }
17949
18354
  });
17950
- var SORTABLE_ITEM_ATTR = "data-iris-sortable-item";
17951
- var IrisSortable = vue.defineComponent({
17952
- name: "IrisSortable",
17953
- inheritAttrs: false,
17954
- props: {
17955
- /** The ordered items. Used to detect which item is at which position. */
17956
- items: {
17957
- type: Array,
17958
- required: true
17959
- },
17960
- /** Called when the user drops an item in a new position. */
17961
- onReorder: {
17962
- type: Function,
17963
- default: void 0
17964
- },
17965
- /** Optional item key getter. Defaults to `String(index)`. */
17966
- getKey: {
17967
- type: Function,
17968
- default: void 0
17969
- },
17970
- disabled: {
17971
- type: Boolean,
17972
- default: false
17973
- },
17974
- class: {
17975
- type: String,
17976
- default: void 0
17977
- },
17978
- style: {
17979
- type: Object,
17980
- default: void 0
17981
- }
17982
- },
17983
- emits: {
17984
- reorder: (_next) => true
17985
- },
17986
- setup(props, { slots, attrs, emit }) {
17987
- const containerRef = vue.ref(null);
17988
- const sortable = core.createSortable();
17989
- const activeKey = vue.ref(null);
17990
- const unsub = sortable.subscribe((state) => {
17991
- activeKey.value = state.activeId;
17992
- });
17993
- vue.onBeforeUnmount(unsub);
17994
- const indexOf = (key) => {
17995
- const container = containerRef.value;
17996
- if (!container) return -1;
17997
- return Array.from(
17998
- container.querySelectorAll(`[${SORTABLE_ITEM_ATTR}]`)
17999
- ).findIndex((el) => el.getAttribute(SORTABLE_ITEM_ATTR) === key);
18000
- };
18001
- const onPointerDown = (e) => {
18002
- if (props.disabled) return;
18003
- const target = e.target.closest(`[${SORTABLE_ITEM_ATTR}]`);
18004
- if (!target) return;
18005
- const container = containerRef.value;
18006
- if (!container) return;
18007
- const key = target.getAttribute(SORTABLE_ITEM_ATTR) ?? "";
18008
- const index = indexOf(key);
18009
- if (index < 0) return;
18010
- sortable.press(key, e.clientX, e.clientY);
18011
- };
18012
- const onPointerMove = (e) => {
18013
- if (!sortable.isPending() && sortable.getState().activeId === null) return;
18014
- const items = containerRef.value?.querySelectorAll(`[${SORTABLE_ITEM_ATTR}]`);
18015
- const rects = Array.from(items ?? []).map((el) => {
18016
- const rect = el.getBoundingClientRect();
18017
- return {
18018
- id: el.getAttribute(SORTABLE_ITEM_ATTR) ?? "",
18019
- left: rect.left,
18020
- top: rect.top,
18021
- width: rect.width,
18022
- height: rect.height
18023
- };
18024
- });
18025
- sortable.tryStart(e.clientX, e.clientY);
18026
- if (sortable.getState().activeId !== null) {
18027
- sortable.moveOver({ x: e.clientX, y: e.clientY }, rects);
18028
- }
18029
- };
18030
- const onPointerUp = () => {
18031
- const state = sortable.getState();
18032
- if (state.activeId === null) {
18033
- sortable.cancel();
18034
- return;
18035
- }
18036
- const result = sortable.end();
18037
- if (result.activeId && result.overId && result.activeId !== result.overId) {
18038
- const from = indexOf(result.activeId);
18039
- const to = indexOf(result.overId);
18040
- if (from >= 0 && to >= 0) {
18041
- const next = [...props.items];
18042
- const [moved] = next.splice(from, 1);
18043
- next.splice(to, 0, moved);
18044
- if (props.onReorder) {
18045
- props.onReorder(next);
18046
- }
18047
- emit("reorder", next);
18048
- }
18049
- }
18050
- };
18051
- const resolveKey = (item, index) => props.getKey ? props.getKey(item, index) : String(index);
18052
- return () => {
18053
- const children = [];
18054
- const defaultSlots = slots.default?.();
18055
- if (defaultSlots) {
18056
- const itemsArray = props.items;
18057
- defaultSlots.forEach((child, index) => {
18058
- const item = itemsArray[index];
18059
- const key = resolveKey(item, index);
18060
- const isDragging = key === activeKey.value;
18061
- children.push(
18062
- vue.h(
18063
- "div",
18064
- {
18065
- key,
18066
- [SORTABLE_ITEM_ATTR]: key,
18067
- "data-iris-sortable-dragging": isDragging ? "" : void 0,
18068
- style: {
18069
- transition: isDragging ? "none" : "transform 150ms ease",
18070
- opacity: isDragging ? 0.4 : 1,
18071
- position: "relative",
18072
- zIndex: isDragging ? 100 : void 0
18073
- }
18074
- },
18075
- [child]
18076
- )
18077
- );
18078
- });
18079
- }
18080
- return vue.h(
18081
- "div",
18082
- {
18083
- ...attrs,
18084
- ref: (el) => {
18085
- containerRef.value = el ?? null;
18086
- },
18087
- "data-iris-sortable": "",
18088
- "data-state": activeKey.value ? "dragging" : "idle",
18089
- class: props.class,
18090
- style: {
18091
- display: "flex",
18092
- flexDirection: "column",
18093
- gap: "var(--iris-gap-sm, 4px)",
18094
- opacity: props.disabled ? 0.6 : 1,
18095
- userSelect: activeKey.value ? "none" : void 0,
18096
- ...props.style ?? {}
18097
- },
18098
- onPointerdown: onPointerDown,
18099
- onPointermove: onPointerMove,
18100
- onPointerup: onPointerUp,
18101
- onPointerleave: onPointerUp
18102
- },
18103
- children
18104
- );
18105
- };
18106
- }
18107
- });
18108
18355
  var IrisLongPress = vue.defineComponent({
18109
18356
  name: "IrisLongPress",
18110
18357
  inheritAttrs: false,
@@ -18160,90 +18407,6 @@ var IrisLongPress = vue.defineComponent({
18160
18407
  }
18161
18408
  });
18162
18409
 
18163
- Object.defineProperty(exports, "applyTheme", {
18164
- enumerable: true,
18165
- get: function () { return theme.applyTheme; }
18166
- });
18167
- Object.defineProperty(exports, "createThemeStore", {
18168
- enumerable: true,
18169
- get: function () { return theme.createThemeStore; }
18170
- });
18171
- Object.defineProperty(exports, "getCssVar", {
18172
- enumerable: true,
18173
- get: function () { return theme.getCssVar; }
18174
- });
18175
- Object.defineProperty(exports, "toCssVarName", {
18176
- enumerable: true,
18177
- get: function () { return theme.toCssVarName; }
18178
- });
18179
- Object.defineProperty(exports, "SkinResolutionError", {
18180
- enumerable: true,
18181
- get: function () { return skins.SkinResolutionError; }
18182
- });
18183
- Object.defineProperty(exports, "applySkin", {
18184
- enumerable: true,
18185
- get: function () { return skins.applySkin; }
18186
- });
18187
- Object.defineProperty(exports, "builtinSkins", {
18188
- enumerable: true,
18189
- get: function () { return skins.builtinSkins; }
18190
- });
18191
- Object.defineProperty(exports, "createSkinCatalog", {
18192
- enumerable: true,
18193
- get: function () { return skins.createSkinCatalog; }
18194
- });
18195
- Object.defineProperty(exports, "createSkinEngine", {
18196
- enumerable: true,
18197
- get: function () { return skins.createSkinEngine; }
18198
- });
18199
- Object.defineProperty(exports, "createSkinRegistry", {
18200
- enumerable: true,
18201
- get: function () { return skins.createSkinRegistry; }
18202
- });
18203
- Object.defineProperty(exports, "darkSkin", {
18204
- enumerable: true,
18205
- get: function () { return skins.darkSkin; }
18206
- });
18207
- Object.defineProperty(exports, "lightSkin", {
18208
- enumerable: true,
18209
- get: function () { return skins.lightSkin; }
18210
- });
18211
- Object.defineProperty(exports, "loadSkin", {
18212
- enumerable: true,
18213
- get: function () { return skins.loadSkin; }
18214
- });
18215
- Object.defineProperty(exports, "localStorageSkinStorage", {
18216
- enumerable: true,
18217
- get: function () { return skins.localStorageSkinStorage; }
18218
- });
18219
- Object.defineProperty(exports, "memorySkinStorage", {
18220
- enumerable: true,
18221
- get: function () { return skins.memorySkinStorage; }
18222
- });
18223
- Object.defineProperty(exports, "renderSkinStyle", {
18224
- enumerable: true,
18225
- get: function () { return skins.renderSkinStyle; }
18226
- });
18227
- Object.defineProperty(exports, "resolveSkin", {
18228
- enumerable: true,
18229
- get: function () { return skins.resolveSkin; }
18230
- });
18231
- Object.defineProperty(exports, "skinBootScript", {
18232
- enumerable: true,
18233
- get: function () { return skins.skinBootScript; }
18234
- });
18235
- Object.defineProperty(exports, "skinError", {
18236
- enumerable: true,
18237
- get: function () { return skins.skinError; }
18238
- });
18239
- Object.defineProperty(exports, "skinToCssEntries", {
18240
- enumerable: true,
18241
- get: function () { return skins.skinToCssEntries; }
18242
- });
18243
- Object.defineProperty(exports, "validateSkin", {
18244
- enumerable: true,
18245
- get: function () { return skins.validateSkin; }
18246
- });
18247
18410
  Object.defineProperty(exports, "addDays", {
18248
18411
  enumerable: true,
18249
18412
  get: function () { return core.addDays; }
@@ -18268,6 +18431,10 @@ Object.defineProperty(exports, "composeEventHandlers", {
18268
18431
  enumerable: true,
18269
18432
  get: function () { return core.composeEventHandlers; }
18270
18433
  });
18434
+ Object.defineProperty(exports, "createAdminPreferences", {
18435
+ enumerable: true,
18436
+ get: function () { return core.createAdminPreferences; }
18437
+ });
18271
18438
  Object.defineProperty(exports, "createClientDataSource", {
18272
18439
  enumerable: true,
18273
18440
  get: function () { return core.createClientDataSource; }
@@ -18308,6 +18475,10 @@ Object.defineProperty(exports, "endOfMonth", {
18308
18475
  enumerable: true,
18309
18476
  get: function () { return core.endOfMonth; }
18310
18477
  });
18478
+ Object.defineProperty(exports, "filterNavByAccess", {
18479
+ enumerable: true,
18480
+ get: function () { return core.filterNavByAccess; }
18481
+ });
18311
18482
  Object.defineProperty(exports, "findNavNode", {
18312
18483
  enumerable: true,
18313
18484
  get: function () { return core.findNavNode; }
@@ -18376,10 +18547,18 @@ Object.defineProperty(exports, "isSameMonth", {
18376
18547
  enumerable: true,
18377
18548
  get: function () { return core.isSameMonth; }
18378
18549
  });
18550
+ Object.defineProperty(exports, "localStorageAdminPreferencesStorage", {
18551
+ enumerable: true,
18552
+ get: function () { return core.localStorageAdminPreferencesStorage; }
18553
+ });
18379
18554
  Object.defineProperty(exports, "mergeProps", {
18380
18555
  enumerable: true,
18381
18556
  get: function () { return core.mergeProps; }
18382
18557
  });
18558
+ Object.defineProperty(exports, "nodeAllowsRoles", {
18559
+ enumerable: true,
18560
+ get: function () { return core.nodeAllowsRoles; }
18561
+ });
18383
18562
  Object.defineProperty(exports, "rgbToHex", {
18384
18563
  enumerable: true,
18385
18564
  get: function () { return core.rgbToHex; }
@@ -18404,6 +18583,90 @@ Object.defineProperty(exports, "visibleNav", {
18404
18583
  enumerable: true,
18405
18584
  get: function () { return core.visibleNav; }
18406
18585
  });
18586
+ Object.defineProperty(exports, "applyTheme", {
18587
+ enumerable: true,
18588
+ get: function () { return theme.applyTheme; }
18589
+ });
18590
+ Object.defineProperty(exports, "createThemeStore", {
18591
+ enumerable: true,
18592
+ get: function () { return theme.createThemeStore; }
18593
+ });
18594
+ Object.defineProperty(exports, "getCssVar", {
18595
+ enumerable: true,
18596
+ get: function () { return theme.getCssVar; }
18597
+ });
18598
+ Object.defineProperty(exports, "toCssVarName", {
18599
+ enumerable: true,
18600
+ get: function () { return theme.toCssVarName; }
18601
+ });
18602
+ Object.defineProperty(exports, "SkinResolutionError", {
18603
+ enumerable: true,
18604
+ get: function () { return skins.SkinResolutionError; }
18605
+ });
18606
+ Object.defineProperty(exports, "applySkin", {
18607
+ enumerable: true,
18608
+ get: function () { return skins.applySkin; }
18609
+ });
18610
+ Object.defineProperty(exports, "builtinSkins", {
18611
+ enumerable: true,
18612
+ get: function () { return skins.builtinSkins; }
18613
+ });
18614
+ Object.defineProperty(exports, "createSkinCatalog", {
18615
+ enumerable: true,
18616
+ get: function () { return skins.createSkinCatalog; }
18617
+ });
18618
+ Object.defineProperty(exports, "createSkinEngine", {
18619
+ enumerable: true,
18620
+ get: function () { return skins.createSkinEngine; }
18621
+ });
18622
+ Object.defineProperty(exports, "createSkinRegistry", {
18623
+ enumerable: true,
18624
+ get: function () { return skins.createSkinRegistry; }
18625
+ });
18626
+ Object.defineProperty(exports, "darkSkin", {
18627
+ enumerable: true,
18628
+ get: function () { return skins.darkSkin; }
18629
+ });
18630
+ Object.defineProperty(exports, "lightSkin", {
18631
+ enumerable: true,
18632
+ get: function () { return skins.lightSkin; }
18633
+ });
18634
+ Object.defineProperty(exports, "loadSkin", {
18635
+ enumerable: true,
18636
+ get: function () { return skins.loadSkin; }
18637
+ });
18638
+ Object.defineProperty(exports, "localStorageSkinStorage", {
18639
+ enumerable: true,
18640
+ get: function () { return skins.localStorageSkinStorage; }
18641
+ });
18642
+ Object.defineProperty(exports, "memorySkinStorage", {
18643
+ enumerable: true,
18644
+ get: function () { return skins.memorySkinStorage; }
18645
+ });
18646
+ Object.defineProperty(exports, "renderSkinStyle", {
18647
+ enumerable: true,
18648
+ get: function () { return skins.renderSkinStyle; }
18649
+ });
18650
+ Object.defineProperty(exports, "resolveSkin", {
18651
+ enumerable: true,
18652
+ get: function () { return skins.resolveSkin; }
18653
+ });
18654
+ Object.defineProperty(exports, "skinBootScript", {
18655
+ enumerable: true,
18656
+ get: function () { return skins.skinBootScript; }
18657
+ });
18658
+ Object.defineProperty(exports, "skinError", {
18659
+ enumerable: true,
18660
+ get: function () { return skins.skinError; }
18661
+ });
18662
+ Object.defineProperty(exports, "skinToCssEntries", {
18663
+ enumerable: true,
18664
+ get: function () { return skins.skinToCssEntries; }
18665
+ });
18666
+ Object.defineProperty(exports, "validateSkin", {
18667
+ enumerable: true,
18668
+ get: function () { return skins.validateSkin; }
18669
+ });
18407
18670
  Object.defineProperty(exports, "createIconRegistry", {
18408
18671
  enumerable: true,
18409
18672
  get: function () { return icons.createIconRegistry; }
@@ -18637,6 +18900,7 @@ exports.installDataStateStyles = installDataStateStyles;
18637
18900
  exports.mergeSlotProps = mergeSlotProps;
18638
18901
  exports.pushToast = pushToast;
18639
18902
  exports.subscribeToasts = subscribeToasts;
18903
+ exports.useAdminPreferences = useAdminPreferences;
18640
18904
  exports.useAdminShell = useAdminShell;
18641
18905
  exports.useAsyncResource = useAsyncResource;
18642
18906
  exports.useBodyScrollLock = useBodyScrollLock;
@@ -18645,6 +18909,7 @@ exports.useDataSource = useDataSource;
18645
18909
  exports.useDataState = useDataState;
18646
18910
  exports.useDirection = useDirection;
18647
18911
  exports.useDismiss = useDismiss;
18912
+ exports.useDisposableScope = useDisposableScope;
18648
18913
  exports.useDrag = useDrag;
18649
18914
  exports.useField = useField;
18650
18915
  exports.useFieldArray = useFieldArray;
@@ -18659,6 +18924,8 @@ exports.usePaginatedResource = usePaginatedResource;
18659
18924
  exports.usePlugin = usePlugin;
18660
18925
  exports.usePluginStore = usePluginStore;
18661
18926
  exports.usePrefersReducedMotion = usePrefersReducedMotion;
18927
+ exports.useReconnectingSource = useReconnectingSource;
18928
+ exports.useResilientFetcher = useResilientFetcher;
18662
18929
  exports.useResourceController = useResourceController;
18663
18930
  exports.useSkin = useSkin;
18664
18931
  exports.useSkinContext = useSkinContext;