@svadmin/lite 0.26.0 → 0.30.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 (109) hide show
  1. package/dist/components/LiteAbacPolicyMatrix.svelte +128 -0
  2. package/dist/components/LiteAbacPolicyMatrix.svelte.d.ts +16 -0
  3. package/dist/components/LiteAnnouncementBanner.svelte +88 -0
  4. package/dist/components/LiteAnnouncementBanner.svelte.d.ts +12 -0
  5. package/dist/components/LiteApiPlayground.svelte +103 -0
  6. package/dist/components/LiteApiPlayground.svelte.d.ts +10 -0
  7. package/dist/components/LiteApprovalChainBuilder.svelte +120 -0
  8. package/dist/components/LiteApprovalChainBuilder.svelte.d.ts +15 -0
  9. package/dist/components/LiteAsyncExportModal.svelte +113 -0
  10. package/dist/components/LiteAsyncExportModal.svelte.d.ts +14 -0
  11. package/dist/components/LiteAuditTrailInspector.svelte +166 -0
  12. package/dist/components/LiteAuditTrailInspector.svelte.d.ts +23 -0
  13. package/dist/components/LiteBillingInvoiceDrawer.svelte +100 -0
  14. package/dist/components/LiteBillingInvoiceDrawer.svelte.d.ts +16 -0
  15. package/dist/components/LiteChartAnnotationOverlay.svelte +101 -0
  16. package/dist/components/LiteChartAnnotationOverlay.svelte.d.ts +16 -0
  17. package/dist/components/LiteColumnMappingTable.svelte +105 -0
  18. package/dist/components/LiteColumnMappingTable.svelte.d.ts +14 -0
  19. package/dist/components/LiteContextMenu.svelte +114 -0
  20. package/dist/components/LiteContextMenu.svelte.d.ts +18 -0
  21. package/dist/components/LiteDashboardGridLayout.svelte +108 -0
  22. package/dist/components/LiteDashboardGridLayout.svelte.d.ts +16 -0
  23. package/dist/components/LiteDashboardLayoutStorage.svelte +88 -0
  24. package/dist/components/LiteDashboardLayoutStorage.svelte.d.ts +16 -0
  25. package/dist/components/LiteDataImportDropzone.svelte +89 -0
  26. package/dist/components/LiteDataImportDropzone.svelte.d.ts +10 -0
  27. package/dist/components/LiteDataLineageGraph.svelte +100 -0
  28. package/dist/components/LiteDataLineageGraph.svelte.d.ts +15 -0
  29. package/dist/components/LiteDataMaskPolicyEngine.svelte +131 -0
  30. package/dist/components/LiteDataMaskPolicyEngine.svelte.d.ts +16 -0
  31. package/dist/components/LiteDataScreenContainer.svelte +34 -0
  32. package/dist/components/LiteDataScreenContainer.svelte.d.ts +9 -0
  33. package/dist/components/LiteDualApprovalGate.svelte +58 -0
  34. package/dist/components/LiteDualApprovalGate.svelte.d.ts +11 -0
  35. package/dist/components/LiteElectronicSealStamp.svelte +56 -0
  36. package/dist/components/LiteElectronicSealStamp.svelte.d.ts +9 -0
  37. package/dist/components/LiteEnvVariableEditor.svelte +114 -0
  38. package/dist/components/LiteEnvVariableEditor.svelte.d.ts +15 -0
  39. package/dist/components/LiteFormulaField.svelte +44 -0
  40. package/dist/components/LiteFormulaField.svelte.d.ts +11 -0
  41. package/dist/components/LiteGeoScatterMap.svelte +117 -0
  42. package/dist/components/LiteGeoScatterMap.svelte.d.ts +16 -0
  43. package/dist/components/LiteHmacSignatureCalculator.svelte +84 -0
  44. package/dist/components/LiteHmacSignatureCalculator.svelte.d.ts +10 -0
  45. package/dist/components/LiteImportPreviewValidator.svelte +136 -0
  46. package/dist/components/LiteImportPreviewValidator.svelte.d.ts +16 -0
  47. package/dist/components/LiteJsonViewer.svelte +88 -0
  48. package/dist/components/LiteJsonViewer.svelte.d.ts +9 -0
  49. package/dist/components/LiteKeyboardShortcutsModal.svelte +56 -0
  50. package/dist/components/LiteKeyboardShortcutsModal.svelte.d.ts +13 -0
  51. package/dist/components/LiteKpiCard.svelte +169 -0
  52. package/dist/components/LiteKpiCard.svelte.d.ts +25 -0
  53. package/dist/components/LiteLiveStreamLogViewer.svelte +84 -0
  54. package/dist/components/LiteLiveStreamLogViewer.svelte.d.ts +14 -0
  55. package/dist/components/LiteOmnibarCommandPalette.svelte +111 -0
  56. package/dist/components/LiteOmnibarCommandPalette.svelte.d.ts +15 -0
  57. package/dist/components/LitePeriodComparisonCard.svelte +60 -0
  58. package/dist/components/LitePeriodComparisonCard.svelte.d.ts +11 -0
  59. package/dist/components/LitePermissionSimulator.svelte +90 -0
  60. package/dist/components/LitePermissionSimulator.svelte.d.ts +14 -0
  61. package/dist/components/LitePivotMatrix.svelte +138 -0
  62. package/dist/components/LitePivotMatrix.svelte.d.ts +18 -0
  63. package/dist/components/LitePlanUsageQuotaBar.svelte +96 -0
  64. package/dist/components/LitePlanUsageQuotaBar.svelte.d.ts +15 -0
  65. package/dist/components/LiteQueryAiExplainer.svelte +85 -0
  66. package/dist/components/LiteQueryAiExplainer.svelte.d.ts +10 -0
  67. package/dist/components/LiteResultPage.svelte +135 -0
  68. package/dist/components/LiteResultPage.svelte.d.ts +17 -0
  69. package/dist/components/LiteScheduledJobManager.svelte +116 -0
  70. package/dist/components/LiteScheduledJobManager.svelte.d.ts +16 -0
  71. package/dist/components/LiteScreenAntiLeakGuard.svelte +56 -0
  72. package/dist/components/LiteScreenAntiLeakGuard.svelte.d.ts +8 -0
  73. package/dist/components/LiteSecureDataExporter.svelte +101 -0
  74. package/dist/components/LiteSecureDataExporter.svelte.d.ts +12 -0
  75. package/dist/components/LiteSensitiveDataMask.svelte +34 -2
  76. package/dist/components/LiteSensitiveDataMask.svelte.d.ts +1 -2
  77. package/dist/components/LiteSqlConsole.svelte +128 -0
  78. package/dist/components/LiteSqlConsole.svelte.d.ts +16 -0
  79. package/dist/components/LiteStepWizard.svelte +98 -0
  80. package/dist/components/LiteStepWizard.svelte.d.ts +16 -0
  81. package/dist/components/LiteSystemCapacityForecastCard.svelte +88 -0
  82. package/dist/components/LiteSystemCapacityForecastCard.svelte.d.ts +11 -0
  83. package/dist/components/LiteSystemHealthCheckDashboard.svelte +142 -0
  84. package/dist/components/LiteSystemHealthCheckDashboard.svelte.d.ts +18 -0
  85. package/dist/components/LiteTableAggregationFooter.svelte +76 -0
  86. package/dist/components/LiteTableAggregationFooter.svelte.d.ts +14 -0
  87. package/dist/components/LiteTenantContextSwitcher.svelte +173 -0
  88. package/dist/components/LiteTenantContextSwitcher.svelte.d.ts +27 -0
  89. package/dist/components/LiteTenantQuotasMatrix.svelte +117 -0
  90. package/dist/components/LiteTenantQuotasMatrix.svelte.d.ts +17 -0
  91. package/dist/components/LiteTextDiffViewer.svelte +111 -0
  92. package/dist/components/LiteTextDiffViewer.svelte.d.ts +10 -0
  93. package/dist/components/LiteThreadedCommentDrawer.svelte +60 -0
  94. package/dist/components/LiteThreadedCommentDrawer.svelte.d.ts +15 -0
  95. package/dist/components/LiteTierFeatureComparison.svelte +97 -0
  96. package/dist/components/LiteTierFeatureComparison.svelte.d.ts +18 -0
  97. package/dist/components/LiteUnsavedChangesGuard.svelte +53 -0
  98. package/dist/components/LiteUnsavedChangesGuard.svelte.d.ts +10 -0
  99. package/dist/components/LiteWatermarkContainer.svelte +58 -0
  100. package/dist/components/LiteWatermarkContainer.svelte.d.ts +9 -0
  101. package/dist/components/LiteWebhookSimulator.svelte +120 -0
  102. package/dist/components/LiteWebhookSimulator.svelte.d.ts +11 -0
  103. package/dist/components/LiteWorkflowNodeInspector.svelte +79 -0
  104. package/dist/components/LiteWorkflowNodeInspector.svelte.d.ts +11 -0
  105. package/dist/components/LiteWorkflowStepper.svelte +56 -0
  106. package/dist/components/LiteWorkflowStepper.svelte.d.ts +14 -0
  107. package/dist/index.d.ts +57 -0
  108. package/dist/index.js +61 -0
  109. package/package.json +2 -2
