djm-ui 0.67.3 → 0.72.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.
Files changed (40) hide show
  1. package/CHANGELOG.md +108 -0
  2. package/README.md +38 -2
  3. package/dist/djm-ui.cjs +1051 -356
  4. package/dist/djm-ui.cjs.map +4 -4
  5. package/dist/djm-ui.css +752 -17
  6. package/dist/djm-ui.esm.js +1127 -432
  7. package/dist/djm-ui.esm.js.map +4 -4
  8. package/dist/djm-ui.esm.min.js +375 -229
  9. package/dist/djm-ui.min.cjs +375 -229
  10. package/dist/djm-ui.min.css +2 -2
  11. package/dist/djm-ui.umd.js +967 -272
  12. package/dist/djm-ui.umd.min.js +375 -229
  13. package/dist/mcp/manifest.json +12195 -0
  14. package/dist/mcp/server.js +90 -0
  15. package/package.json +12 -4
  16. package/src/components/icon/index.js +13 -1
  17. package/src/components/input/index.js +17 -6
  18. package/src/components/rich-editor/index.js +724 -61
  19. package/src/index.js +1 -1
  20. package/src/locale/en-US.js +33 -1
  21. package/src/locale/zh-CN.js +33 -1
  22. package/src/styles/base.css +2 -3
  23. package/src/styles/components/button.css +2 -1
  24. package/src/styles/components/console.css +5 -0
  25. package/src/styles/components/content.css +517 -0
  26. package/src/styles/components/form.css +5 -0
  27. package/src/styles/components/layout.css +327 -1
  28. package/src/styles/components/media-picker.css +3 -3
  29. package/src/styles/components/menu.css +2 -1
  30. package/src/styles/components/org-picker.css +1 -1
  31. package/src/styles/components/responsive.css +86 -0
  32. package/src/styles/components/rich-editor.css +206 -7
  33. package/src/styles/components/skin.css +54 -0
  34. package/src/styles/components/template.css +5 -0
  35. package/src/styles/index.css +1 -0
  36. package/src/styles/theme-dark.css +2 -0
  37. package/src/styles/tokens.css +8 -0
  38. package/src/theme/index.js +40 -0
  39. package/src/utils/sanitize-html.js +44 -6
  40. package/types/index.d.ts +8 -0
@@ -324,7 +324,7 @@
324
324
  display: flex;
325
325
  align-items: center;
326
326
  gap: 8px;
327
- height: 36px;
327
+ height: 33px;
328
328
  padding-right: 8px;
329
329
  border-radius: var(--djm-radius-lg);
330
330
  color: var(--djm-text-side);
@@ -465,6 +465,15 @@
465
465
  align-items: center;
466
466
  gap: 6px;
467
467
  margin-bottom: 3px;
468
+ white-space: nowrap;
469
+ }
470
+
471
+ /* 版权:小一号,避免挤出侧栏宽度 */
472
+ .djm-foot-legal {
473
+ display: block;
474
+ font-size: 10.5px;
475
+ line-height: 1.7;
476
+ color: var(--djm-text-3);
468
477
  }
469
478
 
