@open-feishu-card/renderer 0.1.1 → 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/styles.css CHANGED
@@ -25,6 +25,167 @@
25
25
  max-width: 605px;
26
26
  box-sizing: border-box;
27
27
  box-shadow: 0 4px 14px rgba(31, 35, 41, 0.08);
28
+ /* BEGIN PALETTE VARS (auto-generated from constants.ts PALETTE) */
29
+ /* 正文 color:var(--O400) 等依赖这些变量;与飞书 :root light 色阶对齐 */
30
+ --B50: #f0f4ff;
31
+ --B100: #e0e9ff;
32
+ --B200: #c2d4ff;
33
+ --B300: #94b4ff;
34
+ --B350: #7aa2ff;
35
+ --B400: #5083fb;
36
+ --B500: #336df4;
37
+ --B600: #1456f0;
38
+ --B700: #0442d2;
39
+ --B800: #002f9e;
40
+ --B900: #002270;
41
+ --C50: #fef0f8;
42
+ --C100: #fee2f2;
43
+ --C200: #f8c4e1;
44
+ --C300: #f598cc;
45
+ --C350: #eb78b8;
46
+ --C400: #df58a5;
47
+ --C500: #cc398c;
48
+ --C600: #b82879;
49
+ --C700: #9d1562;
50
+ --C800: #730744;
51
+ --C900: #550c35;
52
+ --G50: #e4fae1;
53
+ --G100: #d0f5ce;
54
+ --G200: #95e599;
55
+ --G300: #5cd168;
56
+ --G350: #35bd4b;
57
+ --G400: #32a645;
58
+ --G500: #258832;
59
+ --G600: #1a7526;
60
+ --G700: #0b6017;
61
+ --G800: #04430c;
62
+ --G900: #022c07;
63
+ --I50: #f2f3fd;
64
+ --I100: #e9eafb;
65
+ --I200: #cccff9;
66
+ --I300: #abb0f2;
67
+ --I350: #959bee;
68
+ --I400: #757df0;
69
+ --I500: #5b65f5;
70
+ --I600: #4752e6;
71
+ --I700: #333dcc;
72
+ --I800: #1e27a4;
73
+ --I900: #151b70;
74
+ --L50: #f2f8d3;
75
+ --L100: #e3f0a3;
76
+ --L200: #c8dd5f;
77
+ --L300: #a2c10b;
78
+ --L350: #91ad00;
79
+ --L400: #7b9207;
80
+ --L500: #6b7f06;
81
+ --L600: #5c6d08;
82
+ --L700: #4a5804;
83
+ --L800: #333d00;
84
+ --L900: #262e00;
85
+ --N00: #ffffff;
86
+ --N50: #f5f6f7;
87
+ --N100: #f2f3f5;
88
+ --N200: #eff0f1;
89
+ --N300: #dee0e3;
90
+ --N350: #d0d3d6;
91
+ --N400: #bbbfc4;
92
+ --N500: #8f959e;
93
+ --N600: #646a73;
94
+ --N650: #51565d;
95
+ --N700: #373c43;
96
+ --N800: #2b2f36;
97
+ --N900: #1f2329;
98
+ --N950: #0f1114;
99
+ --N1000: #000000;
100
+ --O50: #fff3e5;
101
+ --O100: #fee7cd;
102
+ --O200: #fec48b;
103
+ --O300: #ff9d4c;
104
+ --O350: #ff811a;
105
+ --O400: #ed6d0c;
106
+ --O500: #c25705;
107
+ --O600: #a44904;
108
+ --O700: #853a05;
109
+ --O800: #642b02;
110
+ --O900: #3b1a02;
111
+ --P50: #f5f0fe;
112
+ --P100: #efe6fe;
113
+ --P200: #dcc9fd;
114
+ --P300: #c8a9fc;
115
+ --P350: #b791fa;
116
+ --P400: #9f6ff1;
117
+ --P500: #8d55ed;
118
+ --P600: #7a35f0;
119
+ --P700: #611fd6;
120
+ --P800: #4811a6;
121
+ --P900: #2f0080;
122
+ --R50: #fef0f0;
123
+ --R100: #fee3e2;
124
+ --R200: #fdc6c4;
125
+ --R300: #f89e9b;
126
+ --R350: #ff7570;
127
+ --R400: #f54a45;
128
+ --R500: #e22e28;
129
+ --R600: #c02a26;
130
+ --R700: #a11c17;
131
+ --R800: #741915;
132
+ --R900: #590603;
133
+ --S50: #ffffdb;
134
+ --S100: #fffca3;
135
+ --S200: #fff67a;
136
+ --S300: #fff258;
137
+ --S350: #ffe928;
138
+ --S400: #e5ce00;
139
+ --S500: #c2a800;
140
+ --S600: #8f7c00;
141
+ --S700: #5c4f00;
142
+ --S800: #423700;
143
+ --S900: #2c2502;
144
+ --T50: #e2f8f5;
145
+ --T100: #c4f2ec;
146
+ --T200: #6fe8d8;
147
+ --T300: #33d6c0;
148
+ --T350: #2dbeab;
149
+ --T400: #10a893;
150
+ --T500: #0f8575;
151
+ --T600: #067062;
152
+ --T700: #045d51;
153
+ --T800: #03443b;
154
+ --T900: #02312a;
155
+ --V50: #fceefc;
156
+ --V100: #f9e2f9;
157
+ --V200: #f3c4f3;
158
+ --V300: #e59ce5;
159
+ --V350: #de81de;
160
+ --V400: #cf5ecf;
161
+ --V500: #bf3dbf;
162
+ --V600: #a630a6;
163
+ --V700: #872787;
164
+ --V800: #6a116a;
165
+ --V900: #520052;
166
+ --W50: #e7f8fe;
167
+ --W100: #caeffc;
168
+ --W200: #97dcfc;
169
+ --W300: #3ec3f7;
170
+ --W350: #25b0e7;
171
+ --W400: #1295ca;
172
+ --W500: #047fb0;
173
+ --W600: #076a94;
174
+ --W700: #0f587a;
175
+ --W800: #06415c;
176
+ --W900: #072b3d;
177
+ --Y50: #fbf4df;
178
+ --Y100: #faedc2;
179
+ --Y200: #fcdf7e;
180
+ --Y300: #fad355;
181
+ --Y350: #ffc60a;
182
+ --Y400: #d99904;
183
+ --Y500: #ad7a03;
184
+ --Y600: #865b03;
185
+ --Y700: #6f4a01;
186
+ --Y800: #573601;
187
+ --Y900: #382201;
188
+ /* END PALETTE VARS */
28
189
  }
