@composy/log-viewer-core 0.0.1

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 (105) hide show
  1. package/README.md +37 -0
  2. package/dist/index.js +961 -0
  3. package/dist/index.js.map +1 -0
  4. package/dist/index.min.js +1 -0
  5. package/es/core/EventEmitter.d.ts +11 -0
  6. package/es/core/EventEmitter.d.ts.map +1 -0
  7. package/es/core/EventEmitter.js +40 -0
  8. package/es/core/EventEmitter.js.map +1 -0
  9. package/es/core/LogViewer.d.ts +46 -0
  10. package/es/core/LogViewer.d.ts.map +1 -0
  11. package/es/core/LogViewer.js +186 -0
  12. package/es/core/LogViewer.js.map +1 -0
  13. package/es/filters/FilterEngine.d.ts +26 -0
  14. package/es/filters/FilterEngine.d.ts.map +1 -0
  15. package/es/filters/FilterEngine.js +79 -0
  16. package/es/filters/FilterEngine.js.map +1 -0
  17. package/es/index.d.ts +26 -0
  18. package/es/index.d.ts.map +1 -0
  19. package/es/index.js +26 -0
  20. package/es/index.js.map +1 -0
  21. package/es/renderers/DiffRenderer.d.ts +18 -0
  22. package/es/renderers/DiffRenderer.d.ts.map +1 -0
  23. package/es/renderers/DiffRenderer.js +60 -0
  24. package/es/renderers/DiffRenderer.js.map +1 -0
  25. package/es/renderers/TimelineRenderer.d.ts +22 -0
  26. package/es/renderers/TimelineRenderer.d.ts.map +1 -0
  27. package/es/renderers/TimelineRenderer.js +135 -0
  28. package/es/renderers/TimelineRenderer.js.map +1 -0
  29. package/es/styles/index.d.ts +9 -0
  30. package/es/styles/index.d.ts.map +1 -0
  31. package/es/styles/index.js +414 -0
  32. package/es/styles/index.js.map +1 -0
  33. package/es/types/index.d.ts +113 -0
  34. package/es/types/index.d.ts.map +1 -0
  35. package/es/types/index.js +40 -0
  36. package/es/types/index.js.map +1 -0
  37. package/es/utils/index.d.ts +18 -0
  38. package/es/utils/index.d.ts.map +1 -0
  39. package/es/utils/index.js +73 -0
  40. package/es/utils/index.js.map +1 -0
  41. package/esm/core/EventEmitter.d.ts +11 -0
  42. package/esm/core/EventEmitter.d.ts.map +1 -0
  43. package/esm/core/EventEmitter.js +40 -0
  44. package/esm/core/EventEmitter.js.map +1 -0
  45. package/esm/core/LogViewer.d.ts +46 -0
  46. package/esm/core/LogViewer.d.ts.map +1 -0
  47. package/esm/core/LogViewer.js +186 -0
  48. package/esm/core/LogViewer.js.map +1 -0
  49. package/esm/filters/FilterEngine.d.ts +26 -0
  50. package/esm/filters/FilterEngine.d.ts.map +1 -0
  51. package/esm/filters/FilterEngine.js +79 -0
  52. package/esm/filters/FilterEngine.js.map +1 -0
  53. package/esm/index.d.ts +26 -0
  54. package/esm/index.d.ts.map +1 -0
  55. package/esm/index.js +26 -0
  56. package/esm/index.js.map +1 -0
  57. package/esm/renderers/DiffRenderer.d.ts +18 -0
  58. package/esm/renderers/DiffRenderer.d.ts.map +1 -0
  59. package/esm/renderers/DiffRenderer.js +60 -0
  60. package/esm/renderers/DiffRenderer.js.map +1 -0
  61. package/esm/renderers/TimelineRenderer.d.ts +22 -0
  62. package/esm/renderers/TimelineRenderer.d.ts.map +1 -0
  63. package/esm/renderers/TimelineRenderer.js +135 -0
  64. package/esm/renderers/TimelineRenderer.js.map +1 -0
  65. package/esm/styles/index.d.ts +9 -0
  66. package/esm/styles/index.d.ts.map +1 -0
  67. package/esm/styles/index.js +414 -0
  68. package/esm/styles/index.js.map +1 -0
  69. package/esm/types/index.d.ts +113 -0
  70. package/esm/types/index.d.ts.map +1 -0
  71. package/esm/types/index.js +40 -0
  72. package/esm/types/index.js.map +1 -0
  73. package/esm/utils/index.d.ts +18 -0
  74. package/esm/utils/index.d.ts.map +1 -0
  75. package/esm/utils/index.js +73 -0
  76. package/esm/utils/index.js.map +1 -0
  77. package/lib/core/EventEmitter.cjs +41 -0
  78. package/lib/core/EventEmitter.cjs.map +1 -0
  79. package/lib/core/EventEmitter.d.ts +11 -0
  80. package/lib/core/LogViewer.cjs +187 -0
  81. package/lib/core/LogViewer.cjs.map +1 -0
  82. package/lib/core/LogViewer.d.ts +46 -0
  83. package/lib/filters/FilterEngine.cjs +80 -0
  84. package/lib/filters/FilterEngine.cjs.map +1 -0
  85. package/lib/filters/FilterEngine.d.ts +26 -0
  86. package/lib/index.cjs +43 -0
  87. package/lib/index.cjs.map +1 -0
  88. package/lib/index.d.ts +26 -0
  89. package/lib/package.json +3 -0
  90. package/lib/renderers/DiffRenderer.cjs +61 -0
  91. package/lib/renderers/DiffRenderer.cjs.map +1 -0
  92. package/lib/renderers/DiffRenderer.d.ts +18 -0
  93. package/lib/renderers/TimelineRenderer.cjs +136 -0
  94. package/lib/renderers/TimelineRenderer.cjs.map +1 -0
  95. package/lib/renderers/TimelineRenderer.d.ts +22 -0
  96. package/lib/styles/index.cjs +415 -0
  97. package/lib/styles/index.cjs.map +1 -0
  98. package/lib/styles/index.d.ts +9 -0
  99. package/lib/types/index.cjs +42 -0
  100. package/lib/types/index.cjs.map +1 -0
  101. package/lib/types/index.d.ts +113 -0
  102. package/lib/utils/index.cjs +80 -0
  103. package/lib/utils/index.cjs.map +1 -0
  104. package/lib/utils/index.d.ts +18 -0
  105. package/package.json +119 -0