470
479
  .djm-pulse {
@@ -478,11 +487,322 @@
478
487
  .djm-foot-version {
479
488
  font-size: 10.5px;
480
489
  color: var(--djm-text-3);
490
+ white-space: nowrap;
481
491
  }
482
492
 
483
493
  .djm-nav-mask {
484
494
  display: none;
485
495
  }
496
+
497
+ /* ---------------- 侧栏导航的三种形态 ---------------- */
498
+
499
+ /* 侧栏内容区:单列 / 双列两套导航共用同一块高度 */
500
+ .djm-sidebar-body {
501
+ flex: 1;
502
+ min-height: 0;
503
+ display: flex;
504
+ }
505
+
506
+ .djm-sidebar-body > .djm-nav {
507
+ flex: 1;
508
+ min-width: 0;
509
+ }
510
+
511
+ /* 双列与混合布局下才出现的两列,默认不占位 */
512
+ .djm-nav-primary,
513
+ .djm-nav-secondary {
514
+ display: none;
515
+ }
516
+
517
+ /* 双列:左窄列放一级,右列放二级,侧栏整体加宽 */
518
+ .djm-app.djm-menu-double {
519
+ /* 104 一级列 + 192 二级列,二级菜单文字够用又不占太多内容区 */
520
+ --djm-sidebar-w: 296px;
521
+ }
522
+
523
+ .djm-app.djm-menu-double .djm-nav-inline {
524
+ display: none;
525
+ }
526
+
527
+ .djm-app.djm-menu-double .djm-brand {
528
+ width: 104px;
529
+ /* 双列只留 logo,居中对齐下方一级列 */
530
+ justify-content: center;
531
+ padding: 0;
532
+ }
533
+
534
+ .djm-app.djm-menu-double .djm-brand-text {
535
+ display: none;
536
+ }
537
+
538
+ .djm-app.djm-menu-double .djm-nav-primary {
539
+ display: flex;
540
+ flex: 0 0 104px;
541
+ flex-direction: column;
542
+ gap: 2px;
543
+ padding: 12px 6px;
544
+ overflow-y: auto;
545
+ background: var(--djm-surface-2);
546
+ border-right: 1px solid var(--djm-border);
547
+ scrollbar-width: thin;
548
+ }
549
+
550
+ .djm-nav-primary-item {
551
+ display: flex;
552
+ flex-direction: column;
553
+ align-items: center;
554
+ gap: 4px;
555
+ padding: 9px 4px;
556
+ border: 0;
557
+ border-radius: var(--djm-radius-lg);
558
+ background: transparent;
559
+ color: var(--djm-text-side);
560
+ font-size: 11.5px;
561
+ line-height: 1.25;
562
+ text-align: center;
563
+ cursor: pointer;
564
+ transition: background 0.14s, color 0.14s;
565
+ }
566
+
567
+ .djm-nav-primary-item:hover {
568
+ background: var(--djm-hover);
569
+ color: var(--djm-text);
570
+ }
571
+
572
+ .djm-nav-primary-item.djm-is-active {
573
+ background: var(--djm-brand-soft);
574
+ color: var(--djm-brand-700);
575
+ font-weight: 600;
576
+ }
577
+
578
+ .djm-app.djm-menu-double .djm-nav-secondary,
579
+ .djm-app.djm-layout-mix .djm-nav-secondary {
580
+ display: block;
581
+ padding: 10px 8px;
582
+ }
583
+
584
+ /* 二级栏里的分组标题与条目 */
585
+ .djm-nav-group {
586
+ margin: 10px 0 4px;
587
+ padding: 0 8px;
588
+ font-size: 11px;
589
+ font-weight: 500;
590
+ color: var(--djm-text-3);
591
+ }
592
+
593
+ .djm-nav-group:first-child {
594
+ margin-top: 0;
595
+ }
596
+
597
+ .djm-nav-item {
598
+ width: 100%;
599
+ display: flex;
600
+ align-items: center;
601
+ gap: 8px;
602
+ height: 32px;
603
+ padding: 0 8px;
604
+ border: 0;
605
+ border-radius: var(--djm-radius-lg);
606
+ background: transparent;
607
+ color: var(--djm-text-side);
608
+ font-size: 13px;
609
+ text-align: left;
610
+ cursor: pointer;
611
+ transition: background 0.14s, color 0.14s;
612
+ }
613
+
614
+ .djm-nav-item:hover {
615
+ background: var(--djm-surface-3);
616
+ color: var(--djm-text);
617
+ }
618
+
619
+ .djm-nav-item.djm-is-active {
620
+ background: var(--djm-brand-soft);
621
+ color: var(--djm-brand-700);
622
+ font-weight: 600;
623
+ }
624
+
625
+ .djm-nav-item-label {
626
+ min-width: 0;
627
+ overflow: hidden;
628
+ text-overflow: ellipsis;
629
+ white-space: nowrap;
630
+ }
631
+
632
+ .djm-nav-item .djm-nav-count {
633
+ margin-left: auto;
634
+ }
635
+
636
+ /* 混合:顶部一级 + 侧栏二级 */
637
+ .djm-app.djm-layout-mix {
638
+ --djm-sidebar-w: 216px;
639
+ }
640
+
641
+ .djm-app.djm-layout-mix .djm-nav-inline {
642
+ display: none;
643
+ }
644
+
645
+ .djm-app.djm-layout-mix .djm-hamburger {
646
+ display: none;
647
+ }
648
+
649
+ .djm-app.djm-layout-mix .djm-brand {
650
+ width: auto;
651
+ border-right: 0;
652
+ padding-right: 6px;
653
+ }
654
+
655
+ /* 顶栏一级导航(混合布局) */
656
+ .djm-topnav {
657
+ flex: 1;
658
+ min-width: 0;
659
+ display: flex;
660
+ align-items: center;
661
+ gap: 2px;
662
+ overflow: hidden;
663
+ }
664
+
665
+ .djm-topnav-item {
666
+ flex: none;
667
+ display: inline-flex;
668
+ align-items: center;
669
+ gap: 6px;
670
+ height: 32px;
671
+ padding: 0 10px;
672
+ border: 0;
673
+ border-radius: var(--djm-radius);
674
+ background: transparent;
675
+ color: var(--djm-text-2);
676
+ font-size: 13px;
677
+ white-space: nowrap;
678
+ cursor: pointer;
679
+ transition: background 0.14s, color 0.14s;
680
+ }
681
+
682
+ .djm-topnav-item:hover {
683
+ background: var(--djm-surface-3);
684
+ color: var(--djm-text);
685
+ }
686
+
687
+ .djm-topnav-item.djm-is-active {
688
+ background: var(--djm-brand-soft);
689
+ color: var(--djm-brand-700);
690
+ font-weight: 600;
691
+ }
692
+
693
+ /* ---------------- 侧栏配色(与全局明暗解耦) ---------------- */
694
+
695
+ /* 深色侧栏:浅色页面里也能左深右浅 */
696
+ .djm-app.djm-sider-dark .djm-sidebar,
697
+ .djm-app.djm-sider-dark.djm-layout-side .djm-brand {
698
+ --djm-surface: #1b232d;
699
+ --djm-surface-2: #171e27;
700
+ --djm-surface-3: #232c37;
701
+ --djm-hover: #26303c;
702
+ --djm-border: #2b3542;
703
+ --djm-text: #e8edf3;
704
+ --djm-text-nav: #d5dde6;
705
+ --djm-text-side: #c2ccd8;
706
+ --djm-text-2: #a6b2c0;
707
+ --djm-text-3: #8492a1;
708
+ background: var(--djm-surface);
709
+ border-color: var(--djm-border);
710
+ color: var(--djm-text);
711
+ }
712
+
713
+ /* 浅色侧栏:深色页面里也能左浅右深 */
714
+ .djm-app.djm-sider-light .djm-sidebar,
715
+ .djm-app.djm-sider-light.djm-layout-side .djm-brand {
716
+ --djm-surface: #ffffff;
717
+ --djm-surface-2: #f8fafd;
718
+ --djm-surface-3: #f5f8fc;
719
+ --djm-hover: #eef3f9;
720
+ --djm-border: #dde6f0;
721
+ --djm-text: #1e2b3a;
722
+ --djm-text-nav: #35475c;
723
+ --djm-text-side: #3a4b60;
724
+ --djm-text-2: #5a6b7d;
725
+ --djm-text-3: #5f7183;
726
+ background: var(--djm-surface);
727
+ border-color: var(--djm-border);
728
+ color: var(--djm-text);
729
+ }
730
+
731
+ /* 品牌色侧栏:整块用主色实底,条目靠白色透明度分层 */
732
+ .djm-app.djm-sider-brand .djm-sidebar,
733
+ .djm-app.djm-sider-brand.djm-layout-side .djm-brand {
734
+ --djm-surface: var(--djm-brand-solid);
735
+ --djm-surface-2: rgba(255, 255, 255, 0.06);
736
+ --djm-surface-3: rgba(255, 255, 255, 0.12);
737
+ --djm-hover: rgba(255, 255, 255, 0.1);
738
+ --djm-border: rgba(255, 255, 255, 0.16);
739
+ --djm-text: #ffffff;
740
+ --djm-text-nav: rgba(255, 255, 255, 0.94);
741
+ --djm-text-side: rgba(255, 255, 255, 0.82);
742
+ --djm-text-2: rgba(255, 255, 255, 0.9);
743
+ --djm-text-3: rgba(255, 255, 255, 0.8);
744
+ --djm-brand-soft: rgba(255, 255, 255, 0.18);
745
+ --djm-brand-100: rgba(255, 255, 255, 0.26);
746
+ --djm-brand-200: rgba(255, 255, 255, 0.4);
747
+ --djm-brand-600: #ffffff;
748
+ --djm-brand-700: #ffffff;
749
+ background: var(--djm-brand-solid);
750
+ border-color: rgba(255, 255, 255, 0.16);
751
+ color: var(--djm-text);
752
+ }
753
+
754
+ /* 品牌底上选中项用白字 + 白色描边,避免浅蓝字发虚 */
755
+ .djm-app.djm-sider-brand .djm-tree-row.djm-is-active,
756
+ .djm-app.djm-sider-brand .djm-tree-row.djm-is-active:hover,
757
+ .djm-app.djm-sider-brand .djm-nav-item.djm-is-active,
758
+ .djm-app.djm-sider-brand .djm-nav-primary-item.djm-is-active {
759
+ color: #ffffff;
760
+ box-shadow: inset 0 0 0 1px rgba(255, 255, 255, 0.32);
761
+ }
762
+
763
+ /* 深色侧栏的选中态:底色与文字都跟着主色色相走,
764
+ 否则青碧、紫罗兰、朱砂红选出来都是一团近黑 */
765
+ .djm-app.djm-sider-dark .djm-sidebar .djm-tree-row.djm-is-active,
766
+ .djm-app.djm-sider-dark .djm-sidebar .djm-nav-item.djm-is-active,
767
+ .djm-app.djm-sider-dark .djm-sidebar .djm-nav-primary-item.djm-is-active,
768
+ :root[data-djm-theme='dark'] .djm-app.djm-sider-auto .djm-sidebar .djm-tree-row.djm-is-active,
769
+ :root[data-djm-theme='dark'] .djm-app.djm-sider-auto .djm-sidebar .djm-nav-item.djm-is-active,
770
+ :root[data-djm-theme='dark'] .djm-app.djm-sider-auto .djm-sidebar .djm-nav-primary-item.djm-is-active {
771
+ background: var(--djm-sider-active, var(--djm-brand-soft));
772
+ color: var(--djm-sider-active-text, var(--djm-brand-700));
773
+ }
774
+
775
+ /* 选中项 hover 再亮一档,不要掉回接近背景的深色 */
776
+ .djm-app.djm-sider-dark .djm-sidebar .djm-tree-row.djm-is-active:hover,
777
+ .djm-app.djm-sider-dark .djm-sidebar .djm-nav-item.djm-is-active:hover,
778
+ .djm-app.djm-sider-dark .djm-sidebar .djm-nav-primary-item.djm-is-active:hover,
779
+ :root[data-djm-theme='dark'] .djm-app.djm-sider-auto .djm-sidebar .djm-tree-row.djm-is-active:hover,
780
+ :root[data-djm-theme='dark'] .djm-app.djm-sider-auto .djm-sidebar .djm-nav-item.djm-is-active:hover,
781
+ :root[data-djm-theme='dark'] .djm-app.djm-sider-auto .djm-sidebar .djm-nav-primary-item.djm-is-active:hover {
782
+ background: var(--djm-sider-active-hover, var(--djm-brand-100));
783
+ color: var(--djm-sider-active-text, var(--djm-brand-700));
784
+ }
785
+
786
+ .djm-app.djm-sider-dark .djm-sidebar .djm-tree-row.djm-is-active .djm-tree-arrow,
787
+ :root[data-djm-theme='dark'] .djm-app.djm-sider-auto .djm-sidebar .djm-tree-row.djm-is-active .djm-tree-arrow {
788
+ color: var(--djm-sider-active-text, var(--djm-brand-600));
789
+ }
790
+
791
+ .djm-app.djm-sider-brand .djm-brand-mark {
792
+ background: rgba(255, 255, 255, 0.2);
793
+ }
794
+
795
+ /* 品牌底上的计数徽标:用深色半透明压出层次,白字才够对比 */
796
+ .djm-app.djm-sider-brand .djm-tree-row.djm-is-active .djm-nav-count {
797
+ background: rgba(0, 0, 0, 0.22);
798
+ border-color: rgba(255, 255, 255, 0.24);
799
+ color: #ffffff;
800
+ }
801
+
802
+ .djm-app.djm-sider-brand .djm-brand-accent {
803
+ color: #ffffff;
804
+ }
805
+
486
806
  /* ---------------- 主区域 ---------------- */
487
807
 
488
808
  /* 主区域固定视口高度,滚动交给内容区,避免整页上下跳 */
@@ -742,6 +1062,12 @@
742
1062
  flex-wrap: nowrap;
743
1063
  }