29
190
  .universal-card-root *,
30
191
  .universal-card-root *::before,
@@ -43,8 +204,8 @@
43
204
  padding: 12px;
44
205
  background-repeat: no-repeat;
45
206
  background-position: 0 0;
46
- /* 图宽=header宽,使纹理自身的左右暗边落在 header 两端、亮带居中 */
47
- background-size: 100% 140px;
207
+ /* 对齐飞书:max(100%, 605px) 140px,窄卡不把高光拉稀 */
208
+ background-size: max(100%, 605px) 140px;
48
209
  }
49
210
  /* 内容行:左侧图标 + 右侧标题区(对齐网页版 header__content = row) */
50
211
  .universal-card-header__content {
@@ -141,7 +302,7 @@
141
302
  margin: 8px 0;
142
303
  }
143
304
 
144
- /* ---- div ---- */
305
+ /* ---- div / note ---- */
145
306
  .universal-card-div > * + * { margin-top: 8px; }
146
307
  /* div 带前置图标:icon 在左、文本在右排成一行(复刻网页版 .universal-card-div 布局) */
147
308
  .universal-card-div--with-icon {
@@ -153,6 +314,10 @@
153
314
  display: flex; align-items: center; overflow: hidden;
154
315
  }
155
316
  .universal-card-div__content { flex: 1; min-width: 0; }
317
+ .universal-card-note {
318
+ font-size: 12px;
319
+ color: #8f959e;
320
+ }
156
321
 
157
322
  /* ---- 布局:column_set / column ---- */
158
323
  .universal-card-column-set { display: flex; }
@@ -312,6 +477,10 @@
312
477
  word-break: break-word;
313
478
  white-space: break-spaces;
314
479
  }
480
+ /* textStyle.attributes → BEM 修饰类(对齐真机 bold/italic/through) */
481
+ .universal-card-text--bold { font-weight: 600; }
482
+ .universal-card-text--italic { font-style: italic; }
483
+ .universal-card-text--through { text-decoration: line-through; }
315
484
  /* 勾选态:删除线 / 透明度由 :has(:checked) 驱动,本地切换无需 JS */
