@iris-ui-kit/vue 0.2.25 → 0.2.27

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.
Files changed (52) hide show
  1. package/dist/admin.cjs +547 -236
  2. package/dist/admin.cjs.map +1 -1
  3. package/dist/admin.d.cts +4 -2
  4. package/dist/admin.d.ts +4 -2
  5. package/dist/admin.js +2 -2
  6. package/dist/behaviors.cjs +49 -0
  7. package/dist/behaviors.cjs.map +1 -1
  8. package/dist/behaviors.d.cts +57 -1
  9. package/dist/behaviors.d.ts +57 -1
  10. package/dist/behaviors.js +1 -1
  11. package/dist/{chunk-QQ25RKOO.js → chunk-ASFDGYIR.js} +543 -240
  12. package/dist/chunk-ASFDGYIR.js.map +1 -0
  13. package/dist/{chunk-WL67XCH5.js → chunk-IN3DQ55U.js} +2 -2
  14. package/dist/chunk-IN3DQ55U.js.map +1 -0
  15. package/dist/{chunk-7L6UB6MD.js → chunk-IOMKC5OI.js} +53 -5
  16. package/dist/chunk-IOMKC5OI.js.map +1 -0
  17. package/dist/{chunk-3FJUCHCC.js → chunk-IPR5JAVF.js} +11 -3
  18. package/dist/chunk-IPR5JAVF.js.map +1 -0
  19. package/dist/{chunk-BEPH6PPL.js → chunk-LWABTQCB.js} +57 -37
  20. package/dist/chunk-LWABTQCB.js.map +1 -0
  21. package/dist/{chunk-DNRQVM3Q.js → chunk-QBFYIDY7.js} +3 -2
  22. package/dist/chunk-QBFYIDY7.js.map +1 -0
  23. package/dist/data.cjs +1 -0
  24. package/dist/data.cjs.map +1 -1
  25. package/dist/data.d.cts +4 -2
  26. package/dist/data.d.ts +4 -2
  27. package/dist/data.js +1 -1
  28. package/dist/floating.cjs +9 -1
  29. package/dist/floating.cjs.map +1 -1
  30. package/dist/floating.d.cts +6 -0
  31. package/dist/floating.d.ts +6 -0
  32. package/dist/floating.js +1 -1
  33. package/dist/index.cjs +2063 -745
  34. package/dist/index.cjs.map +1 -1
  35. package/dist/index.d.cts +172 -8
  36. package/dist/index.d.ts +172 -8
  37. package/dist/index.js +1412 -475
  38. package/dist/index.js.map +1 -1
  39. package/dist/layouts.cjs.map +1 -1
  40. package/dist/layouts.d.cts +1 -1
  41. package/dist/layouts.d.ts +1 -1
  42. package/dist/layouts.js +1 -1
  43. package/dist/skeletons.cjs +55 -35
  44. package/dist/skeletons.cjs.map +1 -1
  45. package/dist/skeletons.js +1 -1
  46. package/package.json +5 -5
  47. package/dist/chunk-3FJUCHCC.js.map +0 -1
  48. package/dist/chunk-7L6UB6MD.js.map +0 -1
  49. package/dist/chunk-BEPH6PPL.js.map +0 -1
  50. package/dist/chunk-DNRQVM3Q.js.map +0 -1
  51. package/dist/chunk-QQ25RKOO.js.map +0 -1
  52. package/dist/chunk-WL67XCH5.js.map +0 -1
@@ -1,4 +1,4 @@
1
- import { useFloating, useDismiss } from './chunk-3FJUCHCC.js';
1
+ import { useFloating, useDismiss } from './chunk-IPR5JAVF.js';
2
2
  import { useMachine } from './chunk-NNOF7KUH.js';
3
3
  import { findFirstElement, mergeSlotProps } from './chunk-F77KIPOH.js';
4
4
  import { IrisHeaderLayout, IrisSidebarLayout } from './chunk-3V46HGRC.js';
@@ -6,8 +6,8 @@ import { IrisThemeKey } from './chunk-ZTPIXL7Q.js';
6
6
  import { IrisSortable } from './chunk-W3B6E5GN.js';
7
7
  import { useStore } from './chunk-75GSYEJS.js';
8
8
  import { useI18n } from './chunk-TCAXRWT6.js';
9
- import { defineComponent, inject, h, computed, shallowRef, onBeforeUnmount, watch, ref, provide, useId, nextTick, Teleport, Fragment, watchEffect, toValue, onMounted } from 'vue';
10
- import { visibleNav, findNavPath, createExpansion, branchTrail, createFloatingMachine, findNavNode, isBranch, firstLeaf, matchTypeahead, nextEnabledIndex, isClosable, createAdminShell } from '@iris-ui-kit/core';
9
+ import { defineComponent, inject, h, computed, shallowRef, onBeforeUnmount, watch, provide, useId, ref, nextTick, Teleport, Fragment, watchEffect, toValue, onMounted } from 'vue';
10
+ import { visibleNav, findNavPath, createExpansion, branchTrail, createFloatingMachine, isBranch, findNavNode, firstLeaf, matchTypeahead, nextEnabledIndex, isClosable, createAdminShell } from '@iris-ui-kit/core';
11
11
  export { createAdminPreferences, createTabsNav, filterNavByAccess, findNavNode, findNavPath, firstLeaf, flattenNav, isBranch, isClosable, localStorageAdminPreferencesStorage, nodeAllowsRoles, visibleNav } from '@iris-ui-kit/core';
12
12
  import { defaultIconRegistry, resolveThemedIcon } from '@iris-ui-kit/icons';
13
13
 
@@ -73,7 +73,7 @@ var __NAV_MENU_STYLE_ID = "iris-nav-menu-styles";
73
73
  var CSS = `
74
74
  :where(.iris-nav-menu) {
75
75
  --iris-nav-indent-step: 16px;
76
- --iris-nav-item-padding-inline: 10px;
76
+ --iris-nav-item-padding-inline: 12px;
77
77
  --iris-nav-item-padding-block: 8px;
78
78
  --iris-nav-item-border-radius: var(--iris-radius-md, 6px);
79
79
  --iris-nav-item-hover: var(--iris-surface-hover, var(--iris-surface));
@@ -81,7 +81,7 @@ var CSS = `
81
81
  display: flex;
82
82
  flex-direction: column;
83
83
  align-items: stretch;
84
- gap: 2px;
84
+ gap: var(--iris-space-xxs, 4px);
85
85
  width: 100%;
86
86
  }
87
87
 