744
1064
 
1065
+ /* 顶部通栏的一级项多,收紧左右内边距,避免「系统管理」被省略成「系统…」 */
1066
+ .djm-app.djm-layout-top .djm-topbar-menu .djm-menu-link {
1067
+ gap: 6px;
1068
+ padding: 0 9px;
1069
+ }
1070
+
745
1071
  /* 顶部布局下没有抽屉菜单,汉堡按钮无意义 */
746
1072
  .djm-app.djm-layout-top .djm-hamburger {
747
1073
  display: none;
@@ -29,7 +29,7 @@
29
29
  padding: 0 10px;
30
30
  height: 30px;
31
31
  border: 1px solid var(--djm-border);
32
- border-radius: var(--djm-radius-md, 4px);
32
+ border-radius: var(--djm-radius);
33
33
  background: var(--djm-surface);
34
34
  color: var(--djm-text-3);
35
35
  }
@@ -62,14 +62,14 @@
62
62
 
63
63
  .djm-media-item {
64
64
  border: 1px solid var(--djm-border);
65
- border-radius: var(--djm-radius-md, 4px);
65
+ border-radius: var(--djm-radius);
66
66
  overflow: hidden;
67
67
  cursor: pointer;
68
68
  background: var(--djm-surface);
69
69
  }