316
485
  .universal-card-checker--strike:has(.universal-card-checker__input:checked) .universal-card-checker__content {
317
486
  text-decoration-line: line-through;
@@ -383,8 +552,22 @@
383
552
  /* ---- 人员 person_v1 / person_list(对齐网页版 universal-card-person*)---- */
384
553
  .universal-card-person {
385
554
  display: inline-flex; align-items: center; width: auto; max-width: 100%;
555
+ }
556
+ /* 有头像:网页版就是 vertical-align:bottom。middle 按拉丁 x-height 居中,
557
+ * 中文行里整盒(头像 18 + 姓名 22)会视觉偏下。
558
+ * 仅姓名:跟正文基线对齐,不要 bottom/middle。 */
559
+ .universal-card-markdown .universal-card-person--avatar,
560
+ .universal-card-person--avatar {
386
561
  vertical-align: bottom;
387
562
  }
563
+ .universal-card-markdown .universal-card-person:not(.universal-card-person--avatar) {
564
+ vertical-align: baseline;
565
+ align-items: baseline;
566
+ }
567
+ .universal-card-markdown .universal-card-person:not(.universal-card-person--avatar) .universal-card-person__content,
568
+ .universal-card-markdown .universal-card-person:not(.universal-card-person--avatar) .universal-card-person__name {
569
+ align-items: baseline;
570
+ }
388
571
  .universal-card-person__content {
389
572
  display: flex; align-items: center; max-width: 100%; cursor: default;
390
573
  }
@@ -410,9 +593,11 @@
410
593
  display: inline-flex; align-items: center; min-width: 0;
411
594
  color: #1f2329; max-width: 100%;
412
595
  }
596
+ /* 真机 --line-1 是 block + nowrap,不是 -webkit-box clamp;
597
+ * clamp 会破坏 inline-flex 基线,姓名在正文里看起来靠下。 */
413
598
  .universal-card-person__name .universal-card-text--line-1 {
414
- display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 1;
415
- overflow: hidden; word-break: break-all;
599
+ display: block; white-space: nowrap;
600
+ overflow: hidden; text-overflow: ellipsis;
416
601
  }
417
602
  .universal-card-person .universal-card-text { line-height: inherit; }
418
603
 
@@ -517,6 +702,225 @@
517
702
  vertical-align: -0.125em;
518
703
  }
519
704
 