@@ -106,16 +106,16 @@ var CSS = `
106
106
  border: none;
107
107
  border-radius: var(--iris-nav-item-border-radius);
108
108
  background: transparent;
109
- color: var(--iris-foreground, var(--iris-color-text, var(--iris-foreground)));
109
+ color: var(--iris-foreground);
110
110
  font: inherit;
111
- font-size: 14px;
111
+ font-size: var(--iris-font-size-md, 14px);
112
112
  line-height: 1.2;
113
113
  font-weight: 400;
114
114
  text-align: start;
115
115
  cursor: pointer;
116
116
  opacity: 1;
117
117
  margin: 0;
118
- gap: 10px;
118
+ gap: var(--iris-space-sm, 12px);
119
119
  padding-block: var(--iris-nav-item-padding-block);
120
120
  padding-inline: var(--iris-nav-item-padding-inline);
121
121
  text-overflow: ellipsis;
@@ -128,7 +128,7 @@ var CSS = `
128
128
  }
129
129
 
130
130
  :where(.iris-nav-menu-item[data-depth='0']) {
131
- --iris-nav-item-padding-inline-start: 10px;
131
+ --iris-nav-item-padding-inline-start: 12px;
132
132
  }
133
133
 
134
134
  :where(.iris-nav-menu-item[data-depth='1']) {
@@ -176,7 +176,7 @@ var CSS = `
176
176
  background: var(--iris-nav-item-hover);
177
177
  }
178
178
 
179
- :where(.iris-nav-menu-item[data-active='true']) {
179
+ .iris-nav-menu-item[data-active='true'] {
180
180
  background: var(--iris-primary);
181
181
  color: var(--iris-primary-foreground, #fff);
182
182
  font-weight: 600;
@@ -205,13 +205,13 @@ var CSS = `
205
205
  }
206
206
 