70
70
 
71
71
  .djm-media-item:hover {
72
- border-color: var(--djm-brand-400, #79a9d6);
72
+ border-color: var(--djm-brand-500);
73
73
  }
74
74
 
75
75
  .djm-media-item:focus-visible {
@@ -94,7 +94,8 @@
94
94
  height: 16px;
95
95
  padding: 0 4px;
96
96
  border-radius: 8px;
97
- background: var(--djm-red);
97
+ /* 红点底色用实色档,暗色主题下白字才够清楚 */
98
+ background: var(--djm-red-strong);
98
99
  color: var(--djm-text-inverse);
99
100
  font-size: 10px;
100
101
  font-style: normal;
@@ -120,7 +120,7 @@
120
120
  /* 打开在弹窗 / 抽屉里时也要压在遮罩之上 */
121
121
  z-index: var(--djm-z-popper, 1450);
122
122
  border: 1px solid var(--djm-border);
123
- border-radius: var(--djm-radius-md, 4px);
123
+ border-radius: var(--djm-radius);
124
124
  background: var(--djm-surface);
125
125
  box-shadow: var(--djm-shadow-md, 0 6px 20px rgba(0, 0, 0, 0.12));
126
126
  }
@@ -41,6 +41,48 @@
41
41
  }
42
42
  }