705
+ /* ---- video 视频 ---- */
706
+ /* 对齐飞书 .universal-card-video:有 src 时原生 <video controls>;无 src 时封面 + 播放钮。 */
707
+ .universal-card-video {
708
+ position: relative;
709
+ display: block;
710
+ width: 100%;
711
+ min-width: 96px;
712
+ min-height: 54px;
713
+ aspect-ratio: 16 / 9;
714
+ background-color: rgba(0, 0, 0, 0.8);
715
+ overflow: hidden;
716
+ cursor: default;
717
+ border-radius: 4px;
718
+ object-fit: contain;
719
+ box-sizing: border-box;
720
+ }
721
+ .universal-card-video__cover {
722
+ width: 100%;
723
+ height: 100%;
724
+ display: flex;
725
+ justify-content: center;
726
+ align-items: center;
727
+ }
728
+ .universal-card-video__host-image {
729
+ width: 100%;
730
+ height: 100%;
731
+ object-fit: cover;
732
+ display: block;
733
+ }
734
+ .universal-card-video__default-cover {
735
+ width: 100%;
736
+ height: 100%;
737
+ background: linear-gradient(135deg, #2b2f36 0%, #1f2329 100%);
738
+ }
739
+ .universal-card-video__play-btn {
740
+ position: absolute;
741
+ left: 50%;
742
+ top: 50%;
743
+ width: 40px;
744
+ height: 40px;
745
+ margin: -20px 0 0 -20px;
746
+ display: flex;
747
+ justify-content: center;
748
+ align-items: center;
749
+ color: #fff;
750
+ font-size: 18px;
751
+ border: 1px solid #fff;
752
+ border-radius: 50%;
753
+ background: rgba(0, 0, 0, 0.4);
754
+ box-sizing: border-box;
755
+ pointer-events: none;
756
+ }
757
+ .universal-card-video__duration {
758
+ position: absolute;
759
+ bottom: 6px;
760
+ right: 6px;
761
+ padding: 0 4px;
762
+ height: 16px;
763
+ display: flex;
764
+ justify-content: center;
765
+ align-items: center;
766
+ font-size: 10px;
767
+ color: #fff;
768
+ background-color: rgba(0, 0, 0, 0.55);
769
+ border: 1px solid rgba(255, 255, 255, 0.1);
770
+ border-radius: 4px;
771
+ user-select: none;
772
+ box-sizing: border-box;
773
+ }
774
+
775
+ /* ---- audio 音频 ---- */
776
+ /* 对齐飞书 .universal-card-audio__*:自定义播放条,非原生 controls。
777
+ * 顶层 audio = 块级圆角条;markdown_audio = --inline 胶囊(padding/圆角/扁平图标不同)。 */
778
+ .universal-card-audio__wrapper {
779
+ position: relative;
780
+ align-self: flex-start;
781
+ background: var(--universal-card-audio-bg, #f5f6f7);
782
+ cursor: pointer;
783
+ transition: background-color 0.3s ease;
784
+ border: 1px solid #dee0e3;
785
+ border-radius: 8px;
786
+ padding: 12px;
787
+ box-sizing: border-box;
788
+ max-width: 100%;
789
+ }
790
+ .universal-card-audio__wrapper--disabled {
791
+ background: #eff0f1;
792
+ cursor: default;
793
+ opacity: 0.7;
794
+ }
795
+ .universal-card-audio__wrapper:hover:not(.universal-card-audio__wrapper--disabled) {
796
+ background: var(--universal-card-audio-hover-bg, var(--universal-card-audio-bg, #eff0f1));
797
+ }
798
+ /* markdown 内嵌:行内容胶囊(真机 --inline) */
799
+ .universal-card-audio__wrapper--inline {
800
+ display: inline-flex;
801
+ margin: 0 3px;
802
+ padding: 4px 7px;
803
+ border-radius: 30px;
804
+ }
805
+ .universal-card-audio__native {
806
+ display: none;
807
+ }
808
+ .universal-card-audio__component {
809
+ max-width: 100%;
810
+ position: relative;
811
+ }
812
+ .universal-card-audio__control {
813
+ width: 100%;
814
+ display: flex;
815
+ align-items: center;
816
+ column-gap: 12px;
817
+ box-sizing: border-box;
818
+ user-select: none;
819
+ color: #8f959e;
820
+ }
821
+ .universal-card-audio__wrapper--inline .universal-card-audio__control {
822
+ position: relative;
823
+ column-gap: 0;
824
+ padding-left: calc(var(--universal-card-audio-icon-size, 0) + 2px);
825
+ height: var(--universal-card-audio-icon-size, 16px);
826
+ }
827
+ .universal-card-audio__ctrl {
828
+ flex-grow: 0;
829
+ flex-shrink: 0;
830
+ width: var(--universal-card-audio-icon-size, 20px);
831
+ height: var(--universal-card-audio-icon-size, 20px);
832
+ cursor: pointer;
833
+ display: inline-flex;
834
+ align-items: center;
835
+ justify-content: center;
836
+ color: var(--universal-card-audio-fill-color, #1f2329);
837
+ }
838
+ .universal-card-audio__wrapper--inline .universal-card-audio__ctrl {
839
+ position: absolute;
840
+ left: 0;
841
+ top: 50%;
842
+ transform: translateY(-50%);
843
+ }
844
+ .universal-card-audio__ctrl-icon {
845
+ font-size: var(--universal-card-audio-icon-size, 20px);
846
+ line-height: 1;
847
+ display: inline-flex;
848
+ color: inherit;
849
+ position: relative;
850
+ }
851
+ .universal-card-audio__wrapper--inline .universal-card-audio__ctrl-icon {
852
+ left: 8%;
853
+ transform: scale(0.85);
854
+ }
855
+ .universal-card-audio__icon {
856
+ display: inline-flex;
857
+ color: inherit;
858
+ }
859
+ .universal-card-audio__icon--pause { display: none; }
860
+ /* 播放中:隐藏播放钮、显示暂停钮(由 hydrate 给 wrapper 加 --playing) */
861
+ .universal-card-audio__wrapper--playing .universal-card-audio__icon--play { display: none; }
862
+ .universal-card-audio__wrapper--playing .universal-card-audio__icon--pause { display: inline-flex; }
863
+ .universal-card-audio__ctrl-icon svg,
864
+ .universal-card-audio__icon svg {
865
+ display: block;
866
+ width: 1em;
867
+ height: 1em;
868
+ }
869
+ .universal-card-audio__slider {
870
+ position: relative;
871
+ flex-grow: 1;
872
+ min-width: 32px;
873
+ height: 6px;
874
+ cursor: pointer;
875
+ }
876
+ .universal-card-audio__slider-bg {
877
+ position: absolute;
878
+ left: 0;
879
+ top: 50%;
880
+ height: 1px;
881
+ background-color: rgba(31, 35, 41, 0.3);
882
+ margin-top: -1px;
883
+ width: 100%;
884
+ }
885
+ .universal-card-audio__process {
886
+ background-color: var(--universal-card-audio-fill-color, #1f2329);
887
+ width: 0;
888
+ height: 100%;
889
+ left: 0;
890
+ }
891
+ .universal-card-audio__slider-strip {
892
+ position: absolute;
893
+ width: 16px;
894
+ height: 16px;
895
+ margin-top: -8px;
896
+ margin-left: -8px;
897
+ border-radius: 8px;
898
+ box-sizing: border-box;
899
+ background-color: #fff;
900
+ top: 50%;
901
+ left: 0;
902
+ cursor: pointer;
903
+ box-shadow: 0 0 8px 0 rgba(31, 35, 41, 0.16);
904
+ transform: scale(0.5);
905
+ transition: transform 0.3s ease;
906
+ }
907
+ .universal-card-audio__wrapper:hover:not(.universal-card-audio__wrapper--disabled) .universal-card-audio__slider-strip {
908
+ transform: scale(1);
909
+ }
910
+ .universal-card-audio__time {
911
+ color: var(--universal-card-audio-fill-color, #1f2329);
912
+ position: relative;
913
+ width: 38px;
914
+ flex-grow: 0;
915
+ flex-shrink: 0;
916
+ font-size: var(--universal-card-audio-time-font-size, 12px);
917
+ font-weight: 500;
918
+ text-align: center;
919
+ }
920
+ .universal-card-audio__wrapper--inline .universal-card-audio__time {
921
+ width: calc(var(--universal-card-audio-time-font-size, 12px) * 3);
922
+ }
923
+
520
924
  /* ---- chart 图表 ---- */
521
925
  /* 挂载容器:aspect-ratio / height 由内联 style 给(来自 aspect_ratio)。
522
926
  VChart 水合后会往 __vchart 里塞 <canvas>;水合前显示 loading 占位。 */
@@ -603,3 +1007,4 @@
603
1007
  }
604
1008
  .universal-card-root.theme-dark .universal-card-markdown { color: #d6d6d6; }
605
1009
  .universal-card-root.theme-dark .universal-card-hr { background-color: #2e2e30; }
1010
+ .universal-card-root.theme-dark .universal-card-note { color: #8a8a8a; }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@open-feishu-card/renderer",
3
- "version": "0.1.1",
3
+ "version": "0.2.0",
4
4
  "description": "零框架依赖的飞书卡片渲染引擎:Web / DOM / SSR,输入 RAW 或公开 DSL,输出真实 DOM 或 HTML 字符串",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -28,7 +28,7 @@
28
28
  "./dist/*.cjs"
29
29
  ],
30
30
  "dependencies": {
31
- "@open-feishu-card/adapter": "0.1.1"
31
+ "@open-feishu-card/adapter": "0.2.0"
32
32
  },
33
33
  "devDependencies": {
34
34
  "tsup": "^8.3.5",
@@ -45,8 +45,8 @@
45
45
  "directory": "packages/renderer"
46
46
  },
47
47
  "scripts": {
48
- "build": "tsup",
48
+ "build": "node scripts/gen-base-styles.mjs && tsup",
49
49
  "typecheck": "tsc --noEmit -p tsconfig.json",
50
- "test": "node --test test/*.test.mjs"
50
+ "test": "node --test \"test/**/*.test.mjs\""
51
51
  }
52
52
  }