207
207
  :where(.iris-nav-menu-badge) {
208
- margin-inline-start: 6px;
209
- font-size: 11px;
208
+ margin-inline-start: var(--iris-space-xs, 8px);
209
+ font-size: var(--iris-font-size-xs, 12px);
210
210
  line-height: 1;
211
- padding: 2px 6px;
211
+ padding: var(--iris-space-xxs, 4px) var(--iris-space-xs, 8px);
212
212
  border-radius: 999px;
213
- background: var(--iris-danger, #e5484d);
214
- color: #fff;
213
+ background: var(--iris-danger, #ef4444);
214
+ color: var(--iris-primary-foreground, #fff);
215
215
  flex: 0 0 auto;
216
216
  }
217
217
 
@@ -241,44 +241,68 @@ var CSS = `
241
241
  opacity: 0.75;
242
242
  }
243
243
 
244
- :where(.iris-nav-menu-group--depth-0 > .iris-nav-menu-children) {
245
- display: none;
244
+ /* Vertical branches stay in the DOM and animate height via the grid-rows
245
+ trick (0fr \u2192 1fr); the inner wrapper provides the overflow clipping so the
246
+ transition is a smooth accordion without a max-height cap. */
247
+ :where(.iris-nav-menu--vertical .iris-nav-menu-group > .iris-nav-menu-children) {
248
+ display: grid;
249
+ grid-template-rows: 0fr;
250
+ opacity: 0;
251
+ visibility: hidden;
252
+ transition:
253
+ grid-template-rows 200ms ease,
254
+ opacity 150ms ease,
255
+ visibility 0s linear 200ms;
246
256
  }
247
257
 
248
- :where(.iris-nav-menu-group--depth-1 > .iris-nav-menu-children),
249
- :where(.iris-nav-menu-group--depth-2 > .iris-nav-menu-children),
250
- :where(.iris-nav-menu-group--depth-3 > .iris-nav-menu-children),
251
- :where(.iris-nav-menu-group--depth-4 > .iris-nav-menu-children),
252
- :where(.iris-nav-menu-group--depth-5 > .iris-nav-menu-children),
253
- :where(.iris-nav-menu-group--depth-6 > .iris-nav-menu-children),
254
- :where(.iris-nav-menu-group--depth-7 > .iris-nav-menu-children),
255
- :where(.iris-nav-menu-group--depth-8 > .iris-nav-menu-children),
256
- :where(.iris-nav-menu-group--depth-9 > .iris-nav-menu-children),
257
- :where(.iris-nav-menu-group > .iris-nav-menu-children) {
258
- display: none;
258
+ :where(.iris-nav-menu--vertical .iris-nav-menu-group > .iris-nav-menu-children > .iris-nav-menu-children-inner) {
259
+ overflow: hidden;
260
+ min-height: 0;
259
261
  }
260
262
 
261
- :where(.iris-nav-menu-group[data-open='true'] > .iris-nav-menu-children) {
262
- display: block;
263
+ :where(.iris-nav-menu--vertical .iris-nav-menu-group[data-open='true'] > .iris-nav-menu-children) {
264
+ grid-template-rows: 1fr;
265
+ opacity: 1;
266
+ visibility: visible;
267
+ transition:
268
+ grid-template-rows 200ms ease,
269
+ opacity 150ms ease;
263
270
  }
264
271
 
265
- :where(.iris-nav-menu--horizontal .iris-nav-menu-group > .iris-nav-menu-children) {
272
+ /* Flyout popups (horizontal mode + the collapsed rail) share the popup chrome
273
+ and are hard-hidden when closed (no height animation needed). */
274
+ :where(.iris-nav-menu--horizontal .iris-nav-menu-group > .iris-nav-menu-children),
275
+ :where(.iris-nav-menu--collapsed .iris-nav-menu-group > .iris-nav-menu-children) {
276
+ display: none;
266
277
  position: absolute;
267
278
  min-width: 220px;
268
- padding: 6px;
279
+ padding: var(--iris-space-xs, 8px);
269
280
  border: 1px solid var(--iris-border);
270
281
  border-radius: var(--iris-radius-md, 6px);
271
282
  background: var(--iris-surface);
272
283
  box-shadow: var(--iris-shadow-md);
273
284
  }
274
285
 
286
+ :where(.iris-nav-menu--horizontal .iris-nav-menu-group[data-open='true'] > .iris-nav-menu-children),
287
+ :where(.iris-nav-menu--collapsed .iris-nav-menu-group[data-open='true'] > .iris-nav-menu-children) {
288
+ display: block;
289
+ }
290
+
275
291
  :where(.iris-nav-menu--horizontal .iris-nav-menu-group[data-depth='0'] > .iris-nav-menu-children) {
276
292
  inset-block-start: 100%;
277
293
  inset-inline-start: 0;
278
294
  z-index: 60;
279
295
  }
280
296
 
281
- :where(.iris-nav-menu--horizontal .iris-nav-menu-group[data-depth]:not([data-depth='0']) > .iris-nav-menu-children) {
297
+ /* A9: the collapsed rail popup opens to the right of the icon. */
298
+ :where(.iris-nav-menu--collapsed .iris-nav-menu-group[data-depth='0'] > .iris-nav-menu-children) {
299
+ inset-block-start: 0;
300
+ inset-inline-start: 100%;
301
+ z-index: 60;
302
+ }
303
+
304
+ :where(.iris-nav-menu--horizontal .iris-nav-menu-group[data-depth]:not([data-depth='0']) > .iris-nav-menu-children),
305
+ :where(.iris-nav-menu--collapsed .iris-nav-menu-group[data-depth]:not([data-depth='0']) > .iris-nav-menu-children) {
282
306
  inset-block-start: 0;
283
307
  inset-inline-start: 100%;
284
308
  z-index: 61;
@@ -294,10 +318,20 @@ var CSS = `
294
318
  padding-inline: var(--iris-nav-item-padding-inline);
295
319
  }
296
320
 
321
+ /* A9: the collapsed rail stays centered even though rows carry data-depth
322
+ (the vertical indent rules would otherwise win the specificity tie). */
323
+ :where(.iris-nav-menu--collapsed .iris-nav-menu-item[data-depth]) {
324
+ justify-content: center;
325
+ padding-inline: var(--iris-nav-item-padding-inline);
326
+ }
327
+
297
328
  @media (prefers-reduced-motion: reduce) {
298
329
  :where(.iris-nav-menu-arrow) {
299
330
  transition: none;
300
331
  }
332
+ :where(.iris-nav-menu--vertical .iris-nav-menu-group > .iris-nav-menu-children) {
333
+ transition: none;
334
+ }
301
335
  }
302
336
  `.trim();
303
337
  var installed = false;
@@ -314,6 +348,315 @@ function installNavMenuStyles() {
314
348
  document.head.appendChild(style);
315
349
  installed = true;
316
350
  }
351
+ var HOVER_OPEN_DELAY_VAL = 60;
352
+ var HOVER_CLOSE_DELAY_VAL = 150;
353
+ function createNavMenuFlyout(ctx) {
354
+ const hovered = ref(null);
355
+ const hoveredBranches = ref([]);
356
+ const focusedBranches = ref([]);
357
+ const clickedBranches = ref([]);
358
+ let suppressFocusOpen = false;
359
+ let openTimer = null;
360
+ const closeTimers = /* @__PURE__ */ new Map();
361
+ const clearOpenTimer = () => {
362
+ if (openTimer) {
363
+ clearTimeout(openTimer);
364
+ openTimer = null;
365
+ }
366
+ };
367
+ const cancelClose = (key) => {
368
+ const timer = closeTimers.get(key);
369
+ if (timer) {
370
+ clearTimeout(timer);
371
+ closeTimers.delete(key);
372
+ }
373
+ };
374
+ const cancelAllTimers = () => {
375
+ clearOpenTimer();
376
+ for (const timer of closeTimers.values()) clearTimeout(timer);
377
+ closeTimers.clear();
378
+ };
379
+ onBeforeUnmount(cancelAllTimers);
380
+ const flyoutTriggers = /* @__PURE__ */ new Map();
381
+ const flyoutPanels = /* @__PURE__ */ new Map();
382
+ const setFlyoutRef = (map, key, el) => {
383
+ if (el instanceof HTMLElement) map.set(key, el);
384
+ else map.delete(key);
385
+ };
386
+ const positionFlyout = (key) => {
387
+ const trigger = flyoutTriggers.get(key);
388
+ const panel = flyoutPanels.get(key);
389
+ if (!trigger || !panel || typeof document === "undefined") return;
390
+ const rect = trigger.getBoundingClientRect();
391
+ const dir = getComputedStyle(trigger).direction;
392
+ panel.style.position = "fixed";
393
+ panel.style.top = `${ctx.collapsed ? rect.top : rect.bottom}px`;
394
+ if (dir === "rtl") {
395
+ panel.style.left = "";
396
+ panel.style.right = `${window.innerWidth - (ctx.collapsed ? rect.left : rect.right)}px`;
397
+ } else {
398
+ panel.style.right = "";
399
+ panel.style.left = `${ctx.collapsed ? rect.right : rect.left}px`;
400
+ }
401
+ };
402
+ onBeforeUnmount(() => {
403
+ detachViewportListeners();
404
+ flyoutTriggers.clear();
405
+ flyoutPanels.clear();
406
+ });
407
+ const isolateAtDepth = (key) => {
408
+ const depth = findNavPath(ctx.items, key).length - 1;
409
+ const isSameDepthOther = (k) => k !== key && findNavPath(ctx.items, k).length - 1 === depth;
410
+ for (const state of [hoveredBranches, clickedBranches, focusedBranches]) {
411
+ if (state.value.some(isSameDepthOther)) {
412
+ state.value = state.value.filter((k) => !isSameDepthOther(k));
413
+ }
414
+ }
415
+ };
416
+ const scheduleOpen = (key) => {
417
+ clearOpenTimer();
418
+ openTimer = setTimeout(() => {
419
+ openTimer = null;
420
+ isolateAtDepth(key);
421
+ setBranchInteraction(hoveredBranches, key, true);
422
+ }, HOVER_OPEN_DELAY_VAL);
423
+ };
424
+ const scheduleClose = (key) => {
425
+ cancelClose(key);
426
+ closeTimers.set(
427
+ key,
428
+ setTimeout(() => {
429
+ closeTimers.delete(key);
430
+ setBranchInteraction(hoveredBranches, key, false);
431
+ }, HOVER_CLOSE_DELAY_VAL)
432
+ );
433
+ };
434
+ const closeHorizontalMenus = () => {
435
+ if (!ctx.flyoutMode.value) return;
436
+ cancelAllTimers();
437
+ hovered.value = null;
438
+ hoveredBranches.value = [];
439
+ focusedBranches.value = [];
440
+ clickedBranches.value = [];
441
+ };
442
+ const select = (node) => {
443
+ if (node.disabled) return;
444
+ closeHorizontalMenus();
445
+ ctx.emitSelect(node.key, node);
446
+ };
447
+ const toggleFlyout = (key) => {
448
+ cancelAllTimers();
449
+ const current = clickedBranches.value;
450
+ if (current.includes(key)) {
451
+ clickedBranches.value = current.filter((k) => k !== key);
452
+ setBranchInteraction(hoveredBranches, key, false);
453
+ setBranchInteraction(focusedBranches, key, false);
454
+ } else {
455
+ isolateAtDepth(key);
456
+ clickedBranches.value = [...clickedBranches.value, key];
457
+ }
458
+ };
459
+ const openFlyout = (key) => {
460
+ cancelAllTimers();
461
+ isolateAtDepth(key);
462
+ setBranchInteraction(focusedBranches, key, true);
463
+ };
464
+ const setBranchInteraction = (state, key, enabled) => {
465
+ const current = state.value;
466
+ if (enabled) {
467
+ if (!current.includes(key)) state.value = [...current, key];
468
+ } else if (current.includes(key)) {
469
+ state.value = current.filter((item) => item !== key);
470
+ }
471
+ };
472
+ const keepsPointerInside = (container, event) => {
473
+ if (!container || !(container instanceof HTMLElement)) return false;
474
+ const next = event.relatedTarget;
475
+ return !!(next && next instanceof Node && container.contains(next));
476
+ };
477
+ const interactionKeyAtDepth = (keys, depth) => keys.find((key) => findNavPath(ctx.items, key).length === depth + 1);
478
+ const horizontalBranchVisible = (key, depth) => {
479
+ const hoveredAtDepth = interactionKeyAtDepth(hoveredBranches.value, depth);
480
+ if (hoveredAtDepth) return hoveredAtDepth === key;
481
+ const clickedAtDepth = interactionKeyAtDepth(clickedBranches.value, depth);
482
+ if (clickedAtDepth) return clickedAtDepth === key;
483
+ return interactionKeyAtDepth(focusedBranches.value, depth) === key;
484
+ };
485
+ const shownFlyoutKeys = computed(() => {
486
+ if (!ctx.flyoutMode.value) return [];
487
+ const keys = [];
488
+ for (const node of ctx.tree.value) {
489
+ if (isBranch(node) && horizontalBranchVisible(node.key, 0)) keys.push(node.key);
490
+ }
491
+ return keys;
492
+ });
493
+ const repositionOpenFlyouts = () => {
494
+ for (const key of shownFlyoutKeys.value) positionFlyout(key);
495
+ };
496
+ let viewportListenersActive = false;
497
+ const attachViewportListeners = () => {
498
+ if (viewportListenersActive || typeof document === "undefined") return;
499
+ viewportListenersActive = true;
500
+ document.addEventListener("scroll", repositionOpenFlyouts, true);
501
+ window.addEventListener("resize", repositionOpenFlyouts);
502
+ };
503
+ const detachViewportListeners = () => {
504
+ if (!viewportListenersActive || typeof document === "undefined") return;
505
+ viewportListenersActive = false;
506
+ document.removeEventListener("scroll", repositionOpenFlyouts, true);
507
+ window.removeEventListener("resize", repositionOpenFlyouts);
508
+ };
509
+ watch(
510
+ shownFlyoutKeys,
511
+ (keys, prev) => {
512
+ if (keys.length > 0 && prev.length === 0) attachViewportListeners();
513
+ else if (keys.length === 0 && prev.length > 0) detachViewportListeners();
514
+ for (const key of keys) positionFlyout(key);
515
+ },
516
+ { flush: "post" }
517
+ );
518
+ return {
519
+ hovered,
520
+ hoveredBranches,
521
+ focusedBranches,
522
+ clickedBranches,
523
+ select,
524
+ toggleFlyout,
525
+ openFlyout,
526
+ closeHorizontalMenus,
527
+ setBranchInteraction,
528
+ keepsPointerInside,
529
+ interactionKeyAtDepth,
530
+ horizontalBranchVisible,
531
+ shownFlyoutKeys,
532
+ setFlyoutRef,
533
+ flyoutTriggers,
534
+ flyoutPanels,
535
+ suppressFocusOpen: { get: () => suppressFocusOpen },
536
+ setSuppressFocusOpen: (value) => {
537
+ suppressFocusOpen = value;
538
+ },
539
+ cancelClose,
540
+ scheduleOpen,
541
+ scheduleClose,
542
+ cancelAllTimers
543
+ };
544
+ }
545
+ function createNavMenuKeydownHandler(deps) {
546
+ const {
547
+ items,
548
+ flyoutMode,
549
+ expanded,
550
+ toggle,
551
+ openFlyout,
552
+ closeHorizontalMenus,
553
+ horizontalBranchVisible,
554
+ setBranchInteraction,
555
+ focusedBranches,
556
+ collapsed,
557
+ hoveredBranches,
558
+ clickedBranches,
559
+ setSuppressFocusOpen
560
+ } = deps;
561
+ return (e) => {
562
+ const root = e.currentTarget;
563
+ const buttons = Array.from(root.querySelectorAll("[data-iris-nav-item]")).filter(
564
+ (button) => !button.closest('[data-iris-nav-children][aria-hidden="true"]')
565
+ );
566
+ if (buttons.length === 0) return;
567
+ const idx = buttons.indexOf(document.activeElement);
568
+ const focusAt = (i) => buttons[(i + buttons.length) % buttons.length]?.focus();
569
+ const key = idx >= 0 ? buttons[idx]?.getAttribute("data-key") : void 0;
570
+ const node = key ? findNavNode(items, key) : void 0;
571
+ const depth = idx >= 0 ? Number(buttons[idx]?.getAttribute("data-depth") ?? 0) : 0;
572
+ switch (e.key) {
573
+ case "ArrowDown": {
574
+ e.preventDefault();
575
+ if (flyoutMode() && node && isBranch(node)) {
576
+ openFlyout(key);
577
+ const group = buttons[idx].closest("[data-iris-nav-group]");
578
+ void nextTick(() => {
579
+ group?.querySelector("[data-iris-nav-children] [data-iris-nav-item]")?.focus();
580
+ });
581
+ return;
582
+ }
583
+ focusAt(idx < 0 ? 0 : idx + 1);
584
+ return;
585
+ }
586
+ case "ArrowUp": {
587
+ e.preventDefault();
588
+ if (flyoutMode() && node && isBranch(node) && horizontalBranchVisible(key, depth)) {
589
+ setBranchInteraction(focusedBranches, key, false);
590
+ setBranchInteraction(clickedBranches, key, false);
591
+ return;
592
+ }
593
+ focusAt(idx < 0 ? buttons.length - 1 : idx - 1);
594
+ return;
595
+ }
596
+ case "Home":
597
+ e.preventDefault();
598
+ buttons[0]?.focus();
599
+ return;
600
+ case "End":
601
+ e.preventDefault();
602
+ buttons[buttons.length - 1]?.focus();
603
+ return;
604
+ case "Escape": {
605
+ if (flyoutMode()) {
606
+ const openKeys = [
607
+ ...hoveredBranches.value,
608
+ ...clickedBranches.value,
609
+ ...focusedBranches.value
610
+ ];
611
+ if (openKeys.length > 0) {
612
+ e.preventDefault();
613
+ const openTop = openKeys.find((k) => findNavPath(items, k).length === 1);
614
+ closeHorizontalMenus();
615
+ if (openTop) {
616
+ setSuppressFocusOpen(true);
617
+ buttons.find((b) => b.getAttribute("data-key") === openTop)?.focus();
618
+ void nextTick(() => {
619
+ setSuppressFocusOpen(false);
620
+ });
621
+ }
622
+ }
623
+ }
624
+ return;
625
+ }
626
+ }
627
+ if (collapsed || idx < 0 || !key || !node) return;
628
+ if (e.key === "ArrowRight") {
629
+ e.preventDefault();
630
+ if (isBranch(node)) {
631
+ if (flyoutMode() || !expanded().includes(key)) {
632
+ if (flyoutMode()) openFlyout(key);
633
+ else toggle(key);
634
+ const group = buttons[idx].closest("[data-iris-nav-group]");
635
+ void nextTick(() => {
636
+ group?.querySelector("[data-iris-nav-children] [data-iris-nav-item]")?.focus();
637
+ });
638
+ } else {
639
+ focusAt(idx + 1);
640
+ }
641
+ }
642
+ } else if (e.key === "ArrowLeft") {
643
+ e.preventDefault();
644
+ if (flyoutMode() && isBranch(node)) {
645
+ setBranchInteraction(focusedBranches, key, false);
646
+ setBranchInteraction(clickedBranches, key, false);
647
+ return;
648
+ }
649
+ if (isBranch(node) && expanded().includes(key)) {
650
+ toggle(key);
651
+ } else {
652
+ const parentKey = findNavPath(items, key).at(-2)?.key;
653
+ if (parentKey) {
654
+ buttons.find((b) => b.getAttribute("data-key") === parentKey)?.focus();
655
+ }
656
+ }
657
+ }
658
+ };
659
+ }
317
660
 
318
661
  // src/admin/NavMenu.ts
319
662
  var IrisNavMenu = defineComponent({
@@ -347,6 +690,7 @@ var IrisNavMenu = defineComponent({
347
690
  const activePath = computed(
348
691
  () => props.activeKey ? findNavPath(props.items, props.activeKey).map((n) => n.key) : []
349
692
  );
693
+ const flyoutMode = computed(() => props.orientation === "horizontal" || props.collapsed);
350
694
  const isControlled = computed(() => props.expandedKeys !== void 0);
351
695
  const model = createExpansion({
352
696
  mode: "multiple",
@@ -361,12 +705,9 @@ var IrisNavMenu = defineComponent({
361
705
  const expanded = computed(
362
706
  () => isControlled.value ? props.expandedKeys : internalExpanded.value
363
707
  );
364
- watch(
365
- () => props.activeKey,
366
- (key) => {
367
- if (!isControlled.value) model.merge(key ? branchTrail(props.items, key) : []);
368
- }
369
- );
708
+ watch([() => props.activeKey, () => props.items], ([key]) => {
709
+ if (!isControlled.value) model.merge(key ? branchTrail(props.items, key) : []);
710
+ });
370
711
  const toggle = (key) => {
371
712
  if (isControlled.value) {
372
713
  const cur = props.expandedKeys;
@@ -379,39 +720,35 @@ var IrisNavMenu = defineComponent({
379
720
  emit("update:expandedKeys", model.get());
380
721
  }
381
722
  };
382
- const hovered = ref(null);
383
- const hoveredBranches = ref([]);
384
- const focusedBranches = ref([]);
385
- const closeHorizontalMenus = () => {
386
- if (props.orientation !== "horizontal") return;
387
- hovered.value = null;
388
- hoveredBranches.value = [];
389
- focusedBranches.value = [];
390
- };
391
- const select = (node) => {
392
- if (node.disabled) return;
393
- closeHorizontalMenus();
394
- emit("select", node.key, node);
395
- };
396
- const setBranchInteraction = (state, key, enabled) => {
397
- const current = state.value;
398
- if (enabled) {
399
- if (!current.includes(key)) state.value = [...current, key];
400
- } else if (current.includes(key)) {
401
- state.value = current.filter((item) => item !== key);
402
- }
403
- };
404
- const keepsPointerInside = (container, event) => {
405
- if (!container || !(container instanceof HTMLElement)) return false;
406
- const next = event.relatedTarget;
407
- return !!(next && next instanceof Node && container.contains(next));
408
- };
409
- const interactionKeyAtDepth = (keys, depth) => keys.find((key) => findNavPath(props.items, key).length === depth + 1);
410
- const horizontalBranchVisible = (key, depth) => {
411
- const hoveredAtDepth = interactionKeyAtDepth(hoveredBranches.value, depth);
412
- if (hoveredAtDepth) return hoveredAtDepth === key;
413
- return interactionKeyAtDepth(focusedBranches.value, depth) === key;
414
- };
723
+ const flyout = createNavMenuFlyout({
724
+ items: props.items,
725
+ tree,
726
+ expanded,
727
+ flyoutMode: { value: flyoutMode.value },
728
+ collapsed: props.collapsed,
729
+ toggle,
730
+ emitSelect: (key, node) => emit("select", key, node)
731
+ });
732
+ const {
733
+ hovered,
734
+ hoveredBranches,
735
+ focusedBranches,
736
+ clickedBranches,
737
+ select,
738
+ toggleFlyout,
739
+ openFlyout,
740
+ closeHorizontalMenus,
741
+ setBranchInteraction,
742
+ keepsPointerInside,
743
+ horizontalBranchVisible,
744
+ setFlyoutRef,
745
+ flyoutTriggers,
746
+ flyoutPanels,
747
+ suppressFocusOpen,
748
+ cancelClose,
749
+ scheduleOpen,
750
+ scheduleClose
751
+ } = flyout;
415
752
  const itemClass = (opts) => {
416
753
  const depth = Math.min(9, opts.depth);
417
754
  return [
@@ -434,81 +771,47 @@ var IrisNavMenu = defineComponent({
434
771
  },
435
772
  String(node.badge)
436
773
  ) : null;
437
- const renderCollapsed = () => tree.value.map((node) => {
774
+ const renderItem = (node, depth) => {
438
775
  const branch = isBranch(node);
439
- const active = branch ? activePath.value.includes(node.key) : node.key === props.activeKey;
440
- return h(
776
+ const horizontal = flyoutMode.value;
777
+ const open = expanded.value.includes(node.key);
778
+ const shown = horizontal ? horizontalBranchVisible(node.key, depth) : open;
779
+ const active = node.key === props.activeKey;
780
+ const trail = branch && !active && activePath.value.includes(node.key);
781
+ const rowHovered = hovered.value === node.key || horizontal && shown;
782
+ const arrowReversed = branch && !node.disabled && (active || trail || shown || rowHovered);
783
+ const isFlyoutRoot = horizontal && branch && depth === 0;
784
+ const row = h(
441
785
  "button",
442
786
  {
443
- key: node.key,
444
787
  type: "button",
788
+ ref: (el) => {
789
+ if (isFlyoutRoot) setFlyoutRef(flyoutTriggers, node.key, el);
790
+ },
445
791
  class: [
446
792
  ...itemClass({
447
- depth: 0,
793
+ depth,
448
794
  active,
449
- trail: false,
450
- hovered: hovered.value === node.key,
451
- open: false,
795
+ trail,
796
+ hovered: rowHovered,
797
+ open: branch ? shown : false,
452
798
  disabled: !!node.disabled,
453
799
  branch
454
800
  }),
455
- "is-collapsed"
801
+ ...props.collapsed && depth === 0 ? ["is-collapsed"] : []
456
802
  ],
457
803
  "data-iris-nav-item": "",
458
804
  "data-key": node.key,
459
- "data-active": active ? "true" : void 0,
460
- "data-branch": branch ? "true" : void 0,
461
- "data-hovered": hovered.value === node.key ? "true" : void 0,
462
- disabled: node.disabled,
463
- title: node.title,
464
- "aria-label": branch ? `${node.title} (section)` : node.title,
465
- "aria-current": active && !branch ? "page" : void 0,
466
- onMouseenter: () => {
467
- if (!node.disabled) hovered.value = node.key;
468
- },
469
- onMouseleave: (event) => {
470
- if (hovered.value === node.key && !keepsPointerInside(event.currentTarget, event)) {
471
- hovered.value = null;
472
- }
473
- },
474
- onClick: () => select(branch ? firstLeaf(node) : node)
475
- },
476
- [
477
- iconNode(node, 20) ?? h("span", { class: "iris-nav-menu-fallback-icon" }, node.title.charAt(0))
478
- ]
479
- );
480
- });
481
- const renderItem = (node, depth) => {
482
- const branch = isBranch(node);
483
- const open = expanded.value.includes(node.key);
484
- const horizontal = props.orientation === "horizontal";
485
- const shown = horizontal ? horizontalBranchVisible(node.key, depth) : open;
486
- const active = node.key === props.activeKey;
487
- const trail = branch && !active && activePath.value.includes(node.key);
488
- const arrowReversed = branch && !node.disabled && (active || trail || shown || hovered.value === node.key);
489
- const row = h(
490
- "button",
491
- {
492
- type: "button",
493
- class: itemClass({
494
- depth,
495
- active,
496
- trail,
497
- hovered: hovered.value === node.key,
498
- open: branch ? shown : false,
499
- disabled: !!node.disabled,
500
- branch
501
- }),
502
- "data-iris-nav-item": "",
503
- "data-key": node.key,
504
805
  "data-branch": branch ? "true" : void 0,
505
806
  "data-active": active ? "true" : void 0,
506
807
  "data-active-trail": trail ? "true" : void 0,
507
808
  "data-open": branch && shown ? "true" : void 0,
508
- "data-hovered": hovered.value === node.key ? "true" : void 0,
809
+ "data-hovered": rowHovered ? "true" : void 0,
509
810
  "data-depth": String(depth),
510
811
  "data-orientation": props.orientation,
511
812
  disabled: node.disabled,
813
+ title: props.collapsed ? node.title : void 0,
814
+ "aria-label": props.collapsed ? branch ? `${node.title} (section)` : node.title : void 0,
512
815
  "aria-expanded": branch ? shown ? "true" : "false" : void 0,
513
816
  "aria-current": active ? "page" : void 0,
514
817
  onMouseenter: () => {
@@ -519,7 +822,17 @@ var IrisNavMenu = defineComponent({
519
822
  hovered.value = null;
520
823
  }
521
824
  },
522
- onClick: () => branch ? toggle(node.key) : select(node)
825
+ onClick: () => {
826
+ if (props.collapsed && branch) {
827
+ select(firstLeaf(node));
828
+ } else if (horizontal && branch) {
829
+ toggleFlyout(node.key);
830
+ } else if (branch) {
831
+ toggle(node.key);
832
+ } else {
833
+ select(node);
834
+ }
835
+ }
523
836
  },
524
837
  [
525
838
  iconNode(node),
@@ -531,54 +844,49 @@ var IrisNavMenu = defineComponent({
531
844
  node.title
532
845
  ),
533
846
  badgeNode(node),
534
- branch ? h(IrisIcon, {
535
- name: horizontal && depth === 0 ? "chevron-down" : "chevron-right",
847
+ branch && !(props.collapsed && depth === 0) ? h(IrisIcon, {
848
+ name: horizontal && depth === 0 && !props.collapsed ? "chevron-down" : "chevron-right",
536
849
  size: 16,
537
850
  class: "iris-nav-menu-arrow",
538
851
  "data-reversed": arrowReversed ? "true" : void 0
539
852
  }) : null
540
853
  ]
541
854
  );
542
- if (!branch || !horizontal && !open)
543
- return h(
544
- "div",
545
- {
546
- key: node.key,
547
- "data-iris-nav-group": branch ? "" : void 0,
548
- class: ["iris-nav-menu-group", `iris-nav-menu-group--depth-${Math.min(9, depth)}`]
549
- },
550
- [row]
551
- );
552
855
  return h(
553
856
  "div",
554
857
  {
555
858
  key: node.key,
556
- "data-iris-nav-group": "",
557
- "data-open": shown ? "true" : void 0,
859
+ "data-iris-nav-group": branch ? "" : void 0,
860
+ "data-open": branch && shown ? "true" : void 0,
558
861
  "data-depth": String(depth),
559
862
  class: ["iris-nav-menu-group", `iris-nav-menu-group--depth-${Math.min(9, depth)}`],
560
- ...horizontal ? {
863
+ ...horizontal && branch ? {
561
864
  onMouseenter: (event) => {
562
- if (!keepsPointerInside(event.currentTarget, event)) {
563
- setBranchInteraction(hoveredBranches, node.key, true);
865
+ if (!node.disabled && !keepsPointerInside(event.currentTarget, event)) {
866
+ cancelClose(node.key);
867
+ scheduleOpen(node.key);
564
868
  }
565
869
  },
566
870
  onMouseover: (event) => {
567
- if (!keepsPointerInside(event.currentTarget, event)) {
568
- setBranchInteraction(hoveredBranches, node.key, true);
871
+ if (!node.disabled && !keepsPointerInside(event.currentTarget, event)) {
872
+ cancelClose(node.key);
873
+ scheduleOpen(node.key);
569
874
  }
570
875
  },
571
876
  onMouseout: (event) => {
572
- if (!keepsPointerInside(event.currentTarget, event)) {
573
- setBranchInteraction(hoveredBranches, node.key, false);
877
+ if (!node.disabled && !keepsPointerInside(event.currentTarget, event)) {
878
+ scheduleClose(node.key);
574
879
  }
575
880
  },
576
881
  onMouseleave: (event) => {
577
- if (!keepsPointerInside(event.currentTarget, event)) {
578
- setBranchInteraction(hoveredBranches, node.key, false);
882
+ if (!node.disabled && !keepsPointerInside(event.currentTarget, event)) {
883
+ scheduleClose(node.key);
579
884
  }
580
885
  },
581
- onFocusin: () => setBranchInteraction(focusedBranches, node.key, true),
886
+ onFocusin: () => {
887
+ if (suppressFocusOpen.get()) return;
888
+ setBranchInteraction(focusedBranches, node.key, true);
889
+ },
582
890
  onFocusout: (event) => {
583
891
  const group = event.currentTarget;
584
892
  const next = event.relatedTarget;
@@ -590,66 +898,62 @@ var IrisNavMenu = defineComponent({
590
898
  },
591
899
  [
592
900
  row,
593
- h(
901
+ branch ? h(
594
902
  "div",
595
903
  {
596
904
  class: "iris-nav-menu-children",
597
905
  "data-iris-nav-children": "",
906
+ ref: (el) => {
907
+ if (isFlyoutRoot) setFlyoutRef(flyoutPanels, node.key, el);
908
+ },
598
909
  role: "group",
599
- "aria-hidden": horizontal && !shown ? "true" : void 0
910
+ "aria-hidden": shown ? void 0 : "true"
600
911
  },
601
- (node.children ?? []).map((child) => renderItem(child, depth + 1))
602
- )
912
+ [
913
+ h(
914
+ "div",
915
+ { class: "iris-nav-menu-children-inner" },
916
+ (node.children ?? []).map((child) => renderItem(child, depth + 1))
917
+ )
918
+ ]
919
+ ) : null
603
920
  ]
604
921
  );
605
922
  };
606
- const onKeydown = (e) => {
607
- const root = e.currentTarget;
608
- const buttons = Array.from(root.querySelectorAll("[data-iris-nav-item]")).filter(
609
- (button) => !button.closest('[data-iris-nav-children][aria-hidden="true"]')
610
- );
611
- if (buttons.length === 0) return;
612
- const idx = buttons.indexOf(document.activeElement);
613
- const focusAt = (i) => buttons[(i + buttons.length) % buttons.length]?.focus();
614
- switch (e.key) {
615
- case "ArrowDown":
616
- e.preventDefault();
617
- focusAt(idx < 0 ? 0 : idx + 1);
618
- return;
619
- case "ArrowUp":
620
- e.preventDefault();
621
- focusAt(idx < 0 ? buttons.length - 1 : idx - 1);
622
- return;
623
- case "Home":
624
- e.preventDefault();
625
- buttons[0]?.focus();
626
- return;
627
- case "End":
628
- e.preventDefault();
629
- buttons[buttons.length - 1]?.focus();
630
- return;
631
- }
632
- if (props.collapsed || idx < 0) return;
633
- const key = buttons[idx]?.getAttribute("data-key");
634
- if (!key) return;
635
- const node = findNavNode(props.items, key);
636
- if (e.key === "ArrowRight" && node && isBranch(node)) {
637
- e.preventDefault();
638
- if (!expanded.value.includes(key)) toggle(key);
639
- else focusAt(idx + 1);
640
- } else if (e.key === "ArrowLeft") {
641
- if (node && isBranch(node) && expanded.value.includes(key)) {
642
- e.preventDefault();
643
- toggle(key);
644
- } else {
645
- const parentKey = findNavPath(props.items, key).at(-2)?.key;
646
- if (parentKey) {
647
- e.preventDefault();
648
- buttons.find((b) => b.getAttribute("data-key") === parentKey)?.focus();
649
- }
923
+ const rootRef = shallowRef(null);
924
+ watch(
925
+ [() => props.activeKey, () => props.items],
926
+ () => {
927
+ if (!props.activeKey) return;
928
+ const root = rootRef.value;
929
+ if (!root) return;
930
+ const el = root.querySelector('[data-iris-nav-item][data-active="true"]');
931
+ if (!el || typeof el.scrollIntoView !== "function") return;
932
+ let behavior = "auto";
933
+ if (typeof window !== "undefined" && typeof window.matchMedia === "function" && !window.matchMedia("(prefers-reduced-motion: reduce)").matches) {
934
+ behavior = "smooth";
650
935
  }
651
- }
652
- };
936
+ el.scrollIntoView({ block: "nearest", inline: "nearest", behavior });
937
+ },
938
+ { flush: "post" }
939
+ );
940
+ const onKeydown = createNavMenuKeydownHandler({
941
+ items: props.items,
942
+ flyoutMode: () => flyoutMode.value,
943
+ expanded: () => expanded.value,
944
+ toggle,
945
+ openFlyout,
946
+ closeHorizontalMenus,
947
+ horizontalBranchVisible,
948
+ setBranchInteraction,
949
+ focusedBranches,
950
+ hoveredBranches,
951
+ clickedBranches,
952
+ setSuppressFocusOpen: (v) => {
953
+ flyout.setSuppressFocusOpen(v);
954
+ },
955
+ collapsed: props.collapsed
956
+ });
653
957
  const menuClass = [
654
958
  "iris-nav-menu",
655
959
  `iris-nav-menu--${props.orientation}`,
@@ -659,6 +963,9 @@ var IrisNavMenu = defineComponent({
659
963
  "nav",
660
964
  {
661
965
  ...attrs,
966
+ ref: (el) => {
967
+ rootRef.value = el ?? null;
968
+ },
662
969
  class: [...menuClass, attrs.class],
663
970
  "data-iris-nav-menu": "",
664
971
  "data-collapsed": props.collapsed ? "true" : void 0,
@@ -667,7 +974,7 @@ var IrisNavMenu = defineComponent({
667
974
  onKeydown,
668
975
  style: attrs.style
669
976
  },
670
- props.collapsed ? renderCollapsed() : tree.value.map((node) => renderItem(node, 0))
977
+ tree.value.map((node) => renderItem(node, 0))
671
978
  );
672
979
  }
673
980
  });
@@ -737,11 +1044,11 @@ var IrisBreadcrumb = defineComponent({
737
1044
  style: {
738
1045
  display: "inline-flex",
739
1046
  alignItems: "center",
740
- gap: "6px",
1047
+ gap: "var(--iris-space-xs, 8px)",
741
1048
  margin: "0",
742
1049
  padding: "0",
743
1050
  listStyle: "none",
744
- fontSize: "14px"
1051
+ fontSize: "var(--iris-font-size-md, 14px)"
745
1052
  }
746
1053
  },
747
1054
  items
@@ -1069,12 +1376,12 @@ var IrisDropdownMenu = defineComponent({
1069
1376
  onKeydown: onKeyDown,
1070
1377
  style: {
1071
1378
  ...floatingStyles.value,
1072
- background: "var(--iris-surface)",
1379
+ background: "var(--iris-surface-floating)",
1073
1380
  color: "var(--iris-foreground)",
1074
1381
  border: "1px solid var(--iris-border)",
1075
1382
  borderRadius: "var(--iris-radius-md)",
1076
1383
  padding: "var(--iris-padding-sm)",
1077
- boxShadow: "0 8px 24px -8px rgba(0, 0, 0, 0.16), 0 4px 8px -2px rgba(0, 0, 0, 0.08)",
1384
+ boxShadow: "var(--iris-shadow-lg)",
1078
1385
  minWidth: "160px",
1079
1386
  outline: "none",
1080
1387
  zIndex: "1000",
@@ -1139,14 +1446,14 @@ var IrisDropdownItem = defineComponent({
1139
1446
  display: "flex",
1140
1447
  alignItems: "center",
1141
1448
  gap: "var(--iris-gap-sm)",
1142
- padding: "6px var(--iris-padding-md)",
1449
+ padding: "var(--iris-padding-sm, 6px) var(--iris-padding-md)",
1143
1450
  borderRadius: "var(--iris-radius-sm)",
1144
1451
  cursor: props.disabled ? "not-allowed" : "pointer",
1145
1452
  opacity: props.disabled ? "0.5" : "1",
1146
1453
  background: hovered.value && !props.disabled ? "var(--iris-surface-hover)" : "transparent",
1147
1454
  color: "inherit",
1148
1455
  outline: "none",
1149
- fontSize: "14px",
1456
+ fontSize: "var(--iris-font-size-md, 14px)",
1150
1457
  transition: "background-color 80ms ease",
1151
1458
  ...attrs.style ?? {}
1152
1459
  }
@@ -1259,12 +1566,12 @@ var IrisAdminTabs = defineComponent({
1259
1566
  style: {
1260
1567
  display: "inline-flex",
1261
1568
  alignItems: "center",
1262
- gap: "6px",
1569
+ gap: "var(--iris-space-xs, 8px)",
1263
1570
  border: "none",
1264
1571
  background: "transparent",
1265
1572
  color: "inherit",
1266
1573
  font: "inherit",
1267
- fontSize: "13px",
1574
+ fontSize: "var(--iris-font-size-sm, 13px)",
1268
1575
  cursor: "pointer",
1269
1576
  padding: "0"
1270
1577
  },
@@ -1314,7 +1621,7 @@ var IrisAdminTabs = defineComponent({
1314
1621
  display: "inline-flex",
1315
1622
  alignItems: "center",
1316
1623
  gap: "4px",
1317
- padding: "5px 8px 5px 10px",
1624
+ padding: "var(--iris-padding-sm, 6px) var(--iris-space-xs, 8px) var(--iris-padding-sm, 6px) var(--iris-space-sm, 12px)",
1318
1625
  borderRadius: "var(--iris-radius-md, 6px)",
1319
1626
  border: `1px solid ${active ? "var(--iris-primary)" : "var(--iris-border)"}`,
1320
1627
  background: active ? "var(--iris-primary)" : "var(--iris-surface)",
@@ -1330,27 +1637,23 @@ var IrisAdminTabs = defineComponent({
1330
1637
  default: () => [
1331
1638
  h(
1332
1639
  IrisDropdownTrigger,
1333
- { "aria-label": tr("admin.tabActions") },
1334
1640
  {
1335
- default: () => h(
1336
- "span",
1337
- {
1338
- "data-iris-tab-actions": "",
1339
- style: {
1340
- display: "inline-flex",
1341
- alignItems: "center",
1342
- justifyContent: "center",
1343
- width: "28px",
1344
- height: "28px",
1345
- borderRadius: "var(--iris-radius-md, 6px)",
1346
- border: "1px solid var(--iris-border)",
1347
- background: "var(--iris-surface)",
1348
- color: "var(--iris-foreground)",
1349
- cursor: "pointer"
1350
- }
1351
- },
1352
- [h(IrisIcon, { name: "more-horizontal", size: 16 })]
1353
- )
1641
+ "aria-label": tr("admin.tabActions"),
1642
+ style: {
1643
+ display: "inline-flex",
1644
+ alignItems: "center",
1645
+ justifyContent: "center",
1646
+ width: "28px",
1647
+ height: "28px",
1648
+ borderRadius: "var(--iris-radius-md, 6px)",
1649
+ border: "1px solid var(--iris-border)",
1650
+ background: "var(--iris-surface)",
1651
+ color: "var(--iris-foreground)",
1652
+ cursor: "pointer"
1653
+ }
1654
+ },
1655
+ {
1656
+ default: () => h(IrisIcon, { name: "more-horizontal", size: 16 })
1354
1657
  }
1355
1658
  ),
1356
1659
  h(IrisDropdownMenu, null, {
@@ -1379,8 +1682,8 @@ var IrisAdminTabs = defineComponent({
1379
1682
  style: {
1380
1683
  display: "flex",
1381
1684
  alignItems: "center",
1382
- gap: "6px",
1383
- padding: "6px 10px",
1685
+ gap: "var(--iris-space-xs, 8px)",
1686
+ padding: "var(--iris-space-xs, 8px) var(--iris-space-sm, 12px)",
1384
1687
  borderBottom: "1px solid var(--iris-border)",
1385
1688
  background: "var(--iris-background)",
1386
1689
  ...attrs.style ?? {}
@@ -1410,7 +1713,7 @@ var IrisAdminTabs = defineComponent({
1410
1713
  orientation: "horizontal",
1411
1714
  style: {
1412
1715
  alignItems: "center",
1413
- gap: "6px",
1716
+ gap: "var(--iris-space-xs, 8px)",
1414
1717
  width: "max-content"
1415
1718
  }
1416
1719
  },
@@ -1537,12 +1840,12 @@ var IrisAdminLayout = defineComponent({
1537
1840
  style: {
1538
1841
  display: "flex",
1539
1842
  alignItems: "center",
1540
- gap: "10px",
1843
+ gap: "var(--iris-space-sm, 12px)",
1541
1844
  height: "52px",
1542
- padding: "0 16px",
1845
+ padding: "0 var(--iris-space-md, 16px)",
1543
1846
  color: "var(--iris-foreground)",
1544
1847
  fontWeight: "700",
1545
- fontSize: "16px",
1848
+ fontSize: "var(--iris-font-size-lg, 16px)",
1546
1849
  whiteSpace: "nowrap",
1547
1850
  overflow: "hidden",
1548
1851
  flexShrink: 0
@@ -1821,5 +2124,5 @@ function useAdminPreferences(preferences, hydrate = true) {
1821
2124
  }
1822
2125
 
1823
2126
  export { DropdownContextKey, IrisAdminBreadcrumb, IrisAdminLayout, IrisAdminTabs, IrisBreadcrumb, IrisBreadcrumbItem, IrisDropdown, IrisDropdownItem, IrisDropdownMenu, IrisDropdownSeparator, IrisDropdownTrigger, IrisIcon, IrisNavMenu, useAdminPreferences, useAdminShell, useTabsNav };
1824
- //# sourceMappingURL=chunk-QQ25RKOO.js.map
1825
- //# sourceMappingURL=chunk-QQ25RKOO.js.map
2127
+ //# sourceMappingURL=chunk-ASFDGYIR.js.map
2128
+ //# sourceMappingURL=chunk-ASFDGYIR.js.map