@iris-ui-kit/vue 0.2.12 → 0.2.14

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/admin.cjs CHANGED
@@ -327,6 +327,253 @@ function useI18n() {
327
327
  };
328
328
  }
329
329
 
330
+ // src/admin/styles.ts
331
+ var __NAV_MENU_STYLE_ID = "iris-nav-menu-styles";
332
+ var CSS = `
333
+ :where(.iris-nav-menu) {
334
+ --iris-nav-indent-step: 16px;
335
+ --iris-nav-item-padding-inline: 10px;
336
+ --iris-nav-item-padding-block: 8px;
337
+ --iris-nav-item-border-radius: var(--iris-radius-md, 6px);
338
+ --iris-nav-item-hover: var(--iris-surface-hover, var(--iris-surface));
339
+ --iris-nav-item-height: 34px;
340
+ display: flex;
341
+ flex-direction: column;
342
+ align-items: stretch;
343
+ gap: 2px;
344
+ width: 100%;
345
+ }
346
+
347
+ :where(.iris-nav-menu--horizontal) {
348
+ flex-direction: row;
349
+ align-items: center;
350
+ width: auto;
351
+ }
352
+
353
+ :where(.iris-nav-menu-group) {
354
+ position: relative;
355
+ }
356
+
357
+ :where(.iris-nav-menu-item) {
358
+ appearance: none;
359
+ box-sizing: border-box;
360
+ display: flex;
361
+ flex: 0 1 auto;
362
+ align-items: center;
363
+ width: 100%;
364
+ min-height: var(--iris-nav-item-height);
365
+ border: none;
366
+ border-radius: var(--iris-nav-item-border-radius);
367
+ background: transparent;
368
+ color: var(--iris-foreground, var(--iris-color-text, var(--iris-foreground)));
369
+ font: inherit;
370
+ font-size: 14px;
371
+ line-height: 1.2;
372
+ font-weight: 400;
373
+ text-align: start;
374
+ cursor: pointer;
375
+ opacity: 1;
376
+ margin: 0;
377
+ gap: 10px;
378
+ padding-block: var(--iris-nav-item-padding-block);
379
+ padding-inline: var(--iris-nav-item-padding-inline);
380
+ text-overflow: ellipsis;
381
+ white-space: nowrap;
382
+ }
383
+
384
+ :where(.iris-nav-menu--horizontal .iris-nav-menu-item) {
385
+ width: auto;
386
+ padding-inline-start: var(--iris-nav-item-padding-inline);
387
+ }
388
+
389
+ :where(.iris-nav-menu-item[data-depth='0']) {
390
+ --iris-nav-item-padding-inline-start: 10px;
391
+ }
392
+
393
+ :where(.iris-nav-menu-item[data-depth='1']) {
394
+ --iris-nav-item-padding-inline-start: calc(12px + var(--iris-nav-indent-step));
395
+ }
396
+
397
+ :where(.iris-nav-menu-item[data-depth='2']) {
398
+ --iris-nav-item-padding-inline-start: calc(12px + var(--iris-nav-indent-step) * 2);
399
+ }
400
+
401
+ :where(.iris-nav-menu-item[data-depth='3']) {
402
+ --iris-nav-item-padding-inline-start: calc(12px + var(--iris-nav-indent-step) * 3);
403
+ }
404
+
405
+ :where(.iris-nav-menu-item[data-depth='4']) {
406
+ --iris-nav-item-padding-inline-start: calc(12px + var(--iris-nav-indent-step) * 4);
407
+ }
408
+
409
+ :where(.iris-nav-menu-item[data-depth='5']) {
410
+ --iris-nav-item-padding-inline-start: calc(12px + var(--iris-nav-indent-step) * 5);
411
+ }
412
+
413
+ :where(.iris-nav-menu-item[data-depth='6']) {
414
+ --iris-nav-item-padding-inline-start: calc(12px + var(--iris-nav-indent-step) * 6);
415
+ }
416
+
417
+ :where(.iris-nav-menu-item[data-depth='7']) {
418
+ --iris-nav-item-padding-inline-start: calc(12px + var(--iris-nav-indent-step) * 7);
419
+ }
420
+
421
+ :where(.iris-nav-menu-item[data-depth='8']) {
422
+ --iris-nav-item-padding-inline-start: calc(12px + var(--iris-nav-indent-step) * 8);
423
+ }
424
+
425
+ :where(.iris-nav-menu-item[data-depth='9']) {
426
+ --iris-nav-item-padding-inline-start: calc(12px + var(--iris-nav-indent-step) * 9);
427
+ }
428
+
429
+ :where(.iris-nav-menu--vertical .iris-nav-menu-item[data-depth]) {
430
+ padding-inline-start: var(--iris-nav-item-padding-inline-start);
431
+ }
432
+
433
+ :where(.iris-nav-menu-item:hover),
434
+ :where(.iris-nav-menu-item.is-hovered):not([disabled], .is-disabled) {
435
+ background: var(--iris-nav-item-hover);
436
+ }
437
+
438
+ :where(.iris-nav-menu-item[data-active='true']) {
439
+ background: var(--iris-primary);
440
+ color: var(--iris-primary-foreground, #fff);
441
+ font-weight: 600;
442
+ }
443
+
444
+ :where(.iris-nav-menu-item[data-active-trail='true']) {
445
+ color: var(--iris-primary);
446
+ font-weight: 600;
447
+ }
448
+
449
+ :where(.iris-nav-menu-item[disabled], .iris-nav-menu-item.is-disabled) {
450
+ cursor: not-allowed;
451
+ opacity: 0.5;
452
+ }
453
+
454
+ :where(.iris-nav-menu-item:focus-visible) {
455
+ outline: 2px solid var(--iris-ring, var(--iris-primary));
456
+ outline-offset: 1px;
457
+ }
458
+
459
+ :where(.iris-nav-menu-label) {
460
+ flex: 0 1 auto;
461
+ min-width: 0;
462
+ overflow: hidden;
463
+ text-overflow: ellipsis;
464
+ }
465
+
466
+ :where(.iris-nav-menu-badge) {
467
+ margin-inline-start: 6px;
468
+ font-size: 11px;
469
+ line-height: 1;
470
+ padding: 2px 6px;
471
+ border-radius: 999px;
472
+ background: var(--iris-danger, #e5484d);
473
+ color: #fff;
474
+ flex: 0 0 auto;
475
+ }
476
+
477
+ :where(.iris-nav-menu-arrow) {
478
+ flex: 0 0 auto;
479
+ opacity: 0.6;
480
+ transform: rotate(0deg);
481
+ transform-origin: center;
482
+ transition: transform 160ms ease;
483
+ margin-inline-start: auto;
484
+ }
485
+
486
+ :where(.iris-nav-menu-arrow[data-reversed='true']) {
487
+ transform: rotate(180deg);
488
+ }
489
+
490
+ :where(.iris-nav-menu-fallback-icon) {
491
+ display: inline-flex;
492
+ width: 20px;
493
+ height: 20px;
494
+ align-items: center;
495
+ justify-content: center;
496
+ font-weight: 700;
497
+ }
498
+
499
+ :where(.iris-nav-menu-item.is-disabled) .iris-nav-menu-label {
500
+ opacity: 0.75;
501
+ }
502
+
503
+ :where(.iris-nav-menu-group--depth-0 > .iris-nav-menu-children) {
504
+ display: none;
505
+ }
506
+
507
+ :where(.iris-nav-menu-group--depth-1 > .iris-nav-menu-children),
508
+ :where(.iris-nav-menu-group--depth-2 > .iris-nav-menu-children),
509
+ :where(.iris-nav-menu-group--depth-3 > .iris-nav-menu-children),
510
+ :where(.iris-nav-menu-group--depth-4 > .iris-nav-menu-children),
511
+ :where(.iris-nav-menu-group--depth-5 > .iris-nav-menu-children),
512
+ :where(.iris-nav-menu-group--depth-6 > .iris-nav-menu-children),
513
+ :where(.iris-nav-menu-group--depth-7 > .iris-nav-menu-children),
514
+ :where(.iris-nav-menu-group--depth-8 > .iris-nav-menu-children),
515
+ :where(.iris-nav-menu-group--depth-9 > .iris-nav-menu-children),
516
+ :where(.iris-nav-menu-group > .iris-nav-menu-children) {
517
+ display: none;
518
+ }
519
+
520
+ :where(.iris-nav-menu-group[data-open='true'] > .iris-nav-menu-children) {
521
+ display: block;
522
+ }
523
+
524
+ :where(.iris-nav-menu--horizontal .iris-nav-menu-group > .iris-nav-menu-children) {
525
+ position: absolute;
526
+ min-width: 220px;
527
+ padding: 6px;
528
+ border: 1px solid var(--iris-border);
529
+ border-radius: var(--iris-radius-md, 6px);
530
+ background: var(--iris-surface);
531
+ box-shadow: var(--iris-shadow-md);
532
+ }
533
+
534
+ :where(.iris-nav-menu--horizontal .iris-nav-menu-group[data-depth='0'] > .iris-nav-menu-children) {
535
+ inset-block-start: 100%;
536
+ inset-inline-start: 0;
537
+ z-index: 60;
538
+ }
539
+
540
+ :where(.iris-nav-menu--horizontal .iris-nav-menu-group[data-depth]:not([data-depth='0']) > .iris-nav-menu-children) {
541
+ inset-block-start: 0;
542
+ inset-inline-start: 100%;
543
+ z-index: 61;
544
+ }
545
+
546
+ :where(.iris-nav-menu--collapsed .iris-nav-menu-item) {
547
+ justify-content: center;
548
+ padding-inline-start: var(--iris-nav-item-padding-inline);
549
+ }
550
+
551
+ :where(.iris-nav-menu-item.is-collapsed) {
552
+ justify-content: center;
553
+ padding-inline: var(--iris-nav-item-padding-inline);
554
+ }
555
+
556
+ @media (prefers-reduced-motion: reduce) {
557
+ :where(.iris-nav-menu-arrow) {
558
+ transition: none;
559
+ }
560
+ }
561
+ `.trim();
562
+ var installed = false;
563
+ function installNavMenuStyles() {
564
+ if (installed) return;
565
+ if (typeof document === "undefined") return;
566
+ if (document.getElementById(__NAV_MENU_STYLE_ID)) {
567
+ installed = true;
568
+ return;
569
+ }
570
+ const style = document.createElement("style");
571
+ style.id = __NAV_MENU_STYLE_ID;
572
+ style.textContent = CSS;
573
+ document.head.appendChild(style);
574
+ installed = true;
575
+ }
576
+
330
577
  // src/admin/NavMenu.ts