@@ -0,0 +1,415 @@
1
+ /*!
2
+ * ***********************************
3
+ * @composy/log-viewer-core v0.0.1 *
4
+ * Built with rollup *
5
+ * Build time: 2024-08-17 11:33:32 *
6
+ * Build mode: production *
7
+ * Minified: No *
8
+ * ***********************************
9
+ */
10
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
11
+ //#region src/styles/index.ts
12
+ const STYLE_ID = "ldesign-log-viewer-styles";
13
+ function injectStyles() {
14
+ if (typeof document === "undefined") return;
15
+ if (document.getElementById(STYLE_ID)) return;
16
+ const style = document.createElement("style");
17
+ style.id = STYLE_ID;
18
+ style.textContent = CSS_TEXT;
19
+ document.head.appendChild(style);
20
+ }
21
+ const CSS_TEXT = `
22
+ /* ===== CSS Variables ===== */
23
+ .lv-root {
24
+ --lv-bg: #ffffff;
25
+ --lv-bg-secondary: #f7f8fa;
26
+ --lv-bg-hover: #f0f3ff;
27
+ --lv-border: #ebedf0;
28
+ --lv-text: #1a1a2e;
29
+ --lv-text-secondary: #666;
30
+ --lv-text-muted: #999;
31
+ --lv-primary: #4f6ef7;
32
+ --lv-primary-light: #edf0ff;
33
+ --lv-shadow: rgba(0, 0, 0, 0.04);
34
+ --lv-timeline-line: #e0e0e0;
35
+ --lv-timeline-dot: #4f6ef7;
36
+ --lv-diff-add-bg: #f0fff4;
37
+ --lv-diff-add-text: #22863a;
38
+ --lv-diff-del-bg: #fff5f5;
39
+ --lv-diff-del-text: #cb2431;
40
+ --lv-anomaly-bg: #fff2e8;
41
+ --lv-anomaly-border: #ffbb96;
42
+ --lv-radius: 8px;
43
+ --lv-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;
44
+ --lv-font-mono: 'Fira Code', 'SF Mono', Consolas, monospace;
45
+ }
46
+
47
+ .lv-root[data-theme="dark"] {
48
+ --lv-bg: #1a1a2e;
49
+ --lv-bg-secondary: #16213e;
50
+ --lv-bg-hover: #1e2a4a;
51
+ --lv-border: #2a2a4a;
52
+ --lv-text: #e0e0e0;
53
+ --lv-text-secondary: #a0a0b0;
54
+ --lv-text-muted: #666680;
55
+ --lv-primary: #6b85f9;
56
+ --lv-primary-light: #252545;
57
+ --lv-shadow: rgba(0, 0, 0, 0.2);
58
+ --lv-timeline-line: #333355;
59
+ --lv-timeline-dot: #6b85f9;
60
+ --lv-diff-add-bg: #0d2818;
61
+ --lv-diff-add-text: #85e89d;
62
+ --lv-diff-del-bg: #2d1214;
63
+ --lv-diff-del-text: #f97583;
64
+ --lv-anomaly-bg: #2d1a0a;
65
+ --lv-anomaly-border: #8b5e3c;
66
+ }
67
+
68
+ /* ===== Root ===== */
69
+ .lv-root {
70
+ font-family: var(--lv-font);
71
+ font-size: 14px;
72
+ color: var(--lv-text);
73
+ background: var(--lv-bg);
74
+ line-height: 1.6;
75
+ }
76
+
77
+ /* ===== Filter Bar ===== */
78
+ .lv-filter {
79
+ display: flex;
80
+ flex-wrap: wrap;
81
+ gap: 10px;
82
+ padding: 16px;
83
+ background: var(--lv-bg);
84
+ border: 1px solid var(--lv-border);
85
+ border-radius: var(--lv-radius);
86
+ margin-bottom: 16px;
87
+ align-items: center;
88
+ }
89
+
90
+ .lv-filter-item {
91
+ display: flex;
92
+ align-items: center;
93
+ gap: 6px;
94
+ font-size: 13px;
95
+ }
96
+
97
+ .lv-filter-label {
98
+ color: var(--lv-text-secondary);
99
+ font-size: 12px;
100
+ white-space: nowrap;
101
+ }
102
+
103
+ .lv-filter-input {
104
+ padding: 5px 10px;
105
+ border: 1px solid var(--lv-border);
106
+ border-radius: 6px;
107
+ font-size: 13px;
108
+ background: var(--lv-bg);
109
+ color: var(--lv-text);
110
+ outline: none;
111
+ transition: border-color 0.2s;
112
+ min-width: 120px;
113
+ }
114
+
115
+ .lv-filter-input:focus {
116
+ border-color: var(--lv-primary);
117
+ }
118
+
119
+ .lv-filter-select {
120
+ padding: 5px 10px;
121
+ border: 1px solid var(--lv-border);
122
+ border-radius: 6px;
123
+ font-size: 13px;
124
+ background: var(--lv-bg);
125
+ color: var(--lv-text);
126
+ outline: none;
127
+ cursor: pointer;
128
+ }
129
+
130
+ .lv-filter-btn {
131
+ display: inline-flex;
132
+ align-items: center;
133
+ gap: 4px;
134
+ padding: 5px 14px;
135
+ font-size: 13px;
136
+ border: 1px solid var(--lv-border);
137
+ border-radius: 6px;
138
+ background: var(--lv-bg);
139
+ color: var(--lv-text);
140
+ cursor: pointer;
141
+ transition: all 0.15s;
142
+ }
143
+
144
+ .lv-filter-btn:hover {
145
+ border-color: var(--lv-primary);
146
+ color: var(--lv-primary);
147
+ }
148
+
149
+ .lv-filter-btn--primary {
150
+ background: var(--lv-primary);
151
+ border-color: var(--lv-primary);
152
+ color: #fff;
153
+ }
154
+
155
+ .lv-filter-btn--primary:hover {
156
+ opacity: 0.85;
157
+ }
158
+
159
+ /* ===== Timeline ===== */
160
+ .lv-timeline {
161
+ position: relative;
162
+ padding-left: 28px;
163
+ }
164
+
165
+ .lv-timeline::before {
166
+ content: '';
167
+ position: absolute;
168
+ left: 9px;
169
+ top: 0;
170
+ bottom: 0;
171
+ width: 2px;
172
+ background: var(--lv-timeline-line);
173
+ }
174
+
175
+ .lv-timeline-item {
176
+ position: relative;
177
+ padding: 0 0 20px 0;
178
+ }
179
+
180
+ .lv-timeline-dot {
181
+ position: absolute;
182
+ left: -25px;
183
+ top: 6px;
184
+ width: 12px;
185
+ height: 12px;
186
+ border-radius: 50%;
187
+ background: var(--lv-bg);
188
+ border: 2px solid var(--lv-timeline-dot);
189
+ z-index: 1;
190
+ }
191
+
192
+ .lv-timeline-dot--anomaly {
193
+ border-color: #ff4d4f;
194
+ background: #fff1f0;
195
+ }
196
+
197
+ .lv-timeline-card {
198
+ background: var(--lv-bg);
199
+ border: 1px solid var(--lv-border);
200
+ border-radius: var(--lv-radius);
201
+ padding: 14px 18px;
202
+ cursor: pointer;
203
+ transition: all 0.2s;
204
+ box-shadow: 0 1px 3px var(--lv-shadow);
205
+ }
206
+
207
+ .lv-timeline-card:hover {
208
+ border-color: var(--lv-primary);
209
+ box-shadow: 0 2px 8px var(--lv-shadow);
210
+ }
211
+
212
+ .lv-timeline-card--anomaly {
213
+ border-left: 3px solid var(--lv-anomaly-border);
214
+ background: var(--lv-anomaly-bg);
215
+ }
216
+
217
+ .lv-timeline-header {
218
+ display: flex;
219
+ align-items: center;
220
+ gap: 10px;
221
+ flex-wrap: wrap;
222
+ margin-bottom: 4px;
223
+ }
224
+
225
+ .lv-timeline-time {
226
+ font-size: 12px;
227
+ color: var(--lv-text-muted);
228
+ font-family: var(--lv-font-mono);
229
+ }
230
+
231
+ .lv-timeline-user {
232
+ font-weight: 600;
233
+ font-size: 14px;
234
+ }
235
+
236
+ .lv-action-tag {
237
+ display: inline-block;
238
+ padding: 1px 8px;
239
+ font-size: 12px;
240
+ border-radius: 4px;
241
+ font-weight: 500;
242
+ color: #fff;
243
+ }
244
+
245
+ .lv-timeline-module {
246
+ font-size: 12px;
247
+ color: var(--lv-text-secondary);
248
+ background: var(--lv-bg-secondary);
249
+ padding: 1px 8px;
250
+ border-radius: 4px;
251
+ }
252
+
253
+ .lv-timeline-ip {
254
+ font-size: 12px;
255
+ color: var(--lv-text-muted);
256
+ font-family: var(--lv-font-mono);
257
+ }
258
+
259
+ .lv-anomaly-badge {
260
+ font-size: 11px;
261
+ padding: 1px 6px;
262
+ border-radius: 3px;
263
+ background: #fff2e8;
264
+ color: #d46b08;
265
+ border: 1px solid #ffd591;
266
+ }
267
+
268
+ .lv-timeline-detail {
269
+ font-size: 13px;
270
+ color: var(--lv-text-secondary);
271
+ margin-top: 6px;
272
+ }
273
+
274
+ .lv-timeline-expand-hint {
275
+ font-size: 12px;
276
+ color: var(--lv-primary);
277
+ margin-top: 6px;
278
+ cursor: pointer;
279
+ }
280
+
281
+ /* ===== Detail Panel ===== */
282
+ .lv-detail {
283
+ margin-top: 12px;
284
+ padding-top: 12px;
285
+ border-top: 1px dashed var(--lv-border);
286
+ animation: lv-slide-down 0.2s ease;
287
+ }
288
+
289
+ @keyframes lv-slide-down {
290
+ from { opacity: 0; transform: translateY(-8px); }
291
+ to { opacity: 1; transform: translateY(0); }
292
+ }
293
+
294
+ /* ===== Diff Table ===== */
295
+ .lv-diff-table {
296
+ width: 100%;
297
+ border-collapse: collapse;
298
+ font-size: 13px;
299
+ border: 1px solid var(--lv-border);
300
+ border-radius: 6px;
301
+ overflow: hidden;
302
+ }
303
+
304
+ .lv-diff-table th {
305
+ background: var(--lv-bg-secondary);
306
+ padding: 8px 12px;
307
+ text-align: left;
308
+ font-weight: 600;
309
+ font-size: 12px;
310
+ color: var(--lv-text-secondary);
311
+ border-bottom: 1px solid var(--lv-border);
312
+ }
313
+
314
+ .lv-diff-table td {
315
+ padding: 8px 12px;
316
+ border-bottom: 1px solid var(--lv-border);
317
+ vertical-align: top;
318
+ }
319
+
320
+ .lv-diff-table tr:last-child td {
321
+ border-bottom: none;
322
+ }
323
+
324
+ .lv-diff-old {
325
+ background: var(--lv-diff-del-bg);
326
+ color: var(--lv-diff-del-text);
327
+ text-decoration: line-through;
328
+ font-family: var(--lv-font-mono);
329
+ font-size: 12px;
330
+ }
331
+
332
+ .lv-diff-new {
333
+ background: var(--lv-diff-add-bg);
334
+ color: var(--lv-diff-add-text);
335
+ font-family: var(--lv-font-mono);
336
+ font-size: 12px;
337
+ }
338
+
339
+ /* ===== Metadata ===== */
340
+ .lv-metadata {
341
+ margin-top: 10px;
342
+ background: var(--lv-bg-secondary);
343
+ border-radius: 6px;
344
+ padding: 10px 14px;
345
+ font-size: 12px;
346
+ font-family: var(--lv-font-mono);
347
+ white-space: pre-wrap;
348
+ word-break: break-all;
349
+ color: var(--lv-text-secondary);
350
+ }
351
+
352
+ /* ===== Pagination ===== */
353
+ .lv-pagination {
354
+ display: flex;
355
+ align-items: center;
356
+ justify-content: center;
357
+ gap: 6px;
358
+ padding: 16px 0;
359
+ }
360
+
361
+ .lv-pagination-btn {
362
+ display: inline-flex;
363
+ align-items: center;
364
+ justify-content: center;
365
+ width: 32px;
366
+ height: 32px;
367
+ border: 1px solid var(--lv-border);
368
+ border-radius: 6px;
369
+ background: var(--lv-bg);
370
+ color: var(--lv-text);
371
+ font-size: 13px;
372
+ cursor: pointer;
373
+ transition: all 0.15s;
374
+ }
375
+
376
+ .lv-pagination-btn:hover {
377
+ border-color: var(--lv-primary);
378
+ color: var(--lv-primary);
379
+ }
380
+
381
+ .lv-pagination-btn--active {
382
+ background: var(--lv-primary);
383
+ border-color: var(--lv-primary);
384
+ color: #fff;
385
+ }
386
+
387
+ .lv-pagination-btn:disabled {
388
+ opacity: 0.4;
389
+ cursor: not-allowed;
390
+ }
391
+
392
+ .lv-pagination-info {
393
+ font-size: 13px;
394
+ color: var(--lv-text-secondary);
395
+ margin: 0 8px;
396
+ }
397
+
398
+ /* ===== Empty state ===== */
399
+ .lv-empty {
400
+ text-align: center;
401
+ padding: 48px 16px;
402
+ color: var(--lv-text-muted);
403
+ font-size: 14px;
404
+ }
405
+
406
+ .lv-empty-icon {
407
+ font-size: 48px;
408
+ margin-bottom: 12px;
409
+ opacity: 0.3;
410
+ }
411
+ `;
412
+ //#endregion
413
+ exports.injectStyles = injectStyles;
414
+ /*! End of @composy/log-viewer-core | Powered by @composy/builder */
415
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../src/styles/index.ts"],"sourcesContent":["/**\n * 样式注入 - 通过 CSS 变量支持亮色/暗色主题\n */\n\nconst STYLE_ID = 'ldesign-log-viewer-styles'\n\n/**\n * injectStyles - inject Styles function\n * @returns 返回值说明\n */\nexport function injectStyles(): void {\n if (typeof document === 'undefined') return\n if (document.getElementById(STYLE_ID)) return\n\n const style = document.createElement('style')\n style.id = STYLE_ID\n style.textContent = CSS_TEXT\n document.head.appendChild(style)\n}\n\nconst CSS_TEXT = /* css */ `\n/* ===== CSS Variables ===== */\n.lv-root {\n --lv-bg: #ffffff;\n --lv-bg-secondary: #f7f8fa;\n --lv-bg-hover: #f0f3ff;\n --lv-border: #ebedf0;\n --lv-text: #1a1a2e;\n --lv-text-secondary: #666;\n --lv-text-muted: #999;\n --lv-primary: #4f6ef7;\n --lv-primary-light: #edf0ff;\n --lv-shadow: rgba(0, 0, 0, 0.04);\n --lv-timeline-line: #e0e0e0;\n --lv-timeline-dot: #4f6ef7;\n --lv-diff-add-bg: #f0fff4;\n --lv-diff-add-text: #22863a;\n --lv-diff-del-bg: #fff5f5;\n --lv-diff-del-text: #cb2431;\n --lv-anomaly-bg: #fff2e8;\n --lv-anomaly-border: #ffbb96;\n --lv-radius: 8px;\n --lv-font: -apple-system, BlinkMacSystemFont, 'Segoe UI', 'PingFang SC', 'Hiragino Sans GB', 'Microsoft YaHei', sans-serif;\n --lv-font-mono: 'Fira Code', 'SF Mono', Consolas, monospace;\n}\n\n.lv-root[data-theme=\"dark\"] {\n --lv-bg: #1a1a2e;\n --lv-bg-secondary: #16213e;\n --lv-bg-hover: #1e2a4a;\n --lv-border: #2a2a4a;\n --lv-text: #e0e0e0;\n --lv-text-secondary: #a0a0b0;\n --lv-text-muted: #666680;\n --lv-primary: #6b85f9;\n --lv-primary-light: #252545;\n --lv-shadow: rgba(0, 0, 0, 0.2);\n --lv-timeline-line: #333355;\n --lv-timeline-dot: #6b85f9;\n --lv-diff-add-bg: #0d2818;\n --lv-diff-add-text: #85e89d;\n --lv-diff-del-bg: #2d1214;\n --lv-diff-del-text: #f97583;\n --lv-anomaly-bg: #2d1a0a;\n --lv-anomaly-border: #8b5e3c;\n}\n\n/* ===== Root ===== */\n.lv-root {\n font-family: var(--lv-font);\n font-size: 14px;\n color: var(--lv-text);\n background: var(--lv-bg);\n line-height: 1.6;\n}\n\n/* ===== Filter Bar ===== */\n.lv-filter {\n display: flex;\n flex-wrap: wrap;\n gap: 10px;\n padding: 16px;\n background: var(--lv-bg);\n border: 1px solid var(--lv-border);\n border-radius: var(--lv-radius);\n margin-bottom: 16px;\n align-items: center;\n}\n\n.lv-filter-item {\n display: flex;\n align-items: center;\n gap: 6px;\n font-size: 13px;\n}\n\n.lv-filter-label {\n color: var(--lv-text-secondary);\n font-size: 12px;\n white-space: nowrap;\n}\n\n.lv-filter-input {\n padding: 5px 10px;\n border: 1px solid var(--lv-border);\n border-radius: 6px;\n font-size: 13px;\n background: var(--lv-bg);\n color: var(--lv-text);\n outline: none;\n transition: border-color 0.2s;\n min-width: 120px;\n}\n\n.lv-filter-input:focus {\n border-color: var(--lv-primary);\n}\n\n.lv-filter-select {\n padding: 5px 10px;\n border: 1px solid var(--lv-border);\n border-radius: 6px;\n font-size: 13px;\n background: var(--lv-bg);\n color: var(--lv-text);\n outline: none;\n cursor: pointer;\n}\n\n.lv-filter-btn {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n padding: 5px 14px;\n font-size: 13px;\n border: 1px solid var(--lv-border);\n border-radius: 6px;\n background: var(--lv-bg);\n color: var(--lv-text);\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.lv-filter-btn:hover {\n border-color: var(--lv-primary);\n color: var(--lv-primary);\n}\n\n.lv-filter-btn--primary {\n background: var(--lv-primary);\n border-color: var(--lv-primary);\n color: #fff;\n}\n\n.lv-filter-btn--primary:hover {\n opacity: 0.85;\n}\n\n/* ===== Timeline ===== */\n.lv-timeline {\n position: relative;\n padding-left: 28px;\n}\n\n.lv-timeline::before {\n content: '';\n position: absolute;\n left: 9px;\n top: 0;\n bottom: 0;\n width: 2px;\n background: var(--lv-timeline-line);\n}\n\n.lv-timeline-item {\n position: relative;\n padding: 0 0 20px 0;\n}\n\n.lv-timeline-dot {\n position: absolute;\n left: -25px;\n top: 6px;\n width: 12px;\n height: 12px;\n border-radius: 50%;\n background: var(--lv-bg);\n border: 2px solid var(--lv-timeline-dot);\n z-index: 1;\n}\n\n.lv-timeline-dot--anomaly {\n border-color: #ff4d4f;\n background: #fff1f0;\n}\n\n.lv-timeline-card {\n background: var(--lv-bg);\n border: 1px solid var(--lv-border);\n border-radius: var(--lv-radius);\n padding: 14px 18px;\n cursor: pointer;\n transition: all 0.2s;\n box-shadow: 0 1px 3px var(--lv-shadow);\n}\n\n.lv-timeline-card:hover {\n border-color: var(--lv-primary);\n box-shadow: 0 2px 8px var(--lv-shadow);\n}\n\n.lv-timeline-card--anomaly {\n border-left: 3px solid var(--lv-anomaly-border);\n background: var(--lv-anomaly-bg);\n}\n\n.lv-timeline-header {\n display: flex;\n align-items: center;\n gap: 10px;\n flex-wrap: wrap;\n margin-bottom: 4px;\n}\n\n.lv-timeline-time {\n font-size: 12px;\n color: var(--lv-text-muted);\n font-family: var(--lv-font-mono);\n}\n\n.lv-timeline-user {\n font-weight: 600;\n font-size: 14px;\n}\n\n.lv-action-tag {\n display: inline-block;\n padding: 1px 8px;\n font-size: 12px;\n border-radius: 4px;\n font-weight: 500;\n color: #fff;\n}\n\n.lv-timeline-module {\n font-size: 12px;\n color: var(--lv-text-secondary);\n background: var(--lv-bg-secondary);\n padding: 1px 8px;\n border-radius: 4px;\n}\n\n.lv-timeline-ip {\n font-size: 12px;\n color: var(--lv-text-muted);\n font-family: var(--lv-font-mono);\n}\n\n.lv-anomaly-badge {\n font-size: 11px;\n padding: 1px 6px;\n border-radius: 3px;\n background: #fff2e8;\n color: #d46b08;\n border: 1px solid #ffd591;\n}\n\n.lv-timeline-detail {\n font-size: 13px;\n color: var(--lv-text-secondary);\n margin-top: 6px;\n}\n\n.lv-timeline-expand-hint {\n font-size: 12px;\n color: var(--lv-primary);\n margin-top: 6px;\n cursor: pointer;\n}\n\n/* ===== Detail Panel ===== */\n.lv-detail {\n margin-top: 12px;\n padding-top: 12px;\n border-top: 1px dashed var(--lv-border);\n animation: lv-slide-down 0.2s ease;\n}\n\n@keyframes lv-slide-down {\n from { opacity: 0; transform: translateY(-8px); }\n to { opacity: 1; transform: translateY(0); }\n}\n\n/* ===== Diff Table ===== */\n.lv-diff-table {\n width: 100%;\n border-collapse: collapse;\n font-size: 13px;\n border: 1px solid var(--lv-border);\n border-radius: 6px;\n overflow: hidden;\n}\n\n.lv-diff-table th {\n background: var(--lv-bg-secondary);\n padding: 8px 12px;\n text-align: left;\n font-weight: 600;\n font-size: 12px;\n color: var(--lv-text-secondary);\n border-bottom: 1px solid var(--lv-border);\n}\n\n.lv-diff-table td {\n padding: 8px 12px;\n border-bottom: 1px solid var(--lv-border);\n vertical-align: top;\n}\n\n.lv-diff-table tr:last-child td {\n border-bottom: none;\n}\n\n.lv-diff-old {\n background: var(--lv-diff-del-bg);\n color: var(--lv-diff-del-text);\n text-decoration: line-through;\n font-family: var(--lv-font-mono);\n font-size: 12px;\n}\n\n.lv-diff-new {\n background: var(--lv-diff-add-bg);\n color: var(--lv-diff-add-text);\n font-family: var(--lv-font-mono);\n font-size: 12px;\n}\n\n/* ===== Metadata ===== */\n.lv-metadata {\n margin-top: 10px;\n background: var(--lv-bg-secondary);\n border-radius: 6px;\n padding: 10px 14px;\n font-size: 12px;\n font-family: var(--lv-font-mono);\n white-space: pre-wrap;\n word-break: break-all;\n color: var(--lv-text-secondary);\n}\n\n/* ===== Pagination ===== */\n.lv-pagination {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 16px 0;\n}\n\n.lv-pagination-btn {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 32px;\n height: 32px;\n border: 1px solid var(--lv-border);\n border-radius: 6px;\n background: var(--lv-bg);\n color: var(--lv-text);\n font-size: 13px;\n cursor: pointer;\n transition: all 0.15s;\n}\n\n.lv-pagination-btn:hover {\n border-color: var(--lv-primary);\n color: var(--lv-primary);\n}\n\n.lv-pagination-btn--active {\n background: var(--lv-primary);\n border-color: var(--lv-primary);\n color: #fff;\n}\n\n.lv-pagination-btn:disabled {\n opacity: 0.4;\n cursor: not-allowed;\n}\n\n.lv-pagination-info {\n font-size: 13px;\n color: var(--lv-text-secondary);\n margin: 0 8px;\n}\n\n/* ===== Empty state ===== */\n.lv-empty {\n text-align: center;\n padding: 48px 16px;\n color: var(--lv-text-muted);\n font-size: 14px;\n}\n\n.lv-empty-icon {\n font-size: 48px;\n margin-bottom: 12px;\n opacity: 0.3;\n}\n`\n"],"mappings":";;;;;;;;;;;AAIA,MAAM,WAAW;AAMV,SAAS,eAAqB;CACnC,IAAI,OAAO,aAAa,aAAa;CACrC,IAAI,SAAS,eAAe,QAAQ,GAAG;CAEvC,MAAM,QAAQ,SAAS,cAAc,OAAO;CAC5C,MAAM,KAAK;CACX,MAAM,cAAc;CACpB,SAAS,KAAK,YAAY,KAAK;AACjC;AAEA,MAAM,WAAqB"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * 样式注入 - 通过 CSS 变量支持亮色/暗色主题
3
+ */
4
+ /**
5
+ * injectStyles - inject Styles function
6
+ * @returns 返回值说明
7
+ */
8
+ export declare function injectStyles(): void;
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,42 @@
1
+ /*!
2
+ * ***********************************
3
+ * @composy/log-viewer-core v0.0.1 *
4
+ * Built with rollup *
5
+ * Build time: 2024-08-17 11:33:32 *
6
+ * Build mode: production *
7
+ * Minified: No *
8
+ * ***********************************
9
+ */
10
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
11
+ //#region src/types/index.ts
12
+ const ACTION_LABELS = {
13
+ create: "新增",
14
+ update: "修改",
15
+ delete: "删除",
16
+ query: "查询",
17
+ login: "登录",
18
+ logout: "登出",
19
+ export: "导出",
20
+ import: "导入",
21
+ approve: "审批",
22
+ reject: "驳回",
23
+ other: "其他"
24
+ };
25
+ const ACTION_COLORS = {
26
+ create: "#52c41a",
27
+ update: "#1890ff",
28
+ delete: "#ff4d4f",
29
+ query: "#8c8c8c",
30
+ login: "#722ed1",
31
+ logout: "#eb2f96",
32
+ export: "#fa8c16",
33
+ import: "#13c2c2",
34
+ approve: "#52c41a",
35
+ reject: "#ff4d4f",
36
+ other: "#d9d9d9"
37
+ };
38
+ //#endregion
39
+ exports.ACTION_COLORS = ACTION_COLORS;
40
+ exports.ACTION_LABELS = ACTION_LABELS;
41
+ /*! End of @composy/log-viewer-core | Powered by @composy/builder */
42
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.cjs","names":[],"sources":["../../src/types/index.ts"],"sourcesContent":["/**\n * @composy/log-viewer-core 类型定义\n */\n\n/** 操作类型 */\nexport type ActionType =\n | 'create'\n | 'update'\n | 'delete'\n | 'query'\n | 'login'\n | 'logout'\n | 'export'\n | 'import'\n | 'approve'\n | 'reject'\n | 'other'\n\n/** 主题模式 */\nexport type ThemeMode = 'light' | 'dark'\n\n/** 异常标记类型 */\nexport type AnomalyType = 'off-hours' | 'sensitive' | 'high-frequency' | 'none'\n\n/** 字段变更条目 */\nexport interface DiffEntry {\n field: string\n label?: string\n oldValue: unknown\n newValue: unknown\n}\n\n/** 日志条目 */\nexport interface LogEntry {\n id: string\n timestamp: string | number | Date\n user: string\n userId?: string\n action: ActionType\n module: string\n detail?: string\n ip?: string\n changes?: DiffEntry[]\n metadata?: Record<string, unknown>\n anomaly?: AnomalyType\n}\n\n/** 筛选配置 */\nexport interface FilterConfig {\n user?: string\n action?: ActionType | ActionType[]\n module?: string\n ip?: string\n timeRange?: [Date | string | number, Date | string | number]\n keyword?: string\n}\n\n/** 分页配置 */\nexport interface PaginationConfig {\n page: number\n pageSize: number\n total?: number\n}\n\n/** LogViewer 配置 */\nexport interface LogViewerConfig {\n container: string | HTMLElement\n data?: LogEntry[]\n dataSource?: string | (() => Promise<LogEntry[]>)\n columns?: string[]\n filter?: FilterConfig\n pagination?: Partial<PaginationConfig>\n theme?: ThemeMode\n locale?: 'zh-CN' | 'en-US'\n showFilter?: boolean\n showDiff?: boolean\n showAnomalyBadge?: boolean\n pageSize?: number\n onEntryClick?: (entry: LogEntry) => void\n onFilterChange?: (filter: FilterConfig) => void\n onThemeChange?: (theme: ThemeMode) => void\n}\n\n/** LogViewer 实例接口 */\nexport interface LogViewerInstance {\n /** 获取当前数据 */\n getData(): LogEntry[]\n /** 设置数据 */\n setData(entries: LogEntry[]): void\n /** 追加数据 */\n appendData(entries: LogEntry[]): void\n /** 获取当前筛选条件 */\n getFilter(): FilterConfig\n /** 设置筛选条件 */\n setFilter(filter: FilterConfig): void\n /** 重置筛选 */\n resetFilter(): void\n /** 获取当前主题 */\n getTheme(): ThemeMode\n /** 设置主题 */\n setTheme(theme: ThemeMode): void\n /** 展开指定条目详情 */\n expandEntry(id: string): void\n /** 折叠指定条目详情 */\n collapseEntry(id: string): void\n /** 折叠所有详情 */\n collapseAll(): void\n /** 跳转分页 */\n goToPage(page: number): void\n /** 获取分页信息 */\n getPagination(): PaginationConfig\n /** 注册事件监听 */\n on(event: string, callback: (...args: unknown[]) => void): () => void\n /** 刷新渲染 */\n refresh(): void\n /** 销毁实例 */\n destroy(): void\n}\n\n/** 事件映射 */\nexport interface LogViewerEvents {\n 'filter:change': (filter: FilterConfig) => void\n 'entry:click': (entry: LogEntry) => void\n 'entry:expand': (entry: LogEntry) => void\n 'entry:collapse': (entry: LogEntry) => void\n 'theme:change': (theme: ThemeMode) => void\n 'page:change': (page: number) => void\n 'data:change': (entries: LogEntry[]) => void\n}\n\n/** 操作类型标签映射 */\nexport const ACTION_LABELS: Record<ActionType, string> = {\n create: '新增',\n update: '修改',\n delete: '删除',\n query: '查询',\n login: '登录',\n logout: '登出',\n export: '导出',\n import: '导入',\n approve: '审批',\n reject: '驳回',\n other: '其他',\n}\n\n/** 操作类型颜色映射 */\nexport const ACTION_COLORS: Record<ActionType, string> = {\n create: '#52c41a',\n update: '#1890ff',\n delete: '#ff4d4f',\n query: '#8c8c8c',\n login: '#722ed1',\n logout: '#eb2f96',\n export: '#fa8c16',\n import: '#13c2c2',\n approve: '#52c41a',\n reject: '#ff4d4f',\n other: '#d9d9d9',\n}\n"],"mappings":";;;;;;;;;;;AAmIO,MAAM,gBAA4C;CACvD,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,OAAO;CACP,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,OAAO;AACT;AAGO,MAAM,gBAA4C;CACvD,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,OAAO;CACP,OAAO;CACP,QAAQ;CACR,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,QAAQ;CACR,OAAO;AACT"}
@@ -0,0 +1,113 @@
1
+ /**
2
+ * @composy/log-viewer-core 类型定义
3
+ */
4
+ /** 操作类型 */
5
+ export type ActionType = 'create' | 'update' | 'delete' | 'query' | 'login' | 'logout' | 'export' | 'import' | 'approve' | 'reject' | 'other';
6
+ /** 主题模式 */
7
+ export type ThemeMode = 'light' | 'dark';
8
+ /** 异常标记类型 */
9
+ export type AnomalyType = 'off-hours' | 'sensitive' | 'high-frequency' | 'none';
10
+ /** 字段变更条目 */
11
+ export interface DiffEntry {
12
+ field: string;
13
+ label?: string;
14
+ oldValue: unknown;
15
+ newValue: unknown;
16
+ }
17
+ /** 日志条目 */
18
+ export interface LogEntry {
19
+ id: string;
20
+ timestamp: string | number | Date;
21
+ user: string;
22
+ userId?: string;
23
+ action: ActionType;
24
+ module: string;
25
+ detail?: string;
26
+ ip?: string;
27
+ changes?: DiffEntry[];
28
+ metadata?: Record<string, unknown>;
29
+ anomaly?: AnomalyType;
30
+ }
31
+ /** 筛选配置 */
32
+ export interface FilterConfig {
33
+ user?: string;
34
+ action?: ActionType | ActionType[];
35
+ module?: string;
36
+ ip?: string;
37
+ timeRange?: [Date | string | number, Date | string | number];
38
+ keyword?: string;
39
+ }
40
+ /** 分页配置 */
41
+ export interface PaginationConfig {
42
+ page: number;
43
+ pageSize: number;
44
+ total?: number;
45
+ }
46
+ /** LogViewer 配置 */
47
+ export interface LogViewerConfig {
48
+ container: string | HTMLElement;
49
+ data?: LogEntry[];
50
+ dataSource?: string | (() => Promise<LogEntry[]>);
51
+ columns?: string[];
52
+ filter?: FilterConfig;
53
+ pagination?: Partial<PaginationConfig>;
54
+ theme?: ThemeMode;
55
+ locale?: 'zh-CN' | 'en-US';
56
+ showFilter?: boolean;
57
+ showDiff?: boolean;
58
+ showAnomalyBadge?: boolean;
59
+ pageSize?: number;
60
+ onEntryClick?: (entry: LogEntry) => void;
61
+ onFilterChange?: (filter: FilterConfig) => void;
62
+ onThemeChange?: (theme: ThemeMode) => void;
63
+ }
64
+ /** LogViewer 实例接口 */
65
+ export interface LogViewerInstance {
66
+ /** 获取当前数据 */
67
+ getData(): LogEntry[];
68
+ /** 设置数据 */
69
+ setData(entries: LogEntry[]): void;
70
+ /** 追加数据 */
71
+ appendData(entries: LogEntry[]): void;
72
+ /** 获取当前筛选条件 */
73
+ getFilter(): FilterConfig;
74
+ /** 设置筛选条件 */
75
+ setFilter(filter: FilterConfig): void;
76
+ /** 重置筛选 */
77
+ resetFilter(): void;
78
+ /** 获取当前主题 */
79
+ getTheme(): ThemeMode;
80
+ /** 设置主题 */
81
+ setTheme(theme: ThemeMode): void;
82
+ /** 展开指定条目详情 */
83
+ expandEntry(id: string): void;
84
+ /** 折叠指定条目详情 */
85
+ collapseEntry(id: string): void;
86
+ /** 折叠所有详情 */
87
+ collapseAll(): void;
88
+ /** 跳转分页 */
89
+ goToPage(page: number): void;
90
+ /** 获取分页信息 */
91
+ getPagination(): PaginationConfig;
92
+ /** 注册事件监听 */
93
+ on(event: string, callback: (...args: unknown[]) => void): () => void;
94
+ /** 刷新渲染 */
95
+ refresh(): void;
96
+ /** 销毁实例 */
97
+ destroy(): void;
98
+ }
99
+ /** 事件映射 */
100
+ export interface LogViewerEvents {
101
+ 'filter:change': (filter: FilterConfig) => void;
102
+ 'entry:click': (entry: LogEntry) => void;
103
+ 'entry:expand': (entry: LogEntry) => void;
104
+ 'entry:collapse': (entry: LogEntry) => void;
105
+ 'theme:change': (theme: ThemeMode) => void;
106
+ 'page:change': (page: number) => void;
107
+ 'data:change': (entries: LogEntry[]) => void;
108
+ }
109
+ /** 操作类型标签映射 */
110
+ export declare const ACTION_LABELS: Record<ActionType, string>;
111
+ /** 操作类型颜色映射 */
112
+ export declare const ACTION_COLORS: Record<ActionType, string>;
113
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1,80 @@
1
+ /*!
2
+ * ***********************************
3
+ * @composy/log-viewer-core v0.0.1 *
4
+ * Built with rollup *
5
+ * Build time: 2024-08-17 11:33:32 *
6
+ * Build mode: production *
7
+ * Minified: No *
8
+ * ***********************************
9
+ */
10
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
11
+ //#region src/utils/index.ts
12
+ let _uid = 0;
13
+ function uid(prefix = "lv") {
14
+ return `${prefix}-${++_uid}-${Math.random().toString(36).slice(2, 8)}`;
15
+ }
16
+ function formatDate(value, fmt = "YYYY-MM-DD HH:mm:ss") {
17
+ const d = value instanceof Date ? value : new Date(value);
18
+ if (isNaN(d.getTime())) return String(value);
19
+ const pad = (n) => String(n).padStart(2, "0");
20
+ const year = String(d.getFullYear());
21
+ const month = pad(d.getMonth() + 1);
22
+ const day = pad(d.getDate());
23
+ const hours = pad(d.getHours());
24
+ const minutes = pad(d.getMinutes());
25
+ const seconds = pad(d.getSeconds());
26
+ return fmt.replace("YYYY", year).replace("MM", month).replace("DD", day).replace("HH", hours).replace("mm", minutes).replace("ss", seconds);
27
+ }
28
+ function formatRelativeTime(value) {
29
+ const d = value instanceof Date ? value : new Date(value);
30
+ const diff = Date.now() - d.getTime();
31
+ if (diff < 6e4) return "刚刚";
32
+ if (diff < 36e5) return `${Math.floor(diff / 6e4)} \u5206\u949F\u524D`;
33
+ if (diff < 864e5) return `${Math.floor(diff / 36e5)} \u5C0F\u65F6\u524D`;
34
+ if (diff < 6048e5) return `${Math.floor(diff / 864e5)} \u5929\u524D`;
35
+ return formatDate(d);
36
+ }
37
+ function escapeHtml(str) {
38
+ const map = {
39
+ "&": "&amp;",
40
+ "<": "&lt;",
41
+ ">": "&gt;",
42
+ "\"": "&quot;",
43
+ "'": "&#39;"
44
+ };
45
+ return str.replace(/[&<>"']/g, (c) => map[c] || c);
46
+ }
47
+ function debounce(fn, delay) {
48
+ let timer = null;
49
+ return ((...args) => {
50
+ if (timer) clearTimeout(timer);
51
+ timer = setTimeout(() => fn(...args), delay);
52
+ });
53
+ }
54
+ function deepClone(obj) {
55
+ if (obj === null || typeof obj !== "object") return obj;
56
+ try {
57
+ return JSON.parse(JSON.stringify(obj));
58
+ } catch {
59
+ return obj;
60
+ }
61
+ }
62
+ function formatValue(val) {
63
+ if (val === null || val === void 0) return "-";
64
+ if (typeof val === "object") try {
65
+ return JSON.stringify(val, null, 2);
66
+ } catch {
67
+ return String(val);
68
+ }
69
+ return String(val);
70
+ }
71
+ //#endregion
72
+ exports.debounce = debounce;
73
+ exports.deepClone = deepClone;
74
+ exports.escapeHtml = escapeHtml;
75
+ exports.formatDate = formatDate;
76
+ exports.formatRelativeTime = formatRelativeTime;
77
+ exports.formatValue = formatValue;
78
+ exports.uid = uid;
79
+ /*! End of @composy/log-viewer-core | Powered by @composy/builder */
80
+ //# sourceMappingURL=index.cjs.map