@svadmin/lite 0.5.0 → 0.6.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.
Files changed (37) hide show
  1. package/README.md +105 -0
  2. package/dist/compatibility.d.ts +23 -0
  3. package/dist/compatibility.js +95 -0
  4. package/dist/components/LiteShowField.svelte +30 -22
  5. package/dist/components/LiteShowField.svelte.d.ts +3 -2
  6. package/dist/components/LiteTable.svelte +89 -36
  7. package/dist/components/LiteTable.svelte.d.ts +3 -2
  8. package/dist/components/compatibility/LiteCapabilityBoundary.svelte +51 -0
  9. package/dist/components/compatibility/LiteCapabilityBoundary.svelte.d.ts +13 -0
  10. package/dist/components/compatibility/LiteClipboardFallback.svelte +16 -0
  11. package/dist/components/compatibility/LiteClipboardFallback.svelte.d.ts +8 -0
  12. package/dist/components/compatibility/LiteComputeFallback.svelte +50 -0
  13. package/dist/components/compatibility/LiteComputeFallback.svelte.d.ts +14 -0
  14. package/dist/components/compatibility/LiteDirectoryUpload.svelte +44 -0
  15. package/dist/components/compatibility/LiteDirectoryUpload.svelte.d.ts +11 -0
  16. package/dist/components/compatibility/LiteOrderedList.svelte +47 -0
  17. package/dist/components/compatibility/LiteOrderedList.svelte.d.ts +14 -0
  18. package/dist/components/compatibility/LiteRealtimeStatus.svelte +43 -0
  19. package/dist/components/compatibility/LiteRealtimeStatus.svelte.d.ts +11 -0
  20. package/dist/components/compatibility/LiteVisualFallback.svelte +80 -0
  21. package/dist/components/compatibility/LiteVisualFallback.svelte.d.ts +18 -0
  22. package/dist/components/compatibility/index.d.ts +7 -0
  23. package/dist/components/compatibility/index.js +7 -0
  24. package/dist/components/pages/LiteCreatePage.svelte +15 -6
  25. package/dist/components/pages/LiteCreatePage.svelte.d.ts +1 -1
  26. package/dist/components/pages/LiteEditPage.svelte +18 -9
  27. package/dist/components/pages/LiteEditPage.svelte.d.ts +1 -1
  28. package/dist/components/pages/LiteListPage.svelte +86 -16
  29. package/dist/components/pages/LiteListPage.svelte.d.ts +4 -2
  30. package/dist/components/pages/LiteShowPage.svelte +19 -10
  31. package/dist/components/pages/LiteShowPage.svelte.d.ts +1 -1
  32. package/dist/index.d.ts +5 -2
  33. package/dist/index.js +5 -1
  34. package/dist/lite.css +239 -0
  35. package/dist/server-adapter.d.ts +18 -1
  36. package/dist/server-adapter.js +73 -16
  37. package/package.json +2 -2
@@ -19,6 +19,16 @@ function listRequestState(url, resource) {
19
19
  : resource.defaultSort?.order ?? 'asc';
20
20
  return { page, pageSize, sort, order, search: url.searchParams.get('q') ?? undefined };
21
21
  }
22
+ function listRequestFilterValues(resource, url) {
23
+ const values = {};
24
+ for (const field of resource.fields) {
25
+ const raw = url.searchParams.get(`filter_${field.key}`) ?? (field.key !== "q" && field.key !== "sort" && field.key !== "order" && field.key !== "page" ? url.searchParams.get(field.key) : null);
26
+ if (raw != null && raw.trim() !== "") {
27
+ values[field.key] = raw.trim();
28
+ }
29
+ }
30
+ return values;
31
+ }
22
32
  function listRequestFilters(resource, url) {
23
33
  const filters = [];
24
34
  const search = url.searchParams.get('q') ?? undefined;
@@ -76,6 +86,7 @@ export function createListLoader(dp, resource) {
76
86
  currentSort: sort,
77
87
  currentOrder: order,
78
88
  currentSearch: search,
89
+ currentFilters: listRequestFilterValues(resource, url),
79
90
  resource,
80
91
  };
81
92
  };
