@svadmin/lite 0.7.0 → 0.8.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.
- package/README.md +18 -5
- package/dist/components/LiteActivityFeed.svelte +98 -0
- package/dist/components/LiteActivityFeed.svelte.d.ts +19 -0
- package/dist/components/LiteApprovalActionCard.svelte +75 -0
- package/dist/components/LiteApprovalActionCard.svelte.d.ts +10 -0
- package/dist/components/LiteCanvasAnnotation.svelte +136 -0
- package/dist/components/LiteCanvasAnnotation.svelte.d.ts +16 -0
- package/dist/components/LiteColumnHeaderFilter.svelte +38 -0
- package/dist/components/LiteColumnHeaderFilter.svelte.d.ts +8 -0
- package/dist/components/LiteColumnSettings.svelte +82 -0
- package/dist/components/LiteColumnSettings.svelte.d.ts +15 -0
- package/dist/components/LiteDecisionTable.svelte +178 -0
- package/dist/components/LiteDecisionTable.svelte.d.ts +21 -0
- package/dist/components/LiteDraggableRowTable.svelte +70 -0
- package/dist/components/LiteDraggableRowTable.svelte.d.ts +14 -0
- package/dist/components/LiteDrawerForm.svelte +85 -0
- package/dist/components/LiteDrawerForm.svelte.d.ts +13 -0
- package/dist/components/LiteEditableTable.svelte +84 -0
- package/dist/components/LiteEditableTable.svelte.d.ts +19 -0
- package/dist/components/LiteGanttChart.svelte +144 -0
- package/dist/components/LiteGanttChart.svelte.d.ts +17 -0
- package/dist/components/LiteImageCropper.svelte +81 -0
- package/dist/components/LiteImageCropper.svelte.d.ts +9 -0
- package/dist/components/LiteImportWizard.svelte +99 -0
- package/dist/components/LiteImportWizard.svelte.d.ts +11 -0
- package/dist/components/LiteJsonSchemaForm.svelte +102 -0
- package/dist/components/LiteJsonSchemaForm.svelte.d.ts +10 -0
- package/dist/components/LiteKanbanBoard.svelte +169 -0
- package/dist/components/LiteKanbanBoard.svelte.d.ts +21 -0
- package/dist/components/LiteMasterDetailView.svelte +113 -0
- package/dist/components/LiteMasterDetailView.svelte.d.ts +11 -0
- package/dist/components/LiteMediaLibraryModal.svelte +110 -0
- package/dist/components/LiteMediaLibraryModal.svelte.d.ts +17 -0
- package/dist/components/LiteMentionsInput.svelte +98 -0
- package/dist/components/LiteMentionsInput.svelte.d.ts +19 -0
- package/dist/components/LiteModalForm.svelte +84 -0
- package/dist/components/LiteModalForm.svelte.d.ts +13 -0
- package/dist/components/LiteMultiTabKeepAlive.svelte +79 -0
- package/dist/components/LiteMultiTabKeepAlive.svelte.d.ts +15 -0
- package/dist/components/LiteOfflineSyncBanner.svelte +75 -0
- package/dist/components/LiteOfflineSyncBanner.svelte.d.ts +15 -0
- package/dist/components/LitePdfDocumentViewer.svelte +138 -0
- package/dist/components/LitePdfDocumentViewer.svelte.d.ts +17 -0
- package/dist/components/LitePivotTable.svelte +163 -0
- package/dist/components/LitePivotTable.svelte.d.ts +15 -0
- package/dist/components/LitePresenceAvatarGroup.svelte +52 -0
- package/dist/components/LitePresenceAvatarGroup.svelte.d.ts +12 -0
- package/dist/components/LitePrintableBill.svelte +119 -0
- package/dist/components/LitePrintableBill.svelte.d.ts +19 -0
- package/dist/components/LiteSensitiveDataMask.svelte +35 -0
- package/dist/components/LiteSensitiveDataMask.svelte.d.ts +7 -0
- package/dist/components/LiteSignaturePad.svelte +99 -0
- package/dist/components/LiteSignaturePad.svelte.d.ts +11 -0
- package/dist/components/LiteSplitPaneLayout.svelte +66 -0
- package/dist/components/LiteSplitPaneLayout.svelte.d.ts +9 -0
- package/dist/components/LiteSpreadsheetView.svelte +148 -0
- package/dist/components/LiteSpreadsheetView.svelte.d.ts +16 -0
- package/dist/components/LiteStepForm.svelte +144 -0
- package/dist/components/LiteStepForm.svelte.d.ts +18 -0
- package/dist/components/LiteTableSummary.svelte +93 -0
- package/dist/components/LiteTableSummary.svelte.d.ts +17 -0
- package/dist/components/LiteTreeTable.svelte +85 -0
- package/dist/components/LiteTreeTable.svelte.d.ts +13 -0
- package/dist/components/LiteVersionDiffViewer.svelte +129 -0
- package/dist/components/LiteVersionDiffViewer.svelte.d.ts +10 -0
- package/dist/components/LiteVirtualTable.svelte +52 -0
- package/dist/components/LiteVirtualTable.svelte.d.ts +14 -0
- package/dist/components/LiteWatermark.svelte +35 -0
- package/dist/components/LiteWatermark.svelte.d.ts +11 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +34 -0
- package/package.json +2 -2
|
@@ -0,0 +1,163 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export type AggregationFn = 'sum' | 'count' | 'avg' | 'min' | 'max';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
data?: Record<string, unknown>[];
|
|
6
|
+
rowField: string;
|
|
7
|
+
rowLabel?: string;
|
|
8
|
+
columnField: string;
|
|
9
|
+
columnLabel?: string;
|
|
10
|
+
valueField: string;
|
|
11
|
+
valueLabel?: string;
|
|
12
|
+
aggregator?: AggregationFn;
|
|
13
|
+
class?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
data = [],
|
|
18
|
+
rowField,
|
|
19
|
+
rowLabel = rowField,
|
|
20
|
+
columnField,
|
|
21
|
+
columnLabel = columnField,
|
|
22
|
+
valueField,
|
|
23
|
+
valueLabel = valueField,
|
|
24
|
+
aggregator = 'sum',
|
|
25
|
+
class: className = '',
|
|
26
|
+
}: Props = $props();
|
|
27
|
+
|
|
28
|
+
const distinctRowValues = $derived(
|
|
29
|
+
Array.from(new Set(data.map((d) => String(d[rowField] ?? '—')))).sort()
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
const distinctColValues = $derived(
|
|
33
|
+
Array.from(new Set(data.map((d) => String(d[columnField] ?? '—')))).sort()
|
|
34
|
+
);
|
|
35
|
+
|
|
36
|
+
function computeAgg(vals: number[]): number {
|
|
37
|
+
if (vals.length === 0) return 0;
|
|
38
|
+
if (aggregator === 'count') return vals.length;
|
|
39
|
+
if (aggregator === 'sum') return vals.reduce((a, b) => a + b, 0);
|
|
40
|
+
if (aggregator === 'avg') return vals.reduce((a, b) => a + b, 0) / vals.length;
|
|
41
|
+
if (aggregator === 'min') return Math.min(...vals);
|
|
42
|
+
if (aggregator === 'max') return Math.max(...vals);
|
|
43
|
+
return 0;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function getCellValue(r: string, c: string): number {
|
|
47
|
+
const vals = data
|
|
48
|
+
.filter((d) => String(d[rowField] ?? '—') === r && String(d[columnField] ?? '—') === c)
|
|
49
|
+
.map((d) => Number(d[valueField]) || 0);
|
|
50
|
+
return computeAgg(vals);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function getRowTotal(r: string): number {
|
|
54
|
+
const vals = data
|
|
55
|
+
.filter((d) => String(d[rowField] ?? '—') === r)
|
|
56
|
+
.map((d) => Number(d[valueField]) || 0);
|
|
57
|
+
return computeAgg(vals);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function getColTotal(c: string): number {
|
|
61
|
+
const vals = data
|
|
62
|
+
.filter((d) => String(d[columnField] ?? '—') === c)
|
|
63
|
+
.map((d) => Number(d[valueField]) || 0);
|
|
64
|
+
return computeAgg(vals);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
const grandTotal = $derived(
|
|
68
|
+
computeAgg(data.map((d) => Number(d[valueField]) || 0))
|
|
69
|
+
);
|
|
70
|
+
</script>
|
|
71
|
+
|
|
72
|
+
<div class="sv-lite-pivot-container {className}">
|
|
73
|
+
<div class="sv-lite-pivot-header">
|
|
74
|
+
<strong>Pivot Analysis</strong> ({rowLabel} × {columnLabel})
|
|
75
|
+
<span class="sv-lite-pivot-sub">Aggregator: {aggregator.toUpperCase()} ({valueLabel})</span>
|
|
76
|
+
</div>
|
|
77
|
+
|
|
78
|
+
<table class="sv-lite-pivot-table">
|
|
79
|
+
<thead>
|
|
80
|
+
<tr>
|
|
81
|
+
<th class="sv-lite-th-dim">{rowLabel} \ {columnLabel}</th>
|
|
82
|
+
{#each distinctColValues as col (col)}
|
|
83
|
+
<th>{col}</th>
|
|
84
|
+
{/each}
|
|
85
|
+
<th class="sv-lite-th-total">Total</th>
|
|
86
|
+
</tr>
|
|
87
|
+
</thead>
|
|
88
|
+
<tbody>
|
|
89
|
+
{#each distinctRowValues as row (row)}
|
|
90
|
+
<tr>
|
|
91
|
+
<td class="sv-lite-td-dim">{row}</td>
|
|
92
|
+
{#each distinctColValues as col (col)}
|
|
93
|
+
{@const val = getCellValue(row, col)}
|
|
94
|
+
<td class="sv-lite-td-val">{val.toLocaleString(undefined, { maximumFractionDigits: 2 })}</td>
|
|
95
|
+
{/each}
|
|
96
|
+
<td class="sv-lite-td-rowtotal">{getRowTotal(row).toLocaleString(undefined, { maximumFractionDigits: 2 })}</td>
|
|
97
|
+
</tr>
|
|
98
|
+
{/each}
|
|
99
|
+
</tbody>
|
|
100
|
+
<tfoot>
|
|
101
|
+
<tr>
|
|
102
|
+
<td class="sv-lite-td-dim">Grand Total</td>
|
|
103
|
+
{#each distinctColValues as col (col)}
|
|
104
|
+
<td class="sv-lite-td-val">{getColTotal(col).toLocaleString(undefined, { maximumFractionDigits: 2 })}</td>
|
|
105
|
+
{/each}
|
|
106
|
+
<td class="sv-lite-td-grandtotal">{grandTotal.toLocaleString(undefined, { maximumFractionDigits: 2 })}</td>
|
|
107
|
+
</tr>
|
|
108
|
+
</tfoot>
|
|
109
|
+
</table>
|
|
110
|
+
</div>
|
|
111
|
+
|
|
112
|
+
<style>
|
|
113
|
+
.sv-lite-pivot-container {
|
|
114
|
+
display: block;
|
|
115
|
+
border: 1px solid #e2e8f0;
|
|
116
|
+
border-radius: 6px;
|
|
117
|
+
padding: 12px;
|
|
118
|
+
background-color: #ffffff;
|
|
119
|
+
font-size: 12px;
|
|
120
|
+
overflow-x: auto;
|
|
121
|
+
}
|
|
122
|
+
.sv-lite-pivot-header {
|
|
123
|
+
margin-bottom: 10px;
|
|
124
|
+
font-size: 13px;
|
|
125
|
+
color: #0f172a;
|
|
126
|
+
}
|
|
127
|
+
.sv-lite-pivot-sub {
|
|
128
|
+
color: #64748b;
|
|
129
|
+
font-size: 11px;
|
|
130
|
+
margin-left: 8px;
|
|
131
|
+
}
|
|
132
|
+
.sv-lite-pivot-table {
|
|
133
|
+
width: 100%;
|
|
134
|
+
border-collapse: collapse;
|
|
135
|
+
text-align: right;
|
|
136
|
+
}
|
|
137
|
+
.sv-lite-pivot-table th, .sv-lite-pivot-table td {
|
|
138
|
+
border: 1px solid #e2e8f0;
|
|
139
|
+
padding: 6px 10px;
|
|
140
|
+
}
|
|
141
|
+
.sv-lite-pivot-table thead {
|
|
142
|
+
background-color: #f8fafc;
|
|
143
|
+
color: #475569;
|
|
144
|
+
}
|
|
145
|
+
.sv-lite-th-dim, .sv-lite-td-dim {
|
|
146
|
+
text-align: left;
|
|
147
|
+
background-color: #f8fafc;
|
|
148
|
+
font-weight: 600;
|
|
149
|
+
}
|
|
150
|
+
.sv-lite-th-total, .sv-lite-td-rowtotal {
|
|
151
|
+
background-color: #f1f5f9;
|
|
152
|
+
font-weight: 600;
|
|
153
|
+
}
|
|
154
|
+
.sv-lite-pivot-table tfoot {
|
|
155
|
+
background-color: #f1f5f9;
|
|
156
|
+
font-weight: bold;
|
|
157
|
+
border-top: 2px solid #cbd5e1;
|
|
158
|
+
}
|
|
159
|
+
.sv-lite-td-grandtotal {
|
|
160
|
+
color: #4338ca;
|
|
161
|
+
font-weight: bold;
|
|
162
|
+
}
|
|
163
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export type AggregationFn = 'sum' | 'count' | 'avg' | 'min' | 'max';
|
|
2
|
+
interface Props {
|
|
3
|
+
data?: Record<string, unknown>[];
|
|
4
|
+
rowField: string;
|
|
5
|
+
rowLabel?: string;
|
|
6
|
+
columnField: string;
|
|
7
|
+
columnLabel?: string;
|
|
8
|
+
valueField: string;
|
|
9
|
+
valueLabel?: string;
|
|
10
|
+
aggregator?: AggregationFn;
|
|
11
|
+
class?: string;
|
|
12
|
+
}
|
|
13
|
+
declare const LitePivotTable: import("svelte").Component<Props, {}, "">;
|
|
14
|
+
type LitePivotTable = ReturnType<typeof LitePivotTable>;
|
|
15
|
+
export default LitePivotTable;
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface LitePresenceUser {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
status?: 'online' | 'idle' | 'editing';
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
users?: LitePresenceUser[];
|
|
10
|
+
label?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
let {
|
|
14
|
+
users = [],
|
|
15
|
+
label = 'Viewing now',
|
|
16
|
+
}: Props = $props();
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<div class="lite-presence-container">
|
|
20
|
+
<span class="lite-presence-label">{label}:</span>
|
|
21
|
+
{#each users as user (user.id)}
|
|
22
|
+
<span class="lite-presence-badge" title="{user.name} ({user.status ?? 'online'})">
|
|
23
|
+
👤 {user.name}
|
|
24
|
+
</span>
|
|
25
|
+
{/each}
|
|
26
|
+
{#if users.length === 0}
|
|
27
|
+
<span style="color: #94a3b8; font-size: 11px;">No active viewers</span>
|
|
28
|
+
{/if}
|
|
29
|
+
</div>
|
|
30
|
+
|
|
31
|
+
<style>
|
|
32
|
+
.lite-presence-container {
|
|
33
|
+
display: inline-flex;
|
|
34
|
+
align-items: center;
|
|
35
|
+
font-size: 12px;
|
|
36
|
+
margin-bottom: 8px;
|
|
37
|
+
}
|
|
38
|
+
.lite-presence-label {
|
|
39
|
+
color: #64748b;
|
|
40
|
+
margin-right: 6px;
|
|
41
|
+
font-weight: 500;
|
|
42
|
+
}
|
|
43
|
+
.lite-presence-badge {
|
|
44
|
+
display: inline-block;
|
|
45
|
+
padding: 2px 6px;
|
|
46
|
+
background: #f1f5f9;
|
|
47
|
+
border: 1px solid #cbd5e1;
|
|
48
|
+
border-radius: 4px;
|
|
49
|
+
margin-right: 4px;
|
|
50
|
+
font-size: 11px;
|
|
51
|
+
}
|
|
52
|
+
</style>
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
interface LitePresenceUser {
|
|
2
|
+
id: string;
|
|
3
|
+
name: string;
|
|
4
|
+
status?: 'online' | 'idle' | 'editing';
|
|
5
|
+
}
|
|
6
|
+
interface Props {
|
|
7
|
+
users?: LitePresenceUser[];
|
|
8
|
+
label?: string;
|
|
9
|
+
}
|
|
10
|
+
declare const LitePresenceAvatarGroup: import("svelte").Component<Props, {}, "">;
|
|
11
|
+
type LitePresenceAvatarGroup = ReturnType<typeof LitePresenceAvatarGroup>;
|
|
12
|
+
export default LitePresenceAvatarGroup;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface LiteBillItem {
|
|
3
|
+
name: string;
|
|
4
|
+
spec?: string;
|
|
5
|
+
quantity: number;
|
|
6
|
+
unitPrice: number;
|
|
7
|
+
total?: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
interface Props {
|
|
11
|
+
title?: string;
|
|
12
|
+
billNumber: string;
|
|
13
|
+
date: string;
|
|
14
|
+
companyName?: string;
|
|
15
|
+
customerName: string;
|
|
16
|
+
items?: LiteBillItem[];
|
|
17
|
+
notes?: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
let {
|
|
21
|
+
title = 'INVOICE / RECEIPT',
|
|
22
|
+
billNumber,
|
|
23
|
+
date,
|
|
24
|
+
companyName = 'Enterprise Admin',
|
|
25
|
+
customerName,
|
|
26
|
+
items = [],
|
|
27
|
+
notes,
|
|
28
|
+
}: Props = $props();
|
|
29
|
+
|
|
30
|
+
const total = $derived(
|
|
31
|
+
items.reduce((acc, item) => acc + (item.total ?? item.quantity * item.unitPrice), 0)
|
|
32
|
+
);
|
|
33
|
+
</script>
|
|
34
|
+
|
|
35
|
+
<div class="lite-bill-card">
|
|
36
|
+
<div class="lite-bill-header">
|
|
37
|
+
<div style="float: left;">
|
|
38
|
+
<h3 style="margin: 0;">{title}</h3>
|
|
39
|
+
<span style="color: #64748b; font-size: 11px;">No: {billNumber}</span>
|
|
40
|
+
</div>
|
|
41
|
+
<div style="float: right; text-align: right;">
|
|
42
|
+
<strong>{companyName}</strong>
|
|
43
|
+
<div style="color: #64748b; font-size: 11px;">Date: {date}</div>
|
|
44
|
+
</div>
|
|
45
|
+
<div style="clear: both;"></div>
|
|
46
|
+
</div>
|
|
47
|
+
|
|
48
|
+
<div class="lite-bill-customer">
|
|
49
|
+
<strong>Bill To:</strong> {customerName}
|
|
50
|
+
</div>
|
|
51
|
+
|
|
52
|
+
<table class="lite-table lite-bill-table">
|
|
53
|
+
<thead>
|
|
54
|
+
<tr>
|
|
55
|
+
<th style="width: 30px;">#</th>
|
|
56
|
+
<th>Item Description</th>
|
|
57
|
+
<th style="width: 50px; text-align: center;">Qty</th>
|
|
58
|
+
<th style="width: 80px; text-align: right;">Price</th>
|
|
59
|
+
<th style="width: 90px; text-align: right;">Total</th>
|
|
60
|
+
</tr>
|
|
61
|
+
</thead>
|
|
62
|
+
<tbody>
|
|
63
|
+
{#each items as item, index (index)}
|
|
64
|
+
{@const rowTotal = item.total ?? item.quantity * item.unitPrice}
|
|
65
|
+
<tr>
|
|
66
|
+
<td style="text-align: center;">{index + 1}</td>
|
|
67
|
+
<td>{item.name} {#if item.spec}({item.spec}){/if}</td>
|
|
68
|
+
<td style="text-align: center;">{item.quantity}</td>
|
|
69
|
+
<td style="text-align: right;">¥{item.unitPrice.toFixed(2)}</td>
|
|
70
|
+
<td style="text-align: right; font-weight: bold;">¥{rowTotal.toFixed(2)}</td>
|
|
71
|
+
</tr>
|
|
72
|
+
{/each}
|
|
73
|
+
</tbody>
|
|
74
|
+
<tfoot>
|
|
75
|
+
<tr>
|
|
76
|
+
<td colspan="4" style="text-align: right; font-weight: bold;">Grand Total:</td>
|
|
77
|
+
<td style="text-align: right; font-weight: bold; color: #2563eb;">¥{total.toFixed(2)}</td>
|
|
78
|
+
</tr>
|
|
79
|
+
</tfoot>
|
|
80
|
+
</table>
|
|
81
|
+
|
|
82
|
+
{#if notes}
|
|
83
|
+
<div class="lite-bill-notes">
|
|
84
|
+
<strong>Notes:</strong> {notes}
|
|
85
|
+
</div>
|
|
86
|
+
{/if}
|
|
87
|
+
</div>
|
|
88
|
+
|
|
89
|
+
<style>
|
|
90
|
+
.lite-bill-card {
|
|
91
|
+
background: #ffffff;
|
|
92
|
+
border: 1px solid #cbd5e1;
|
|
93
|
+
border-radius: 6px;
|
|
94
|
+
padding: 20px;
|
|
95
|
+
margin-bottom: 16px;
|
|
96
|
+
}
|
|
97
|
+
.lite-bill-header {
|
|
98
|
+
border-bottom: 2px solid #3b82f6;
|
|
99
|
+
padding-bottom: 12px;
|
|
100
|
+
margin-bottom: 12px;
|
|
101
|
+
}
|
|
102
|
+
.lite-bill-customer {
|
|
103
|
+
background: #f8fafc;
|
|
104
|
+
padding: 8px 12px;
|
|
105
|
+
border-radius: 4px;
|
|
106
|
+
margin-bottom: 16px;
|
|
107
|
+
font-size: 13px;
|
|
108
|
+
}
|
|
109
|
+
.lite-bill-table {
|
|
110
|
+
width: 100%;
|
|
111
|
+
margin-bottom: 12px;
|
|
112
|
+
}
|
|
113
|
+
.lite-bill-notes {
|
|
114
|
+
font-size: 12px;
|
|
115
|
+
color: #64748b;
|
|
116
|
+
border-top: 1px solid #e2e8f0;
|
|
117
|
+
padding-top: 8px;
|
|
118
|
+
}
|
|
119
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface LiteBillItem {
|
|
2
|
+
name: string;
|
|
3
|
+
spec?: string;
|
|
4
|
+
quantity: number;
|
|
5
|
+
unitPrice: number;
|
|
6
|
+
total?: number;
|
|
7
|
+
}
|
|
8
|
+
interface Props {
|
|
9
|
+
title?: string;
|
|
10
|
+
billNumber: string;
|
|
11
|
+
date: string;
|
|
12
|
+
companyName?: string;
|
|
13
|
+
customerName: string;
|
|
14
|
+
items?: LiteBillItem[];
|
|
15
|
+
notes?: string;
|
|
16
|
+
}
|
|
17
|
+
declare const LitePrintableBill: import("svelte").Component<Props, {}, "">;
|
|
18
|
+
type LitePrintableBill = ReturnType<typeof LitePrintableBill>;
|
|
19
|
+
export default LitePrintableBill;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
value?: string | number | null;
|
|
4
|
+
type?: 'phone' | 'id-card' | 'email' | 'bank-card' | 'secret' | 'custom';
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
let {
|
|
8
|
+
value = '',
|
|
9
|
+
type = 'phone',
|
|
10
|
+
}: Props = $props();
|
|
11
|
+
|
|
12
|
+
const rawString = $derived(String(value ?? ''));
|
|
13
|
+
|
|
14
|
+
function mask(val: string, maskType: string): string {
|
|
15
|
+
if (!val) return '—';
|
|
16
|
+
switch (maskType) {
|
|
17
|
+
case 'phone':
|
|
18
|
+
return val.length >= 7 ? `${val.slice(0, 3)}****${val.slice(-4)}` : '****';
|
|
19
|
+
case 'id-card':
|
|
20
|
+
return val.length >= 10 ? `${val.slice(0, 6)}********${val.slice(-4)}` : '********';
|
|
21
|
+
case 'email': {
|
|
22
|
+
const parts = val.split('@');
|
|
23
|
+
return parts.length === 2 ? `${parts[0].slice(0, 1)}***@${parts[1]}` : '***@***.***';
|
|
24
|
+
}
|
|
25
|
+
default:
|
|
26
|
+
return '••••••••';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const masked = $derived(mask(rawString, type));
|
|
31
|
+
</script>
|
|
32
|
+
|
|
33
|
+
<span class="lite-sensitive-mask" style="font-family: monospace; font-size: 12px;">
|
|
34
|
+
{masked}
|
|
35
|
+
</span>
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
value?: string | number | null;
|
|
3
|
+
type?: 'phone' | 'id-card' | 'email' | 'bank-card' | 'secret' | 'custom';
|
|
4
|
+
}
|
|
5
|
+
declare const LiteSensitiveDataMask: import("svelte").Component<Props, {}, "">;
|
|
6
|
+
type LiteSensitiveDataMask = ReturnType<typeof LiteSensitiveDataMask>;
|
|
7
|
+
export default LiteSensitiveDataMask;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface Props {
|
|
3
|
+
name?: string;
|
|
4
|
+
value?: string;
|
|
5
|
+
label?: string;
|
|
6
|
+
formAction?: string;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
class?: string;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let {
|
|
12
|
+
name = 'signature',
|
|
13
|
+
value = '',
|
|
14
|
+
label = 'Electronic Signature',
|
|
15
|
+
formAction = '',
|
|
16
|
+
disabled = false,
|
|
17
|
+
class: className = '',
|
|
18
|
+
}: Props = $props();
|
|
19
|
+
</script>
|
|
20
|
+
|
|
21
|
+
<div class="sv-lite-signature-card {className}">
|
|
22
|
+
<div class="sv-lite-sig-header">
|
|
23
|
+
<strong>{label}</strong>
|
|
24
|
+
<span class="sv-lite-sig-sub">(Upload or review signed receipt)</span>
|
|
25
|
+
</div>
|
|
26
|
+
|
|
27
|
+
{#if value}
|
|
28
|
+
<div class="sv-lite-sig-preview">
|
|
29
|
+
<img src={value} alt="Signature Preview" class="sv-lite-sig-img" />
|
|
30
|
+
</div>
|
|
31
|
+
{:else}
|
|
32
|
+
<div class="sv-lite-sig-empty">
|
|
33
|
+
No signature registered
|
|
34
|
+
</div>
|
|
35
|
+
{/if}
|
|
36
|
+
|
|
37
|
+
<div class="sv-lite-sig-actions">
|
|
38
|
+
<form method="POST" action={formAction} enctype="multipart/form-data">
|
|
39
|
+
<input type="file" name={name} accept="image/*" {disabled} class="sv-lite-sig-file" />
|
|
40
|
+
<button type="submit" {disabled} class="sv-lite-sig-btn">Upload Signature</button>
|
|
41
|
+
</form>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
<style>
|
|
46
|
+
.sv-lite-signature-card {
|
|
47
|
+
display: block;
|
|
48
|
+
border: 1px solid #e2e8f0;
|
|
49
|
+
border-radius: 6px;
|
|
50
|
+
padding: 12px;
|
|
51
|
+
background-color: #ffffff;
|
|
52
|
+
font-size: 12px;
|
|
53
|
+
}
|
|
54
|
+
.sv-lite-sig-header {
|
|
55
|
+
margin-bottom: 8px;
|
|
56
|
+
font-size: 13px;
|
|
57
|
+
color: #0f172a;
|
|
58
|
+
}
|
|
59
|
+
.sv-lite-sig-sub {
|
|
60
|
+
color: #64748b;
|
|
61
|
+
font-size: 11px;
|
|
62
|
+
margin-left: 6px;
|
|
63
|
+
}
|
|
64
|
+
.sv-lite-sig-preview {
|
|
65
|
+
border: 2px dashed #cbd5e1;
|
|
66
|
+
border-radius: 4px;
|
|
67
|
+
padding: 10px;
|
|
68
|
+
text-align: center;
|
|
69
|
+
background-color: #f8fafc;
|
|
70
|
+
margin-bottom: 10px;
|
|
71
|
+
}
|
|
72
|
+
.sv-lite-sig-img {
|
|
73
|
+
max-height: 80px;
|
|
74
|
+
max-width: 100%;
|
|
75
|
+
vertical-align: middle;
|
|
76
|
+
}
|
|
77
|
+
.sv-lite-sig-empty {
|
|
78
|
+
border: 2px dashed #cbd5e1;
|
|
79
|
+
border-radius: 4px;
|
|
80
|
+
padding: 24px;
|
|
81
|
+
text-align: center;
|
|
82
|
+
color: #94a3b8;
|
|
83
|
+
background-color: #f8fafc;
|
|
84
|
+
margin-bottom: 10px;
|
|
85
|
+
}
|
|
86
|
+
.sv-lite-sig-file {
|
|
87
|
+
font-size: 11px;
|
|
88
|
+
margin-right: 8px;
|
|
89
|
+
}
|
|
90
|
+
.sv-lite-sig-btn {
|
|
91
|
+
padding: 4px 10px;
|
|
92
|
+
font-size: 11px;
|
|
93
|
+
background-color: #4f46e5;
|
|
94
|
+
color: #ffffff;
|
|
95
|
+
border: none;
|
|
96
|
+
border-radius: 3px;
|
|
97
|
+
cursor: pointer;
|
|
98
|
+
}
|
|
99
|
+
</style>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
interface Props {
|
|
2
|
+
name?: string;
|
|
3
|
+
value?: string;
|
|
4
|
+
label?: string;
|
|
5
|
+
formAction?: string;
|
|
6
|
+
disabled?: boolean;
|
|
7
|
+
class?: string;
|
|
8
|
+
}
|
|
9
|
+
declare const LiteSignaturePad: import("svelte").Component<Props, {}, "">;
|
|
10
|
+
type LiteSignaturePad = ReturnType<typeof LiteSignaturePad>;
|
|
11
|
+
export default LiteSignaturePad;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
direction?: 'horizontal' | 'vertical';
|
|
6
|
+
pane1?: Snippet;
|
|
7
|
+
pane2?: Snippet;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
let {
|
|
11
|
+
direction = 'horizontal',
|
|
12
|
+
pane1,
|
|
13
|
+
pane2,
|
|
14
|
+
}: Props = $props();
|
|
15
|
+
</script>
|
|
16
|
+
|
|
17
|
+
<div class="lite-split-layout lite-split-{direction}">
|
|
18
|
+
<div class="lite-split-pane-1">
|
|
19
|
+
{#if pane1}
|
|
20
|
+
{@render pane1()}
|
|
21
|
+
{/if}
|
|
22
|
+
</div>
|
|
23
|
+
|
|
24
|
+
<div class="lite-split-divider"></div>
|
|
25
|
+
|
|
26
|
+
<div class="lite-split-pane-2">
|
|
27
|
+
{#if pane2}
|
|
28
|
+
{@render pane2()}
|
|
29
|
+
{/if}
|
|
30
|
+
</div>
|
|
31
|
+
</div>
|
|
32
|
+
|
|
33
|
+
<style>
|
|
34
|
+
.lite-split-layout {
|
|
35
|
+
display: flex;
|
|
36
|
+
background: #ffffff;
|
|
37
|
+
border: 1px solid #cbd5e1;
|
|
38
|
+
border-radius: 6px;
|
|
39
|
+
margin-bottom: 16px;
|
|
40
|
+
min-height: 300px;
|
|
41
|
+
}
|
|
42
|
+
.lite-split-horizontal {
|
|
43
|
+
flex-direction: row;
|
|
44
|
+
}
|
|
45
|
+
.lite-split-vertical {
|
|
46
|
+
flex-direction: column;
|
|
47
|
+
}
|
|
48
|
+
.lite-split-pane-1 {
|
|
49
|
+
flex: 0 0 35%;
|
|
50
|
+
padding: 12px;
|
|
51
|
+
overflow-y: auto;
|
|
52
|
+
}
|
|
53
|
+
.lite-split-pane-2 {
|
|
54
|
+
flex: 1 1 auto;
|
|
55
|
+
padding: 12px;
|
|
56
|
+
overflow-y: auto;
|
|
57
|
+
}
|
|
58
|
+
.lite-split-divider {
|
|
59
|
+
background: #e2e8f0;
|
|
60
|
+
width: 2px;
|
|
61
|
+
}
|
|
62
|
+
.lite-split-vertical .lite-split-divider {
|
|
63
|
+
width: 100%;
|
|
64
|
+
height: 2px;
|
|
65
|
+
}
|
|
66
|
+
</style>
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
interface Props {
|
|
3
|
+
direction?: 'horizontal' | 'vertical';
|
|
4
|
+
pane1?: Snippet;
|
|
5
|
+
pane2?: Snippet;
|
|
6
|
+
}
|
|
7
|
+
declare const LiteSplitPaneLayout: import("svelte").Component<Props, {}, "">;
|
|
8
|
+
type LiteSplitPaneLayout = ReturnType<typeof LiteSplitPaneLayout>;
|
|
9
|
+
export default LiteSplitPaneLayout;
|