43
43
 
44
+ /* 混合布局:屏幕不够宽时顶部一级菜单收起,改用完整树的抽屉 */
45
+ @media (max-width: 1320px) {
46
+ .djm-app.djm-layout-mix {
47
+ --djm-sidebar-w: 232px;
48
+ }
49
+ .djm-app.djm-layout-mix .djm-topnav {
50
+ display: none;
51
+ }
52
+ .djm-app.djm-layout-mix .djm-sidebar {
53
+ display: flex;
54
+ transform: translateX(-100%);
55
+ transition: transform 0.22s ease;
56
+ box-shadow: var(--djm-shadow-lg);
57
+ }
58
+ .djm-app.djm-layout-mix .djm-sidebar.djm-is-open {
59
+ transform: none;
60
+ }
61
+ .djm-app.djm-layout-mix .djm-main {
62
+ margin-left: 0;
63
+ }
64
+ .djm-app.djm-layout-mix .djm-brand {
65
+ width: auto;
66
+ border-right: 0;
67
+ }
68
+ .djm-app.djm-layout-mix .djm-hamburger {
69
+ display: inline-flex;
70
+ }
71
+ .djm-app.djm-layout-mix .djm-nav-secondary {
72
+ display: none;
73
+ }
74
+ .djm-app.djm-layout-mix .djm-nav-inline {
75
+ display: block;
76
+ }
77
+ .djm-app.djm-layout-mix .djm-nav-mask {
78
+ display: block;
79
+ position: fixed;
80
+ inset: var(--djm-topbar-h) 0 0;
81
+ background: var(--djm-mask);
82
+ z-index: 29;
83
+ }
84
+ }
85
+
44
86
  @media (max-width: 1024px) {
45
87
  .djm-dash-stats {
46
88
  grid-template-columns: repeat(2, minmax(0, 1fr));
@@ -50,6 +92,28 @@
50
92
  }
51
93
  }
