@happyvertical/smrt-content 0.30.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 (291) hide show
  1. package/AGENTS.md +194 -0
  2. package/CLAUDE.md +1 -0
  3. package/LICENSE +7 -0
  4. package/README.md +634 -0
  5. package/dist/__smrt-register__.d.ts +2 -0
  6. package/dist/__smrt-register__.d.ts.map +1 -0
  7. package/dist/asset-associable.d.ts +115 -0
  8. package/dist/asset-associable.d.ts.map +1 -0
  9. package/dist/body-format.d.ts +29 -0
  10. package/dist/body-format.d.ts.map +1 -0
  11. package/dist/body-format.js +604 -0
  12. package/dist/body-format.js.map +1 -0
  13. package/dist/content-asset.d.ts +17 -0
  14. package/dist/content-asset.d.ts.map +1 -0
  15. package/dist/content-assets.d.ts +10 -0
  16. package/dist/content-assets.d.ts.map +1 -0
  17. package/dist/content-chat-handlers.d.ts +115 -0
  18. package/dist/content-chat-handlers.d.ts.map +1 -0
  19. package/dist/content-chat-prompts.d.ts +3 -0
  20. package/dist/content-chat-prompts.d.ts.map +1 -0
  21. package/dist/content-chat-session.d.ts +26 -0
  22. package/dist/content-chat-session.d.ts.map +1 -0
  23. package/dist/content-contribution-attachment.d.ts +42 -0
  24. package/dist/content-contribution-attachment.d.ts.map +1 -0
  25. package/dist/content-contribution-attachments.d.ts +8 -0
  26. package/dist/content-contribution-attachments.d.ts.map +1 -0
  27. package/dist/content-contribution-config.d.ts +84 -0
  28. package/dist/content-contribution-config.d.ts.map +1 -0
  29. package/dist/content-contribution-revision.d.ts +38 -0
  30. package/dist/content-contribution-revision.d.ts.map +1 -0
  31. package/dist/content-contribution-revisions.d.ts +8 -0
  32. package/dist/content-contribution-revisions.d.ts.map +1 -0
  33. package/dist/content-contribution-type.d.ts +51 -0
  34. package/dist/content-contribution-type.d.ts.map +1 -0
  35. package/dist/content-contribution-types.d.ts +7 -0
  36. package/dist/content-contribution-types.d.ts.map +1 -0
  37. package/dist/content-contribution.d.ts +161 -0
  38. package/dist/content-contribution.d.ts.map +1 -0
  39. package/dist/content-contributions.d.ts +53 -0
  40. package/dist/content-contributions.d.ts.map +1 -0
  41. package/dist/content-contributor.d.ts +30 -0
  42. package/dist/content-contributor.d.ts.map +1 -0
  43. package/dist/content-contributors.d.ts +13 -0
  44. package/dist/content-contributors.d.ts.map +1 -0
  45. package/dist/content-correction.d.ts +39 -0
  46. package/dist/content-correction.d.ts.map +1 -0
  47. package/dist/content-corrections.d.ts +9 -0
  48. package/dist/content-corrections.d.ts.map +1 -0
  49. package/dist/content-editor-assistant.d.ts +68 -0
  50. package/dist/content-editor-assistant.d.ts.map +1 -0
  51. package/dist/content-editor-assistant.js +97 -0
  52. package/dist/content-editor-assistant.js.map +1 -0
  53. package/dist/content-feed-parser.d.ts +19 -0
  54. package/dist/content-feed-parser.d.ts.map +1 -0
  55. package/dist/content-feed-source.d.ts +52 -0
  56. package/dist/content-feed-source.d.ts.map +1 -0
  57. package/dist/content-feed-sources.d.ts +11 -0
  58. package/dist/content-feed-sources.d.ts.map +1 -0
  59. package/dist/content-feed-sync.d.ts +23 -0
  60. package/dist/content-feed-sync.d.ts.map +1 -0
  61. package/dist/content-governance-assignment.d.ts +42 -0
  62. package/dist/content-governance-assignment.d.ts.map +1 -0
  63. package/dist/content-governance-assignments.d.ts +11 -0
  64. package/dist/content-governance-assignments.d.ts.map +1 -0
  65. package/dist/content-governance-policies.d.ts +7 -0
  66. package/dist/content-governance-policies.d.ts.map +1 -0
  67. package/dist/content-governance-policy.d.ts +29 -0
  68. package/dist/content-governance-policy.d.ts.map +1 -0
  69. package/dist/content-governance-profile.d.ts +31 -0
  70. package/dist/content-governance-profile.d.ts.map +1 -0
  71. package/dist/content-governance-profiles.d.ts +7 -0
  72. package/dist/content-governance-profiles.d.ts.map +1 -0
  73. package/dist/content-governance.d.ts +188 -0
  74. package/dist/content-governance.d.ts.map +1 -0
  75. package/dist/content-prompts.d.ts +10 -0
  76. package/dist/content-prompts.d.ts.map +1 -0
  77. package/dist/content-reference.d.ts +17 -0
  78. package/dist/content-reference.d.ts.map +1 -0
  79. package/dist/content-references.d.ts +55 -0
  80. package/dist/content-references.d.ts.map +1 -0
  81. package/dist/content-review.d.ts +34 -0
  82. package/dist/content-review.d.ts.map +1 -0
  83. package/dist/content-reviews.d.ts +21 -0
  84. package/dist/content-reviews.d.ts.map +1 -0
  85. package/dist/content-transparency.d.ts +72 -0
  86. package/dist/content-transparency.d.ts.map +1 -0
  87. package/dist/content-types.d.ts +51 -0
  88. package/dist/content-types.d.ts.map +1 -0
  89. package/dist/content-version.d.ts +38 -0
  90. package/dist/content-version.d.ts.map +1 -0
  91. package/dist/content-versions.d.ts +16 -0
  92. package/dist/content-versions.d.ts.map +1 -0
  93. package/dist/content.d.ts +736 -0
  94. package/dist/content.d.ts.map +1 -0
  95. package/dist/contents.d.ts +292 -0
  96. package/dist/contents.d.ts.map +1 -0
  97. package/dist/database-utils.d.ts +3 -0
  98. package/dist/database-utils.d.ts.map +1 -0
  99. package/dist/index.d.ts +78 -0
  100. package/dist/index.d.ts.map +1 -0
  101. package/dist/index.js +11602 -0
  102. package/dist/index.js.map +1 -0
  103. package/dist/manifest.json +12308 -0
  104. package/dist/mock-smrt-client.d.ts +493 -0
  105. package/dist/mock-smrt-client.d.ts.map +1 -0
  106. package/dist/mock-smrt-client.js +390 -0
  107. package/dist/mock-smrt-client.js.map +1 -0
  108. package/dist/playground.d.ts +2 -0
  109. package/dist/playground.d.ts.map +1 -0
  110. package/dist/playground.js +454 -0
  111. package/dist/playground.js.map +1 -0
  112. package/dist/publish-readiness.d.ts +30 -0
  113. package/dist/publish-readiness.d.ts.map +1 -0
  114. package/dist/publish-readiness.js +74 -0
  115. package/dist/publish-readiness.js.map +1 -0
  116. package/dist/safe-remote-url.d.ts +52 -0
  117. package/dist/safe-remote-url.d.ts.map +1 -0
  118. package/dist/serialization.d.ts +78 -0
  119. package/dist/serialization.d.ts.map +1 -0
  120. package/dist/smrt-knowledge.json +6130 -0
  121. package/dist/svelte/api.d.ts +3 -0
  122. package/dist/svelte/api.d.ts.map +1 -0
  123. package/dist/svelte/api.js +10 -0
  124. package/dist/svelte/components/ArticleCard.svelte +159 -0
  125. package/dist/svelte/components/ArticleCard.svelte.d.ts +17 -0
  126. package/dist/svelte/components/ArticleCard.svelte.d.ts.map +1 -0
  127. package/dist/svelte/components/ArticleList.svelte +75 -0
  128. package/dist/svelte/components/ArticleList.svelte.d.ts +21 -0
  129. package/dist/svelte/components/ArticleList.svelte.d.ts.map +1 -0
  130. package/dist/svelte/components/ContentAgentChat.svelte +652 -0
  131. package/dist/svelte/components/ContentAgentChat.svelte.d.ts +17 -0
  132. package/dist/svelte/components/ContentAgentChat.svelte.d.ts.map +1 -0
  133. package/dist/svelte/components/ContentBodyEditor.svelte +1446 -0
  134. package/dist/svelte/components/ContentBodyEditor.svelte.d.ts +25 -0
  135. package/dist/svelte/components/ContentBodyEditor.svelte.d.ts.map +1 -0
  136. package/dist/svelte/components/ContentBodyRenderer.svelte +152 -0
  137. package/dist/svelte/components/ContentBodyRenderer.svelte.d.ts +10 -0
  138. package/dist/svelte/components/ContentBodyRenderer.svelte.d.ts.map +1 -0
  139. package/dist/svelte/components/ContentClaimAuditTool.svelte +441 -0
  140. package/dist/svelte/components/ContentClaimAuditTool.svelte.d.ts +12 -0
  141. package/dist/svelte/components/ContentClaimAuditTool.svelte.d.ts.map +1 -0
  142. package/dist/svelte/components/ContentContributionForm.svelte +226 -0
  143. package/dist/svelte/components/ContentContributionForm.svelte.d.ts +23 -0
  144. package/dist/svelte/components/ContentContributionForm.svelte.d.ts.map +1 -0
  145. package/dist/svelte/components/ContentContributionInbox.svelte +322 -0
  146. package/dist/svelte/components/ContentContributionInbox.svelte.d.ts +22 -0
  147. package/dist/svelte/components/ContentContributionInbox.svelte.d.ts.map +1 -0
  148. package/dist/svelte/components/ContentContributionPortal.svelte +182 -0
  149. package/dist/svelte/components/ContentContributionPortal.svelte.d.ts +12 -0
  150. package/dist/svelte/components/ContentContributionPortal.svelte.d.ts.map +1 -0
  151. package/dist/svelte/components/ContentContributionTypeManager.svelte +281 -0
  152. package/dist/svelte/components/ContentContributionTypeManager.svelte.d.ts +10 -0
  153. package/dist/svelte/components/ContentContributionTypeManager.svelte.d.ts.map +1 -0
  154. package/dist/svelte/components/ContentContributorManager.svelte +140 -0
  155. package/dist/svelte/components/ContentContributorManager.svelte.d.ts +10 -0
  156. package/dist/svelte/components/ContentContributorManager.svelte.d.ts.map +1 -0
  157. package/dist/svelte/components/ContentCorrectionsTool.svelte +361 -0
  158. package/dist/svelte/components/ContentCorrectionsTool.svelte.d.ts +11 -0
  159. package/dist/svelte/components/ContentCorrectionsTool.svelte.d.ts.map +1 -0
  160. package/dist/svelte/components/ContentEditor.svelte +2166 -0
  161. package/dist/svelte/components/ContentEditor.svelte.d.ts +26 -0
  162. package/dist/svelte/components/ContentEditor.svelte.d.ts.map +1 -0
  163. package/dist/svelte/components/ContentGovernanceAssignmentEditor.svelte +199 -0
  164. package/dist/svelte/components/ContentGovernanceAssignmentEditor.svelte.d.ts +11 -0
  165. package/dist/svelte/components/ContentGovernanceAssignmentEditor.svelte.d.ts.map +1 -0
  166. package/dist/svelte/components/ContentGovernanceManager.svelte +340 -0
  167. package/dist/svelte/components/ContentGovernanceManager.svelte.d.ts +11 -0
  168. package/dist/svelte/components/ContentGovernanceManager.svelte.d.ts.map +1 -0
  169. package/dist/svelte/components/ContentGovernancePanel.svelte +2244 -0
  170. package/dist/svelte/components/ContentGovernancePanel.svelte.d.ts +26 -0
  171. package/dist/svelte/components/ContentGovernancePanel.svelte.d.ts.map +1 -0
  172. package/dist/svelte/components/ContentGovernancePolicyEditor.svelte +110 -0
  173. package/dist/svelte/components/ContentGovernancePolicyEditor.svelte.d.ts +10 -0
  174. package/dist/svelte/components/ContentGovernancePolicyEditor.svelte.d.ts.map +1 -0
  175. package/dist/svelte/components/ContentGovernanceProfileEditor.svelte +185 -0
  176. package/dist/svelte/components/ContentGovernanceProfileEditor.svelte.d.ts +11 -0
  177. package/dist/svelte/components/ContentGovernanceProfileEditor.svelte.d.ts.map +1 -0
  178. package/dist/svelte/components/ContentGovernanceTool.svelte +56 -0
  179. package/dist/svelte/components/ContentGovernanceTool.svelte.d.ts +13 -0
  180. package/dist/svelte/components/ContentGovernanceTool.svelte.d.ts.map +1 -0
  181. package/dist/svelte/components/ContentImageBrowser.svelte +243 -0
  182. package/dist/svelte/components/ContentImageBrowser.svelte.d.ts +18 -0
  183. package/dist/svelte/components/ContentImageBrowser.svelte.d.ts.map +1 -0
  184. package/dist/svelte/components/ContentImageChooser.svelte +134 -0
  185. package/dist/svelte/components/ContentImageChooser.svelte.d.ts +11 -0
  186. package/dist/svelte/components/ContentImageChooser.svelte.d.ts.map +1 -0
  187. package/dist/svelte/components/ContentList.svelte +906 -0
  188. package/dist/svelte/components/ContentList.svelte.d.ts +16 -0
  189. package/dist/svelte/components/ContentList.svelte.d.ts.map +1 -0
  190. package/dist/svelte/components/ContentMetadataFields.svelte +107 -0
  191. package/dist/svelte/components/ContentMetadataFields.svelte.d.ts +8 -0
  192. package/dist/svelte/components/ContentMetadataFields.svelte.d.ts.map +1 -0
  193. package/dist/svelte/components/ContentReferencesPanel.svelte +221 -0
  194. package/dist/svelte/components/ContentReferencesPanel.svelte.d.ts +20 -0
  195. package/dist/svelte/components/ContentReferencesPanel.svelte.d.ts.map +1 -0
  196. package/dist/svelte/components/ContentReviewStatusTray.svelte +151 -0
  197. package/dist/svelte/components/ContentReviewStatusTray.svelte.d.ts +20 -0
  198. package/dist/svelte/components/ContentReviewStatusTray.svelte.d.ts.map +1 -0
  199. package/dist/svelte/components/ContentStatusFields.svelte +85 -0
  200. package/dist/svelte/components/ContentStatusFields.svelte.d.ts +8 -0
  201. package/dist/svelte/components/ContentStatusFields.svelte.d.ts.map +1 -0
  202. package/dist/svelte/components/ContentTitleField.svelte +54 -0
  203. package/dist/svelte/components/ContentTitleField.svelte.d.ts +10 -0
  204. package/dist/svelte/components/ContentTitleField.svelte.d.ts.map +1 -0
  205. package/dist/svelte/components/ContentTransparencyReport.svelte +322 -0
  206. package/dist/svelte/components/ContentTransparencyReport.svelte.d.ts +10 -0
  207. package/dist/svelte/components/ContentTransparencyReport.svelte.d.ts.map +1 -0
  208. package/dist/svelte/components/ContentTransparencyTool.svelte +314 -0
  209. package/dist/svelte/components/ContentTransparencyTool.svelte.d.ts +10 -0
  210. package/dist/svelte/components/ContentTransparencyTool.svelte.d.ts.map +1 -0
  211. package/dist/svelte/components/ContentVersionsTool.svelte +291 -0
  212. package/dist/svelte/components/ContentVersionsTool.svelte.d.ts +10 -0
  213. package/dist/svelte/components/ContentVersionsTool.svelte.d.ts.map +1 -0
  214. package/dist/svelte/components/GovernedContentEditor.svelte +409 -0
  215. package/dist/svelte/components/GovernedContentEditor.svelte.d.ts +35 -0
  216. package/dist/svelte/components/GovernedContentEditor.svelte.d.ts.map +1 -0
  217. package/dist/svelte/components/ImageThumbnail.cache.d.ts +14 -0
  218. package/dist/svelte/components/ImageThumbnail.cache.d.ts.map +1 -0
  219. package/dist/svelte/components/ImageThumbnail.cache.js +36 -0
  220. package/dist/svelte/components/ImageThumbnail.svelte +159 -0
  221. package/dist/svelte/components/ImageThumbnail.svelte.d.ts +8 -0
  222. package/dist/svelte/components/ImageThumbnail.svelte.d.ts.map +1 -0
  223. package/dist/svelte/components/Markdown.svelte +125 -0
  224. package/dist/svelte/components/Markdown.svelte.d.ts +11 -0
  225. package/dist/svelte/components/Markdown.svelte.d.ts.map +1 -0
  226. package/dist/svelte/content-editor-form.d.ts +63 -0
  227. package/dist/svelte/content-editor-form.d.ts.map +1 -0
  228. package/dist/svelte/content-editor-form.js +94 -0
  229. package/dist/svelte/content-editor-media.d.ts +12 -0
  230. package/dist/svelte/content-editor-media.d.ts.map +1 -0
  231. package/dist/svelte/content-editor-media.js +84 -0
  232. package/dist/svelte/content-editor-state.svelte.d.ts +35 -0
  233. package/dist/svelte/content-editor-state.svelte.d.ts.map +1 -0
  234. package/dist/svelte/content-editor-state.svelte.js +141 -0
  235. package/dist/svelte/governance-manager-client.d.ts +22 -0
  236. package/dist/svelte/governance-manager-client.d.ts.map +1 -0
  237. package/dist/svelte/governance-manager-client.js +1 -0
  238. package/dist/svelte/i18n.contribution.d.ts +57 -0
  239. package/dist/svelte/i18n.contribution.d.ts.map +1 -0
  240. package/dist/svelte/i18n.contribution.js +64 -0
  241. package/dist/svelte/i18n.editor.d.ts +71 -0
  242. package/dist/svelte/i18n.editor.d.ts.map +1 -0
  243. package/dist/svelte/i18n.editor.js +87 -0
  244. package/dist/svelte/i18n.governance.d.ts +66 -0
  245. package/dist/svelte/i18n.governance.d.ts.map +1 -0
  246. package/dist/svelte/i18n.governance.js +66 -0
  247. package/dist/svelte/i18n.routes.d.ts +66 -0
  248. package/dist/svelte/i18n.routes.d.ts.map +1 -0
  249. package/dist/svelte/i18n.routes.js +75 -0
  250. package/dist/svelte/i18n.tools.d.ts +81 -0
  251. package/dist/svelte/i18n.tools.d.ts.map +1 -0
  252. package/dist/svelte/i18n.tools.js +90 -0
  253. package/dist/svelte/index.d.ts +101 -0
  254. package/dist/svelte/index.d.ts.map +1 -0
  255. package/dist/svelte/index.js +63 -0
  256. package/dist/svelte/playground.d.ts +281 -0
  257. package/dist/svelte/playground.d.ts.map +1 -0
  258. package/dist/svelte/playground.js +438 -0
  259. package/dist/svelte/routes/ContentContributionsRoute.svelte +809 -0
  260. package/dist/svelte/routes/ContentContributionsRoute.svelte.d.ts +10 -0
  261. package/dist/svelte/routes/ContentContributionsRoute.svelte.d.ts.map +1 -0
  262. package/dist/svelte/routes/ContentFactsRoute.svelte +612 -0
  263. package/dist/svelte/routes/ContentFactsRoute.svelte.d.ts +11 -0
  264. package/dist/svelte/routes/ContentFactsRoute.svelte.d.ts.map +1 -0
  265. package/dist/svelte/routes/ContentGovernanceRoute.svelte +218 -0
  266. package/dist/svelte/routes/ContentGovernanceRoute.svelte.d.ts +10 -0
  267. package/dist/svelte/routes/ContentGovernanceRoute.svelte.d.ts.map +1 -0
  268. package/dist/svelte/routes/ContentWorkspaceRoute.svelte +431 -0
  269. package/dist/svelte/routes/ContentWorkspaceRoute.svelte.d.ts +12 -0
  270. package/dist/svelte/routes/ContentWorkspaceRoute.svelte.d.ts.map +1 -0
  271. package/dist/svelte/routes/PublishedArticleRoute.svelte +194 -0
  272. package/dist/svelte/routes/PublishedArticleRoute.svelte.d.ts +10 -0
  273. package/dist/svelte/routes/PublishedArticleRoute.svelte.d.ts.map +1 -0
  274. package/dist/svelte/routes/index.d.ts +8 -0
  275. package/dist/svelte/routes/index.d.ts.map +1 -0
  276. package/dist/svelte/routes/index.js +6 -0
  277. package/dist/svelte/routes/shared.d.ts +90 -0
  278. package/dist/svelte/routes/shared.d.ts.map +1 -0
  279. package/dist/svelte/routes/shared.js +104 -0
  280. package/dist/svelte/types.d.ts +69 -0
  281. package/dist/svelte/types.d.ts.map +1 -0
  282. package/dist/svelte/types.js +6 -0
  283. package/dist/thumbnail-generator.d.ts +174 -0
  284. package/dist/thumbnail-generator.d.ts.map +1 -0
  285. package/dist/ui.d.ts +10 -0
  286. package/dist/ui.d.ts.map +1 -0
  287. package/dist/ui.js +42 -0
  288. package/dist/ui.js.map +1 -0
  289. package/dist/utils.d.ts +18 -0
  290. package/dist/utils.d.ts.map +1 -0
  291. package/package.json +119 -0
