@svadmin/lite 0.6.0 → 0.8.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/README.md +85 -9
- 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/LiteDynamicFormList.svelte +169 -0
- package/dist/components/LiteDynamicFormList.svelte.d.ts +45 -0
- package/dist/components/LiteEditableTable.svelte +84 -0
- package/dist/components/LiteEditableTable.svelte.d.ts +19 -0
- package/dist/components/LiteFilterBuilder.svelte +205 -0
- package/dist/components/LiteFilterBuilder.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/LiteShowField.svelte +22 -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/LiteTransfer.svelte +185 -0
- package/dist/components/LiteTransfer.svelte.d.ts +18 -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/components/fields/LiteAvatarField.svelte +127 -0
- package/dist/components/fields/LiteAvatarField.svelte.d.ts +21 -0
- package/dist/components/fields/LiteCascader.svelte +119 -0
- package/dist/components/fields/LiteCascader.svelte.d.ts +24 -0
- package/dist/components/fields/LiteCodeField.svelte +71 -0
- package/dist/components/fields/LiteCodeField.svelte.d.ts +16 -0
- package/dist/components/fields/LiteCopyField.svelte +74 -0
- package/dist/components/fields/LiteCopyField.svelte.d.ts +18 -0
- package/dist/components/fields/LiteCurrencyField.svelte +126 -0
- package/dist/components/fields/LiteCurrencyField.svelte.d.ts +21 -0
- package/dist/components/fields/LiteDateRangeField.svelte +147 -0
- package/dist/components/fields/LiteDateRangeField.svelte.d.ts +26 -0
- package/dist/components/fields/LitePercentField.svelte +124 -0
- package/dist/components/fields/LitePercentField.svelte.d.ts +17 -0
- package/dist/components/fields/LitePhoneField.svelte +81 -0
- package/dist/components/fields/LitePhoneField.svelte.d.ts +17 -0
- package/dist/components/fields/LiteRatingField.svelte +105 -0
- package/dist/components/fields/LiteRatingField.svelte.d.ts +16 -0
- package/dist/components/fields/LiteTreeSelect.svelte +143 -0
- package/dist/components/fields/LiteTreeSelect.svelte.d.ts +23 -0
- package/dist/components/fields/index.d.ts +12 -0
- package/dist/components/fields/index.js +10 -0
- package/dist/components/pages/LiteListPage.svelte +14 -12
- package/dist/index.d.ts +40 -0
- package/dist/index.js +37 -0
- package/dist/lite.css +205 -0
- package/dist/schema-generator.js +15 -4
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -10,6 +10,12 @@ The bundled CSS follows an IE11-oriented baseline, but Svelte 5, SvelteKit, Tail
|
|
|
10
10
|
|
|
11
11
|
The main `@svadmin/ui` package delivers a premium SPA experience using Svelte 5, Tailwind CSS v4, and TanStack. Those tools target modern browsers. Some enterprise/government environments instead prefer server-driven navigation, native forms, and a smaller client-side runtime.
|
|
12
12
|
|
|
13
|
+
**What Lite is:**
|
|
14
|
+
- A **Zero-JS SSR-first admin component suite** designed with an IE11-safe CSS baseline.
|
|
15
|
+
- 100% interoperable with `@svadmin/core` — sharing the same `DataProvider`, `AuthProvider`, `Resource`, and `FieldDefinition` contracts.
|
|
16
|
+
- An architectural companion to `@svadmin/ui` achieving **100% component parity (72/72 components)** through 1:1 server-rendered matches or deliberate semantic fallbacks.
|
|
17
|
+
- **Not** a generic Tailwind-to-IE11 compiler or a full client-side port of shadcn-svelte (which depends on modern browser JS runtimes and CSS custom properties).
|
|
18
|
+
|
|
13
19
|
`@svadmin/lite` provides a server-rendered fallback that **shares the same DataProvider, AuthProvider, and Resource definitions** — only the rendering layer is different.
|
|
14
20
|
|
|
15
21
|
## Features
|
|
@@ -29,6 +35,7 @@ The main `@svadmin/ui` package delivers a premium SPA experience using Svelte 5,
|
|
|
29
35
|
| **Capability fallbacks** | Canvas, WASM, realtime, directory upload, observers, storage, media, and other browser-only features have server-safe alternatives |
|
|
30
36
|
| **i18n** | Uses `@svadmin/core` `t()` translations |
|
|
31
37
|
| **Multi-level Menu** | Always-expanded, config-driven nested links via `MenuItem[]` |
|
|
38
|
+
| **Parity Tracking** | Built-in CLI matrix, CI parity verification gate, and live interactive visual showroom |
|
|
32
39
|
| **Print** | `@media print` optimized styles |
|
|
33
40
|
|
|
34
41
|
## Quick Start
|
|
@@ -44,6 +51,20 @@ are required peers rather than optional dependencies.
|
|
|
44
51
|
|
|
45
52
|
### 2. Create a list page
|
|
46
53
|
|
|
54
|
+
For an existing SvelteKit project, the route tree can be generated once instead
|
|
55
|
+
of being handwritten for every resource:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
bunx @svadmin/create lite init .
|
|
59
|
+
bunx @svadmin/create lite init . --write
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
The generator adds a shared `$lib/svadmin-lite.ts` adapter and dynamic
|
|
63
|
+
`[resource]` list/create/show/edit routes. `$lib/admin` only needs to export
|
|
64
|
+
`resources` and `dataProvider`; the existing SPA files are not changed. The
|
|
65
|
+
generated Lite subtree is `ssr = true` and `csr = false`, and existing files are
|
|
66
|
+
preserved on repeat runs.
|
|
67
|
+
|
|
47
68
|
```typescript
|
|
48
69
|
// src/routes/lite/posts/+page.server.ts
|
|
49
70
|
import { createListLoader, createCrudActions } from '@svadmin/lite';
|
|
@@ -223,18 +244,56 @@ If the application is behind a reverse proxy, the same rule can be implemented
|
|
|
223
244
|
there instead. The important property is that the SPA JavaScript is not sent to
|
|
224
245
|
IE11 before the decision is made.
|
|
225
246
|
|
|
226
|
-
## Components
|
|
247
|
+
## Components & Parity (100% Coverage)
|
|
248
|
+
|
|
249
|
+
`@svadmin/lite` provides **100% component parity** (72/72 components) corresponding to `@svadmin/ui`. See [PARITY.md](./PARITY.md) for the complete matrix.
|
|
250
|
+
|
|
251
|
+
### Core Pages & Layout
|
|
252
|
+
|
|
253
|
+
| Component | Description |
|
|
254
|
+
|-----------|-------------|
|
|
255
|
+
| `LiteLayout` | Responsive sidebar + header + main shell (supports nested `menu` links) |
|
|
256
|
+
| `LiteSidebar` / `LiteHeader` | Discrete layout primitives |
|
|
257
|
+
| `LiteListPage` | Full-featured list view with search, table, bulk actions, and pagination |
|
|
258
|
+
| `LiteCreatePage` / `LiteEditPage` | Auto-generated CRUD form pages |
|
|
259
|
+
| `LiteShowPage` | Key-value record view with typed field renderers |
|
|
260
|
+
| `LiteProfilePage` | User profile management page with avatar and info |
|
|
261
|
+
| `LiteRegisterPage` | User registration page with server-side validation |
|
|
262
|
+
| `LiteForgotPasswordPage` / `LiteUpdatePasswordPage` | Password recovery and credential rotation flows |
|
|
263
|
+
| `LiteTable` | HTML table with sort links, selectable rows, and delete confirmation |
|
|
264
|
+
| `LiteForm` | Schema-driven form renderer supporting all field definitions |
|
|
265
|
+
| `LiteShow` | Detailed field-by-field record viewer |
|
|
266
|
+
| `LitePagination` / `LiteSearch` | URL-driven pagination and GET search controls |
|
|
267
|
+
| `LiteAlert` | Inline notification banner for success/error/warning states |
|
|
268
|
+
| `LiteBreadcrumbs` / `LiteTabs` / `LiteEmptyState` | Semantic navigation and placeholder primitives |
|
|
269
|
+
|
|
270
|
+
### Field Components (23 Fields)
|
|
271
|
+
|
|
272
|
+
| Category | Components |
|
|
273
|
+
|----------|------------|
|
|
274
|
+
| **Text & Numeric** | `LiteTextField`, `LiteNumberField`, `LiteCurrencyField`, `LitePercentField`, `LitePhoneField`, `LiteEmailField`, `LiteUrlField`, `LiteRatingField`, `LiteCopyField` |
|
|
275
|
+
| **Date & Choice** | `LiteDateField`, `LiteDateRangeField`, `LiteBooleanField`, `LiteSelectField`, `LiteMultiSelectField`, `LiteTreeSelect`, `LiteCascader`, `LiteTagField`, `LiteRelationField` |
|
|
276
|
+
| **Media & Rich & Array** | `LiteAvatarField`, `LiteImageField`, `LiteFileField`, `LiteCodeField`, `LiteMarkdownField`, `LiteRichTextField`, `LiteJsonField`, `LiteArrayField`, `LiteDynamicFormList`, `LiteTransfer` |
|
|
277
|
+
|
|
278
|
+
### Action Buttons (10 Buttons)
|
|
279
|
+
|
|
280
|
+
| Component | Description |
|
|
281
|
+
|-----------|-------------|
|
|
282
|
+
| `LiteListButton`, `LiteCreateButton`, `LiteEditButton`, `LiteShowButton`, `LiteCloneButton` | Server-rendered `<a>` navigation buttons |
|
|
283
|
+
| `LiteDeleteButton` | Fragment-target modal confirmation with native POST form action |
|
|
284
|
+
| `LiteSaveButton`, `LiteRefreshButton`, `LiteExportButton`, `LiteImportButton` | Form submission, page refresh, and file action buttons |
|
|
285
|
+
|
|
286
|
+
### Widgets & Charts (SSR-Safe)
|
|
287
|
+
|
|
288
|
+
| Component | Description |
|
|
289
|
+
|-----------|-------------|
|
|
290
|
+
| `LiteStatsCard`, `LiteInsightCard`, `LiteAnomalyBadge` | Metric KPI cards and status badges |
|
|
291
|
+
| `LiteBarChart`, `LiteLineChart`, `LitePieChart` | Server-rendered SVG/HTML charts with fallback data tables |
|
|
292
|
+
|
|
293
|
+
### Compatibility & Degradation Primitives
|
|
227
294
|
|
|
228
295
|
| Component | Description |
|
|
229
296
|
|-----------|-------------|
|
|
230
|
-
| `LiteLayout` | Sidebar + main area layout (supports `menu` prop for multi-level menus) |
|
|
231
|
-
| `LiteTable` | HTML table with sort links and delete confirmation |
|
|
232
|
-
| `LiteSearch` | GET-based search form |
|
|
233
|
-
| `LitePagination` | Page number links |
|
|
234
|
-
| `LiteForm` | Auto-generated form from `FieldDefinition[]` |
|
|
235
|
-
| `LiteShow` | Record detail/view page |
|
|
236
|
-
| `LiteLogin` | Login form |
|
|
237
|
-
| `LiteAlert` | Success/error notification banner |
|
|
238
297
|
| `LiteCapabilityBoundary` | Documents and selects a server-safe fallback for an optional browser capability |
|
|
239
298
|
| `LiteVisualFallback` | Snapshot plus accessible table for Canvas, WebGL, map, chart, and flow UIs |
|
|
240
299
|
| `LiteDirectoryUpload` | Directory enhancement with multiple-file and ZIP upload fallbacks |
|
|
@@ -242,6 +301,23 @@ IE11 before the decision is made.
|
|
|
242
301
|
| `LiteComputeFallback` | Native POST action for WASM, Worker, and long-running compute fallback |
|
|
243
302
|
| `LiteOrderedList` | Up/down POST actions for drag-and-drop ordering fallback |
|
|
244
303
|
| `LiteClipboardFallback` | Selectable textarea when Clipboard API is unavailable |
|
|
304
|
+
| `LiteAutoSaveIndicator` | Server persistence timestamp indicator |
|
|
305
|
+
| `LiteInlineEdit` | Non-JS inline edit modal fallback |
|
|
306
|
+
| `LiteModalForm` / `LiteDrawerForm` | Fragment-target `#modal` forms for zero-JS popups |
|
|
307
|
+
| `LiteVirtualTable` | Graceful fallback to server-paginated table |
|
|
308
|
+
| `LiteDraggableHeader` | Static column header with URL sorter links |
|
|
309
|
+
| `LiteToast` / `LiteUndoableNotification` | Server-driven flash messages and undo actions |
|
|
310
|
+
| `LiteFilterBuilder` | Native multi-rule CRUD filter builder with AND/OR logical operators |
|
|
311
|
+
|
|
312
|
+
## Parity Tracking & Visualization
|
|
313
|
+
|
|
314
|
+
To monitor and maintain 100% component parity between `@svadmin/ui` and `@svadmin/lite`:
|
|
315
|
+
|
|
316
|
+
- **CLI Dashboard**: Run `bun run check:parity` to inspect the live coverage matrix in terminal.
|
|
317
|
+
- **Parity Matrix Document**: [PARITY.md](./PARITY.md) is auto-generated with exhaustive module-by-module tables.
|
|
318
|
+
- **Machine-Readable JSON**: `packages/lite/parity.json` provides structured data for automation.
|
|
319
|
+
- **Interactive Showroom**: Visit `/lite/parity` in the example app to interactively preview all 72 components and live metrics.
|
|
320
|
+
- **CI Contract Test**: `scripts/parity-contract.test.ts` runs in CI to prevent regression and ensure every new UI component has a documented Lite counterpart.
|
|
245
321
|
|
|
246
322
|
## Server Utilities
|
|
247
323
|
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
interface LiteActivityItem {
|
|
3
|
+
id: string;
|
|
4
|
+
user?: { name: string };
|
|
5
|
+
action: string;
|
|
6
|
+
target?: string;
|
|
7
|
+
timestamp: string;
|
|
8
|
+
comment?: string;
|
|
9
|
+
status?: 'info' | 'success' | 'warning' | 'destructive';
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
interface Props {
|
|
13
|
+
activities?: LiteActivityItem[];
|
|
14
|
+
action?: string;
|
|
15
|
+
method?: 'get' | 'post' | 'dialog' | 'GET' | 'POST' | 'DIALOG' | null;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
let {
|
|
19
|
+
activities = [],
|
|
20
|
+
action = '',
|
|
21
|
+
method = 'POST',
|
|
22
|
+
}: Props = $props();
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<div class="lite-activity-card">
|
|
26
|
+
<div class="lite-activity-header">
|
|
27
|
+
<strong>Activity & Timeline Stream</strong>
|
|
28
|
+
</div>
|
|
29
|
+
|
|
30
|
+
<ul class="lite-activity-list">
|
|
31
|
+
{#each activities as act (act.id)}
|
|
32
|
+
<li class="lite-activity-item">
|
|
33
|
+
<div class="lite-activity-title">
|
|
34
|
+
<strong>{act.user?.name ?? 'System'}</strong> {act.action}
|
|
35
|
+
{#if act.target}<strong>{act.target}</strong>{/if}
|
|
36
|
+
<span class="lite-activity-time">{act.timestamp}</span>
|
|
37
|
+
</div>
|
|
38
|
+
{#if act.comment}
|
|
39
|
+
<div class="lite-activity-comment">
|
|
40
|
+
{act.comment}
|
|
41
|
+
</div>
|
|
42
|
+
{/if}
|
|
43
|
+
</li>
|
|
44
|
+
{/each}
|
|
45
|
+
</ul>
|
|
46
|
+
|
|
47
|
+
<!-- Comment Form -->
|
|
48
|
+
<form {action} {method} class="lite-activity-form">
|
|
49
|
+
<div style="margin-bottom: 8px;">
|
|
50
|
+
<label for="lite_act_comment" class="lite-label">Add Note / Comment:</label>
|
|
51
|
+
<textarea id="lite_act_comment" name="comment" class="lite-textarea" style="height: 50px;" placeholder="Write a comment..."></textarea>
|
|
52
|
+
</div>
|
|
53
|
+
<div style="text-align: right;">
|
|
54
|
+
<button type="submit" class="lite-btn lite-btn-primary lite-btn-sm">
|
|
55
|
+
Post Comment
|
|
56
|
+
</button>
|
|
57
|
+
</div>
|
|
58
|
+
</form>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<style>
|
|
62
|
+
.lite-activity-card {
|
|
63
|
+
background: #ffffff;
|
|
64
|
+
border: 1px solid #cbd5e1;
|
|
65
|
+
border-radius: 6px;
|
|
66
|
+
padding: 16px;
|
|
67
|
+
margin-bottom: 16px;
|
|
68
|
+
}
|
|
69
|
+
.lite-activity-header {
|
|
70
|
+
padding-bottom: 8px;
|
|
71
|
+
border-bottom: 1px solid #e2e8f0;
|
|
72
|
+
margin-bottom: 12px;
|
|
73
|
+
font-size: 13px;
|
|
74
|
+
}
|
|
75
|
+
.lite-activity-list {
|
|
76
|
+
list-style: none;
|
|
77
|
+
padding: 0;
|
|
78
|
+
margin: 0 0 16px 0;
|
|
79
|
+
}
|
|
80
|
+
.lite-activity-item {
|
|
81
|
+
padding: 8px 0;
|
|
82
|
+
border-bottom: 1px solid #f1f5f9;
|
|
83
|
+
font-size: 12px;
|
|
84
|
+
}
|
|
85
|
+
.lite-activity-time {
|
|
86
|
+
color: #94a3b8;
|
|
87
|
+
margin-left: 8px;
|
|
88
|
+
font-size: 11px;
|
|
89
|
+
}
|
|
90
|
+
.lite-activity-comment {
|
|
91
|
+
background: #f8fafc;
|
|
92
|
+
border: 1px solid #e2e8f0;
|
|
93
|
+
padding: 6px 10px;
|
|
94
|
+
border-radius: 4px;
|
|
95
|
+
margin-top: 4px;
|
|
96
|
+
color: #475569;
|
|
97
|
+
}
|
|
98
|
+
</style>
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
interface LiteActivityItem {
|
|
2
|
+
id: string;
|
|
3
|
+
user?: {
|
|
4
|
+
name: string;
|
|
5
|
+
};
|
|
6
|
+
action: string;
|
|
7
|
+
target?: string;
|
|
8
|
+
timestamp: string;
|
|
9
|
+
comment?: string;
|
|
10
|
+
status?: 'info' | 'success' | 'warning' | 'destructive';
|
|
11
|
+
}
|
|
12
|
+
interface Props {
|
|
13
|
+
activities?: LiteActivityItem[];
|
|
14
|
+
action?: string;
|
|
15
|
+
method?: 'get' | 'post' | 'dialog' | 'GET' | 'POST' | 'DIALOG' | null;
|
|
16
|
+
}
|
|
17
|
+
declare const LiteActivityFeed: import("svelte").Component<Props, {}, "">;
|
|
18
|
+
type LiteActivityFeed = ReturnType<typeof LiteActivityFeed>;
|
|
19
|
+
export default LiteActivityFeed;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { Snippet } from 'svelte';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
title?: string;
|
|
6
|
+
status?: 'pending' | 'approved' | 'rejected' | 'recalled';
|
|
7
|
+
action?: string;
|
|
8
|
+
children?: Snippet;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
let {
|
|
12
|
+
title = 'Approval Request',
|
|
13
|
+
status = 'pending',
|
|
14
|
+
action = '',
|
|
15
|
+
children,
|
|
16
|
+
}: Props = $props();
|
|
17
|
+
</script>
|
|
18
|
+
|
|
19
|
+
<div class="lite-approval-card lite-form-group">
|
|
20
|
+
<div class="lite-approval-header">
|
|
21
|
+
<strong>{title}</strong>
|
|
22
|
+
<span class="lite-badge lite-badge-{status}">{status.toUpperCase()}</span>
|
|
23
|
+
</div>
|
|
24
|
+
|
|
25
|
+
{#if children}
|
|
26
|
+
<div class="lite-approval-body">
|
|
27
|
+
{@render children()}
|
|
28
|
+
</div>
|
|
29
|
+
{/if}
|
|
30
|
+
|
|
31
|
+
{#if status === 'pending'}
|
|
32
|
+
<form {action} method="POST" class="lite-approval-form">
|
|
33
|
+
<div class="lite-approval-field">
|
|
34
|
+
<label for="approval_comment" class="lite-label">Approval / Rejection Comment:</label>
|
|
35
|
+
<textarea id="approval_comment" name="comment" class="lite-textarea" style="height: 60px;" placeholder="Optional comment or rejection reason..."></textarea>
|
|
36
|
+
</div>
|
|
37
|
+
<div class="lite-approval-actions">
|
|
38
|
+
<button type="submit" name="_action" value="approve" class="lite-btn lite-btn-sm lite-btn-success">
|
|
39
|
+
✔ Approve
|
|
40
|
+
</button>
|
|
41
|
+
<button type="submit" name="_action" value="reject" class="lite-btn lite-btn-sm lite-btn-danger" style="margin-left: 8px;">
|
|
42
|
+
✕ Reject
|
|
43
|
+
</button>
|
|
44
|
+
</div>
|
|
45
|
+
</form>
|
|
46
|
+
{/if}
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<style>
|
|
50
|
+
.lite-approval-card {
|
|
51
|
+
padding: 12px;
|
|
52
|
+
background: #f8fafc;
|
|
53
|
+
border: 1px solid #cbd5e1;
|
|
54
|
+
border-radius: 6px;
|
|
55
|
+
margin-bottom: 16px;
|
|
56
|
+
}
|
|
57
|
+
.lite-approval-header {
|
|
58
|
+
display: flex;
|
|
59
|
+
justify-content: space-between;
|
|
60
|
+
align-items: center;
|
|
61
|
+
margin-bottom: 8px;
|
|
62
|
+
font-size: 13px;
|
|
63
|
+
}
|
|
64
|
+
.lite-approval-body {
|
|
65
|
+
font-size: 12px;
|
|
66
|
+
color: #475569;
|
|
67
|
+
margin-bottom: 12px;
|
|
68
|
+
}
|
|
69
|
+
.lite-approval-field {
|
|
70
|
+
margin-bottom: 8px;
|
|
71
|
+
}
|
|
72
|
+
.lite-approval-actions {
|
|
73
|
+
display: flex;
|
|
74
|
+
}
|
|
75
|
+
</style>
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Snippet } from 'svelte';
|
|
2
|
+
interface Props {
|
|
3
|
+
title?: string;
|
|
4
|
+
status?: 'pending' | 'approved' | 'rejected' | 'recalled';
|
|
5
|
+
action?: string;
|
|
6
|
+
children?: Snippet;
|
|
7
|
+
}
|
|
8
|
+
declare const LiteApprovalActionCard: import("svelte").Component<Props, {}, "">;
|
|
9
|
+
type LiteApprovalActionCard = ReturnType<typeof LiteApprovalActionCard>;
|
|
10
|
+
export default LiteApprovalActionCard;
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export interface AnnotationItem {
|
|
3
|
+
id: string;
|
|
4
|
+
type: string;
|
|
5
|
+
text?: string;
|
|
6
|
+
color?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
interface Props {
|
|
10
|
+
imageUrl?: string;
|
|
11
|
+
annotations?: AnnotationItem[];
|
|
12
|
+
title?: string;
|
|
13
|
+
formAction?: string;
|
|
14
|
+
class?: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
let {
|
|
18
|
+
imageUrl = '',
|
|
19
|
+
annotations = [],
|
|
20
|
+
title = 'Image Annotation & Markings',
|
|
21
|
+
formAction = '',
|
|
22
|
+
class: className = '',
|
|
23
|
+
}: Props = $props();
|
|
24
|
+
</script>
|
|
25
|
+
|
|
26
|
+
<div class="sv-lite-annotation-box {className}">
|
|
27
|
+
<div class="sv-lite-anno-header">
|
|
28
|
+
<strong>{title}</strong>
|
|
29
|
+
<span class="sv-lite-anno-count">({annotations.length} markers)</span>
|
|
30
|
+
</div>
|
|
31
|
+
|
|
32
|
+
{#if imageUrl}
|
|
33
|
+
<div class="sv-lite-anno-preview">
|
|
34
|
+
<img src={imageUrl} alt="Annotation Target" class="sv-lite-anno-img" />
|
|
35
|
+
</div>
|
|
36
|
+
{/if}
|
|
37
|
+
|
|
38
|
+
{#if annotations.length > 0}
|
|
39
|
+
<div class="sv-lite-anno-list">
|
|
40
|
+
<div class="sv-lite-list-title">Annotations:</div>
|
|
41
|
+
{#each annotations as anno (anno.id)}
|
|
42
|
+
<div class="sv-lite-anno-item">
|
|
43
|
+
<span class="sv-lite-anno-badge">{anno.type}</span>
|
|
44
|
+
<span class="sv-lite-anno-text">{anno.text ?? 'Defect / Mark'}</span>
|
|
45
|
+
</div>
|
|
46
|
+
{/each}
|
|
47
|
+
</div>
|
|
48
|
+
{/if}
|
|
49
|
+
|
|
50
|
+
{#if formAction}
|
|
51
|
+
<div class="sv-lite-anno-upload">
|
|
52
|
+
<form method="POST" action={formAction} enctype="multipart/form-data">
|
|
53
|
+
<input type="file" name="annotatedImage" accept="image/*" class="sv-lite-file-input" />
|
|
54
|
+
<button type="submit" class="sv-lite-upload-btn">Upload Markup</button>
|
|
55
|
+
</form>
|
|
56
|
+
</div>
|
|
57
|
+
{/if}
|
|
58
|
+
</div>
|
|
59
|
+
|
|
60
|
+
<style>
|
|
61
|
+
.sv-lite-annotation-box {
|
|
62
|
+
display: block;
|
|
63
|
+
border: 1px solid #e2e8f0;
|
|
64
|
+
border-radius: 6px;
|
|
65
|
+
padding: 12px;
|
|
66
|
+
background-color: #ffffff;
|
|
67
|
+
font-size: 12px;
|
|
68
|
+
}
|
|
69
|
+
.sv-lite-anno-header {
|
|
70
|
+
margin-bottom: 10px;
|
|
71
|
+
font-size: 13px;
|
|
72
|
+
color: #0f172a;
|
|
73
|
+
}
|
|
74
|
+
.sv-lite-anno-count {
|
|
75
|
+
color: #64748b;
|
|
76
|
+
font-size: 11px;
|
|
77
|
+
margin-left: 6px;
|
|
78
|
+
}
|
|
79
|
+
.sv-lite-anno-preview {
|
|
80
|
+
text-align: center;
|
|
81
|
+
background-color: #f8fafc;
|
|
82
|
+
border: 1px solid #cbd5e1;
|
|
83
|
+
border-radius: 4px;
|
|
84
|
+
padding: 8px;
|
|
85
|
+
margin-bottom: 10px;
|
|
86
|
+
}
|
|
87
|
+
.sv-lite-anno-img {
|
|
88
|
+
max-width: 100%;
|
|
89
|
+
max-height: 240px;
|
|
90
|
+
vertical-align: middle;
|
|
91
|
+
}
|
|
92
|
+
.sv-lite-anno-list {
|
|
93
|
+
margin-bottom: 10px;
|
|
94
|
+
padding: 8px;
|
|
95
|
+
background-color: #f8fafc;
|
|
96
|
+
border-radius: 4px;
|
|
97
|
+
}
|
|
98
|
+
.sv-lite-list-title {
|
|
99
|
+
font-weight: 600;
|
|
100
|
+
color: #475569;
|
|
101
|
+
margin-bottom: 6px;
|
|
102
|
+
}
|
|
103
|
+
.sv-lite-anno-item {
|
|
104
|
+
margin-bottom: 4px;
|
|
105
|
+
}
|
|
106
|
+
.sv-lite-anno-badge {
|
|
107
|
+
display: inline-block;
|
|
108
|
+
padding: 1px 5px;
|
|
109
|
+
background-color: #fee2e2;
|
|
110
|
+
color: #991b1b;
|
|
111
|
+
border-radius: 3px;
|
|
112
|
+
font-size: 10px;
|
|
113
|
+
text-transform: uppercase;
|
|
114
|
+
margin-right: 6px;
|
|
115
|
+
}
|
|
116
|
+
.sv-lite-anno-text {
|
|
117
|
+
color: #334155;
|
|
118
|
+
}
|
|
119
|
+
.sv-lite-anno-upload {
|
|
120
|
+
padding-top: 8px;
|
|
121
|
+
border-top: 1px solid #e2e8f0;
|
|
122
|
+
}
|
|
123
|
+
.sv-lite-file-input {
|
|
124
|
+
font-size: 11px;
|
|
125
|
+
margin-right: 8px;
|
|
126
|
+
}
|
|
127
|
+
.sv-lite-upload-btn {
|
|
128
|
+
padding: 4px 10px;
|
|
129
|
+
font-size: 11px;
|
|
130
|
+
background-color: #4f46e5;
|
|
131
|
+
color: #ffffff;
|
|
132
|
+
border: none;
|
|
133
|
+
border-radius: 3px;
|
|
134
|
+
cursor: pointer;
|
|
135
|
+
}
|
|
136
|
+
</style>
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface AnnotationItem {
|
|
2
|
+
id: string;
|
|
3
|
+
type: string;
|
|
4
|
+
text?: string;
|
|
5
|
+
color?: string;
|
|
6
|
+
}
|
|
7
|
+
interface Props {
|
|
8
|
+
imageUrl?: string;
|
|
9
|
+
annotations?: AnnotationItem[];
|
|
10
|
+
title?: string;
|
|
11
|
+
formAction?: string;
|
|
12
|
+
class?: string;
|
|
13
|
+
}
|
|
14
|
+
declare const LiteCanvasAnnotation: import("svelte").Component<Props, {}, "">;
|
|
15
|
+
type LiteCanvasAnnotation = ReturnType<typeof LiteCanvasAnnotation>;
|
|
16
|
+
export default LiteCanvasAnnotation;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
import type { FieldDefinition } from '@svadmin/core';
|
|
3
|
+
|
|
4
|
+
interface Props {
|
|
5
|
+
field: FieldDefinition;
|
|
6
|
+
action?: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
let {
|
|
10
|
+
field,
|
|
11
|
+
action = '',
|
|
12
|
+
}: Props = $props();
|
|
13
|
+
</script>
|
|
14
|
+
|
|
15
|
+
<span class="lite-column-header-filter">
|
|
16
|
+
<a
|
|
17
|
+
href="{action}?filter_field={field.key}"
|
|
18
|
+
class="lite-filter-icon"
|
|
19
|
+
title="Filter by {field.label}"
|
|
20
|
+
>
|
|
21
|
+
🔍
|
|
22
|
+
</a>
|
|
23
|
+
</span>
|
|
24
|
+
|
|
25
|
+
<style>
|
|
26
|
+
.lite-column-header-filter {
|
|
27
|
+
display: inline-block;
|
|
28
|
+
margin-left: 4px;
|
|
29
|
+
}
|
|
30
|
+
.lite-filter-icon {
|
|
31
|
+
font-size: 11px;
|
|
32
|
+
text-decoration: none;
|
|
33
|
+
opacity: 0.6;
|
|
34
|
+
}
|
|
35
|
+
.lite-filter-icon:hover {
|
|
36
|
+
opacity: 1;
|
|
37
|
+
}
|
|
38
|
+
</style>
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type { FieldDefinition } from '@svadmin/core';
|
|
2
|
+
interface Props {
|
|
3
|
+
field: FieldDefinition;
|
|
4
|
+
action?: string;
|
|
5
|
+
}
|
|
6
|
+
declare const LiteColumnHeaderFilter: import("svelte").Component<Props, {}, "">;
|
|
7
|
+
type LiteColumnHeaderFilter = ReturnType<typeof LiteColumnHeaderFilter>;
|
|
8
|
+
export default LiteColumnHeaderFilter;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<script lang="ts">
|
|
2
|
+
export interface LiteColumnOption {
|
|
3
|
+
key: string;
|
|
4
|
+
label: string;
|
|
5
|
+
visible: boolean;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
interface Props {
|
|
9
|
+
columns: LiteColumnOption[];
|
|
10
|
+
action?: string;
|
|
11
|
+
method?: 'GET' | 'POST' | 'get' | 'post';
|
|
12
|
+
title?: string;
|
|
13
|
+
submitText?: string;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
let {
|
|
17
|
+
columns = [],
|
|
18
|
+
action = '',
|
|
19
|
+
method = 'GET',
|
|
20
|
+
title = 'Column Visibility',
|
|
21
|
+
submitText = 'Apply',
|
|
22
|
+
}: Props = $props();
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<div class="lite-column-settings lite-form-group">
|
|
26
|
+
<div class="lite-column-settings-title">
|
|
27
|
+
<strong>⚙ {title}</strong>
|
|
28
|
+
</div>
|
|
29
|
+
<form {action} {method} class="lite-column-settings-form">
|
|
30
|
+
<div class="lite-column-options">
|
|
31
|
+
{#each columns as col (col.key)}
|
|
32
|
+
<label class="lite-column-option">
|
|
33
|
+
<input
|
|
34
|
+
type="checkbox"
|
|
35
|
+
name="columns"
|
|
36
|
+
value={col.key}
|
|
37
|
+
checked={col.visible}
|
|
38
|
+
/>
|
|
39
|
+
<span>{col.label}</span>
|
|
40
|
+
</label>
|
|
41
|
+
{/each}
|
|
42
|
+
</div>
|
|
43
|
+
<div class="lite-column-actions">
|
|
44
|
+
<button type="submit" class="lite-btn lite-btn-sm lite-btn-primary">
|
|
45
|
+
{submitText}
|
|
46
|
+
</button>
|
|
47
|
+
</div>
|
|
48
|
+
</form>
|
|
49
|
+
</div>
|
|
50
|
+
|
|
51
|
+
<style>
|
|
52
|
+
.lite-column-settings {
|
|
53
|
+
margin-bottom: 12px;
|
|
54
|
+
padding: 8px 12px;
|
|
55
|
+
background: #f8fafc;
|
|
56
|
+
border: 1px solid #cbd5e1;
|
|
57
|
+
border-radius: 4px;
|
|
58
|
+
}
|
|
59
|
+
.lite-column-settings-title {
|
|
60
|
+
font-size: 12px;
|
|
61
|
+
color: #475569;
|
|
62
|
+
margin-bottom: 6px;
|
|
63
|
+
}
|
|
64
|
+
.lite-column-options {
|
|
65
|
+
display: flex;
|
|
66
|
+
flex-wrap: wrap;
|
|
67
|
+
}
|
|
68
|
+
.lite-column-option {
|
|
69
|
+
display: inline-flex;
|
|
70
|
+
align-items: center;
|
|
71
|
+
margin-right: 12px;
|
|
72
|
+
margin-bottom: 4px;
|
|
73
|
+
font-size: 12px;
|
|
74
|
+
cursor: pointer;
|
|
75
|
+
}
|
|
76
|
+
.lite-column-option input {
|
|
77
|
+
margin-right: 4px;
|
|
78
|
+
}
|
|
79
|
+
.lite-column-actions {
|
|
80
|
+
margin-top: 6px;
|
|
81
|
+
}
|
|
82
|
+
</style>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export interface LiteColumnOption {
|
|
2
|
+
key: string;
|
|
3
|
+
label: string;
|
|
4
|
+
visible: boolean;
|
|
5
|
+
}
|
|
6
|
+
interface Props {
|
|
7
|
+
columns: LiteColumnOption[];
|
|
8
|
+
action?: string;
|
|
9
|
+
method?: 'GET' | 'POST' | 'get' | 'post';
|
|
10
|
+
title?: string;
|
|
11
|
+
submitText?: string;
|
|
12
|
+
}
|
|
13
|
+
declare const LiteColumnSettings: import("svelte").Component<Props, {}, "">;
|
|
14
|
+
type LiteColumnSettings = ReturnType<typeof LiteColumnSettings>;
|
|
15
|
+
export default LiteColumnSettings;
|