@@ -0,0 +1,117 @@
1
+ <script lang="ts">
2
+ interface QuotaItem {
3
+ id: string;
4
+ resourceName: string;
5
+ used: number;
6
+ limit: number;
7
+ unit: string;
8
+ status?: 'normal' | 'warning' | 'exhausted';
9
+ }
10
+
11
+ interface Props {
12
+ tenantName?: string;
13
+ tierName?: string;
14
+ quotas?: QuotaItem[];
15
+ class?: string;
16
+ }
17
+
18
+ let {
19
+ tenantName = '上海创智多租户研发中心',
20
+ tierName = '旗舰尊享版 (Enterprise Tier)',
21
+ quotas = [
22
+ { id: 'q1', resourceName: 'API 请求吞吐', used: 840000, limit: 1000000, unit: 'req/天', status: 'normal' },
23
+ { id: 'q2', resourceName: '分布式对象存储', used: 480, limit: 500, unit: 'GB', status: 'warning' },
24
+ { id: 'q3', resourceName: '组织席位数', used: 120, limit: 120, unit: '席位', status: 'exhausted' },
25
+ { id: 'q4', resourceName: 'AI 智能算力点', used: 3200, limit: 10000, unit: '点', status: 'normal' }
26
+ ],
27
+ class: className = '',
28
+ }: Props = $props();
29
+
30
+ function calcPct(u: number, l: number): number {
31
+ if (l <= 0) return 0;
32
+ return Math.min(100, Math.round((u / l) * 100));
33
+ }
34
+ </script>
35
+
36
+ <div
37
+ class="lite-tenant-quotas {className}"
38
+ data-svadmin-component="LiteTenantQuotasMatrix"
39
+ role="region"
40
+ aria-label="Tenant Quotas Matrix"
41
+ >
42
+ <header class="lite-quotas-header">
43
+ <div>
44
+ <h4 class="lite-quotas-tenant">{tenantName}</h4>
45
+ <span class="lite-quotas-tier">{tierName}</span>
46
+ </div>
47
+ </header>
48
+
49
+ <div class="lite-quotas-grid">
50
+ {#each quotas as q (q.id)}
51
+ {@const pct = calcPct(q.used, q.limit)}
52
+ <div class="lite-quota-card">
53
+ <div class="lite-card-top">
54
+ <span class="lite-card-name">{q.resourceName}</span>
55
+ <span class="lite-card-usage">{q.used.toLocaleString()} / {q.limit.toLocaleString()} {q.unit}</span>
56
+ </div>
57
+ <div class="lite-card-track">
58
+ <div
59
+ class="lite-card-bar"
60
+ class:lite-bar-warn={pct >= 85 && pct < 100}
61
+ class:lite-bar-danger={pct >= 100}
62
+ style="width: {pct}%;"
63
+ ></div>
64
+ </div>
65
+ <div class="lite-card-bottom">
66
+ <span class="lite-card-pct">{pct}% 已用</span>
67
+ {#if pct >= 100}
68
+ <span class="lite-card-state text-danger">已达硬配额上限</span>
69
+ {:else if pct >= 85}
70
+ <span class="lite-card-state text-warn">接近用量预警线</span>
71
+ {:else}
72
+ <span class="lite-card-state text-ok">配额容量充裕</span>
73
+ {/if}
74
+ </div>
75
+ </div>
76
+ {/each}
77
+ </div>
78
+ </div>
79
+
80
+ <style>
81
+ .lite-tenant-quotas {
82
+ border: 1px solid #e5e6eb;
83
+ border-radius: 6px;
84
+ background: #ffffff;
85
+ font-size: 12px;
86
+ overflow: hidden;
87
+ }
88
+ .lite-quotas-header {
89
+ padding: 10px 14px;
90
+ background: #f7f8fa;
91
+ border-bottom: 1px solid #e5e6eb;
92
+ }
93
+ .lite-quotas-tenant { margin: 0; font-size: 13px; font-weight: 600; color: #1d2129; }
94
+ .lite-quotas-tier { font-size: 11px; color: #165dff; font-weight: 500; display: block; margin-top: 2px; }
95
+ .lite-quotas-grid { padding: 12px 14px; overflow: hidden; }
96
+ .lite-quotas-grid .lite-quota-card { float: left; width: calc(50% - 6px); margin: 0 12px 12px 0; box-sizing: border-box; }
97
+ .lite-quotas-grid .lite-quota-card:nth-child(2n) { margin-right: 0; }
98
+ @media (max-width: 640px) { .lite-quotas-grid .lite-quota-card { float: none; width: 100%; margin-right: 0; } }
99
+ .lite-quota-card {
100
+ border: 1px solid #f2f3f5;
101
+ border-radius: 4px;
102
+ padding: 10px;
103
+ background: #fafbfc;
104
+ }
105
+ .lite-card-top { display: flex; justify-content: space-between; margin-bottom: 6px; font-size: 11px; }
106
+ .lite-card-name { font-weight: 600; color: #1d2129; }
107
+ .lite-card-usage { font-family: monospace; color: #4e5969; }
108
+ .lite-card-track { height: 6px; background: #e5e6eb; border-radius: 3px; overflow: hidden; margin-bottom: 6px; }
109
+ .lite-card-bar { height: 100%; background: #165dff; border-radius: 3px; }
110
+ .lite-bar-warn { background: #ff7d00; }
111
+ .lite-bar-danger { background: #f53f3f; }
112
+ .lite-card-bottom { display: flex; justify-content: space-between; font-size: 10px; }
113
+ .lite-card-pct { font-family: monospace; font-weight: 600; color: #1d2129; }
114
+ .text-danger { color: #f53f3f; font-weight: 600; }
115
+ .text-warn { color: #ff7d00; font-weight: 600; }
116
+ .text-ok { color: #00b42a; }
117
+ </style>
@@ -0,0 +1,17 @@
1
+ interface QuotaItem {
2
+ id: string;
3
+ resourceName: string;
4
+ used: number;
5
+ limit: number;
6
+ unit: string;
7
+ status?: 'normal' | 'warning' | 'exhausted';
8
+ }
9
+ interface Props {
10
+ tenantName?: string;
11
+ tierName?: string;
12
+ quotas?: QuotaItem[];
13
+ class?: string;
14
+ }
15
+ declare const LiteTenantQuotasMatrix: import("svelte").Component<Props, {}, "">;
16
+ type LiteTenantQuotasMatrix = ReturnType<typeof LiteTenantQuotasMatrix>;
17
+ export default LiteTenantQuotasMatrix;
@@ -0,0 +1,111 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ oldText?: string;
4
+ newText?: string;
5
+ oldTitle?: string;
6
+ newTitle?: string;
7
+ class?: string;
8
+ }
9
+
10
+ let {
11
+ oldText = '',
12
+ newText = '',
13
+ oldTitle = 'Baseline',
14
+ newTitle = 'Current',
15
+ class: className = '',
16
+ }: Props = $props();
17
+
18
+ interface DiffEntry {
19
+ type: 'same' | 'add' | 'del';
20
+ lineNo: number;
21
+ text: string;
22
+ }
23
+
24
+ const diffEntries = $derived.by<DiffEntry[]>(() => {
25
+ const oldLines = oldText.split(/\r?\n/u);
26
+ const newLines = newText.split(/\r?\n/u);
27
+ const result: DiffEntry[] = [];
28
+
29
+ let lineCounter = 1;
30
+ let i = 0;
31
+ let j = 0;
32
+
33
+ while (i < oldLines.length && j < newLines.length) {
34
+ if (oldLines[i] === newLines[j]) {
35
+ result.push({ type: 'same', lineNo: lineCounter++, text: oldLines[i] ?? '' });
36
+ i++;
37
+ j++;
38
+ } else {
39
+ result.push({ type: 'del', lineNo: lineCounter++, text: oldLines[i] ?? '' });
40
+ result.push({ type: 'add', lineNo: lineCounter++, text: newLines[j] ?? '' });
41
+ i++;
42
+ j++;
43
+ }
44
+ }
45
+ while (i < oldLines.length) {
46
+ result.push({ type: 'del', lineNo: lineCounter++, text: oldLines[i] ?? '' });
47
+ i++;
48
+ }
49
+ while (j < newLines.length) {
50
+ result.push({ type: 'add', lineNo: lineCounter++, text: newLines[j] ?? '' });
51
+ j++;
52
+ }
53
+
54
+ return result;
55
+ });
56
+ </script>
57
+
58
+ <div
59
+ class="lite-text-diff {className}"
60
+ data-svadmin-component="LiteTextDiffViewer"
61
+ role="region"
62
+ aria-label="Text Diff"
63
+ >
64
+ <header class="lite-diff-header">
65
+ <span class="lite-diff-title">{oldTitle} ↔ {newTitle}</span>
66
+ </header>
67
+
68
+ <div class="lite-diff-body">
69
+ <table class="lite-diff-table">
70
+ <tbody>
71
+ {#each diffEntries as entry (entry.lineNo)}
72
+ <tr class="lite-diff-row lite-diff-{entry.type}">
73
+ <td class="lite-diff-line-no">{entry.lineNo}</td>
74
+ <td class="lite-diff-sign">
75
+ {#if entry.type === 'add'}+{/if}
76
+ {#if entry.type === 'del'}-{/if}
77
+ </td>
78
+ <td class="lite-diff-content">{entry.text}</td>
79
+ </tr>
80
+ {/each}
81
+ </tbody>
82
+ </table>
83
+ </div>
84
+ </div>
85
+
86
+ <style>
87
+ .lite-text-diff {
88
+ border: 1px solid #e5e6eb;
89
+ border-radius: 6px;
90
+ background: #ffffff;
91
+ font-family: monospace;
92
+ font-size: 12px;
93
+ overflow: hidden;
94
+ }
95
+ .lite-diff-header {
96
+ padding: 8px 12px;
97
+ background: #f7f8fa;
98
+ border-bottom: 1px solid #e5e6eb;
99
+ font-weight: 600;
100
+ color: #4e5969;
101
+ }
102
+ .lite-diff-body { max-height: 400px; overflow: auto; }
103
+ .lite-diff-table { width: 100%; border-collapse: collapse; }
104
+ .lite-diff-row td { padding: 2px 6px; }
105
+ .lite-diff-line-no { width: 40px; text-align: right; color: #86909c; user-select: none; border-right: 1px solid #f2f3f5; }
106
+ .lite-diff-sign { width: 20px; text-align: center; font-weight: 700; user-select: none; }
107
+ .lite-diff-content { white-space: pre-wrap; word-break: break-all; }
108
+ .lite-diff-add { background: #e8ffea; color: #00b42a; }
109
+ .lite-diff-del { background: #ffece8; color: #f53f3f; }
110
+ .lite-diff-same { color: #1d2129; }
111
+ </style>
@@ -0,0 +1,10 @@
1
+ interface Props {
2
+ oldText?: string;
3
+ newText?: string;
4
+ oldTitle?: string;
5
+ newTitle?: string;
6
+ class?: string;
7
+ }
8
+ declare const LiteTextDiffViewer: import("svelte").Component<Props, {}, "">;
9
+ type LiteTextDiffViewer = ReturnType<typeof LiteTextDiffViewer>;
10
+ export default LiteTextDiffViewer;
@@ -0,0 +1,60 @@
1
+ <script lang="ts">
2
+ export interface LiteComment {
3
+ id: string;
4
+ author: string;
5
+ content: string;
6
+ createdAt: string;
7
+ }
8
+
9
+ interface Props {
10
+ comments?: LiteComment[];
11
+ title?: string;
12
+ action?: string;
13
+ class?: string;
14
+ }
15
+
16
+ let {
17
+ comments = [],
18
+ title = 'Comments',
19
+ action = '/comments/create',
20
+ class: className = '',
21
+ }: Props = $props();
22
+ </script>
23
+
24
+ <div
25
+ class="lite-comment-box {className}"
26
+ data-svadmin-component="LiteThreadedCommentDrawer"
27
+ >
28
+ <h4 class="lite-comment-title">{title}</h4>
29
+ <ul class="lite-comment-list">
30
+ {#each comments as c (c.id)}
31
+ <li class="lite-comment-item">
32
+ <div class="lite-comment-head">
33
+ <span class="lite-comment-author">{c.author}</span>
34
+ <span class="lite-comment-time">{c.createdAt}</span>
35
+ </div>
36
+ <p class="lite-comment-content">{c.content}</p>
37
+ </li>
38
+ {/each}
39
+ </ul>
40
+
41
+ <form {action} method="POST" class="lite-comment-form">
42
+ <textarea name="content" required placeholder="Leave a reply..." class="lite-comment-input"></textarea>
43
+ <button type="submit" class="lite-comment-btn">Submit Reply</button>
44
+ </form>
45
+ </div>
46
+
47
+ <style>
48
+ .lite-comment-box { border: 1px solid #e5e6eb; border-radius: 8px; background: #ffffff; padding: 16px; font-size: 12px; }
49
+ .lite-comment-title { font-size: 14px; font-weight: 600; margin: 0 0 12px 0; color: #1d2129; }
50
+ .lite-comment-list { list-style: none; margin: 0 0 16px 0; padding: 0; }
51
+ .lite-comment-item { border-bottom: 1px solid #f2f3f5; padding: 8px 0; }
52
+ .lite-comment-head { display: flex; justify-content: space-between; margin-bottom: 4px; }
53
+ .lite-comment-author { font-weight: 600; color: #1d2129; }
54
+ .lite-comment-time { color: #86909c; font-size: 11px; }
55
+ .lite-comment-content { margin: 0; color: #4e5969; }
56
+ .lite-comment-form { display: flex; flex-direction: column; }
57
+ .lite-comment-form > * + * { margin-top: 8px; }
58
+ .lite-comment-input { height: 60px; border: 1px solid #e5e6eb; border-radius: 4px; padding: 6px 10px; font-size: 12px; }
59
+ .lite-comment-btn { height: 32px; background: #165dff; color: #fff; border: none; border-radius: 4px; font-size: 12px; font-weight: 600; cursor: pointer; }
60
+ </style>
@@ -0,0 +1,15 @@
1
+ export interface LiteComment {
2
+ id: string;
3
+ author: string;
4
+ content: string;
5
+ createdAt: string;
6
+ }
7
+ interface Props {
8
+ comments?: LiteComment[];
9
+ title?: string;
10
+ action?: string;
11
+ class?: string;
12
+ }
13
+ declare const LiteThreadedCommentDrawer: import("svelte").Component<Props, {}, "">;
14
+ type LiteThreadedCommentDrawer = ReturnType<typeof LiteThreadedCommentDrawer>;
15
+ export default LiteThreadedCommentDrawer;
@@ -0,0 +1,97 @@
1
+ <script lang="ts">
2
+ interface Tier {
3
+ key: string;
4
+ name: string;
5
+ price: string;
6
+ isCurrent?: boolean;
7
+ }
8
+
9
+ interface Feature {
10
+ name: string;
11
+ values: Record<string, boolean | string>;
12
+ }
13
+
14
+ interface Props {
15
+ tiers?: Tier[];
16
+ features?: Feature[];
17
+ class?: string;
18
+ }
19
+
20
+ let {
21
+ tiers = [
22
+ { key: 'starter', name: 'Starter', price: '$29/mo', isCurrent: true },
23
+ { key: 'pro', name: 'Pro', price: '$99/mo' },
24
+ ],
25
+ features = [
26
+ { name: 'Multi-tenant', values: { starter: true, pro: true } },
27
+ { name: 'Seats', values: { starter: '5', pro: '50' } },
28
+ { name: 'Dedicated support', values: { starter: false, pro: true } },
29
+ ],
30
+ class: className = '',
31
+ }: Props = $props();
32
+ </script>
33
+
34
+ <div
35
+ class="lite-tier-comparison {className}"
36
+ data-svadmin-component="LiteTierFeatureComparison"
37
+ role="region"
38
+ aria-label="Tier Feature Comparison"
39
+ >
40
+ <table class="lite-tier-table">
41
+ <thead>
42
+ <tr>
43
+ <th class="lite-tier-feat-th">功能特性</th>
44
+ {#each tiers as t (t.key)}
45
+ <th class="lite-tier-th">
46
+ <span class="lite-tier-name">{t.name}</span>
47
+ <span class="lite-tier-price">{t.price}</span>
48
+ {#if t.isCurrent}
49
+ <span class="lite-tier-current">当前套餐</span>
50
+ {/if}
51
+ </th>
52
+ {/each}
53
+ </tr>
54
+ </thead>
55
+ <tbody>
56
+ {#each features as feat (feat.name)}
57
+ <tr>
58
+ <td class="lite-tier-feat-td">{feat.name}</td>
59
+ {#each tiers as t (t.key)}
60
+ {@const val = feat.values[t.key]}
61
+ <td class="lite-tier-val-td">
62
+ {#if val === true}
63
+ <span class="lite-check">✓</span>
64
+ {:else if val === false}
65
+ <span class="lite-dash">—</span>
66
+ {:else}
67
+ <span class="lite-val-text">{val}</span>
68
+ {/if}
69
+ </td>
70
+ {/each}
71
+ </tr>
72
+ {/each}
73
+ </tbody>
74
+ </table>
75
+ </div>
76
+
77
+ <style>
78
+ .lite-tier-comparison {
79
+ border: 1px solid #e5e6eb;
80
+ border-radius: 6px;
81
+ background: #ffffff;
82
+ overflow-x: auto;
83
+ font-size: 12px;
84
+ }
85
+ .lite-tier-table { width: 100%; border-collapse: collapse; }
86
+ .lite-tier-table th, .lite-tier-table td { padding: 8px 12px; border-bottom: 1px solid #e5e6eb; }
87
+ .lite-tier-feat-th { text-align: left; color: #4e5969; font-weight: 600; width: 40%; }
88
+ .lite-tier-th { text-align: center; background: #f7f8fa; width: 30%; }
89
+ .lite-tier-name { display: block; font-weight: 700; color: #1d2129; }
90
+ .lite-tier-price { display: block; font-family: monospace; color: #165dff; font-weight: 600; margin-top: 2px; }
91
+ .lite-tier-current { display: inline-block; font-size: 10px; background: #e5e6eb; color: #4e5969; padding: 1px 6px; border-radius: 3px; margin-top: 4px; }
92
+ .lite-tier-feat-td { color: #1d2129; font-weight: 500; }
93
+ .lite-tier-val-td { text-align: center; }
94
+ .lite-check { color: #00b42a; font-weight: 700; }
95
+ .lite-dash { color: #86909c; }
96
+ .lite-val-text { font-family: monospace; font-weight: 600; color: #1d2129; }
97
+ </style>
@@ -0,0 +1,18 @@
1
+ interface Tier {
2
+ key: string;
3
+ name: string;
4
+ price: string;
5
+ isCurrent?: boolean;
6
+ }
7
+ interface Feature {
8
+ name: string;
9
+ values: Record<string, boolean | string>;
10
+ }
11
+ interface Props {
12
+ tiers?: Tier[];
13
+ features?: Feature[];
14
+ class?: string;
15
+ }
16
+ declare const LiteTierFeatureComparison: import("svelte").Component<Props, {}, "">;
17
+ type LiteTierFeatureComparison = ReturnType<typeof LiteTierFeatureComparison>;
18
+ export default LiteTierFeatureComparison;
@@ -0,0 +1,53 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ hasChanges?: boolean;
6
+ message?: string;
7
+ class?: string;
8
+ children?: Snippet;
9
+ }
10
+
11
+ let {
12
+ hasChanges = false,
13
+ message = 'You have unsaved changes that may be lost.',
14
+ class: className = '',
15
+ children,
16
+ }: Props = $props();
17
+ </script>
18
+
19
+ <div
20
+ class="lite-unsaved-guard {className}"
21
+ data-svadmin-component="LiteUnsavedChangesGuard"
22
+ data-dirty={hasChanges ? 'true' : 'false'}
23
+ >
24
+ {#if hasChanges}
25
+ <aside class="lite-unsaved-banner" role="status">
26
+ <span class="lite-unsaved-icon">⚠️</span>
27
+ <span class="lite-unsaved-text">{message}</span>
28
+ </aside>
29
+ {/if}
30
+
31
+ <div class="lite-unsaved-content">
32
+ {#if children}{@render children()}{/if}
33
+ </div>
34
+ </div>
35
+
36
+ <style>
37
+ .lite-unsaved-guard { display: block; }
38
+ .lite-unsaved-banner {
39
+ display: flex;
40
+ align-items: center;
41
+ padding: 8px 12px;
42
+ background: #fff7e8;
43
+ border: 1px solid #ffd591;
44
+ border-radius: 6px;
45
+ margin-bottom: 12px;
46
+ font-size: 13px;
47
+ color: #d46b08;
48
+ }
49
+ .lite-unsaved-banner > * + * { margin-left: 8px; }
50
+ .lite-unsaved-icon { font-size: 14px; }
51
+ .lite-unsaved-text { font-weight: 500; }
52
+ .lite-unsaved-content { position: relative; }
53
+ </style>
@@ -0,0 +1,10 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ hasChanges?: boolean;
4
+ message?: string;
5
+ class?: string;
6
+ children?: Snippet;
7
+ }
8
+ declare const LiteUnsavedChangesGuard: import("svelte").Component<Props, {}, "">;
9
+ type LiteUnsavedChangesGuard = ReturnType<typeof LiteUnsavedChangesGuard>;
10
+ export default LiteUnsavedChangesGuard;
@@ -0,0 +1,58 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ content?: string | string[];
6
+ class?: string;
7
+ children?: Snippet;
8
+ }
9
+
10
+ let {
11
+ content = 'SVAdmin Lite',
12
+ class: className = '',
13
+ children,
14
+ }: Props = $props();
15
+
16
+ const watermarkText = $derived(
17
+ Array.isArray(content) ? content.join(' ') : String(content)
18
+ );
19
+
20
+ const encodedSvg = $derived.by(() => {
21
+ const escaped = watermarkText
22
+ .replace(/&/g, '&amp;')
23
+ .replace(/</g, '&lt;')
24
+ .replace(/>/g, '&gt;')
25
+ .replace(/"/g, '&quot;');
26
+ const svg = `<svg xmlns="http://www.w3.org/2000/svg" width="220" height="120" viewBox="0 0 220 120"><text x="20" y="60" fill="rgba(0,0,0,0.07)" font-family="sans-serif" font-size="12" transform="rotate(-18 110 60)">${escaped}</text></svg>`;
27
+ return `data:image/svg+xml;utf8,${encodeURIComponent(svg)}`;
28
+ });
29
+ </script>
30
+
31
+ <div
32
+ class="lite-watermark-container {className}"
33
+ data-svadmin-component="LiteWatermarkContainer"
34
+ style="--lite-watermark-pattern: url('{encodedSvg}');"
35
+ >
36
+ <div class="lite-watermark-overlay" aria-hidden="true" style="background-image: url('{encodedSvg}');"></div>
37
+ <div class="lite-watermark-content">
38
+ {#if children}{@render children()}{/if}
39
+ </div>
40
+ </div>
41
+
42
+ <style>
43
+ .lite-watermark-container {
44
+ position: relative;
45
+ overflow: hidden;
46
+ }
47
+ .lite-watermark-overlay {
48
+ position: absolute;
49
+ inset: 0;
50
+ pointer-events: none;
51
+ z-index: 9;
52
+ background-repeat: repeat;
53
+ }
54
+ .lite-watermark-content {
55
+ position: relative;
56
+ z-index: 1;
57
+ }
58
+ </style>
@@ -0,0 +1,9 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ content?: string | string[];
4
+ class?: string;
5
+ children?: Snippet;
6
+ }
7
+ declare const LiteWatermarkContainer: import("svelte").Component<Props, {}, "">;
8
+ type LiteWatermarkContainer = ReturnType<typeof LiteWatermarkContainer>;
9
+ export default LiteWatermarkContainer;