@svadmin/lite 0.8.0 → 0.8.2
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 +21 -6
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/schema-generator.d.ts +6 -33
- package/dist/schema-generator.js +16 -44
- package/dist/server-adapter.js +7 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -13,7 +13,7 @@ The main `@svadmin/ui` package delivers a premium SPA experience using Svelte 5,
|
|
|
13
13
|
**What Lite is:**
|
|
14
14
|
- A **Zero-JS SSR-first admin component suite** designed with an IE11-safe CSS baseline.
|
|
15
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 (
|
|
16
|
+
- An architectural companion to `@svadmin/ui` achieving **100% component parity (103/103 components)** through 1:1 server-rendered matches, deliberate semantic fallbacks, or explicit SPA-only classification.
|
|
17
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
18
|
|
|
19
19
|
`@svadmin/lite` provides a server-rendered fallback that **shares the same DataProvider, AuthProvider, and Resource definitions** — only the rendering layer is different.
|
|
@@ -246,7 +246,7 @@ IE11 before the decision is made.
|
|
|
246
246
|
|
|
247
247
|
## Components & Parity (100% Coverage)
|
|
248
248
|
|
|
249
|
-
`@svadmin/lite` provides **100% component parity** (
|
|
249
|
+
`@svadmin/lite` provides **100% component parity** (103/103 components) corresponding to `@svadmin/ui`. See [PARITY.md](./PARITY.md) for the generated complete matrix and status details.
|
|
250
250
|
|
|
251
251
|
### Core Pages & Layout
|
|
252
252
|
|
|
@@ -257,6 +257,9 @@ IE11 before the decision is made.
|
|
|
257
257
|
| `LiteListPage` | Full-featured list view with search, table, bulk actions, and pagination |
|
|
258
258
|
| `LiteCreatePage` / `LiteEditPage` | Auto-generated CRUD form pages |
|
|
259
259
|
| `LiteShowPage` | Key-value record view with typed field renderers |
|
|
260
|
+
| `LiteMasterDetailView` | URL-synchronized master/detail workspace |
|
|
261
|
+
| `LitePrintableBill` | Controlled A4-style printable business record |
|
|
262
|
+
| `LitePdfDocumentViewer` | Embedded PDF review with document stamp and annotation support |
|
|
260
263
|
| `LiteProfilePage` | User profile management page with avatar and info |
|
|
261
264
|
| `LiteRegisterPage` | User registration page with server-side validation |
|
|
262
265
|
| `LiteForgotPasswordPage` / `LiteUpdatePasswordPage` | Password recovery and credential rotation flows |
|
|
@@ -266,14 +269,17 @@ IE11 before the decision is made.
|
|
|
266
269
|
| `LitePagination` / `LiteSearch` | URL-driven pagination and GET search controls |
|
|
267
270
|
| `LiteAlert` | Inline notification banner for success/error/warning states |
|
|
268
271
|
| `LiteBreadcrumbs` / `LiteTabs` / `LiteEmptyState` | Semantic navigation and placeholder primitives |
|
|
272
|
+
| `LiteCanAccess` / `LiteErrorBoundary` | Server-side access gate and constrained-environment error boundary |
|
|
273
|
+
| `LiteSplitPaneLayout` / `LiteMultiTabKeepAlive` | Dense two-pane layouts and multi-workspace navigation |
|
|
269
274
|
|
|
270
|
-
### Field Components (
|
|
275
|
+
### Field Components (33 Fields)
|
|
271
276
|
|
|
272
277
|
| Category | Components |
|
|
273
278
|
|----------|------------|
|
|
274
279
|
| **Text & Numeric** | `LiteTextField`, `LiteNumberField`, `LiteCurrencyField`, `LitePercentField`, `LitePhoneField`, `LiteEmailField`, `LiteUrlField`, `LiteRatingField`, `LiteCopyField` |
|
|
275
280
|
| **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` |
|
|
281
|
+
| **Media & Rich & Array** | `LiteAvatarField`, `LiteImageField`, `LiteFileField`, `LiteCodeField`, `LiteMarkdownField`, `LiteRichTextField`, `LiteJsonField`, `LiteArrayField`, `LiteDynamicFormList`, `LiteTransfer`, `LiteImageCropper`, `LiteJsonSchemaForm`, `LiteMentionsInput`, `LiteSignaturePad` |
|
|
282
|
+
| **SPA-only** | `VoiceInput` (Web Speech API; no SSR counterpart) |
|
|
277
283
|
|
|
278
284
|
### Action Buttons (10 Buttons)
|
|
279
285
|
|
|
@@ -289,6 +295,7 @@ IE11 before the decision is made.
|
|
|
289
295
|
|-----------|-------------|
|
|
290
296
|
| `LiteStatsCard`, `LiteInsightCard`, `LiteAnomalyBadge` | Metric KPI cards and status badges |
|
|
291
297
|
| `LiteBarChart`, `LiteLineChart`, `LitePieChart` | Server-rendered SVG/HTML charts with fallback data tables |
|
|
298
|
+
| `LitePresenceAvatarGroup`, `LiteGanttChart`, `LiteOfflineSyncBanner` | Presence, schedule, and offline mutation status rendered without client hydration |
|
|
292
299
|
|
|
293
300
|
### Compatibility & Degradation Primitives
|
|
294
301
|
|
|
@@ -308,6 +315,12 @@ IE11 before the decision is made.
|
|
|
308
315
|
| `LiteDraggableHeader` | Static column header with URL sorter links |
|
|
309
316
|
| `LiteToast` / `LiteUndoableNotification` | Server-driven flash messages and undo actions |
|
|
310
317
|
| `LiteFilterBuilder` | Native multi-rule CRUD filter builder with AND/OR logical operators |
|
|
318
|
+
| `LiteConfirmDialog`, `LiteWatermark`, `LiteColumnSettings`, `LiteImportWizard` | Server-safe confirmation, watermark, column, and import workflows |
|
|
319
|
+
| `LiteColumnHeaderFilter`, `LiteTreeTable`, `LiteSensitiveDataMask`, `LiteApprovalActionCard` | Query, hierarchy, masking, and approval fallbacks |
|
|
320
|
+
| `LiteStepForm`, `LiteTableSummary`, `LiteVersionDiffViewer`, `LiteEditableTable`, `LiteDraggableRowTable` | Server-driven enterprise data interaction components |
|
|
321
|
+
| `LiteMediaLibraryModal`, `LiteActivityFeed`, `LiteKanbanBoard`, `LitePivotTable` | Media, activity, workflow, and analysis views |
|
|
322
|
+
| `LiteCanvasAnnotation`, `LiteSpreadsheetView`, `LiteDecisionTable` | SSR-compatible annotation, spreadsheet, and rules views |
|
|
323
|
+
| `DevTools`, `CopilotPanel` | SPA-only components with no Lite counterpart |
|
|
311
324
|
|
|
312
325
|
## Parity Tracking & Visualization
|
|
313
326
|
|
|
@@ -316,7 +329,7 @@ To monitor and maintain 100% component parity between `@svadmin/ui` and `@svadmi
|
|
|
316
329
|
- **CLI Dashboard**: Run `bun run check:parity` to inspect the live coverage matrix in terminal.
|
|
317
330
|
- **Parity Matrix Document**: [PARITY.md](./PARITY.md) is auto-generated with exhaustive module-by-module tables.
|
|
318
331
|
- **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
|
|
332
|
+
- **Interactive Showroom**: Visit `/lite/parity` in the example app to interactively preview all 103 components and live metrics.
|
|
320
333
|
- **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.
|
|
321
334
|
|
|
322
335
|
## Server Utilities
|
|
@@ -329,7 +342,9 @@ To monitor and maintain 100% component parity between `@svadmin/ui` and `@svadmi
|
|
|
329
342
|
| `createAuthGuard(authProvider)` | Server hook for authentication |
|
|
330
343
|
| `createAuthActions(authProvider)` | Login/logout actions plus optional provider-delegating account actions |
|
|
331
344
|
| `createLegacyRedirectHook()` | Auto-redirect IE11 to `/lite/` |
|
|
332
|
-
| `fieldsToTypeBoxSchema(fields)` | Generate the TypeBox schema used by Lite actions or other consumers
|
|
345
|
+
| `fieldsToTypeBoxSchema(fields)` | Generate the TypeBox schema used by Lite actions or other consumers |
|
|
346
|
+
|
|
347
|
+
Schema generation is TypeBox-only. The former Zod-named exports and parser-compatible methods were removed; use `Check`, `Errors`, and `Decode` on the returned schema.
|
|
333
348
|
|
|
334
349
|
## CSS
|
|
335
350
|
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ export { createListLoader, createDetailLoader, createCrudActions, createAuthGuar
|
|
|
2
2
|
export type { LegacyRedirectOptions, ListLoaderResult } from './server-adapter';
|
|
3
3
|
export { LITE_COMPATIBILITY_CATALOG, detectLiteCapabilities, resolveLiteCompatibility, } from './compatibility';
|
|
4
4
|
export type { LiteCapability, LiteCapabilitySupport, LiteCompatibilityDescriptor, LiteCompatibilityResolution, LiteFallbackKind, } from './compatibility';
|
|
5
|
-
export { fieldsToTypeBoxSchema, resourceToTypeBoxSchema,
|
|
5
|
+
export { fieldsToTypeBoxSchema, resourceToTypeBoxSchema, fieldToInputType, fieldToPlaceholder, } from './schema-generator';
|
|
6
6
|
export { getStatusBadgeClass, parseExplicitBoolean, isExplicitBooleanTrue } from './value-normalization';
|
|
7
7
|
export { default as LiteLayout } from './components/LiteLayout.svelte';
|
|
8
8
|
export { default as LiteTable } from './components/LiteTable.svelte';
|
package/dist/index.js
CHANGED
|
@@ -5,7 +5,7 @@ export { createListLoader, createDetailLoader, createCrudActions, createAuthGuar
|
|
|
5
5
|
// Optional browser capabilities. The SSR baseline does not import browser globals.
|
|
6
6
|
export { LITE_COMPATIBILITY_CATALOG, detectLiteCapabilities, resolveLiteCompatibility, } from './compatibility';
|
|
7
7
|
// Schema generator (TypeBox schemas used by Lite actions and client forms)
|
|
8
|
-
export { fieldsToTypeBoxSchema, resourceToTypeBoxSchema,
|
|
8
|
+
export { fieldsToTypeBoxSchema, resourceToTypeBoxSchema, fieldToInputType, fieldToPlaceholder, } from './schema-generator';
|
|
9
9
|
// UI Components (use in +page.svelte with csr = false)
|
|
10
10
|
export { getStatusBadgeClass, parseExplicitBoolean, isExplicitBooleanTrue } from './value-normalization';
|
|
11
11
|
export { default as LiteLayout } from './components/LiteLayout.svelte';
|
|
@@ -10,33 +10,14 @@ export interface SchemaValidationIssue {
|
|
|
10
10
|
path: (string | number)[];
|
|
11
11
|
message: string;
|
|
12
12
|
}
|
|
13
|
-
export
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
} | {
|
|
18
|
-
success: false;
|
|
19
|
-
error: {
|
|
20
|
-
issues: SchemaValidationIssue[];
|
|
21
|
-
};
|
|
22
|
-
data?: never;
|
|
23
|
-
};
|
|
13
|
+
export interface TypeBoxValidationError {
|
|
14
|
+
path: string;
|
|
15
|
+
message: string;
|
|
16
|
+
}
|
|
24
17
|
export type TypeBoxEnhancedSchema<T = Record<string, unknown>> = TObject & {
|
|
25
|
-
parse: (values: unknown) => T;
|
|
26
|
-
safeParse: (values: unknown) => SchemaValidationResult<T>;
|
|
27
18
|
Check: (values: unknown) => boolean;
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
vendor: "svadmin";
|
|
31
|
-
validate: (values: unknown) => {
|
|
32
|
-
value: T;
|
|
33
|
-
} | {
|
|
34
|
-
issues: Array<{
|
|
35
|
-
message: string;
|
|
36
|
-
path?: (string | number)[];
|
|
37
|
-
}>;
|
|
38
|
-
};
|
|
39
|
-
};
|
|
19
|
+
Errors: (values: unknown) => Iterable<TypeBoxValidationError>;
|
|
20
|
+
Decode: (values: unknown) => T;
|
|
40
21
|
};
|
|
41
22
|
/**
|
|
42
23
|
* Generate a TypeBox object schema from a list of FieldDefinitions.
|
|
@@ -47,14 +28,6 @@ export declare function fieldsToTypeBoxSchema(fields: FieldDefinition[], mode?:
|
|
|
47
28
|
* Convenience wrapper around fieldsToTypeBoxSchema.
|
|
48
29
|
*/
|
|
49
30
|
export declare function resourceToTypeBoxSchema(resource: ResourceDefinition, mode?: "create" | "edit"): TypeBoxEnhancedSchema;
|
|
50
|
-
/**
|
|
51
|
-
* Backward compatibility alias for fieldsToTypeBoxSchema
|
|
52
|
-
*/
|
|
53
|
-
export declare const fieldsToZodSchema: typeof fieldsToTypeBoxSchema;
|
|
54
|
-
/**
|
|
55
|
-
* Backward compatibility alias for resourceToTypeBoxSchema
|
|
56
|
-
*/
|
|
57
|
-
export declare const resourceToZodSchema: typeof resourceToTypeBoxSchema;
|
|
58
31
|
/**
|
|
59
32
|
* Determine a conservative HTML input type for server-rendered forms.
|
|
60
33
|
*/
|
package/dist/schema-generator.js
CHANGED
|
@@ -361,11 +361,10 @@ export function fieldsToTypeBoxSchema(fields, mode = "create") {
|
|
|
361
361
|
}
|
|
362
362
|
}
|
|
363
363
|
const baseSchema = Type.Object(shape, { additionalProperties: true });
|
|
364
|
-
const
|
|
364
|
+
const validateAndNormalize = (values) => {
|
|
365
365
|
if (typeof values !== "object" || values === null) {
|
|
366
366
|
return {
|
|
367
|
-
|
|
368
|
-
error: { issues: [{ path: ["_root"], message: "Values must be an object" }] },
|
|
367
|
+
issues: [{ path: ["_root"], message: "Values must be an object" }],
|
|
369
368
|
};
|
|
370
369
|
}
|
|
371
370
|
const input = values;
|
|
@@ -380,45 +379,26 @@ export function fieldsToTypeBoxSchema(fields, mode = "create") {
|
|
|
380
379
|
}
|
|
381
380
|
}
|
|
382
381
|
if (allIssues.length > 0) {
|
|
383
|
-
return {
|
|
384
|
-
success: false,
|
|
385
|
-
error: { issues: allIssues },
|
|
386
|
-
};
|
|
382
|
+
return { issues: allIssues };
|
|
387
383
|
}
|
|
388
|
-
return {
|
|
389
|
-
success: true,
|
|
390
|
-
data: resultData,
|
|
391
|
-
};
|
|
384
|
+
return { data: resultData, issues: [] };
|
|
392
385
|
};
|
|
393
|
-
const
|
|
394
|
-
const
|
|
395
|
-
if (
|
|
396
|
-
const err = new Error(
|
|
397
|
-
err.
|
|
386
|
+
const decode = (values) => {
|
|
387
|
+
const validation = validateAndNormalize(values);
|
|
388
|
+
if (validation.issues.length > 0) {
|
|
389
|
+
const err = new Error(validation.issues[0]?.message || "Validation failed");
|
|
390
|
+
err.errors = validation.issues;
|
|
398
391
|
throw err;
|
|
399
392
|
}
|
|
400
|
-
return
|
|
393
|
+
return validation.data ?? {};
|
|
401
394
|
};
|
|
402
395
|
return Object.assign(baseSchema, {
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
validate: (val) => {
|
|
410
|
-
const res = safeParse(val);
|
|
411
|
-
if (res.success) {
|
|
412
|
-
return { value: res.data ?? {} };
|
|
413
|
-
}
|
|
414
|
-
return {
|
|
415
|
-
issues: (res.error?.issues ?? []).map((iss) => ({
|
|
416
|
-
message: iss.message,
|
|
417
|
-
path: iss.path,
|
|
418
|
-
})),
|
|
419
|
-
};
|
|
420
|
-
},
|
|
421
|
-
},
|
|
396
|
+
Check: (val) => validateAndNormalize(val).issues.length === 0,
|
|
397
|
+
Errors: (val) => validateAndNormalize(val).issues.map((issue) => ({
|
|
398
|
+
path: issue.path.length > 0 ? `/${issue.path.map(String).join("/")}` : "",
|
|
399
|
+
message: issue.message,
|
|
400
|
+
})),
|
|
401
|
+
Decode: decode,
|
|
422
402
|
});
|
|
423
403
|
}
|
|
424
404
|
/**
|
|
@@ -429,14 +409,6 @@ export function resourceToTypeBoxSchema(resource, mode = "create") {
|
|
|
429
409
|
const primaryKey = resource.primaryKey ?? "id";
|
|
430
410
|
return fieldsToTypeBoxSchema(resource.fields.filter((field) => field.key !== primaryKey), mode);
|
|
431
411
|
}
|
|
432
|
-
/**
|
|
433
|
-
* Backward compatibility alias for fieldsToTypeBoxSchema
|
|
434
|
-
*/
|
|
435
|
-
export const fieldsToZodSchema = fieldsToTypeBoxSchema;
|
|
436
|
-
/**
|
|
437
|
-
* Backward compatibility alias for resourceToTypeBoxSchema
|
|
438
|
-
*/
|
|
439
|
-
export const resourceToZodSchema = resourceToTypeBoxSchema;
|
|
440
412
|
/**
|
|
441
413
|
* Determine a conservative HTML input type for server-rendered forms.
|
|
442
414
|
*/
|
package/dist/server-adapter.js
CHANGED
|
@@ -473,16 +473,19 @@ function formatValidationErrors(issues) {
|
|
|
473
473
|
return errors;
|
|
474
474
|
}
|
|
475
475
|
function validateFormVariables(resource, mode, values) {
|
|
476
|
-
const
|
|
477
|
-
if (
|
|
478
|
-
return { success: true, data:
|
|
476
|
+
const schema = resourceToTypeBoxSchema(resource, mode);
|
|
477
|
+
if (schema.Check(values))
|
|
478
|
+
return { success: true, data: schema.Decode(values) };
|
|
479
479
|
return {
|
|
480
480
|
success: false,
|
|
481
481
|
failure: {
|
|
482
482
|
success: false,
|
|
483
483
|
error: 'Validation failed',
|
|
484
484
|
values: formValuesForResponse(resource.fields, values),
|
|
485
|
-
errors: formatValidationErrors(
|
|
485
|
+
errors: formatValidationErrors([...schema.Errors(values)].map((issue) => ({
|
|
486
|
+
path: issue.path.split('/').filter(Boolean),
|
|
487
|
+
message: issue.message,
|
|
488
|
+
}))),
|
|
486
489
|
},
|
|
487
490
|
};
|
|
488
491
|
}
|