52
94
 
95
+ /* 平板宽度下双列菜单太占地方,退回单列完整树 */
96
+ @media (max-width: 1100px) {
97
+ .djm-app.djm-menu-double {
98
+ --djm-sidebar-w: 228px;
99
+ }
100
+ .djm-app.djm-menu-double .djm-nav-primary,
101
+ .djm-app.djm-menu-double .djm-nav-secondary {
102
+ display: none;
103
+ }
104
+ .djm-app.djm-menu-double .djm-nav-inline {
105
+ display: block;
106
+ }
107
+ .djm-app.djm-menu-double .djm-brand {
108
+ width: var(--djm-sidebar-w);
109
+ justify-content: flex-start;
110
+ padding: 0 14px;
111
+ }
112
+ .djm-app.djm-menu-double .djm-brand-text {
113
+ display: flex;
114
+ }
115
+ }
116
+
53
117
  @media (max-width: 960px) {
54
118
  .djm-sidebar {
55
119
  transform: translateX(-100%);
@@ -62,6 +126,24 @@
62
126
  .djm-main {
63
127
  margin-left: 0;
64
128
  }
129
+ /* 双列菜单在手机端退回单列完整树,抽屉才放得下 */
130
+ .djm-app.djm-menu-double {
131
+ --djm-sidebar-w: 232px;
132
+ }
133
+ .djm-app.djm-menu-double .djm-nav-primary,
134
+ .djm-app.djm-menu-double .djm-nav-secondary {
135
+ display: none;
136
+ }
137
+ .djm-app.djm-menu-double .djm-nav-inline {
138
+ display: block;
139
+ }
140
+ .djm-app.djm-menu-double .djm-brand {
141
+ width: auto;
142
+ padding: 0 8px;
143
+ }
144
+ .djm-app.djm-menu-double .djm-brand-text {
145
+ display: flex;
146
+ }
65
147
  .djm-brand {
66
148
  width: auto;
67
149
  border-right: 0;
@@ -279,6 +361,10 @@
279
361
  .djm-table-tools-right {
280
362
  flex-wrap: wrap;
281
363
  }
364
+ /* 工具栏提示在窄屏只会多占一行 */
365
+ .djm-toolbar-tip {
366
+ display: none;
367
+ }
282
368
  /* 表格在手机上收紧内边距,能多露出一列信息 */
283
369
  .djm-data-table th,
284
370
  .djm-data-table td {