@@ -0,0 +1,906 @@
1
+ <script lang="ts">
2
+ import { useI18n } from '@happyvertical/smrt-ui/i18n';
3
+ import type { Snippet } from 'svelte';
4
+ import { untrack } from 'svelte';
5
+ import { M } from '../i18n.contribution.js';
6
+ import ImageThumbnail from './ImageThumbnail.svelte';
7
+
8
+ const { t } = useI18n();
9
+
10
+ let {
11
+ apiBaseUrl = '/api/v1',
12
+ contents,
13
+ type = undefined,
14
+ defaultViewMode = 'grid',
15
+ onEdit,
16
+ onDelete,
17
+ onAdd,
18
+ controls,
19
+ getViewHref = undefined,
20
+ } = $props<{
21
+ apiBaseUrl?: string;
22
+ contents: any[];
23
+ type?: string;
24
+ defaultViewMode?: 'grid' | 'detailed' | 'compact';
25
+ onEdit: (content: any) => void;
26
+ onDelete: (content: any) => void;
27
+ onAdd: () => void;
28
+ controls?: Snippet;
29
+ getViewHref?: (content: any) => string | null;
30
+ }>();
31
+
32
+ let searchTerm = $state('');
33
+ let selectedType = $state('All Types');
34
+ let selectedStatus = $state('All Statuses');
35
+ let viewMode: 'grid' | 'detailed' | 'compact' = $state(
36
+ untrack(() => defaultViewMode),
37
+ );
38
+
39
+ $effect(() => {
40
+ selectedType = type || 'All Types';
41
+ });
42
+
43
+ function getTextValue(value: unknown): string {
44
+ return typeof value === 'string' ? value : '';
45
+ }
46
+
47
+ function getDisplayTitle(content: any): string {
48
+ return getTextValue(content.title) || 'Untitled content';
49
+ }
50
+
51
+ function getDisplayDescription(content: any): string {
52
+ return getTextValue(content.description);
53
+ }
54
+
55
+ function getDisplayAuthor(content: any): string {
56
+ return getTextValue(content.author);
57
+ }
58
+
59
+ function getNormalizedType(value: unknown): string {
60
+ return getTextValue(value).toLowerCase() || 'content';
61
+ }
62
+
63
+ const filteredContents = $derived(
64
+ contents.filter((content: any) => {
65
+ const title = getDisplayTitle(content);
66
+ const description = getDisplayDescription(content);
67
+ const author = getDisplayAuthor(content);
68
+
69
+ const matchesSearch =
70
+ searchTerm === '' ||
71
+ title.toLowerCase().includes(searchTerm.toLowerCase()) ||
72
+ description.toLowerCase().includes(searchTerm.toLowerCase()) ||
73
+ author.toLowerCase().includes(searchTerm.toLowerCase());
74
+
75
+ const isLockedType = !!type;
76
+ const matchesType = isLockedType
77
+ ? content.type === type
78
+ : selectedType === 'All Types' ||
79
+ (selectedType === 'Articles' && content.type === 'article') ||
80
+ (selectedType === 'Documents' && content.type === 'document') ||
81
+ (selectedType === 'Mirrors' && content.type === 'mirror');
82
+
83
+ const matchesStatus =
84
+ selectedStatus === 'All Statuses' ||
85
+ content.status.toLowerCase() === selectedStatus.toLowerCase();
86
+
87
+ return matchesSearch && matchesType && matchesStatus;
88
+ }),
89
+ );
90
+
91
+ function getTypeLabel(value: unknown) {
92
+ switch (getNormalizedType(value)) {
93
+ case 'article':
94
+ return 'Article';
95
+ case 'mirror':
96
+ return 'Mirror';
97
+ case 'document':
98
+ return 'Document';
99
+ default:
100
+ return 'Content';
101
+ }
102
+ }
103
+
104
+ function getStatusBadge(value: unknown) {
105
+ switch (getTextValue(value).toLowerCase()) {
106
+ case 'published':
107
+ return 'published';
108
+ case 'draft':
109
+ return 'draft';
110
+ case 'archived':
111
+ return 'archived';
112
+ default:
113
+ return 'unknown';
114
+ }
115
+ }
116
+
117
+ function getStateBadge(value: unknown) {
118
+ switch (getTextValue(value).toLowerCase()) {
119
+ case 'highlighted':
120
+ return 'highlighted';
121
+ case 'active':
122
+ return 'active';
123
+ case 'deprecated':
124
+ return 'deprecated';
125
+ default:
126
+ return 'unknown';
127
+ }
128
+ }
129
+
130
+ function handleDeleteContent(content: any) {
131
+ if (
132
+ confirm(`Are you sure you want to delete "${getDisplayTitle(content)}"?`)
133
+ ) {
134
+ onDelete(content);
135
+ }
136
+ }
137
+ </script>
138
+
139
+ <div class="content-list-wrapper">
140
+
141
+ <div class="content-controls">
142
+ <div class="search-filters">
143
+ <input type="text" placeholder={t(M['content.content_list.search_placeholder'])} bind:value={searchTerm} />
144
+
145
+ {#if !type}
146
+ <select bind:value={selectedType}>
147
+ <option value="All Types">{t(M['content.content_list.all_types'])}</option>
148
+ <option value="Articles">Articles</option>
149
+ <option value="Documents">Documents</option>
150
+ <option value="Mirrors">Mirrors</option>
151
+ </select>
152
+ {/if}
153
+
154
+ <select bind:value={selectedStatus}>
155
+ <option value="All Statuses">{t(M['content.content_list.all_statuses'])}</option>
156
+ <option value="Published">Published</option>
157
+ <option value="Draft">Draft</option>
158
+ <option value="Archived">Archived</option>
159
+ </select>
160
+
161
+ {#if controls}
162
+ {@render controls()}
163
+ {/if}
164
+ </div>
165
+
166
+ <div class="actions-group">
167
+ <div class="view-toggles">
168
+ <button
169
+ type="button"
170
+ class:active={viewMode === 'grid'}
171
+ onclick={() => viewMode = 'grid'}
172
+ title={t(M['content.content_list.grid_view'])}
173
+ >
174
+ <svg viewBox="0 0 24 24" width="18" height="18" stroke="currentColor" stroke-width="2" fill="none">
175
+ <rect x="3" y="3" width="7" height="7"></rect>
176
+ <rect x="14" y="3" width="7" height="7"></rect>
177
+ <rect x="14" y="14" width="7" height="7"></rect>
178
+ <rect x="3" y="14" width="7" height="7"></rect>
179
+ </svg>
180
+ </button>
181
+ <button
182
+ type="button"
183
+ class:active={viewMode === 'detailed'}
184
+ onclick={() => viewMode = 'detailed'}
185
+ title={t(M['content.content_list.detailed_list'])}
186
+ >
187
+ <svg viewBox="0 0 24 24" width="18" height="18" stroke="currentColor" stroke-width="2" fill="none">
188
+ <line x1="8" y1="6" x2="21" y2="6"></line>
189
+ <line x1="8" y1="12" x2="21" y2="12"></line>
190
+ <line x1="8" y1="18" x2="21" y2="18"></line>
191
+ <line x1="3" y1="6" x2="3.01" y2="6"></line>
192
+ <line x1="3" y1="12" x2="3.01" y2="12"></line>
193
+ <line x1="3" y1="18" x2="3.01" y2="18"></line>
194
+ </svg>
195
+ </button>
196
+ <button
197
+ type="button"
198
+ class:active={viewMode === 'compact'}
199
+ onclick={() => viewMode = 'compact'}
200
+ title={t(M['content.content_list.compact_list'])}
201
+ >
202
+ <svg viewBox="0 0 24 24" width="18" height="18" stroke="currentColor" stroke-width="2" fill="none">
203
+ <line x1="3" y1="6" x2="21" y2="6"></line>
204
+ <line x1="3" y1="12" x2="21" y2="12"></line>
205
+ <line x1="3" y1="18" x2="21" y2="18"></line>
206
+ </svg>
207
+ </button>
208
+ </div>
209
+
210
+ <button class="add-button" type="button" onclick={() => onAdd()}>
211
+ <svg viewBox="0 0 24 24" width="16" height="16" stroke="currentColor" stroke-width="2" fill="none">
212
+ <line x1="12" y1="5" x2="12" y2="19"></line>
213
+ <line x1="5" y1="12" x2="19" y2="12"></line>
214
+ </svg>
215
+ {t(M['content.content_list.add_content'])}
216
+ </button>
217
+ </div>
218
+ </div>
219
+
220
+ {#if filteredContents.length === 0}
221
+ <div class="empty-state">
222
+ {t(M['content.content_list.empty'])}
223
+ </div>
224
+ {:else if viewMode === 'compact'}
225
+ <div class="content-table-wrapper">
226
+ <table class="content-table">
227
+ <thead>
228
+ <tr>
229
+ <th>Type</th>
230
+ <th>Title</th>
231
+ <th>Author</th>
232
+ <th>Status</th>
233
+ <th>State</th>
234
+ <th class="actions-col">Actions</th>
235
+ </tr>
236
+ </thead>
237
+ <tbody>
238
+ {#each filteredContents as content (content.id)}
239
+ <tr>
240
+ <td class="type-cell">
241
+ <span class={`type-pill type-pill--${getNormalizedType(content.type)}`}>
242
+ {getTypeLabel(content.type)}
243
+ </span>
244
+ </td>
245
+ <td class="title-cell"><strong>{getDisplayTitle(content)}</strong></td>
246
+ <td>{getDisplayAuthor(content) || '-'}</td>
247
+ <td><span class="badge status-{getStatusBadge(content.status)}">{content.status}</span></td>
248
+ <td><span class="badge state-{getStateBadge(content.state)}">{content.state}</span></td>
249
+ <td class="actions-cell">
250
+ {#if getViewHref?.(content)}
251
+ <a class="icon-btn" href={getViewHref(content) || '#'} title={t(M['content.content_list.view_published_article'])}>🔎</a>
252
+ {/if}
253
+ <button class="icon-btn" type="button" onclick={() => onEdit(content)} title={t(M['content.content_list.edit'])}>✏️</button>
254
+ <button class="icon-btn delete-icon" type="button" onclick={() => handleDeleteContent(content)} title={t(M['content.content_list.delete'])}>🗑️</button>
255
+ </td>
256
+ </tr>
257
+ {/each}
258
+ </tbody>
259
+ </table>
260
+ </div>
261
+ {:else if viewMode === 'detailed'}
262
+ <div class="content-detailed">
263
+ {#each filteredContents as content (content.id)}
264
+ <article class="content-row">
265
+ <div class="content-row__main">
266
+ <div class="content-row__eyebrow">
267
+ <span class={`type-pill type-pill--${getNormalizedType(content.type)}`}>
268
+ {getTypeLabel(content.type)}
269
+ </span>
270
+ {#if getDisplayAuthor(content)}
271
+ <span class="content-row__author">By {getDisplayAuthor(content)}</span>
272
+ {/if}
273
+ </div>
274
+
275
+ <h3>{getDisplayTitle(content)}</h3>
276
+
277
+ {#if getDisplayDescription(content)}
278
+ <p class="content-row__description">{getDisplayDescription(content)}</p>
279
+ {/if}
280
+
281
+ {#if content.url || content.fileKey}
282
+ <div class="content-row__links">
283
+ {#if content.url}
284
+ <a href={content.url} target="_blank" rel="noreferrer">
285
+ {t(M['content.content_list.source_material'])}
286
+ </a>
287
+ {/if}
288
+ {#if content.fileKey}
289
+ <span>{content.fileKey}</span>
290
+ {/if}
291
+ </div>
292
+ {/if}
293
+ </div>
294
+
295
+ <div class="content-row__meta">
296
+ <span class="meta-label">Status</span>
297
+ <span class="badge status-{getStatusBadge(content.status)}">{content.status}</span>
298
+ <span class="meta-label">State</span>
299
+ <span class="badge state-{getStateBadge(content.state)}">{content.state}</span>
300
+ </div>
301
+
302
+ <div class="content-row__actions">
303
+ {#if getViewHref?.(content)}
304
+ <a href={getViewHref(content) || '#'} class="quiet-action">{t(M['content.content_list.view_article'])}</a>
305
+ {/if}
306
+ <button type="button" class="quiet-action" onclick={() => onEdit(content)}>{t(M['content.content_list.edit'])}</button>
307
+ <button
308
+ type="button"
309
+ class="quiet-action quiet-action--danger"
310
+ onclick={() => handleDeleteContent(content)}
311
+ >
312
+ {t(M['content.content_list.delete'])}
313
+ </button>
314
+ </div>
315
+ </article>
316
+ {/each}
317
+ </div>
318
+ {:else}
319
+ <div class="content-{viewMode}">
320
+ {#each filteredContents as content (content.id)}
321
+ <div class="content-card">
322
+ {#if content.thumbnailAssetId}
323
+ <div class="card-thumbnail">
324
+ <ImageThumbnail
325
+ apiBaseUrl={apiBaseUrl}
326
+ assetId={content.thumbnailAssetId}
327
+ />
328
+ </div>
329
+ {/if}
330
+ <div class="content-header">
331
+ <div class="content-header__eyebrow">
332
+ <span class={`type-pill type-pill--${getNormalizedType(content.type)}`}>
333
+ {getTypeLabel(content.type)}
334
+ </span>
335
+ {#if getDisplayAuthor(content)}
336
+ <div class="author">{getDisplayAuthor(content)}</div>
337
+ {/if}
338
+ </div>
339
+ <h3>{getDisplayTitle(content)}</h3>
340
+ </div>
341
+
342
+ <div class="content-meta">
343
+ <div>{getTypeLabel(content.type)}</div>
344
+ <div class="badges">
345
+ <span class="badge status-{getStatusBadge(content.status)}">{content.status}</span>
346
+ <span class="badge state-{getStateBadge(content.state)}">{content.state}</span>
347
+ </div>
348
+ </div>
349
+
350
+ <p class="content-description">{getDisplayDescription(content)}</p>
351
+
352
+ <div class="content-footer">
353
+ <div class="meta-links">
354
+ {#if content.url}
355
+ <div class="source">Source: <a href={content.url} target="_blank">{content.url}</a></div>
356
+ {/if}
357
+ {#if content.fileKey}
358
+ <div class="file">File: {content.fileKey}</div>
359
+ {/if}
360
+ </div>
361
+
362
+ <div class="content-actions">
363
+ {#if getViewHref?.(content)}
364
+ <a href={getViewHref(content) || '#'} class="view-btn">{t(M['content.content_list.view_article_button'])}</a>
365
+ {/if}
366
+ <button onclick={() => onEdit(content)}>{t(M['content.content_list.edit'])}</button>
367
+ <button onclick={() => handleDeleteContent(content)} class="delete-btn">{t(M['content.content_list.delete'])}</button>
368
+ </div>
369
+ </div>
370
+ </div>
371
+ {/each}
372
+ </div>
373
+ {/if}
374
+
375
+ </div>
376
+
377
+ <style>
378
+ .content-list-wrapper {
379
+ display: flex;
380
+ flex-direction: column;
381
+ width: 100%;
382
+ }
383
+
384
+ .content-controls {
385
+ display: flex;
386
+ justify-content: space-between;
387
+ align-items: center;
388
+ margin-bottom: 1.25rem;
389
+ flex-wrap: wrap;
390
+ gap: 1rem;
391
+ background: var(--smrt-color-surface);
392
+ padding: 0.9rem 1.1rem;
393
+ border-radius: 0.75rem;
394
+ box-shadow: var(--smrt-elevation-1, 0 1px 3px rgba(0,0,0,0.1));
395
+ }
396
+
397
+ .search-filters {
398
+ display: flex;
399
+ gap: 1rem;
400
+ flex-wrap: wrap;
401
+ align-items: center;
402
+ }
403
+
404
+ .search-filters input,
405
+ .search-filters select {
406
+ padding: 0.5rem 0.9rem;
407
+ border: 1px solid var(--smrt-color-outline);
408
+ border-radius: 0.5rem;
409
+ font-size: var(--smrt-typography-body-medium-size, 0.875rem);
410
+ height: 38px;
411
+ background: var(--smrt-color-surface-container-low);
412
+ color: var(--smrt-color-on-surface);
413
+ }
414
+
415
+ .search-filters input:focus,
416
+ .search-filters select:focus {
417
+ outline: none;
418
+ border-color: var(--smrt-color-primary);
419
+ box-shadow: 0 0 0 2px color-mix(in srgb, var(--smrt-color-primary) 20%, transparent);
420
+ }
421
+
422
+ .actions-group {
423
+ display: flex;
424
+ gap: 0.75rem;
425
+ align-items: center;
426
+ }
427
+
428
+ .view-toggles {
429
+ display: flex;
430
+ background: var(--smrt-color-surface-container-low);
431
+ border-radius: 0.5rem;
432
+ padding: 0.25rem;
433
+ border: 1px solid var(--smrt-color-outline-variant);
434
+ }
435
+
436
+ .view-toggles button {
437
+ background: transparent;
438
+ border: none;
439
+ padding: 0.4rem;
440
+ color: var(--smrt-color-on-surface-variant);
441
+ border-radius: 0.375rem;
442
+ cursor: pointer;
443
+ display: flex;
444
+ align-items: center;
445
+ justify-content: center;
446
+ transition: all 0.2s;
447
+ }
448
+
449
+ .view-toggles button:hover {
450
+ color: var(--smrt-color-on-surface);
451
+ background: color-mix(in srgb, var(--smrt-color-shadow) 5%, transparent);
452
+ }
453
+
454
+ .view-toggles button.active {
455
+ background: var(--smrt-color-surface);
456
+ color: var(--smrt-color-on-surface);
457
+ box-shadow: var(--smrt-elevation-1, 0 1px 2px rgba(0,0,0,0.1));
458
+ }
459
+
460
+ .add-button {
461
+ display: flex;
462
+ align-items: center;
463
+ gap: 0.5rem;
464
+ background: linear-gradient(
465
+ 135deg,
466
+ var(--smrt-color-primary) 0%,
467
+ color-mix(in srgb, var(--smrt-color-primary) 80%, black) 100%
468
+ );
469
+ color: var(--smrt-color-on-primary);
470
+ border: none;
471
+ padding: 0.5rem 1rem;
472
+ height: 38px;
473
+ border-radius: 0.5rem;
474
+ font-weight: var(--smrt-typography-weight-semibold, 600);
475
+ cursor: pointer;
476
+ transition: transform 0.2s, box-shadow 0.2s;
477
+ }
478
+
479
+ .add-button:hover {
480
+ transform: translateY(-1px);
481
+ box-shadow: 0 4px 6px -1px color-mix(in srgb, var(--smrt-color-primary) 50%, transparent);
482
+ }
483
+
484
+ .content-header__eyebrow,
485
+ .content-row__eyebrow {
486
+ display: flex;
487
+ align-items: center;
488
+ gap: 0.65rem;
489
+ flex-wrap: wrap;
490
+ margin-bottom: 0.55rem;
491
+ }
492
+
493
+ .type-pill {
494
+ display: inline-flex;
495
+ align-items: center;
496
+ border-radius: var(--smrt-radius-full, 9999px);
497
+ padding: 0.2rem 0.65rem;
498
+ font-size: var(--smrt-typography-label-medium-size, 0.72rem);
499
+ font-weight: var(--smrt-typography-weight-bold, 700);
500
+ letter-spacing: var(--smrt-typography-label-medium-tracking, 0.06em);
501
+ text-transform: uppercase;
502
+ background: var(--smrt-color-surface-container-low);
503
+ color: var(--smrt-color-on-surface-variant);
504
+ }
505
+
506
+ .type-pill--article {
507
+ background: color-mix(in srgb, var(--smrt-color-primary) 11%, transparent);
508
+ color: var(--smrt-color-primary);
509
+ }
510
+
511
+ .type-pill--document {
512
+ background: color-mix(in srgb, var(--smrt-color-tertiary, #0f766e) 12%, transparent);
513
+ color: var(--smrt-color-tertiary, #0f766e);
514
+ }
515
+
516
+ .type-pill--mirror {
517
+ background: color-mix(in srgb, var(--smrt-color-secondary, #9333ea) 12%, transparent);
518
+ color: var(--smrt-color-secondary, #9333ea);
519
+ }
520
+
521
+ /* Shared Card Styles */
522
+ .content-card {
523
+ background: var(--smrt-color-surface);
524
+ border-radius: 0.75rem;
525
+ padding: 1.5rem;
526
+ border: 1px solid var(--smrt-color-outline-variant);
527
+ transition: transform 0.2s, box-shadow 0.2s;
528
+ display: flex;
529
+ flex-direction: column;
530
+ }
531
+
532
+ .content-card:hover {
533
+ transform: translateY(-2px);
534
+ box-shadow: var(--smrt-elevation-3, 0 10px 25px -3px rgba(0, 0, 0, 0.1));
535
+ }
536
+
537
+ .card-thumbnail {
538
+ width: calc(100% + 3rem);
539
+ margin: -1.5rem -1.5rem 1rem -1.5rem;
540
+ height: 160px;
541
+ border-bottom: 1px solid var(--smrt-color-outline-variant);
542
+ overflow: hidden;
543
+ background: var(--smrt-color-surface-container-high, #242424);
544
+ }
545
+
546
+ .content-header {
547
+ margin-bottom: 1rem;
548
+ }
549
+
550
+ .content-header h3 {
551
+ margin: 0 0 0.25rem 0;
552
+ color: var(--smrt-color-on-surface);
553
+ font-size: var(--smrt-typography-title-large-size, 1.25rem);
554
+ line-height: var(--smrt-typography-title-large-line-height, 1.3);
555
+ }
556
+
557
+ .author {
558
+ color: var(--smrt-color-on-surface-variant);
559
+ font-size: var(--smrt-typography-body-medium-size, 0.875rem);
560
+ }
561
+
562
+ .content-meta {
563
+ display: flex;
564
+ justify-content: space-between;
565
+ align-items: center;
566
+ margin-bottom: 1rem;
567
+ font-size: var(--smrt-typography-body-medium-size, 0.875rem);
568
+ color: var(--smrt-color-on-surface-variant);
569
+ }
570
+
571
+ .badges {
572
+ display: flex;
573
+ gap: 0.5rem;
574
+ flex-wrap: wrap;
575
+ }
576
+
577
+ .badge {
578
+ padding: 0.25rem 0.6rem;
579
+ border-radius: var(--smrt-radius-full, 9999px);
580
+ font-size: var(--smrt-typography-label-medium-size, 0.75rem);
581
+ font-weight: var(--smrt-typography-weight-semibold, 600);
582
+ text-transform: uppercase;
583
+ letter-spacing: var(--smrt-typography-label-medium-tracking, 0.05em);
584
+ }
585
+
586
+ .status-published { background: var(--smrt-color-success-container); color: var(--smrt-color-on-success-container); border: 1px solid var(--smrt-color-success); }
587
+ .status-draft { background: var(--smrt-color-warning-container); color: var(--smrt-color-on-warning-container); border: 1px solid var(--smrt-color-warning); }
588
+ .status-archived { background: var(--smrt-color-surface-container); color: var(--smrt-color-on-surface-variant); border: 1px solid var(--smrt-color-outline-variant); }
589
+
590
+ .state-highlighted { background: var(--smrt-color-warning-container); color: var(--smrt-color-on-warning-container); border: 1px solid var(--smrt-color-warning);}
591
+ .state-active { background: var(--smrt-color-success-container); color: var(--smrt-color-on-success-container); border: 1px solid var(--smrt-color-success); }
592
+ .state-deprecated { background: var(--smrt-color-error-container); color: var(--smrt-color-on-error-container); border: 1px solid var(--smrt-color-error); }
593
+
594
+ .content-description {
595
+ color: var(--smrt-color-on-surface-variant);
596
+ line-height: 1.6;
597
+ margin-bottom: 1.5rem;
598
+ flex: 1;
599
+ }
600
+
601
+ .content-footer {
602
+ display: flex;
603
+ flex-direction: column;
604
+ gap: 1rem;
605
+ margin-top: auto;
606
+ }
607
+
608
+ .meta-links {
609
+ display: flex;
610
+ flex-direction: column;
611
+ gap: 0.25rem;
612
+ }
613
+
614
+ .source, .file {
615
+ font-size: var(--smrt-typography-body-small-size, 0.75rem);
616
+ color: var(--smrt-color-on-surface-variant);
617
+ white-space: nowrap;
618
+ overflow: hidden;
619
+ text-overflow: ellipsis;
620
+ }
621
+
622
+ .source a {
623
+ color: var(--smrt-color-primary);
624
+ text-decoration: none;
625
+ }
626
+
627
+ .source a:hover {
628
+ text-decoration: underline;
629
+ }
630
+
631
+ .content-actions {
632
+ display: flex;
633
+ gap: 0.75rem;
634
+ margin-top: 0.5rem;
635
+ border-top: 1px solid var(--smrt-color-outline-variant);
636
+ padding-top: 1rem;
637
+ }
638
+
639
+ .content-actions button,
640
+ .content-actions a {
641
+ flex: 1;
642
+ padding: 0.5rem 1rem;
643
+ border: 1px solid var(--smrt-color-outline-variant);
644
+ border-radius: 0.375rem;
645
+ background: var(--smrt-color-surface-container-low);
646
+ color: var(--smrt-color-on-surface);
647
+ font-size: var(--smrt-typography-label-large-size, 0.875rem);
648
+ font-weight: var(--smrt-typography-weight-medium, 500);
649
+ cursor: pointer;
650
+ transition: all 0.2s;
651
+ text-align: center;
652
+ text-decoration: none;
653
+ }
654
+
655
+ .content-actions button:hover,
656
+ .content-actions a:hover {
657
+ background: var(--smrt-color-surface-variant);
658
+ border-color: var(--smrt-color-outline);
659
+ }
660
+
661
+ .view-btn {
662
+ color: var(--smrt-color-primary) !important;
663
+ }
664
+
665
+ .delete-btn {
666
+ color: var(--smrt-color-error) !important;
667
+ }
668
+
669
+ .delete-btn:hover {
670
+ background: var(--smrt-color-error-container) !important;
671
+ border-color: var(--smrt-color-error) !important;
672
+ }
673
+
674
+ /* GRID View Specifics */
675
+ .content-grid {
676
+ display: grid;
677
+ grid-template-columns: repeat(auto-fill, minmax(320px, 1fr));
678
+ gap: 1.5rem;
679
+ }
680
+
681
+ /* DETAILED View Specifics */
682
+ .content-detailed {
683
+ display: flex;
684
+ flex-direction: column;
685
+ gap: 0;
686
+ border-top: 1px solid var(--smrt-color-outline-variant);
687
+ }
688
+
689
+ .content-row {
690
+ display: grid;
691
+ grid-template-columns: minmax(0, 1.8fr) auto auto;
692
+ gap: 1.25rem;
693
+ align-items: start;
694
+ padding: 1.1rem 0;
695
+ border-bottom: 1px solid var(--smrt-color-outline-variant);
696
+ }
697
+
698
+ .content-row h3 {
699
+ margin: 0;
700
+ font-size: var(--smrt-typography-title-medium-size, 1.1rem);
701
+ line-height: var(--smrt-typography-title-medium-line-height, 1.3);
702
+ }
703
+
704
+ .content-row__description {
705
+ margin: 0.45rem 0 0;
706
+ color: var(--smrt-color-on-surface-variant);
707
+ line-height: 1.55;
708
+ }
709
+
710
+ .content-row__meta {
711
+ display: grid;
712
+ gap: 0.45rem;
713
+ justify-items: start;
714
+ align-content: start;
715
+ min-width: 7.25rem;
716
+ }
717
+
718
+ .meta-label {
719
+ font-size: var(--smrt-typography-label-medium-size, 0.72rem);
720
+ text-transform: uppercase;
721
+ letter-spacing: var(--smrt-typography-label-medium-tracking, 0.06em);
722
+ font-weight: var(--smrt-typography-weight-bold, 700);
723
+ color: var(--smrt-color-on-surface-variant);
724
+ }
725
+
726
+ .content-row__actions {
727
+ display: grid;
728
+ gap: 0.55rem;
729
+ justify-items: stretch;
730
+ min-width: 8.5rem;
731
+ }
732
+
733
+ .quiet-action {
734
+ display: inline-flex;
735
+ align-items: center;
736
+ justify-content: center;
737
+ min-height: 2.4rem;
738
+ padding: 0 0.85rem;
739
+ border-radius: var(--smrt-radius-full, 9999px);
740
+ border: 1px solid var(--smrt-color-outline-variant);
741
+ background: transparent;
742
+ color: var(--smrt-color-on-surface);
743
+ font-weight: var(--smrt-typography-weight-semibold, 600);
744
+ text-decoration: none;
745
+ cursor: pointer;
746
+ }
747
+
748
+ .quiet-action:hover {
749
+ background: var(--smrt-color-surface-container-low);
750
+ }
751
+
752
+ .quiet-action--danger {
753
+ color: var(--smrt-color-error);
754
+ }
755
+
756
+ .content-row__links {
757
+ display: flex;
758
+ gap: 0.9rem;
759
+ flex-wrap: wrap;
760
+ margin-top: 0.8rem;
761
+ font-size: var(--smrt-typography-body-medium-size, 0.82rem);
762
+ color: var(--smrt-color-on-surface-variant);
763
+ }
764
+
765
+ .content-row__links a {
766
+ color: var(--smrt-color-primary);
767
+ text-decoration: none;
768
+ }
769
+
770
+ .content-row__author {
771
+ font-size: var(--smrt-typography-body-medium-size, 0.85rem);
772
+ color: var(--smrt-color-on-surface-variant);
773
+ }
774
+
775
+ /* COMPACT View Specifics */
776
+ .content-table-wrapper {
777
+ background: var(--smrt-color-surface);
778
+ border-radius: 0.75rem;
779
+ border: 1px solid var(--smrt-color-outline-variant);
780
+ overflow: hidden;
781
+ box-shadow: var(--smrt-elevation-1, 0 1px 3px rgba(0,0,0,0.05));
782
+ }
783
+
784
+ .content-table {
785
+ width: 100%;
786
+ border-collapse: collapse;
787
+ text-align: left;
788
+ }
789
+
790
+ .content-table th {
791
+ background: var(--smrt-color-surface-container-low);
792
+ padding: 1rem;
793
+ font-size: var(--smrt-typography-title-small-size, 0.875rem);
794
+ font-weight: var(--smrt-typography-weight-semibold, 600);
795
+ color: var(--smrt-color-on-surface-variant);
796
+ border-bottom: 1px solid var(--smrt-color-outline-variant);
797
+ }
798
+
799
+ .content-table td {
800
+ padding: 1rem;
801
+ border-bottom: 1px solid var(--smrt-color-outline-variant);
802
+ color: var(--smrt-color-on-surface);
803
+ font-size: var(--smrt-typography-body-medium-size, 0.875rem);
804
+ vertical-align: middle;
805
+ }
806
+
807
+ .content-table tr:last-child td {
808
+ border-bottom: none;
809
+ }
810
+
811
+ .content-table tr:hover {
812
+ background: var(--smrt-color-surface-container-low);
813
+ }
814
+
815
+ .type-cell {
816
+ white-space: nowrap;
817
+ }
818
+
819
+ .title-cell strong {
820
+ color: var(--smrt-color-on-surface);
821
+ font-weight: var(--smrt-typography-weight-semibold, 600);
822
+ }
823
+
824
+ .actions-col {
825
+ width: 100px;
826
+ text-align: right;
827
+ }
828
+
829
+ .actions-cell {
830
+ text-align: right;
831
+ white-space: nowrap;
832
+ }
833
+
834
+ .icon-btn {
835
+ background: transparent;
836
+ border: none;
837
+ cursor: pointer;
838
+ font-size: var(--smrt-typography-title-medium-size, 1.1rem);
839
+ padding: 0.25rem;
840
+ border-radius: 0.25rem;
841
+ transition: background 0.2s;
842
+ opacity: 0.7;
843
+ }
844
+
845
+ .icon-btn:hover {
846
+ background: var(--smrt-color-surface-variant);
847
+ opacity: 1;
848
+ }
849
+
850
+ .delete-icon:hover {
851
+ background: var(--smrt-color-error-container);
852
+ }
853
+
854
+ .empty-state {
855
+ background: var(--smrt-color-surface);
856
+ padding: 4rem;
857
+ text-align: center;
858
+ border-radius: 0.75rem;
859
+ border: 1px dashed var(--smrt-color-outline);
860
+ color: var(--smrt-color-on-surface-variant);
861
+ font-size: var(--smrt-typography-body-large-size, 1.1rem);
862
+ }
863
+
864
+ .source, .file {
865
+ color: var(--smrt-color-on-surface-variant);
866
+ }
867
+
868
+ @media (max-width: 960px) {
869
+ .content-row {
870
+ grid-template-columns: minmax(0, 1fr);
871
+ gap: 0.9rem;
872
+ }
873
+
874
+ .content-row__actions {
875
+ grid-auto-flow: column;
876
+ grid-auto-columns: 1fr;
877
+ min-width: 0;
878
+ }
879
+ }
880
+
881
+ @media (max-width: 720px) {
882
+ .content-controls {
883
+ align-items: stretch;
884
+ }
885
+
886
+ .search-filters,
887
+ .actions-group {
888
+ width: 100%;
889
+ }
890
+
891
+ .search-filters input,
892
+ .search-filters select,
893
+ .add-button {
894
+ width: 100%;
895
+ }
896
+
897
+ .actions-group {
898
+ justify-content: space-between;
899
+ flex-wrap: wrap;
900
+ }
901
+
902
+ .content-row__actions {
903
+ grid-auto-flow: row;
904
+ }
905
+ }
906
+ </style>