@svadmin/lite 0.17.0 → 0.22.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 (226) hide show
  1. package/README.md +71 -2
  2. package/dist/components/LiteActivityFeed.svelte +24 -2
  3. package/dist/components/LiteActivityFeed.svelte.d.ts +6 -0
  4. package/dist/components/LiteAffix.svelte +29 -0
  5. package/dist/components/LiteAffix.svelte.d.ts +13 -0
  6. package/dist/components/LiteAnchor.svelte +38 -0
  7. package/dist/components/LiteAnchor.svelte.d.ts +14 -0
  8. package/dist/components/LiteApprovalActionCard.svelte +4 -1
  9. package/dist/components/LiteApprovalActionCard.svelte.d.ts +2 -0
  10. package/dist/components/LiteAutoComplete.svelte +41 -0
  11. package/dist/components/LiteAutoComplete.svelte.d.ts +13 -0
  12. package/dist/components/LiteBackTop.svelte +16 -0
  13. package/dist/components/LiteBackTop.svelte.d.ts +8 -0
  14. package/dist/components/LiteBreadcrumbs.svelte +4 -1
  15. package/dist/components/LiteBreadcrumbs.svelte.d.ts +2 -0
  16. package/dist/components/LiteCalendar.svelte +124 -0
  17. package/dist/components/LiteCalendar.svelte.d.ts +20 -0
  18. package/dist/components/LiteCarousel.svelte +72 -0
  19. package/dist/components/LiteCarousel.svelte.d.ts +14 -0
  20. package/dist/components/LiteCollapse.svelte +49 -0
  21. package/dist/components/LiteCollapse.svelte.d.ts +15 -0
  22. package/dist/components/LiteColumnHeaderFilter.svelte +4 -1
  23. package/dist/components/LiteColumnHeaderFilter.svelte.d.ts +2 -0
  24. package/dist/components/LiteColumnSettings.svelte +4 -1
  25. package/dist/components/LiteColumnSettings.svelte.d.ts +2 -0
  26. package/dist/components/LiteCommentThread.svelte +113 -0
  27. package/dist/components/LiteCommentThread.svelte.d.ts +26 -0
  28. package/dist/components/LiteCountdown.svelte +49 -0
  29. package/dist/components/LiteCountdown.svelte.d.ts +10 -0
  30. package/dist/components/LiteDetailDrawer.svelte +45 -0
  31. package/dist/components/LiteDetailDrawer.svelte.d.ts +14 -0
  32. package/dist/components/LiteDraggableRowTable.svelte +4 -1
  33. package/dist/components/LiteDraggableRowTable.svelte.d.ts +2 -0
  34. package/dist/components/LiteDrawerForm.svelte +4 -1
  35. package/dist/components/LiteDrawerForm.svelte.d.ts +2 -0
  36. package/dist/components/LiteEditableTable.svelte +4 -1
  37. package/dist/components/LiteEditableTable.svelte.d.ts +2 -0
  38. package/dist/components/LiteEmptyState.svelte +8 -1
  39. package/dist/components/LiteEmptyState.svelte.d.ts +3 -0
  40. package/dist/components/LiteFilterBuilder.svelte +4 -1
  41. package/dist/components/LiteFilterBuilder.svelte.d.ts +2 -0
  42. package/dist/components/LiteFloatButton.svelte +54 -0
  43. package/dist/components/LiteFloatButton.svelte.d.ts +15 -0
  44. package/dist/components/LiteGrid.svelte +34 -0
  45. package/dist/components/LiteGrid.svelte.d.ts +11 -0
  46. package/dist/components/LiteImage.svelte +54 -0
  47. package/dist/components/LiteImage.svelte.d.ts +14 -0
  48. package/dist/components/LiteImageCropper.svelte +4 -1
  49. package/dist/components/LiteImageCropper.svelte.d.ts +2 -0
  50. package/dist/components/LiteImagePreview.svelte +36 -0
  51. package/dist/components/LiteImagePreview.svelte.d.ts +13 -0
  52. package/dist/components/LiteItemList.svelte +50 -0
  53. package/dist/components/LiteItemList.svelte.d.ts +15 -0
  54. package/dist/components/LiteJsonSchemaForm.svelte +4 -1
  55. package/dist/components/LiteJsonSchemaForm.svelte.d.ts +2 -0
  56. package/dist/components/LiteLayout.svelte +16 -4
  57. package/dist/components/LiteLayout.svelte.d.ts +8 -0
  58. package/dist/components/LiteLink.svelte +32 -0
  59. package/dist/components/LiteLink.svelte.d.ts +11 -0
  60. package/dist/components/LiteLogin.svelte +9 -2
  61. package/dist/components/LiteLogin.svelte.d.ts +2 -0
  62. package/dist/components/LiteMasterDetailView.svelte +4 -1
  63. package/dist/components/LiteMasterDetailView.svelte.d.ts +2 -0
  64. package/dist/components/LiteMediaLibraryModal.svelte +4 -1
  65. package/dist/components/LiteMediaLibraryModal.svelte.d.ts +2 -0
  66. package/dist/components/LiteMenu.svelte +22 -0
  67. package/dist/components/LiteMenu.svelte.d.ts +12 -0
  68. package/dist/components/LiteMenuList.svelte +55 -0
  69. package/dist/components/LiteMenuList.svelte.d.ts +17 -0
  70. package/dist/components/LiteModalForm.svelte +4 -1
  71. package/dist/components/LiteModalForm.svelte.d.ts +2 -0
  72. package/dist/components/LiteNotificationCenter.svelte +85 -0
  73. package/dist/components/LiteNotificationCenter.svelte.d.ts +22 -0
  74. package/dist/components/LiteOtpInput.svelte +50 -0
  75. package/dist/components/LiteOtpInput.svelte.d.ts +15 -0
  76. package/dist/components/LitePageHeader.svelte +34 -0
  77. package/dist/components/LitePageHeader.svelte.d.ts +13 -0
  78. package/dist/components/LitePagination.svelte +10 -2
  79. package/dist/components/LitePagination.svelte.d.ts +2 -0
  80. package/dist/components/LitePopconfirm.svelte +49 -0
  81. package/dist/components/LitePopconfirm.svelte.d.ts +14 -0
  82. package/dist/components/LitePresenceAvatarGroup.svelte +4 -1
  83. package/dist/components/LitePresenceAvatarGroup.svelte.d.ts +2 -0
  84. package/dist/components/LitePrintableBill.svelte +4 -1
  85. package/dist/components/LitePrintableBill.svelte.d.ts +2 -0
  86. package/dist/components/LiteProgress.svelte +46 -0
  87. package/dist/components/LiteProgress.svelte.d.ts +12 -0
  88. package/dist/components/LiteQRCode.svelte +62 -0
  89. package/dist/components/LiteQRCode.svelte.d.ts +14 -0
  90. package/dist/components/LiteResizeBox.svelte +34 -0
  91. package/dist/components/LiteResizeBox.svelte.d.ts +12 -0
  92. package/dist/components/LiteResult.svelte +52 -0
  93. package/dist/components/LiteResult.svelte.d.ts +14 -0
  94. package/dist/components/LiteRowActions.svelte +36 -0
  95. package/dist/components/LiteRowActions.svelte.d.ts +17 -0
  96. package/dist/components/LiteSensitiveDataMask.svelte +4 -1
  97. package/dist/components/LiteSensitiveDataMask.svelte.d.ts +2 -0
  98. package/dist/components/LiteSkeleton.svelte +100 -0
  99. package/dist/components/LiteSkeleton.svelte.d.ts +19 -0
  100. package/dist/components/LiteSpace.svelte +31 -0
  101. package/dist/components/LiteSpace.svelte.d.ts +12 -0
  102. package/dist/components/LiteSpin.svelte +27 -0
  103. package/dist/components/LiteSpin.svelte.d.ts +10 -0
  104. package/dist/components/LiteSplitPaneLayout.svelte +16 -4
  105. package/dist/components/LiteSplitPaneLayout.svelte.d.ts +8 -0
  106. package/dist/components/LiteStatistic.svelte +63 -0
  107. package/dist/components/LiteStatistic.svelte.d.ts +15 -0
  108. package/dist/components/LiteStatsCard.svelte +5 -2
  109. package/dist/components/LiteStatsCard.svelte.d.ts +2 -0
  110. package/dist/components/LiteStatusBadge.svelte +33 -0
  111. package/dist/components/LiteStatusBadge.svelte.d.ts +12 -0
  112. package/dist/components/LiteStatusTabs.svelte +35 -0
  113. package/dist/components/LiteStatusTabs.svelte.d.ts +14 -0
  114. package/dist/components/LiteStepForm.svelte +4 -1
  115. package/dist/components/LiteStepForm.svelte.d.ts +2 -0
  116. package/dist/components/LiteSteps.svelte +64 -0
  117. package/dist/components/LiteSteps.svelte.d.ts +18 -0
  118. package/dist/components/LiteTable.svelte +4 -1
  119. package/dist/components/LiteTable.svelte.d.ts +2 -0
  120. package/dist/components/LiteTableSummary.svelte +4 -1
  121. package/dist/components/LiteTableSummary.svelte.d.ts +2 -0
  122. package/dist/components/LiteTabs.svelte +28 -18
  123. package/dist/components/LiteTabs.svelte.d.ts +11 -2
  124. package/dist/components/LiteTag.svelte +31 -0
  125. package/dist/components/LiteTag.svelte.d.ts +13 -0
  126. package/dist/components/LiteTimeline.svelte +48 -0
  127. package/dist/components/LiteTimeline.svelte.d.ts +17 -0
  128. package/dist/components/LiteTour.svelte +54 -0
  129. package/dist/components/LiteTour.svelte.d.ts +15 -0
  130. package/dist/components/LiteTransfer.svelte +4 -1
  131. package/dist/components/LiteTransfer.svelte.d.ts +2 -0
  132. package/dist/components/LiteTree.svelte +48 -0
  133. package/dist/components/LiteTree.svelte.d.ts +17 -0
  134. package/dist/components/LiteTwoFactorStepper.svelte +53 -0
  135. package/dist/components/LiteTwoFactorStepper.svelte.d.ts +16 -0
  136. package/dist/components/LiteVersionDiffViewer.svelte +4 -1
  137. package/dist/components/LiteVersionDiffViewer.svelte.d.ts +2 -0
  138. package/dist/components/LiteVideoPlayer.svelte +67 -0
  139. package/dist/components/LiteVideoPlayer.svelte.d.ts +22 -0
  140. package/dist/components/advanced/LiteAutoSaveIndicator.svelte +42 -13
  141. package/dist/components/advanced/LiteAutoSaveIndicator.svelte.d.ts +10 -4
  142. package/dist/components/advanced/LiteDrawerForm.svelte +4 -1
  143. package/dist/components/advanced/LiteDrawerForm.svelte.d.ts +2 -0
  144. package/dist/components/advanced/LiteModalForm.svelte +4 -1
  145. package/dist/components/advanced/LiteModalForm.svelte.d.ts +2 -0
  146. package/dist/components/compatibility/LiteRealtimeStatus.svelte +41 -2
  147. package/dist/components/compatibility/LiteRealtimeStatus.svelte.d.ts +15 -0
  148. package/dist/components/fields/LiteBooleanField.svelte +4 -2
  149. package/dist/components/fields/LiteBooleanField.svelte.d.ts +2 -0
  150. package/dist/components/fields/LiteCascader.svelte +5 -2
  151. package/dist/components/fields/LiteCascader.svelte.d.ts +2 -0
  152. package/dist/components/fields/LiteDateField.svelte +39 -9
  153. package/dist/components/fields/LiteDateField.svelte.d.ts +2 -0
  154. package/dist/components/fields/LiteImageField.svelte +6 -2
  155. package/dist/components/fields/LiteImageField.svelte.d.ts +2 -0
  156. package/dist/components/fields/LiteMarkdownField.svelte +49 -3
  157. package/dist/components/fields/LiteMarkdownField.svelte.d.ts +5 -0
  158. package/dist/components/fields/LiteNumberField.svelte +5 -3
  159. package/dist/components/fields/LiteNumberField.svelte.d.ts +2 -0
  160. package/dist/components/fields/LiteRichTextField.svelte +45 -8
  161. package/dist/components/fields/LiteRichTextField.svelte.d.ts +3 -0
  162. package/dist/components/fields/LiteSelectField.svelte +5 -3
  163. package/dist/components/fields/LiteSelectField.svelte.d.ts +2 -0
  164. package/dist/components/fields/LiteTagField.svelte +38 -15
  165. package/dist/components/fields/LiteTagField.svelte.d.ts +2 -0
  166. package/dist/components/fields/LiteTextField.svelte +26 -5
  167. package/dist/components/fields/LiteTextField.svelte.d.ts +2 -0
  168. package/dist/components/fields/LiteTreeSelect.svelte +5 -2
  169. package/dist/components/fields/LiteTreeSelect.svelte.d.ts +2 -0
  170. package/dist/components/fields/LiteUrlField.svelte +5 -3
  171. package/dist/components/fields/LiteUrlField.svelte.d.ts +2 -0
  172. package/dist/components/layout/LiteSidebar.svelte +4 -1
  173. package/dist/components/layout/LiteSidebar.svelte.d.ts +2 -0
  174. package/dist/components/pages/LiteCreatePage.svelte +4 -1
  175. package/dist/components/pages/LiteCreatePage.svelte.d.ts +2 -0
  176. package/dist/components/pages/LiteEditPage.svelte +4 -1
  177. package/dist/components/pages/LiteEditPage.svelte.d.ts +2 -0
  178. package/dist/components/pages/LiteListPage.svelte +4 -1
  179. package/dist/components/pages/LiteListPage.svelte.d.ts +2 -0
  180. package/dist/components/pages/LiteShowPage.svelte +4 -1
  181. package/dist/components/pages/LiteShowPage.svelte.d.ts +2 -0
  182. package/dist/components/widgets/LiteAnomalyBadge.svelte +5 -2
  183. package/dist/components/widgets/LiteAnomalyBadge.svelte.d.ts +2 -0
  184. package/dist/components/widgets/LiteAreaChart.svelte +20 -0
  185. package/dist/components/widgets/LiteAreaChart.svelte.d.ts +10 -0
  186. package/dist/components/widgets/LiteChartSvg.svelte +102 -0
  187. package/dist/components/widgets/LiteChartSvg.svelte.d.ts +10 -0
  188. package/dist/components/widgets/LiteChartTable.svelte +44 -0
  189. package/dist/components/widgets/LiteChartTable.svelte.d.ts +10 -0
  190. package/dist/components/widgets/LiteDonutChart.svelte +20 -0
  191. package/dist/components/widgets/LiteDonutChart.svelte.d.ts +10 -0
  192. package/dist/components/widgets/LiteFunnelChart.svelte +20 -0
  193. package/dist/components/widgets/LiteFunnelChart.svelte.d.ts +10 -0
  194. package/dist/components/widgets/LiteGaugeChart.svelte +20 -0
  195. package/dist/components/widgets/LiteGaugeChart.svelte.d.ts +10 -0
  196. package/dist/components/widgets/LiteHeatmapChart.svelte +20 -0
  197. package/dist/components/widgets/LiteHeatmapChart.svelte.d.ts +10 -0
  198. package/dist/components/widgets/LiteInsightCard.svelte +34 -12
  199. package/dist/components/widgets/LiteInsightCard.svelte.d.ts +7 -4
  200. package/dist/components/widgets/LiteLineChart.svelte +6 -3
  201. package/dist/components/widgets/LiteLineChart.svelte.d.ts +0 -5
  202. package/dist/components/widgets/LitePieChart.svelte +5 -3
  203. package/dist/components/widgets/LitePieChart.svelte.d.ts +0 -5
  204. package/dist/components/widgets/LiteRadarChart.svelte +20 -0
  205. package/dist/components/widgets/LiteRadarChart.svelte.d.ts +10 -0
  206. package/dist/components/widgets/LiteRoseChart.svelte +20 -0
  207. package/dist/components/widgets/LiteRoseChart.svelte.d.ts +10 -0
  208. package/dist/components/widgets/LiteScatterChart.svelte +20 -0
  209. package/dist/components/widgets/LiteScatterChart.svelte.d.ts +10 -0
  210. package/dist/components/widgets/LiteWaterfallChart.svelte +20 -0
  211. package/dist/components/widgets/LiteWaterfallChart.svelte.d.ts +10 -0
  212. package/dist/components/widgets/chart-geometry.d.ts +65 -0
  213. package/dist/components/widgets/chart-geometry.js +229 -0
  214. package/dist/components/widgets/index.d.ts +10 -0
  215. package/dist/components/widgets/index.js +10 -0
  216. package/dist/index.d.ts +40 -0
  217. package/dist/index.js +47 -0
  218. package/dist/lite-code-theme.css +139 -0
  219. package/dist/lite.css +108 -1
  220. package/dist/rich-content.d.ts +47 -0
  221. package/dist/rich-content.js +498 -0
  222. package/dist/schema-generator.js +3 -1
  223. package/dist/server-adapter.js +6 -11
  224. package/dist/value-normalization.d.ts +4 -0
  225. package/dist/value-normalization.js +13 -0
  226. package/package.json +18 -4