@@ -343,28 +354,74 @@ export function createAuthActions(authProvider) {
343
354
  export function isLegacyBrowser(userAgent) {
344
355
  return /MSIE|Trident|rv:11/.test(userAgent);
345
356
  }
357
+ function normalizeRoutePrefix(prefix) {
358
+ const segments = prefix.split('/').filter(Boolean);
359
+ return segments.length > 0 ? `/${segments.join('/')}` : '/';
360
+ }
361
+ function pathWithinPrefix(pathname, prefix) {
362
+ return prefix === '/' || pathname === prefix || pathname.startsWith(`${prefix}/`);
363
+ }
364
+ function redirectOptions(options) {
365
+ const configured = typeof options === 'string' ? { litePrefix: options } : options;
366
+ return {
367
+ litePrefix: normalizeRoutePrefix(configured.litePrefix ?? '/lite'),
368
+ spaPrefix: normalizeRoutePrefix(configured.spaPrefix ?? '/'),
369
+ exclude: (configured.exclude ?? []).map(normalizeRoutePrefix),
370
+ mapPath: configured.mapPath,
371
+ status: configured.status ?? 302,
372
+ };
373
+ }
374
+ /**
375
+ * Computes a legacy redirect without importing or modifying the modern SPA.
376
+ * This pure helper can be used from non-SvelteKit server middleware.
377
+ */
378
+ export function getLegacyRedirectLocation(request, url, options = '/lite') {
379
+ const configured = redirectOptions(options);
380
+ const userAgent = request.headers.get('user-agent') ?? '';
381
+ const acceptsHtml = request.headers.get('accept')?.includes('text/html') === true;
382
+ const isDocumentRequest = (request.method === 'GET' || request.method === 'HEAD') && acceptsHtml;
383
+ if (!isLegacyBrowser(userAgent) || !isDocumentRequest)
384
+ return undefined;
385
+ if (pathWithinPrefix(url.pathname, configured.litePrefix))
386
+ return undefined;
387
+ if (configured.exclude.some((prefix) => pathWithinPrefix(url.pathname, prefix)))
388
+ return undefined;
389
+ if (!configured.mapPath
390
+ && configured.spaPrefix !== '/'
391
+ && !pathWithinPrefix(url.pathname, configured.spaPrefix))
392
+ return undefined;
393
+ let mappedPath;
394
+ if (configured.mapPath) {
395
+ mappedPath = configured.mapPath(url.pathname);
396
+ }
397
+ else if (configured.spaPrefix !== '/' && pathWithinPrefix(url.pathname, configured.spaPrefix)) {
398
+ mappedPath = url.pathname.slice(configured.spaPrefix.length) || '/';
399
+ }
400
+ else {
401
+ mappedPath = url.pathname;
402
+ }
403
+ const normalizedMappedPath = mappedPath.startsWith('/') ? mappedPath : `/${mappedPath}`;
404
+ const location = configured.litePrefix === '/'
405
+ ? normalizedMappedPath
406
+ : `${configured.litePrefix}${normalizedMappedPath === '/' ? '' : normalizedMappedPath}`;
407
+ return `${location}${url.search}`;
408
+ }
346
409
  /**
347
410
  * Creates an opt-in SvelteKit hook that redirects detected IE11 user agents.
348
411
  * Consumers remain responsible for their own transpilation and browser support.
349
412
  */
350
- export function createLegacyRedirectHook(litePrefix = '/lite') {
351
- const prefixSegments = litePrefix.split('/').filter(Boolean);
352
- const normalizedPrefix = prefixSegments.length > 0 ? `/${prefixSegments.join('/')}` : '/';
413
+ export function createLegacyRedirectHook(options = '/lite') {
414
+ const configured = redirectOptions(options);
353
415
  return async ({ event, resolve }) => {
354
- const ua = event.request.headers.get('user-agent') ?? '';
355
- const acceptsHtml = event.request.headers.get('accept')?.includes('text/html') === true;
356
- const isDocumentRequest = (event.request.method === 'GET' || event.request.method === 'HEAD')
357
- && acceptsHtml;
358
- const isWithinLite = normalizedPrefix === '/'
359
- || event.url.pathname === normalizedPrefix
360
- || event.url.pathname.startsWith(`${normalizedPrefix}/`);
361
- if (isLegacyBrowser(ua) && isDocumentRequest && !isWithinLite) {
362
- const targetPath = normalizedPrefix === '/'
363
- ? event.url.pathname
364
- : `${normalizedPrefix}${event.url.pathname}`;
416
+ const location = getLegacyRedirectLocation(event.request, event.url, configured);
417
+ if (location) {
365
418
  return new Response(null, {
366
- status: 302,
367
- headers: { Location: `${targetPath}${event.url.search}` },
419
+ status: configured.status,
420
+ headers: {
421
+ Location: location,
422
+ 'Cache-Control': 'private, no-store',
423
+ Vary: 'User-Agent',
424
+ },
368
425
  });
369
426
  }
370
427
  return resolve(event);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@svadmin/lite",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "SSR-first lightweight admin UI for @svadmin with optional progressive enhancement",
5
5
  "type": "module",
6
6
  "sideEffects": [
@@ -69,7 +69,7 @@
69
69
  "build": "node ../../node_modules/@sveltejs/package/svelte-package.js -i src -o dist && bun ../../scripts/copy-package-assets.ts static/enhance.js dist/enhance.js",
70
70
  "test": "bun run test:components && bun run test:server && bun run test:security",
71
71
  "test:components": "vitest run --config ./vitest.config.ts",
72
- "test:server": "bun test ./src/schema-generator.test.ts ./src/server-adapter.test.ts ./src/fragment-id.test.ts ./src/ie11-ssr-contract.test.ts",
72
+ "test:server": "bun test ./src/schema-generator.test.ts ./src/server-adapter.test.ts ./src/fragment-id.test.ts ./src/compatibility.test.ts ./src/ie11-ssr-contract.test.ts",
73
73
  "test:security": "vitest run --config ./src/security.test.config.ts"
74
74
  },
75
75
  "license": "MIT",