331
578
  var IrisNavMenu = vue.defineComponent({
332
579
  name: "IrisNavMenu",
@@ -353,6 +600,7 @@ var IrisNavMenu = vue.defineComponent({
353
600
  "update:expandedKeys": (_keys) => true
354
601
  },
355
602
  setup(props, { emit, attrs }) {
603
+ installNavMenuStyles();
356
604
  const { t } = useI18n();
357
605
  const tree = vue.computed(() => core.visibleNav(props.items));
358
606
  const activePath = vue.computed(
@@ -418,49 +666,25 @@ var IrisNavMenu = vue.defineComponent({
418
666
  if (hoveredAtDepth) return hoveredAtDepth === key;
419
667
  return interactionKeyAtDepth(focusedBranches.value, depth) === key;
420
668
  };
421
- const itemStyle = (opts) => {
422
- const bg = opts.active ? "var(--iris-primary)" : opts.hovered && !opts.disabled ? "var(--iris-surface-hover, var(--iris-surface))" : "transparent";
423
- return {
424
- display: "flex",
425
- alignItems: "center",
426
- gap: "10px",
427
- width: props.orientation === "horizontal" && opts.depth === 0 ? "auto" : "100%",
428
- boxSizing: "border-box",
429
- border: "none",
430
- borderRadius: "var(--iris-radius-md, 6px)",
431
- background: bg,
432
- color: opts.active ? "var(--iris-primary-foreground, #fff)" : opts.trail ? "var(--iris-primary)" : "var(--iris-foreground)",
433
- font: "inherit",
434
- fontSize: "14px",
435
- fontWeight: opts.active || opts.trail ? "600" : "400",
436
- textAlign: "start",
437
- cursor: opts.disabled ? "not-allowed" : "pointer",
438
- opacity: opts.disabled ? "0.5" : "1",
439
- padding: props.collapsed ? "10px" : "8px 10px",
440
- paddingInlineStart: props.collapsed || props.orientation === "horizontal" ? "10px" : `${12 + opts.depth * 16}px`,
441
- justifyContent: props.collapsed ? "center" : "flex-start"
442
- };
669
+ const itemClass = (opts) => {
670
+ const depth = Math.min(9, opts.depth);
671
+ return [
672
+ "iris-nav-menu-item",
673
+ `iris-nav-menu-item--depth-${depth}`,
674
+ `iris-nav-menu-item--${opts.branch ? "branch" : "leaf"}`,
675
+ opts.active ? "is-active" : void 0,
676
+ opts.trail ? "is-trail" : void 0,
677
+ opts.hovered ? "is-hovered" : void 0,
678
+ opts.open ? "is-open" : void 0,
679
+ opts.disabled ? "is-disabled" : void 0
680
+ ].filter(Boolean);
443
681
  };
444
- const hoverHandlers = (key) => ({
445
- onMouseenter: () => hovered.value = key,
446
- onMouseleave: () => {
447
- if (hovered.value === key) hovered.value = null;
448
- }
449
- });
450
682
  const iconNode = (node, size = 18) => node.icon ? vue.h(IrisIcon, { name: node.icon, size }) : null;
451
683
  const badgeNode = (node) => node.badge !== void 0 && node.badge !== "" && !props.collapsed ? vue.h(
452
684
  "span",
453
685
  {
454
- "data-iris-nav-badge": "",
455
- style: {
456
- marginInlineStart: "auto",
457
- fontSize: "11px",
458
- lineHeight: "1",
459
- padding: "2px 6px",
460
- borderRadius: "999px",
461
- background: "var(--iris-danger, #e5484d)",
462
- color: "#fff"
463
- }
686
+ class: "iris-nav-menu-badge",
687
+ "data-iris-nav-badge": ""
464
688
  },
465
689
  String(node.badge)
466
690
  ) : null;
@@ -472,25 +696,38 @@ var IrisNavMenu = vue.defineComponent({
472
696
  {
473
697
  key: node.key,
474
698
  type: "button",
699
+ class: [
700
+ ...itemClass({
701
+ depth: 0,
702
+ active,
703
+ trail: false,
704
+ hovered: hovered.value === node.key,
705
+ open: false,
706
+ disabled: !!node.disabled,
707
+ branch
708
+ }),
709
+ "is-collapsed"
710
+ ],
475
711
  "data-iris-nav-item": "",
476
712
  "data-key": node.key,
477
713
  "data-active": active ? "true" : void 0,
478
714
  "data-branch": branch ? "true" : void 0,
715
+ "data-hovered": hovered.value === node.key ? "true" : void 0,
479
716
  disabled: node.disabled,
480
717
  title: node.title,
481
718
  "aria-label": branch ? `${node.title} (section)` : node.title,
482
719
  "aria-current": active && !branch ? "page" : void 0,
483
- style: itemStyle({
484
- depth: 0,
485
- active,
486
- trail: false,
487
- hovered: hovered.value === node.key,
488
- disabled: !!node.disabled
489
- }),
490
- ...hoverHandlers(node.key),
720
+ onMouseenter: () => {
721
+ if (!node.disabled) hovered.value = node.key;
722
+ },
723
+ onMouseleave: () => {
724
+ if (hovered.value === node.key) hovered.value = null;
725
+ },
491
726
  onClick: () => select(branch ? core.firstLeaf(node) : node)
492
727
  },
493
- [iconNode(node, 20) ?? vue.h("span", { style: { fontWeight: "700" } }, node.title.charAt(0))]
728
+ [
729
+ iconNode(node, 20) ?? vue.h("span", { class: "iris-nav-menu-fallback-icon" }, node.title.charAt(0))
730
+ ]
494
731
  );
495
732
  });
496
733
  const renderItem = (node, depth) => {
@@ -500,28 +737,38 @@ var IrisNavMenu = vue.defineComponent({
500
737
  const shown = horizontal ? horizontalBranchVisible(node.key, depth) : open;
501
738
  const active = node.key === props.activeKey;
502
739
  const trail = branch && !active && activePath.value.includes(node.key);
740
+ const arrowReversed = branch && !node.disabled && (active || trail || shown || hovered.value === node.key);
503
741
  const row = vue.h(
504
742
  "button",
505
743
  {
506
744
  type: "button",
745
+ class: itemClass({
746
+ depth,
747
+ active,
748
+ trail,
749
+ hovered: hovered.value === node.key,
750
+ open: branch ? shown : false,
751
+ disabled: !!node.disabled,
752
+ branch
753
+ }),
507
754
  "data-iris-nav-item": "",
508
755
  "data-key": node.key,
509
756
  "data-branch": branch ? "true" : void 0,
510
757
  "data-active": active ? "true" : void 0,
511
758
  "data-active-trail": trail ? "true" : void 0,
512
759
  "data-open": branch && shown ? "true" : void 0,
760
+ "data-hovered": hovered.value === node.key ? "true" : void 0,
513
761
  "data-depth": String(depth),
762
+ "data-orientation": props.orientation,
514
763
  disabled: node.disabled,
515
764
  "aria-expanded": branch ? shown ? "true" : "false" : void 0,
516
765
  "aria-current": active ? "page" : void 0,
517
- style: itemStyle({
518
- depth,
519
- active,
520
- trail,
521
- hovered: hovered.value === node.key,
522
- disabled: !!node.disabled
523
- }),
524
- ...hoverHandlers(node.key),
766
+ onMouseenter: () => {
767
+ if (!node.disabled) hovered.value = node.key;
768
+ },
769
+ onMouseleave: () => {
770
+ if (hovered.value === node.key) hovered.value = null;
771
+ },
525
772
  onClick: () => branch ? toggle(node.key) : select(node)
526
773
  },
527
774
  [
@@ -529,12 +776,7 @@ var IrisNavMenu = vue.defineComponent({
529
776
  vue.h(
530
777
  "span",
531
778
  {
532
- style: {
533
- flex: branch ? "1" : "0 1 auto",
534
- overflow: "hidden",
535
- textOverflow: "ellipsis",
536
- whiteSpace: "nowrap"
537
- }
779
+ class: "iris-nav-menu-label"
538
780
  },
539
781
  node.title
540
782
  ),
@@ -542,15 +784,19 @@ var IrisNavMenu = vue.defineComponent({
542
784
  branch ? vue.h(IrisIcon, {
543
785
  name: horizontal && depth === 0 ? "chevron-down" : "chevron-right",
544
786
  size: 16,
545
- style: { marginInlineStart: badgeNode(node) ? "6px" : "auto", opacity: "0.6" }
787
+ class: "iris-nav-menu-arrow",
788
+ "data-reversed": arrowReversed ? "true" : void 0
546
789
  }) : null
547
790
  ]
548
791
  );
549
- const groupStyle = horizontal && branch ? { position: "relative" } : void 0;
550
792
  if (!branch || !horizontal && !open)
551
793
  return vue.h(
552
794
  "div",
553
- { key: node.key, "data-iris-nav-group": branch ? "" : void 0, style: groupStyle },
795
+ {
796
+ key: node.key,
797
+ "data-iris-nav-group": branch ? "" : void 0,
798
+ class: ["iris-nav-menu-group", `iris-nav-menu-group--depth-${Math.min(9, depth)}`]
799
+ },
554
800
  [row]
555
801
  );
556
802
  return vue.h(
@@ -559,7 +805,11 @@ var IrisNavMenu = vue.defineComponent({
559
805
  key: node.key,
560
806
  "data-iris-nav-group": "",
561
807
  "data-open": shown ? "true" : void 0,
562
- style: groupStyle,
808
+ "data-depth": String(depth),
809
+ class: [
810
+ "iris-nav-menu-group",
811
+ `iris-nav-menu-group--depth-${Math.min(9, depth)}`
812
+ ],
563
813
  ...horizontal ? {
564
814
  onMouseenter: () => setBranchInteraction(hoveredBranches, node.key, true),
565
815
  onMouseleave: () => setBranchInteraction(hoveredBranches, node.key, false),
@@ -578,22 +828,10 @@ var IrisNavMenu = vue.defineComponent({
578
828
  vue.h(
579
829
  "div",
580
830
  {
831
+ class: "iris-nav-menu-children",
581
832
  "data-iris-nav-children": "",
582
833
  role: "group",
583
- "aria-hidden": horizontal && !shown ? "true" : void 0,
584
- style: horizontal ? {
585
- display: shown ? "block" : "none",
586
- position: "absolute",
587
- insetBlockStart: depth === 0 ? "100%" : "0",
588
- insetInlineStart: depth === 0 ? "0" : "100%",
589
- zIndex: depth === 0 ? "60" : "61",
590
- minWidth: "220px",
591
- padding: "6px",
592
- border: "1px solid var(--iris-border)",
593
- borderRadius: "var(--iris-radius-md, 6px)",
594
- background: "var(--iris-surface)",
595
- boxShadow: "var(--iris-shadow-md)"
596
- } : void 0
834
+ "aria-hidden": horizontal && !shown ? "true" : void 0
597
835
  },
598
836
  (node.children ?? []).map((child) => renderItem(child, depth + 1))
599
837
  )
@@ -647,22 +885,22 @@ var IrisNavMenu = vue.defineComponent({
647
885
  }
648
886
  }
649
887
  };
888
+ const menuClass = [
889
+ "iris-nav-menu",
890
+ `iris-nav-menu--${props.orientation}`,
891
+ props.collapsed ? "iris-nav-menu--collapsed" : "iris-nav-menu--expanded"
892
+ ];
650
893
  return () => vue.h(
651
894
  "nav",
652
895
  {
653
896
  ...attrs,
897
+ class: [...menuClass, attrs.class],
654
898
  "data-iris-nav-menu": "",
655
899
  "data-collapsed": props.collapsed ? "true" : void 0,
656
900
  "data-orientation": props.orientation,
657
901
  "aria-label": props.ariaLabel ?? t("admin.nav"),
658
902
  onKeydown,
659
- style: {
660
- display: "flex",
661
- flexDirection: props.orientation === "horizontal" ? "row" : "column",
662
- alignItems: props.orientation === "horizontal" ? "center" : void 0,
663
- gap: "2px",
664
- ...attrs.style ?? {}
665
- }
903
+ style: attrs.style
666
904
  },
667
905
  props.collapsed ? renderCollapsed() : tree.value.map((node) => renderItem(node, 0))
668
906
  );