package/README.md CHANGED
@@ -253,13 +253,31 @@ IE11 before the decision is made.
253
253
 
254
254
  ## Components & Parity (100% Coverage)
255
255
 
256
- `@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.
256
+ `LiteQRCode` is an opt-in subpath export because it statically imports the
257
+ optional `qrcode` peer. The root entry `@svadmin/lite` stays importable without
258
+ it, so the rest of Lite has no extra runtime dependency. Install the peer with
259
+ `bun add qrcode` and import the component directly only when you render QR codes:
260
+
261
+ ```ts
262
+ import LiteQRCode from '@svadmin/lite/components/LiteQRCode.svelte';
263
+ ```
264
+
265
+ `@svadmin/lite` provides **100% component parity** (179/179 components) corresponding to `@svadmin/ui`. See [PARITY.md](./PARITY.md) for the generated complete matrix and status details.
257
266
 
258
267
  ### Core Pages & Layout
259
268
 
260
269
  | Component | Description |
261
270
  |-----------|-------------|
262
271
  | `LiteLayout` | Responsive sidebar + header + main shell (supports nested `menu` links) |
272
+ | `LitePageHeader` / `LiteStatusTabs` / `LiteStatusBadge` | Page heading, status filters and semantic status pills |
273
+ | `LiteMenu` / `LiteAnchor` / `LiteAffix` / `LiteCollapse` / `LiteLink` | Static navigation, in-page anchors and native disclosure |
274
+ | `LiteSpace` / `LiteGrid` / `LiteResizeBox` / `LiteFloatButton` / `LiteBackTop` | Layout and fixed-action primitives |
275
+ | `LiteImage` / `LiteImagePreview` / `LiteVideoPlayer` / `LiteQRCode` | Media rendering with native controls, links and server-rendered QR |
276
+ | `LiteCalendar` / `LiteCarousel` / `LiteTimeline` / `LiteStatistic` / `LiteCountdown` | Read-only dashboards and chronological displays |
277
+ | `LiteCommentThread` / `LiteTour` / `LiteNotificationCenter` / `LiteDetailDrawer` / `LitePopconfirm` | Server-rendered collaboration and disclosure surfaces |
278
+ | `LiteSteps` / `LiteProgress` / `LiteSpin` / `LiteSkeleton` / `LiteResult` | Progress, loading and outcome surfaces |
279
+ | `LiteTree` / `LiteItemList` / `LiteRowActions` / `LiteOtpInput` / `LiteTwoFactorStepper` | Hierarchical data, row actions and verification flows |
280
+ | `LiteAutoComplete` | Native `datalist` suggestions without async client popovers |
263
281
  | `LiteSidebar` / `LiteHeader` | Discrete layout primitives |
264
282
  | `LiteListPage` | Full-featured list view with search, table, bulk actions, and pagination |
265
283
  | `LiteCreatePage` / `LiteEditPage` | Auto-generated CRUD form pages |
@@ -301,6 +319,8 @@ IE11 before the decision is made.
301
319
  |-----------|-------------|
302
320
  | `LiteStatsCard`, `LiteMetricStrip`, `LiteInsightCard`, `LiteAnomalyBadge`, `LiteBadge` | Metric KPI cards/strips and semantic status badges |
303
321
  | `LiteBarChart`, `LiteLineChart`, `LitePieChart` | Server-rendered SVG/HTML charts with fallback data tables |
322
+ | `LiteAreaChart`, `LiteScatterChart`, `LiteRadarChart`, `LiteGaugeChart` | Bounded chart data tables where a client chart engine is unavailable |
323
+ | `LiteFunnelChart`, `LiteHeatmapChart`, `LiteWaterfallChart`, `LiteRoseChart`, `LiteDonutChart` | Bounded chart data tables with the same fallback contract |
304
324
  | `LitePresenceAvatarGroup`, `LiteGanttChart`, `LiteOfflineSyncBanner` | Presence, schedule, and offline mutation status rendered without client hydration |
305
325
 
306
326
  ### Compatibility & Degradation Primitives
@@ -335,7 +355,7 @@ To monitor and maintain 100% component parity between `@svadmin/ui` and `@svadmi
335
355
  - **CLI Dashboard**: Run `bun run check:parity` to inspect the live coverage matrix in terminal.
336
356
  - **Parity Matrix Document**: [PARITY.md](./PARITY.md) is auto-generated with exhaustive module-by-module tables.
337
357
  - **Machine-Readable JSON**: `packages/lite/parity.json` provides structured data for automation.
338
- - **Interactive Showroom**: Visit `/lite/parity` in the example app to interactively preview all 103 components and live metrics.
358
+ - **Interactive Showroom**: Visit `/lite/parity` in the example app to interactively preview all 179 components and live metrics.
339
359
  - **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.
340
360
 
341
361
  ## Server Utilities
@@ -352,6 +372,43 @@ To monitor and maintain 100% component parity between `@svadmin/ui` and `@svadmi
352
372
 
353
373
  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.
354
374
 
375
+ ## Styling Hooks
376
+
377
+ Most components accept a single `class` that is **merged** with the built-in class
378
+ list, never replacing it:
379
+
380
+ ```svelte
381
+ <LiteStatsCard class="dense" label="Orders" value={42} />
382
+ <!-- renders class="lite-stats-card lite-card dense" -->
383
+ ```
384
+
385
+ Fields take the hook on both of their render roots, so one prop covers show and
386
+ edit mode (`LiteTextField` → `.lite-field-value` / `.lite-field-edit`,
387
+ `LiteTagField` → tag container / `.lite-tags-input`, …).
388
+
389
+ Structural components take **named** hooks, because the part you usually restyle is
390
+ inside the wrapper:
391
+
392
+ | Component | Hooks | Lands on |
393
+ | --- | --- | --- |
394
+ | `LiteLayout` | `class`, `classSidebar`, `classMobileNav`, `classMain` | wrapper, desktop sidebar, mobile nav, main region |
395
+ | `LiteSidebar` | `class` | the sidebar `nav` |
396
+ | `LiteSplitPaneLayout` | `class`, `classPane1`, `classDivider`, `classPane2` | container, first pane, divider, second pane |
397
+
398
+ Omitting every hook leaves the rendered HTML byte-identical (the class attribute is
399
+ built with a trimmed template, not an empty interpolation). This is covered by
400
+ `packages/lite/src/components/LiteClassHooks.test.svelte.ts`.
401
+
402
+ Styling hook coverage — how many `exact` mappings expose the same `class` entry the
403
+ reference component does — is tracked separately in `CLASS-HOOKS.md` and never
404
+ changes a parity status. `Lite` ships `lite.css`, so a missing hook is styling debt,
405
+ not a capability gap. Regenerate both artifacts with:
406
+
407
+ ```bash
408
+ bun run check:parity # writes PARITY.md, parity.json, CLASS-HOOKS.md, class-hooks.json
409
+ bun run check:parity:verify
410
+ ```
411
+
355
412
  ## CSS
356
413
 
357
414
  Import `@svadmin/lite/lite.css` in your layout. It's fully self-contained:
@@ -364,6 +421,18 @@ Import `@svadmin/lite/lite.css` in your layout. It's fully self-contained:
364
421
  - Print-optimized styles
365
422
  - ~800 lines, ~19KB unminified
366
423
 
424
+ Rich content previews (Markdown, insight, comments, notifications, activity) ship
425
+ literal `tok-*` token colours here. Hosts that can rely on CSS custom properties
426
+ may also import the opt-in theme:
427
+
428
+ ```ts
429
+ import '@svadmin/lite/lite-code-theme.css';
430
+ ```
431
+
432
+ It exposes `--lite-token-{comment,keyword,string,number,function,type}` with the
433
+ literal palette as fallbacks and a `lite-dark` preset class, so one override
434
+ re-themes every preview surface.
435
+
367
436
  This CSS baseline helps older browsers, but the generated Svelte/SvelteKit application and any Tailwind v4 UI used alongside Lite still require the browser targets configured by those tools (Tailwind v4 itself targets modern browsers).
368
437
 
369
438
  ## Optional: Progressive Enhancement
@@ -1,4 +1,6 @@
1
1
  <script lang="ts">
2
+ import { renderRichContent, type MarkdownRenderOptions } from '../rich-content.js';
3
+
2
4
  interface LiteActivityItem {
3
5
  id: string;
4
6
  user?: { name: string };
@@ -13,16 +15,28 @@
13
15
  activities?: LiteActivityItem[];
14
16
  action?: string;
15
17
  method?: 'get' | 'post' | 'dialog' | 'GET' | 'POST' | 'DIALOG' | null;
18
+ /** Render note bodies as Markdown/allowlisted HTML. Defaults to plain text. */
19
+ richContent?: boolean;
20
+ richContentOptions?: MarkdownRenderOptions;
21
+ /** Caller class merged with the built-in class list. */
22
+ class?: string;
16
23
  }
17
24
 
18
25
  let {
19
26
  activities = [],
20
27
  action = '',
21
28
  method = 'POST',
29
+ richContent = false,
30
+ richContentOptions,
31
+ class: className = '',
22
32
  }: Props = $props();
33
+
34
+ function body(value: string): string {
35
+ return renderRichContent(value, richContentOptions);
36
+ }
23
37
  </script>
24
38
 
25
- <div class="lite-activity-card">
39
+ <div class="lite-activity-card {className}">
26
40
  <div class="lite-activity-header">
27
41
  <strong>Activity & Timeline Stream</strong>
28
42
  </div>
@@ -37,7 +51,12 @@
37
51
  </div>
38
52
  {#if act.comment}
39
53
  <div class="lite-activity-comment">
40
- {act.comment}
54
+ {#if richContent}
55
+ <!-- eslint-disable-next-line svelte/no-at-html-tags -- 内容由 renderRichContent 转义或白名单过滤,高亮回调仅允许可信服务端实现。 -->
56
+ <div class="lite-activity-rich">{@html body(act.comment)}</div>
57
+ {:else}
58
+ {act.comment}
59
+ {/if}
41
60
  </div>
42
61
  {/if}
43
62
  </li>
@@ -95,4 +114,7 @@
95
114
  margin-top: 4px;
96
115
  color: #4E5969;
97
116
  }
117
+ .lite-activity-rich :global(p) { margin: 0; }
118
+ .lite-activity-rich :global(a) { color: #165DFF; }
119
+ .lite-activity-rich :global(code) { padding: 1px 4px; border-radius: 3px; background: #F2F3F5; font-family: monospace; font-size: 12px; }
98
120
  </style>
@@ -1,3 +1,4 @@
1
+ import { type MarkdownRenderOptions } from '../rich-content.js';
1
2
  interface LiteActivityItem {
2
3
  id: string;
3
4
  user?: {
@@ -13,6 +14,11 @@ interface Props {
13
14
  activities?: LiteActivityItem[];
14
15
  action?: string;
15
16
  method?: 'get' | 'post' | 'dialog' | 'GET' | 'POST' | 'DIALOG' | null;
17
+ /** Render note bodies as Markdown/allowlisted HTML. Defaults to plain text. */
18
+ richContent?: boolean;
19
+ richContentOptions?: MarkdownRenderOptions;
20
+ /** Caller class merged with the built-in class list. */
21
+ class?: string;
16
22
  }
17
23
  declare const LiteActivityFeed: import("svelte").Component<Props, {}, "">;
18
24
  type LiteActivityFeed = ReturnType<typeof LiteActivityFeed>;
@@ -0,0 +1,29 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ top?: number;
6
+ bottom?: number;
7
+ zIndex?: number;
8
+ label?: string;
9
+ /** Caller class merged with the built-in class list. */
10
+ class?: string;
11
+ children: Snippet;
12
+ }
13
+
14
+ let { top = 16, bottom, zIndex = 10, label = 'Affixed content', class: className = '', children }: Props = $props();
15
+
16
+ // The reference applies `top` always and `bottom` when provided; dropping `top`
17
+ // whenever `bottom` was set made the offset silently wrong.
18
+ const style = $derived(
19
+ `top:${top}px;${bottom === undefined ? '' : `bottom:${bottom}px;`}z-index:${zIndex}`,
20
+ );
21
+ </script>
22
+
23
+ <div class={`lite-affix ${className}`.trim()} style={style} aria-label={label}>
24
+ {@render children()}
25
+ </div>
26
+
27
+ <style>
28
+ .lite-affix { position: sticky; }
29
+ </style>
@@ -0,0 +1,13 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ top?: number;
4
+ bottom?: number;
5
+ zIndex?: number;
6
+ label?: string;
7
+ /** Caller class merged with the built-in class list. */
8
+ class?: string;
9
+ children: Snippet;
10
+ }
11
+ declare const LiteAffix: import("svelte").Component<Props, {}, "">;
12
+ type LiteAffix = ReturnType<typeof LiteAffix>;
13
+ export default LiteAffix;
@@ -0,0 +1,38 @@
1
+ <script lang="ts">
2
+ interface AnchorItem {
3
+ id: string;
4
+ label: string;
5
+ level?: number;
6
+ }
7
+
8
+ interface Props {
9
+ items: AnchorItem[];
10
+ label?: string;
11
+ /** Caller class merged with the built-in class list. */
12
+ class?: string;
13
+ }
14
+
15
+ let { items, label = 'On this page', class: className = '' }: Props = $props();
16
+ </script>
17
+
18
+ <nav class="lite-anchor {className}" aria-label={label}>
19
+ <p class="lite-anchor__title">{label}</p>
20
+ <ul>
21
+ {#each items as item (item.id)}
22
+ <li style={`padding-left:${Math.max(0, (item.level ?? 1) - 1) * 12}px`}>
23
+ <a href={`#${item.id}`}>{item.label}</a>
24
+ </li>
25
+ {/each}
26
+ </ul>
27
+ </nav>
28
+
29
+ <style>
30
+ .lite-anchor { display: block; min-width: 0; }
31
+ .lite-anchor__title { margin: 0; color: #86909C; font-size: 12px; font-weight: 600; text-transform: uppercase; letter-spacing: 0.04em; }
32
+ .lite-anchor ul { display: block; margin: 0; padding: 0; list-style: none; }
33
+ .lite-anchor a { display: block; padding: 4px 8px; border-left: 2px solid transparent; color: #4E5969; font-size: 13px; text-decoration: none; }
34
+ .lite-anchor a:hover { border-left-color: #165DFF; background: #F7F8FA; color: #165DFF; }
35
+
36
+ .lite-anchor > * + * { margin-top: 8px; }
37
+ .lite-anchor li + li { margin-top: 4px; }
38
+ </style>
@@ -0,0 +1,14 @@
1
+ interface AnchorItem {
2
+ id: string;
3
+ label: string;
4
+ level?: number;
5
+ }
6
+ interface Props {
7
+ items: AnchorItem[];
8
+ label?: string;
9
+ /** Caller class merged with the built-in class list. */
10
+ class?: string;
11
+ }
12
+ declare const LiteAnchor: import("svelte").Component<Props, {}, "">;
13
+ type LiteAnchor = ReturnType<typeof LiteAnchor>;
14
+ export default LiteAnchor;
@@ -6,6 +6,8 @@
6
6
  status?: 'pending' | 'approved' | 'rejected' | 'recalled';
7
7
  action?: string;
8
8
  children?: Snippet;
9
+ /** Caller class merged with the built-in class list. */
10
+ class?: string;
9
11
  }
10
12
 
11
13
  let {
@@ -13,10 +15,11 @@
13
15
  status = 'pending',
14
16
  action = '',
15
17
  children,
18
+ class: className = '',
16
19
  }: Props = $props();
17
20
  </script>
18
21
 
19
- <div class="lite-approval-card lite-form-group">
22
+ <div class="lite-approval-card lite-form-group {className}">
20
23
  <div class="lite-approval-header">
21
24
  <strong>{title}</strong>
22
25
  <span class="lite-badge lite-badge-{status}">{status}</span>
@@ -4,6 +4,8 @@ interface Props {
4
4
  status?: 'pending' | 'approved' | 'rejected' | 'recalled';
5
5
  action?: string;
6
6
  children?: Snippet;
7
+ /** Caller class merged with the built-in class list. */
8
+ class?: string;
7
9
  }
8
10
  declare const LiteApprovalActionCard: import("svelte").Component<Props, {}, "">;
9
11
  type LiteApprovalActionCard = ReturnType<typeof LiteApprovalActionCard>;
@@ -0,0 +1,41 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ name: string;
4
+ options: string[];
5
+ value?: string;
6
+ label?: string;
7
+ placeholder?: string;
8
+ required?: boolean;
9
+ disabled?: boolean;
10
+ listId?: string;
11
+ }
12
+
13
+ let {
14
+ name,
15
+ options,
16
+ value = '',
17
+ label,
18
+ placeholder = 'Type or choose a suggestion',
19
+ required = false,
20
+ disabled = false,
21
+ listId = `${name}-options`,
22
+ }: Props = $props();
23
+ </script>
24
+
25
+ <label class="lite-form-group">
26
+ {#if label}<span>{label}</span>{/if}
27
+ <input
28
+ class="lite-input"
29
+ type="text"
30
+ {name}
31
+ {value}
32
+ {placeholder}
33
+ {required}
34
+ {disabled}
35
+ list={listId}
36
+ autocomplete="off"
37
+ />
38
+ <datalist id={listId}>
39
+ {#each options as option (option)}<option value={option}></option>{/each}
40
+ </datalist>
41
+ </label>
@@ -0,0 +1,13 @@
1
+ interface Props {
2
+ name: string;
3
+ options: string[];
4
+ value?: string;
5
+ label?: string;
6
+ placeholder?: string;
7
+ required?: boolean;
8
+ disabled?: boolean;
9
+ listId?: string;
10
+ }
11
+ declare const LiteAutoComplete: import("svelte").Component<Props, {}, "">;
12
+ type LiteAutoComplete = ReturnType<typeof LiteAutoComplete>;
13
+ export default LiteAutoComplete;
@@ -0,0 +1,16 @@
1
+ <script lang="ts">
2
+ interface Props {
3
+ href?: string;
4
+ label?: string;
5
+ thresholdText?: string;
6
+ }
7
+
8
+ let { href = '#top', label = 'Back to top', thresholdText = '↑ Top' }: Props = $props();
9
+ </script>
10
+
11
+ <a class="lite-back-top" {href} aria-label={label}>{thresholdText}</a>
12
+
13
+ <style>
14
+ .lite-back-top { position: fixed; right: 24px; bottom: 80px; display: inline-grid; place-items: center; min-width: 40px; height: 40px; padding: 0 12px; border: 1px solid #E5E6EB; border-radius: 999px; background: #fff; color: #1D2129; box-shadow: 0 6px 20px rgba(29, 33, 41, 0.16); font-size: 12px; text-decoration: none; }
15
+ .lite-back-top:hover { color: #165DFF; text-decoration: none; }
16
+ </style>
@@ -0,0 +1,8 @@
1
+ interface Props {
2
+ href?: string;
3
+ label?: string;
4
+ thresholdText?: string;
5
+ }
6
+ declare const LiteBackTop: import("svelte").Component<Props, {}, "">;
7
+ type LiteBackTop = ReturnType<typeof LiteBackTop>;
8
+ export default LiteBackTop;
@@ -13,15 +13,18 @@
13
13
  items: BreadcrumbItem[];
14
14
  /** Separator character between items */
15
15
  separator?: string;
16
+ /** Caller class merged with the built-in class list. */
17
+ class?: string;
16
18
  }
17
19
 
18
20
  let {
19
21
  items,
20
22
  separator = '/',
23
+ class: className = '',
21
24
  }: Props = $props();
22
25
  </script>
23
26
 
24
- <nav class="lite-breadcrumbs" aria-label="Breadcrumb">
27
+ <nav class="lite-breadcrumbs {className}" aria-label="Breadcrumb">
25
28
  <ol>
26
29
  {#each items as item, i (i)}
27
30
  <li>
@@ -10,6 +10,8 @@ interface Props {
10
10
  items: BreadcrumbItem[];
11
11
  /** Separator character between items */
12
12
  separator?: string;
13
+ /** Caller class merged with the built-in class list. */
14
+ class?: string;
13
15
  }
14
16
  declare const LiteBreadcrumbs: import("svelte").Component<Props, {}, "">;
15
17
  type LiteBreadcrumbs = ReturnType<typeof LiteBreadcrumbs>;
@@ -0,0 +1,124 @@
1
+ <script lang="ts">
2
+ interface CalendarEvent {
3
+ id: string;
4
+ date: string;
5
+ label: string;
6
+ href?: string;
7
+ tone?: 'neutral' | 'info' | 'success' | 'warning' | 'danger';
8
+ }
9
+
10
+ interface Props {
11
+ value?: string;
12
+ events?: CalendarEvent[];
13
+ locale?: string;
14
+ weekStartsOn?: 0 | 1;
15
+ min?: string;
16
+ max?: string;
17
+ title?: string;
18
+ hrefFor?: (iso: string) => string;
19
+ }
20
+
21
+ let {
22
+ value = '',
23
+ events = [],
24
+ locale,
25
+ weekStartsOn = 0,
26
+ min,
27
+ max,
28
+ title,
29
+ hrefFor,
30
+ }: Props = $props();
31
+
32
+ const initial = $derived(value ? new Date(`${value}T12:00:00`) : new Date());
33
+ const year = $derived(initial.getFullYear());
34
+ const month = $derived(initial.getMonth());
35
+ const heading = $derived(title ?? new Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }).format(new Date(year, month, 1)));
36
+ const weekdays = $derived.by(() => {
37
+ const format = new Intl.DateTimeFormat(locale, { weekday: 'short' });
38
+ return Array.from({ length: 7 }, (_, index) => format.format(new Date(2024, 0, 7 + ((index + weekStartsOn) % 7))));
39
+ });
40
+ const days = $derived.by(() => {
41
+ const first = new Date(year, month, 1);
42
+ const offset = (first.getDay() - weekStartsOn + 7) % 7;
43
+ return Array.from({ length: 42 }, (_, index) => {
44
+ const date = new Date(year, month, 1 - offset + index);
45
+ const iso = toIso(date);
46
+ return {
47
+ iso,
48
+ day: date.getDate(),
49
+ outside: date.getMonth() !== month,
50
+ selected: iso === value,
51
+ events: events.filter((event) => event.date === iso),
52
+ disabled: Boolean(min && iso < min) || Boolean(max && iso > max),
53
+ };
54
+ });
55
+ });
56
+ const upcoming = $derived(events.filter((event) => !value || event.date >= value).slice(0, 8));
57
+
58
+ function toIso(date: Date): string {
59
+ return `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')}`;
60
+ }
61
+ </script>
62
+
63
+ <section class="lite-calendar lite-card" aria-label={heading}>
64
+ <header>
65
+ <h2>{heading}</h2>
66
+ {#if value}<span>{value}</span>{/if}
67
+ </header>
68
+ <table>
69
+ <thead>
70
+ <tr>{#each weekdays as weekday (weekday)}<th scope="col">{weekday}</th>{/each}</tr>
71
+ </thead>
72
+ <tbody>
73
+ {#each Array.from({ length: 6 }, (_, week) => week) as week (week)}
74
+ <tr>
75
+ {#each days.slice(week * 7, week * 7 + 7) as day (day.iso)}
76
+ <td data-outside={day.outside || undefined} data-selected={day.selected || undefined} data-disabled={day.disabled || undefined}>
77
+ {#if day.disabled}
78
+ <span>{day.day}</span>
79
+ {:else if hrefFor}
80
+ <a href={hrefFor(day.iso)} aria-current={day.selected ? 'date' : undefined}>{day.day}</a>
81
+ {:else}
82
+ <span aria-current={day.selected ? 'date' : undefined}>{day.day}</span>
83
+ {/if}
84
+ {#if day.events.length > 0}<span class="lite-calendar__dot" title={`${day.events.length} event(s)`}></span>{/if}
85
+ </td>
86
+ {/each}
87
+ </tr>
88
+ {/each}
89
+ </tbody>
90
+ </table>
91
+ {#if upcoming.length > 0}
92
+ <ul class="lite-calendar__events">
93
+ {#each upcoming as event (event.id)}
94
+ <li data-tone={event.tone ?? 'neutral'}>
95
+ <time>{event.date}</time>
96
+ {#if event.href}<a href={event.href}>{event.label}</a>{:else}<span>{event.label}</span>{/if}
97
+ </li>
98
+ {/each}
99
+ </ul>
100
+ {/if}
101
+ </section>
102
+
103
+ <style>
104
+ .lite-calendar { padding: 0; overflow: hidden; }
105
+ .lite-calendar header { display: flex; align-items: baseline; justify-content: space-between; padding: 12px 16px; border-bottom: 1px solid #E5E6EB; }
106
+ .lite-calendar h2 { margin: 0; color: #1D2129; font-size: 14px; }
107
+ .lite-calendar header span { color: #86909C; font-size: 12px; }
108
+ .lite-calendar table { width: 100%; border-collapse: collapse; table-layout: fixed; }
109
+ .lite-calendar th { padding: 8px 4px; color: #86909C; font-size: 11px; font-weight: 600; text-align: center; }
110
+ .lite-calendar td { position: relative; height: 40px; padding: 4px; border: 1px solid #F2F3F5; color: #1D2129; font-size: 12px; text-align: center; }
111
+ .lite-calendar td a, .lite-calendar td > span:first-child { display: inline-grid; place-items: center; width: 28px; height: 28px; border-radius: 999px; color: inherit; text-decoration: none; }
112
+ .lite-calendar td a:hover { background: #F7F8FA; color: #165DFF; }
113
+ .lite-calendar td[data-selected] a, .lite-calendar td[data-selected] > span:first-child { background: #165DFF; color: #fff; }
114
+ .lite-calendar td[data-outside] { color: #C9CDD4; }
115
+ .lite-calendar td[data-disabled] { color: #E5E6EB; }
116
+ .lite-calendar__dot { position: absolute; right: 50%; bottom: 3px; width: 4px; height: 4px; margin-right: -2px; border-radius: 999px; background: #165DFF; }
117
+ .lite-calendar__events { margin: 0; padding: 8px 16px 12px; border-top: 1px solid #E5E6EB; list-style: none; }
118
+ .lite-calendar__events li { display: flex; padding: 4px 0; color: #4E5969; font-size: 12px; }
119
+ .lite-calendar__events time { color: #86909C; font-variant-numeric: tabular-nums; }
120
+ .lite-calendar__events a { color: #165DFF; }
121
+
122
+ .lite-calendar header > * + * { margin-left: 12px; }
123
+ .lite-calendar__events li > * + * { margin-left: 8px; }
124
+ </style>
@@ -0,0 +1,20 @@
1
+ interface CalendarEvent {
2
+ id: string;
3
+ date: string;
4
+ label: string;
5
+ href?: string;
6
+ tone?: 'neutral' | 'info' | 'success' | 'warning' | 'danger';
7
+ }
8
+ interface Props {
9
+ value?: string;
10
+ events?: CalendarEvent[];
11
+ locale?: string;
12
+ weekStartsOn?: 0 | 1;
13
+ min?: string;
14
+ max?: string;
15
+ title?: string;
16
+ hrefFor?: (iso: string) => string;
17
+ }
18
+ declare const LiteCalendar: import("svelte").Component<Props, {}, "">;
19
+ type LiteCalendar = ReturnType<typeof LiteCalendar>;
20
+ export default LiteCalendar;
@@ -0,0 +1,72 @@
1
+ <script lang="ts">
2
+ import type { Snippet } from 'svelte';
3
+
4
+ interface Props {
5
+ count: number;
6
+ label?: string;
7
+ id?: string;
8
+ /** Zero-based slide rendered as current (matches the reference `index`). */
9
+ index?: number;
10
+ /** Caller class merged with the built-in class list. */
11
+ class?: string;
12
+ children?: Snippet<[number]>;
13
+ }
14
+
15
+ let {
16
+ count,
17
+ label = 'Carousel',
18
+ id = 'lite-carousel',
19
+ index = 0,
20
+ class: className = '',
21
+ children,
22
+ }: Props = $props();
23
+
24
+ const current = $derived(count > 0 ? Math.min(Math.max(0, Math.trunc(index)), count - 1) : 0);
25
+ </script>
26
+
27
+ <section
28
+ class={`lite-carousel ${className}`.trim()}
29
+ aria-label={label}
30
+ aria-roledescription="carousel"
31
+ data-current={current + 1}
32
+ >
33
+ <div class="lite-carousel__track">
34
+ {#each Array.from({ length: Math.max(0, count) }, (_, index) => index) as index (index)}
35
+ <div
36
+ class="lite-carousel__slide"
37
+ id={`${id}-${index + 1}`}
38
+ role="group"
39
+ aria-roledescription="slide"
40
+ aria-label={`${index + 1} / ${count}`}
41
+ data-current={index === current || undefined}
42
+ >
43
+ {#if children}{@render children(index)}{:else}<p class="lite-muted">Slide {index + 1}</p>{/if}
44
+ </div>
45
+ {/each}
46
+ </div>
47
+ {#if count > 1}
48
+ <nav class="lite-carousel__dots" aria-label="Slides">
49
+ {#each Array.from({ length: count }, (_, index) => index) as index (index)}
50
+ <a
51
+ href={`#${id}-${index + 1}`}
52
+ aria-label={`Go to slide ${index + 1}`}
53
+ aria-current={index === current ? 'true' : undefined}
54
+ class={index === current ? 'active' : undefined}
55
+ >{index + 1}</a>
56
+ {/each}
57
+ </nav>
58
+ {/if}
59
+ </section>
60
+
61
+ <style>
62
+ .lite-carousel { display: block; }
63
+ .lite-carousel__track { display: flex; overflow-x: auto; scroll-snap-type: x mandatory; border: 1px solid #E5E6EB; border-radius: 8px; background: #fff; }
64
+ .lite-carousel__slide { flex: 0 0 100%; min-width: 0; padding: 16px; scroll-snap-align: start; }
65
+ .lite-carousel__dots { display: flex; flex-wrap: wrap; justify-content: center; }
66
+ .lite-carousel__dots a { display: inline-grid; place-items: center; min-width: 24px; height: 24px; border: 1px solid #E5E6EB; border-radius: 999px; color: #4E5969; font-size: 11px; text-decoration: none; }
67
+ .lite-carousel__dots a:hover { border-color: #165DFF; color: #165DFF; text-decoration: none; }
68
+ .lite-carousel__dots a.active { border-color: #165DFF; background: #E8F3FF; color: #165DFF; }
69
+
70
+ .lite-carousel__dots a + a { margin-left: 4px; }
71
+ .lite-carousel__track { margin-bottom: 8px; }
72
+ </style>
@@ -0,0 +1,14 @@
1
+ import type { Snippet } from 'svelte';
2
+ interface Props {
3
+ count: number;
4
+ label?: string;
5
+ id?: string;
6
+ /** Zero-based slide rendered as current (matches the reference `index`). */
7
+ index?: number;
8
+ /** Caller class merged with the built-in class list. */
9
+ class?: string;
10
+ children?: Snippet<[number]>;
11
+ }
12
+ declare const LiteCarousel: import("svelte").Component<Props, {}, "">;
13
+ type LiteCarousel = ReturnType<typeof LiteCarousel>;
14
+ export default LiteCarousel;