@aphexcms/cms-core 0.1.3 → 0.1.5

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 (280) hide show
  1. package/dist/api/assets.d.ts +48 -0
  2. package/dist/api/assets.d.ts.map +1 -0
  3. package/dist/api/assets.js +52 -0
  4. package/dist/api/client.d.ts +37 -0
  5. package/dist/api/client.d.ts.map +1 -0
  6. package/dist/api/client.js +125 -0
  7. package/dist/api/documents.d.ts +56 -0
  8. package/dist/api/documents.d.ts.map +1 -0
  9. package/dist/api/documents.js +77 -0
  10. package/dist/api/index.d.ts +7 -0
  11. package/dist/api/index.d.ts.map +1 -0
  12. package/dist/api/index.js +5 -0
  13. package/dist/api/organizations.d.ts +101 -0
  14. package/dist/api/organizations.d.ts.map +1 -0
  15. package/dist/api/organizations.js +92 -0
  16. package/dist/api/types.d.ts +23 -0
  17. package/dist/api/types.d.ts.map +1 -0
  18. package/dist/api/types.js +1 -0
  19. package/dist/app.d.ts +19 -0
  20. package/dist/auth/MULTI_TENANCY_PLAN.md +1183 -0
  21. package/dist/auth/auth-errors.d.ts +7 -0
  22. package/dist/auth/auth-errors.d.ts.map +1 -0
  23. package/dist/auth/auth-errors.js +13 -0
  24. package/dist/auth/auth-hooks.d.ts +6 -0
  25. package/dist/auth/auth-hooks.d.ts.map +1 -0
  26. package/dist/auth/auth-hooks.js +108 -0
  27. package/dist/auth/provider.d.ts +17 -0
  28. package/dist/auth/provider.d.ts.map +1 -0
  29. package/dist/auth/provider.js +1 -0
  30. package/dist/client/index.d.ts +24 -0
  31. package/dist/client/index.d.ts.map +1 -0
  32. package/dist/client/index.js +31 -0
  33. package/dist/components/AdminApp.svelte +1077 -0
  34. package/dist/components/AdminApp.svelte.d.ts +24 -0
  35. package/dist/components/AdminApp.svelte.d.ts.map +1 -0
  36. package/dist/components/admin/AdminLayout.svelte +115 -0
  37. package/dist/components/admin/AdminLayout.svelte.d.ts +15 -0
  38. package/dist/components/admin/AdminLayout.svelte.d.ts.map +1 -0
  39. package/dist/components/admin/DocumentEditor.svelte +795 -0
  40. package/dist/components/admin/DocumentEditor.svelte.d.ts +18 -0
  41. package/dist/components/admin/DocumentEditor.svelte.d.ts.map +1 -0
  42. package/dist/components/admin/DocumentTypesList.svelte +97 -0
  43. package/dist/components/admin/DocumentTypesList.svelte.d.ts +14 -0
  44. package/dist/components/admin/DocumentTypesList.svelte.d.ts.map +1 -0
  45. package/dist/components/admin/ObjectModal.svelte +135 -0
  46. package/dist/components/admin/ObjectModal.svelte.d.ts +15 -0
  47. package/dist/components/admin/ObjectModal.svelte.d.ts.map +1 -0
  48. package/dist/components/admin/SchemaField.svelte +171 -0
  49. package/dist/components/admin/SchemaField.svelte.d.ts +19 -0
  50. package/dist/components/admin/SchemaField.svelte.d.ts.map +1 -0
  51. package/dist/components/admin/fields/ArrayField.svelte +266 -0
  52. package/dist/components/admin/fields/ArrayField.svelte.d.ts +12 -0
  53. package/dist/components/admin/fields/ArrayField.svelte.d.ts.map +1 -0
  54. package/dist/components/admin/fields/BooleanField.svelte +35 -0
  55. package/dist/components/admin/fields/BooleanField.svelte.d.ts +13 -0
  56. package/dist/components/admin/fields/BooleanField.svelte.d.ts.map +1 -0
  57. package/dist/components/admin/fields/ImageField.svelte +284 -0
  58. package/dist/components/admin/fields/ImageField.svelte.d.ts +15 -0
  59. package/dist/components/admin/fields/ImageField.svelte.d.ts.map +1 -0
  60. package/dist/components/admin/fields/NumberField.svelte +82 -0
  61. package/dist/components/admin/fields/NumberField.svelte.d.ts +14 -0
  62. package/dist/components/admin/fields/NumberField.svelte.d.ts.map +1 -0
  63. package/dist/components/admin/fields/ReferenceField.svelte +260 -0
  64. package/dist/components/admin/fields/ReferenceField.svelte.d.ts +12 -0
  65. package/dist/components/admin/fields/ReferenceField.svelte.d.ts.map +1 -0
  66. package/dist/components/admin/fields/SlugField.svelte +74 -0
  67. package/dist/components/admin/fields/SlugField.svelte.d.ts +15 -0
  68. package/dist/components/admin/fields/SlugField.svelte.d.ts.map +1 -0
  69. package/dist/components/admin/fields/StringField.svelte +40 -0
  70. package/dist/components/admin/fields/StringField.svelte.d.ts +14 -0
  71. package/dist/components/admin/fields/StringField.svelte.d.ts.map +1 -0
  72. package/dist/components/admin/fields/TextareaField.svelte +40 -0
  73. package/dist/components/admin/fields/TextareaField.svelte.d.ts +14 -0
  74. package/dist/components/admin/fields/TextareaField.svelte.d.ts.map +1 -0
  75. package/dist/components/fields/index.d.ts +9 -0
  76. package/dist/components/fields/index.d.ts.map +1 -0
  77. package/dist/components/fields/index.js +9 -0
  78. package/dist/components/index.d.ts +7 -0
  79. package/dist/components/index.d.ts.map +1 -0
  80. package/dist/components/index.js +12 -0
  81. package/dist/components/layout/OrganizationSwitcher.svelte +218 -0
  82. package/dist/components/layout/OrganizationSwitcher.svelte.d.ts +11 -0
  83. package/dist/components/layout/OrganizationSwitcher.svelte.d.ts.map +1 -0
  84. package/dist/components/layout/Sidebar.svelte +88 -0
  85. package/dist/components/layout/Sidebar.svelte.d.ts +14 -0
  86. package/dist/components/layout/Sidebar.svelte.d.ts.map +1 -0
  87. package/dist/components/layout/sidebar/AppSidebar.svelte +63 -0
  88. package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts +11 -0
  89. package/dist/components/layout/sidebar/AppSidebar.svelte.d.ts.map +1 -0
  90. package/dist/components/layout/sidebar/NavMain.svelte +95 -0
  91. package/dist/components/layout/sidebar/NavMain.svelte.d.ts +19 -0
  92. package/dist/components/layout/sidebar/NavMain.svelte.d.ts.map +1 -0
  93. package/dist/components/layout/sidebar/NavSecondary.svelte +69 -0
  94. package/dist/components/layout/sidebar/NavSecondary.svelte.d.ts +9 -0
  95. package/dist/components/layout/sidebar/NavSecondary.svelte.d.ts.map +1 -0
  96. package/dist/components/layout/sidebar/NavUser.svelte +85 -0
  97. package/dist/components/layout/sidebar/NavUser.svelte.d.ts +9 -0
  98. package/dist/components/layout/sidebar/NavUser.svelte.d.ts.map +1 -0
  99. package/dist/config.d.ts +3 -0
  100. package/dist/config.d.ts.map +1 -0
  101. package/dist/config.js +15 -0
  102. package/dist/db/adapters/index.d.ts +1 -0
  103. package/dist/db/adapters/index.d.ts.map +1 -0
  104. package/dist/db/adapters/index.js +4 -0
  105. package/dist/db/index.d.ts +2 -0
  106. package/dist/db/index.d.ts.map +1 -0
  107. package/dist/db/index.js +4 -0
  108. package/dist/db/interfaces/asset.d.ts +51 -0
  109. package/dist/db/interfaces/asset.d.ts.map +1 -0
  110. package/dist/db/interfaces/asset.js +1 -0
  111. package/dist/db/interfaces/document.d.ts +36 -0
  112. package/dist/db/interfaces/document.d.ts.map +1 -0
  113. package/dist/db/interfaces/document.js +1 -0
  114. package/dist/db/interfaces/index.d.ts +73 -0
  115. package/dist/db/interfaces/index.d.ts.map +1 -0
  116. package/dist/db/interfaces/index.js +1 -0
  117. package/dist/db/interfaces/organization.d.ts +27 -0
  118. package/dist/db/interfaces/organization.d.ts.map +1 -0
  119. package/dist/db/interfaces/organization.js +1 -0
  120. package/dist/db/interfaces/schema.d.ts +21 -0
  121. package/dist/db/interfaces/schema.d.ts.map +1 -0
  122. package/dist/db/interfaces/schema.js +1 -0
  123. package/dist/db/interfaces/user.d.ts +15 -0
  124. package/dist/db/interfaces/user.d.ts.map +1 -0
  125. package/dist/db/interfaces/user.js +1 -0
  126. package/dist/db/utils/reference-resolver.d.ts +18 -0
  127. package/dist/db/utils/reference-resolver.d.ts.map +1 -0
  128. package/dist/db/utils/reference-resolver.js +80 -0
  129. package/dist/define.d.ts +3 -0
  130. package/dist/define.d.ts.map +1 -0
  131. package/dist/define.js +4 -0
  132. package/dist/email/index.d.ts +2 -0
  133. package/dist/email/index.d.ts.map +1 -0
  134. package/dist/email/index.js +4 -0
  135. package/dist/email/interfaces/email.d.ts +42 -0
  136. package/dist/email/interfaces/email.d.ts.map +1 -0
  137. package/dist/email/interfaces/email.js +1 -0
  138. package/dist/engine.d.ts +26 -0
  139. package/dist/engine.d.ts.map +1 -0
  140. package/dist/engine.js +66 -0
  141. package/dist/field-validation/rule.d.ts +51 -0
  142. package/dist/field-validation/rule.d.ts.map +1 -0
  143. package/dist/field-validation/rule.js +221 -0
  144. package/dist/field-validation/utils.d.ts +21 -0
  145. package/dist/field-validation/utils.d.ts.map +1 -0
  146. package/dist/field-validation/utils.js +66 -0
  147. package/dist/hooks.d.ts +23 -0
  148. package/dist/hooks.d.ts.map +1 -0
  149. package/dist/hooks.js +96 -0
  150. package/dist/index.d.ts +2 -0
  151. package/dist/index.d.ts.map +1 -0
  152. package/dist/index.js +4 -0
  153. package/dist/plugins/README.md +154 -0
  154. package/dist/routes/assets-by-id.d.ts +5 -0
  155. package/dist/routes/assets-by-id.d.ts.map +1 -0
  156. package/dist/routes/assets-by-id.js +138 -0
  157. package/dist/routes/assets-cdn.d.ts +3 -0
  158. package/dist/routes/assets-cdn.d.ts.map +1 -0
  159. package/dist/routes/assets-cdn.js +155 -0
  160. package/dist/routes/assets.d.ts +4 -0
  161. package/dist/routes/assets.d.ts.map +1 -0
  162. package/dist/routes/assets.js +94 -0
  163. package/dist/routes/documents-by-id.d.ts +5 -0
  164. package/dist/routes/documents-by-id.d.ts.map +1 -0
  165. package/dist/routes/documents-by-id.js +142 -0
  166. package/dist/routes/documents-publish.d.ts +4 -0
  167. package/dist/routes/documents-publish.d.ts.map +1 -0
  168. package/dist/routes/documents-publish.js +151 -0
  169. package/dist/routes/documents.d.ts +4 -0
  170. package/dist/routes/documents.d.ts.map +1 -0
  171. package/dist/routes/documents.js +131 -0
  172. package/dist/routes/index.d.ts +6 -0
  173. package/dist/routes/index.d.ts.map +1 -0
  174. package/dist/routes/index.js +10 -0
  175. package/dist/routes/organizations-by-id.d.ts +5 -0
  176. package/dist/routes/organizations-by-id.d.ts.map +1 -0
  177. package/dist/routes/organizations-by-id.js +187 -0
  178. package/dist/routes/organizations-invitations.d.ts +4 -0
  179. package/dist/routes/organizations-invitations.d.ts.map +1 -0
  180. package/dist/routes/organizations-invitations.js +125 -0
  181. package/dist/routes/organizations-members.d.ts +5 -0
  182. package/dist/routes/organizations-members.d.ts.map +1 -0
  183. package/dist/routes/organizations-members.js +206 -0
  184. package/dist/routes/organizations-switch.d.ts +3 -0
  185. package/dist/routes/organizations-switch.d.ts.map +1 -0
  186. package/dist/routes/organizations-switch.js +53 -0
  187. package/dist/routes/organizations.d.ts +4 -0
  188. package/dist/routes/organizations.d.ts.map +1 -0
  189. package/dist/routes/organizations.js +108 -0
  190. package/dist/routes/schemas-by-type.d.ts +3 -0
  191. package/dist/routes/schemas-by-type.d.ts.map +1 -0
  192. package/dist/routes/schemas-by-type.js +25 -0
  193. package/dist/routes/schemas.d.ts +3 -0
  194. package/dist/routes/schemas.d.ts.map +1 -0
  195. package/dist/routes/schemas.js +11 -0
  196. package/dist/routes-exports.d.ts +14 -0
  197. package/dist/routes-exports.d.ts.map +1 -0
  198. package/dist/routes-exports.js +19 -0
  199. package/dist/schema-context.svelte.d.ts +10 -0
  200. package/dist/schema-context.svelte.d.ts.map +1 -0
  201. package/dist/schema-context.svelte.js +18 -0
  202. package/dist/schema-utils/cleanup.d.ts +21 -0
  203. package/dist/schema-utils/cleanup.d.ts.map +1 -0
  204. package/dist/schema-utils/cleanup.js +80 -0
  205. package/dist/schema-utils/index.d.ts +4 -0
  206. package/dist/schema-utils/index.d.ts.map +1 -0
  207. package/dist/schema-utils/index.js +4 -0
  208. package/dist/schema-utils/utils.d.ts +30 -0
  209. package/dist/schema-utils/utils.d.ts.map +1 -0
  210. package/dist/schema-utils/utils.js +37 -0
  211. package/dist/schema-utils/validator.d.ts +6 -0
  212. package/dist/schema-utils/validator.d.ts.map +1 -0
  213. package/dist/schema-utils/validator.js +45 -0
  214. package/dist/server/index.d.ts +16 -0
  215. package/dist/server/index.d.ts.map +1 -0
  216. package/dist/server/index.js +28 -0
  217. package/dist/services/asset-service.d.ts +86 -0
  218. package/dist/services/asset-service.d.ts.map +1 -0
  219. package/dist/services/asset-service.js +187 -0
  220. package/dist/services/index.d.ts +3 -0
  221. package/dist/services/index.d.ts.map +1 -0
  222. package/dist/services/index.js +4 -0
  223. package/dist/storage/adapters/index.d.ts +2 -0
  224. package/dist/storage/adapters/index.d.ts.map +1 -0
  225. package/dist/storage/adapters/index.js +2 -0
  226. package/dist/storage/adapters/local-storage-adapter.d.ts +54 -0
  227. package/dist/storage/adapters/local-storage-adapter.d.ts.map +1 -0
  228. package/dist/storage/adapters/local-storage-adapter.js +187 -0
  229. package/dist/storage/index.d.ts +3 -0
  230. package/dist/storage/index.d.ts.map +1 -0
  231. package/dist/storage/index.js +6 -0
  232. package/dist/storage/interfaces/index.d.ts +2 -0
  233. package/dist/storage/interfaces/index.d.ts.map +1 -0
  234. package/dist/storage/interfaces/index.js +2 -0
  235. package/dist/storage/interfaces/storage.d.ts +91 -0
  236. package/dist/storage/interfaces/storage.d.ts.map +1 -0
  237. package/dist/storage/interfaces/storage.js +1 -0
  238. package/dist/storage/providers/storage.d.ts +43 -0
  239. package/dist/storage/providers/storage.d.ts.map +1 -0
  240. package/dist/storage/providers/storage.js +64 -0
  241. package/dist/types/asset.d.ts +73 -0
  242. package/dist/types/asset.d.ts.map +1 -0
  243. package/dist/types/asset.js +2 -0
  244. package/dist/types/auth.d.ts +50 -0
  245. package/dist/types/auth.d.ts.map +1 -0
  246. package/dist/types/auth.js +41 -0
  247. package/dist/types/config.d.ts +47 -0
  248. package/dist/types/config.d.ts.map +1 -0
  249. package/dist/types/config.js +1 -0
  250. package/dist/types/document.d.ts +34 -0
  251. package/dist/types/document.d.ts.map +1 -0
  252. package/dist/types/document.js +1 -0
  253. package/dist/types/index.d.ts +9 -0
  254. package/dist/types/index.d.ts.map +1 -0
  255. package/dist/types/index.js +8 -0
  256. package/dist/types/organization.d.ts +105 -0
  257. package/dist/types/organization.d.ts.map +1 -0
  258. package/dist/types/organization.js +3 -0
  259. package/dist/types/schemas.d.ts +114 -0
  260. package/dist/types/schemas.d.ts.map +1 -0
  261. package/dist/types/schemas.js +1 -0
  262. package/dist/types/sidebar.d.ts +33 -0
  263. package/dist/types/sidebar.d.ts.map +1 -0
  264. package/dist/types/sidebar.js +1 -0
  265. package/dist/types/user.d.ts +14 -0
  266. package/dist/types/user.d.ts.map +1 -0
  267. package/dist/types/user.js +1 -0
  268. package/dist/utils/content-hash.d.ts +22 -0
  269. package/dist/utils/content-hash.d.ts.map +1 -0
  270. package/dist/utils/content-hash.js +67 -0
  271. package/dist/utils/image-url.d.ts +88 -0
  272. package/dist/utils/image-url.d.ts.map +1 -0
  273. package/dist/utils/image-url.js +165 -0
  274. package/dist/utils/index.d.ts +6 -0
  275. package/dist/utils/index.d.ts.map +1 -0
  276. package/dist/utils/index.js +9 -0
  277. package/dist/utils/slug.d.ts +13 -0
  278. package/dist/utils/slug.d.ts.map +1 -0
  279. package/dist/utils/slug.js +30 -0
  280. package/package.json +11 -41
@@ -0,0 +1,218 @@
1
+ <script lang="ts">
2
+ import { organizations } from '../../api/index.js';
3
+ import { invalidateAll, goto } from '$app/navigation';
4
+ import { page } from '$app/state';
5
+ import { SvelteURLSearchParams } from 'svelte/reactivity';
6
+ import {
7
+ DropdownMenu,
8
+ DropdownMenuContent,
9
+ DropdownMenuItem,
10
+ DropdownMenuLabel,
11
+ DropdownMenuSeparator,
12
+ DropdownMenuTrigger
13
+ } from '@aphexcms/ui/shadcn/dropdown-menu';
14
+ import {
15
+ SidebarMenu,
16
+ SidebarMenuItem,
17
+ SidebarMenuButton,
18
+ useSidebar
19
+ } from '@aphexcms/ui/shadcn/sidebar';
20
+ import type { SidebarOrganization } from '../../types/sidebar.js';
21
+
22
+ type Props = {
23
+ organizations?: SidebarOrganization[];
24
+ activeOrganization?: SidebarOrganization;
25
+ canCreateOrganization?: boolean;
26
+ onOpenChange?: (open: boolean) => void;
27
+ };
28
+
29
+ let {
30
+ organizations: orgs = [],
31
+ activeOrganization,
32
+ canCreateOrganization = false,
33
+ onOpenChange
34
+ }: Props = $props();
35
+
36
+ const sidebar = useSidebar();
37
+
38
+ let isSwitching = $state(false);
39
+
40
+ // Set initial orgId in URL if not present
41
+ $effect(() => {
42
+ if (activeOrganization && !page.url.searchParams.has('orgId')) {
43
+ const params = new SvelteURLSearchParams(page.url.searchParams);
44
+ params.set('orgId', activeOrganization.id);
45
+ goto(`${page.url.pathname}?${params.toString()}`, { replaceState: true });
46
+ }
47
+ });
48
+
49
+ async function handleSwitchOrganization(org: SidebarOrganization) {
50
+ if (org.id === activeOrganization?.id) return;
51
+
52
+ isSwitching = true;
53
+ try {
54
+ // Switch organization on the server
55
+ await organizations.switch({ organizationId: org.id });
56
+
57
+ // Update URL with new orgId and clear editor state
58
+ const params = new SvelteURLSearchParams();
59
+ params.set('orgId', org.id);
60
+
61
+ // Preserve docType if present, but clear editor-specific params
62
+ const currentDocType = page.url.searchParams.get('docType');
63
+ if (currentDocType) {
64
+ params.set('docType', currentDocType);
65
+ }
66
+
67
+ await goto(`${page.url.pathname}?${params.toString()}`, { replaceState: false });
68
+
69
+ // Invalidate all data to refetch with new organization context
70
+ await invalidateAll();
71
+ } catch (error) {
72
+ console.error('Failed to switch organization:', error);
73
+ // TODO: Show error toast
74
+ } finally {
75
+ isSwitching = false;
76
+ }
77
+ }
78
+
79
+ function getOrganizationInitials(name: string): string {
80
+ return name
81
+ .split(' ')
82
+ .map((word) => word[0])
83
+ .join('')
84
+ .toUpperCase()
85
+ .slice(0, 2);
86
+ }
87
+
88
+ function getRoleLabel(role: string): string {
89
+ return role.charAt(0).toUpperCase() + role.slice(1);
90
+ }
91
+ </script>
92
+
93
+ <SidebarMenu>
94
+ <SidebarMenuItem>
95
+ <DropdownMenu {onOpenChange}>
96
+ <DropdownMenuTrigger>
97
+ {#snippet child({ props })}
98
+ <SidebarMenuButton
99
+ {...props}
100
+ size="lg"
101
+ class="data-[state=open]:bg-sidebar-accent data-[state=open]:text-sidebar-accent-foreground"
102
+ disabled={isSwitching}
103
+ >
104
+ {#if activeOrganization}
105
+ <div
106
+ class="bg-sidebar-primary text-sidebar-primary-foreground flex aspect-square size-8 items-center justify-center rounded-lg text-sm font-semibold"
107
+ >
108
+ {getOrganizationInitials(activeOrganization.name)}
109
+ </div>
110
+ <div class="grid flex-1 text-left text-sm leading-tight">
111
+ <span class="truncate font-medium">
112
+ {activeOrganization.name}
113
+ </span>
114
+ <span class="text-muted-foreground truncate text-xs">
115
+ {getRoleLabel(activeOrganization.role)}
116
+ </span>
117
+ </div>
118
+ {:else}
119
+ <div
120
+ class="bg-muted flex aspect-square size-8 items-center justify-center rounded-lg"
121
+ >
122
+ <span class="text-muted-foreground text-xs">?</span>
123
+ </div>
124
+ <span class="text-muted-foreground">No organization</span>
125
+ {/if}
126
+ <svg
127
+ xmlns="http://www.w3.org/2000/svg"
128
+ width="16"
129
+ height="16"
130
+ viewBox="0 0 24 24"
131
+ fill="none"
132
+ stroke="currentColor"
133
+ stroke-width="2"
134
+ stroke-linecap="round"
135
+ stroke-linejoin="round"
136
+ class="ml-auto"
137
+ >
138
+ <path d="m7 15 5 5 5-5" />
139
+ <path d="m7 9 5-5 5 5" />
140
+ </svg>
141
+ </SidebarMenuButton>
142
+ {/snippet}
143
+ </DropdownMenuTrigger>
144
+ <DropdownMenuContent
145
+ class="w-[--bits-dropdown-menu-anchor-width] min-w-56 rounded-lg"
146
+ align="start"
147
+ side={sidebar.isMobile ? 'bottom' : 'right'}
148
+ sideOffset={4}
149
+ >
150
+ <DropdownMenuLabel class="text-muted-foreground text-xs">Organizations</DropdownMenuLabel>
151
+ {#each orgs as org, index (org.id)}
152
+ <DropdownMenuItem
153
+ onSelect={() => handleSwitchOrganization(org)}
154
+ class="gap-2 p-2"
155
+ disabled={isSwitching || org.id === activeOrganization?.id}
156
+ >
157
+ <div
158
+ class="flex size-6 items-center justify-center rounded-md border text-xs font-semibold"
159
+ >
160
+ {getOrganizationInitials(org.name)}
161
+ </div>
162
+ <div class="flex flex-1 flex-col">
163
+ <span class="text-sm">{org.name}</span>
164
+ <span class="text-muted-foreground text-xs">{getRoleLabel(org.role)}</span>
165
+ </div>
166
+ {#if org.id === activeOrganization?.id}
167
+ <svg
168
+ xmlns="http://www.w3.org/2000/svg"
169
+ width="16"
170
+ height="16"
171
+ viewBox="0 0 24 24"
172
+ fill="none"
173
+ stroke="currentColor"
174
+ stroke-width="2"
175
+ stroke-linecap="round"
176
+ stroke-linejoin="round"
177
+ class="text-primary"
178
+ >
179
+ <path d="M20 6 9 17l-5-5" />
180
+ </svg>
181
+ {/if}
182
+ </DropdownMenuItem>
183
+ {/each}
184
+ <DropdownMenuSeparator />
185
+ <DropdownMenuItem onSelect={() => goto('/admin/organizations')} class="gap-2 p-2">
186
+ <button class="text-muted-foreground font-medium">View all organizations</button>
187
+ </DropdownMenuItem>
188
+ {#if canCreateOrganization}
189
+ <DropdownMenuSeparator />
190
+ <DropdownMenuItem class="gap-2 p-2">
191
+ <div class="flex size-6 items-center justify-center rounded-md border bg-transparent">
192
+ <svg
193
+ xmlns="http://www.w3.org/2000/svg"
194
+ width="16"
195
+ height="16"
196
+ viewBox="0 0 24 24"
197
+ fill="none"
198
+ stroke="currentColor"
199
+ stroke-width="2"
200
+ stroke-linecap="round"
201
+ stroke-linejoin="round"
202
+ >
203
+ <path d="M5 12h14" />
204
+ <path d="M12 5v14" />
205
+ </svg>
206
+ </div>
207
+ <button
208
+ class="text-muted-foreground font-medium"
209
+ onclick={() => {
210
+ goto('/admin/organizations?action=create');
211
+ }}>Create organization</button
212
+ >
213
+ </DropdownMenuItem>
214
+ {/if}
215
+ </DropdownMenuContent>
216
+ </DropdownMenu>
217
+ </SidebarMenuItem>
218
+ </SidebarMenu>
@@ -0,0 +1,11 @@
1
+ import type { SidebarOrganization } from '../../types/sidebar.js';
2
+ type Props = {
3
+ organizations?: SidebarOrganization[];
4
+ activeOrganization?: SidebarOrganization;
5
+ canCreateOrganization?: boolean;
6
+ onOpenChange?: (open: boolean) => void;
7
+ };
8
+ declare const OrganizationSwitcher: import("svelte").Component<Props, {}, "">;
9
+ type OrganizationSwitcher = ReturnType<typeof OrganizationSwitcher>;
10
+ export default OrganizationSwitcher;
11
+ //# sourceMappingURL=OrganizationSwitcher.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrganizationSwitcher.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/layout/OrganizationSwitcher.svelte.ts"],"names":[],"mappings":"AAqBA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAGjE,KAAK,KAAK,GAAG;IACZ,aAAa,CAAC,EAAE,mBAAmB,EAAE,CAAC;IACtC,kBAAkB,CAAC,EAAE,mBAAmB,CAAC;IACzC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC,CAAC;AAqJH,QAAA,MAAM,oBAAoB,2CAAwC,CAAC;AACnE,KAAK,oBAAoB,GAAG,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC;AACpE,eAAe,oBAAoB,CAAC"}
@@ -0,0 +1,88 @@
1
+ <script lang="ts">
2
+ import { SidebarProvider, SidebarInset, SidebarTrigger } from '@aphexcms/ui/shadcn/sidebar';
3
+ import { Separator } from '@aphexcms/ui/shadcn/separator';
4
+ import { Button } from '@aphexcms/ui/shadcn/button';
5
+ import { ModeWatcher } from 'mode-watcher';
6
+ import { Sun, Moon } from 'lucide-svelte';
7
+ import { toggleMode } from 'mode-watcher';
8
+ import { page } from '$app/state';
9
+ import type { SidebarData } from '../../types/sidebar.js';
10
+ import AppSidebar from './sidebar/AppSidebar.svelte';
11
+
12
+ type Props = {
13
+ data: SidebarData;
14
+ onSignOut?: () => void | Promise<void>;
15
+ children: any;
16
+ enableGraphiQL?: boolean;
17
+ activeTab?: { value: 'structure' | 'vision' };
18
+ };
19
+
20
+ let { data, onSignOut, children, enableGraphiQL = false, activeTab }: Props = $props();
21
+
22
+ // Only show tabs on the main /admin page
23
+ const showTabs = $derived(page.url.pathname === '/admin');
24
+ </script>
25
+
26
+ <ModeWatcher />
27
+ <SidebarProvider class="h-screen">
28
+ <AppSidebar {data} {onSignOut} />
29
+ <SidebarInset class="flex h-full flex-col">
30
+ <header
31
+ class="flex h-16 shrink-0 items-center gap-2 border-b transition-[width,height] ease-linear group-has-[[data-collapsible=icon]]/sidebar-wrapper:h-12"
32
+ >
33
+ <div class="flex w-full items-center px-4" class:justify-between={showTabs}>
34
+ <!-- Left: Trigger and Separator -->
35
+ <div class="flex items-center gap-2">
36
+ <SidebarTrigger class="-ml-1" />
37
+ <Separator orientation="vertical" class="mr-2 h-4" />
38
+ </div>
39
+
40
+ <!-- Center: Structure/Vision Tabs (only on /admin page) -->
41
+ {#if showTabs && activeTab}
42
+ <div
43
+ class="bg-muted text-muted-foreground mx-auto inline-flex h-9 w-fit items-center justify-center rounded-lg p-[3px]"
44
+ >
45
+ <button
46
+ onclick={() => {
47
+ if (activeTab) activeTab.value = 'structure';
48
+ }}
49
+ class="{activeTab.value === 'structure'
50
+ ? 'bg-background text-foreground shadow'
51
+ : 'text-muted-foreground'} ring-offset-background focus-visible:ring-ring inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
52
+ >
53
+ Structure
54
+ </button>
55
+ {#if enableGraphiQL}
56
+ <button
57
+ onclick={() => {
58
+ if (activeTab) activeTab.value = 'vision';
59
+ }}
60
+ class="{activeTab.value === 'vision'
61
+ ? 'bg-background text-foreground shadow'
62
+ : 'text-muted-foreground'} ring-offset-background focus-visible:ring-ring inline-flex items-center justify-center whitespace-nowrap rounded-md px-3 py-1 text-sm font-medium transition-all focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 disabled:pointer-events-none disabled:opacity-50"
63
+ >
64
+ Vision
65
+ </button>
66
+ {/if}
67
+ </div>
68
+ {/if}
69
+
70
+ <!-- Right: Theme Toggle -->
71
+ <div class:ml-auto={!showTabs}>
72
+ <Button onclick={toggleMode} variant="outline" size="icon">
73
+ <Sun
74
+ class="h-[1.2rem] w-[1.2rem] rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0"
75
+ />
76
+ <Moon
77
+ class="absolute h-[1.2rem] w-[1.2rem] rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100"
78
+ />
79
+ <span class="sr-only">Toggle theme</span>
80
+ </Button>
81
+ </div>
82
+ </div>
83
+ </header>
84
+ <main class="flex flex-1 flex-col overflow-hidden pt-0">
85
+ {@render children()}
86
+ </main>
87
+ </SidebarInset>
88
+ </SidebarProvider>
@@ -0,0 +1,14 @@
1
+ import type { SidebarData } from '../../types/sidebar.js';
2
+ type Props = {
3
+ data: SidebarData;
4
+ onSignOut?: () => void | Promise<void>;
5
+ children: any;
6
+ enableGraphiQL?: boolean;
7
+ activeTab?: {
8
+ value: 'structure' | 'vision';
9
+ };
10
+ };
11
+ declare const Sidebar: import("svelte").Component<Props, {}, "">;
12
+ type Sidebar = ReturnType<typeof Sidebar>;
13
+ export default Sidebar;
14
+ //# sourceMappingURL=Sidebar.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Sidebar.svelte.d.ts","sourceRoot":"","sources":["../../../src/lib/components/layout/Sidebar.svelte.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAIzD,KAAK,KAAK,GAAG;IACZ,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACvC,QAAQ,EAAE,GAAG,CAAC;IACd,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE;QAAE,KAAK,EAAE,WAAW,GAAG,QAAQ,CAAA;KAAE,CAAC;CAC9C,CAAC;AAuEH,QAAA,MAAM,OAAO,2CAAwC,CAAC;AACtD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAe,OAAO,CAAC"}
@@ -0,0 +1,63 @@
1
+ <script lang="ts">
2
+ import {
3
+ Sidebar,
4
+ SidebarContent,
5
+ SidebarFooter,
6
+ SidebarHeader,
7
+ SidebarRail
8
+ } from '@aphexcms/ui/shadcn/sidebar';
9
+ import OrganizationSwitcher from '../OrganizationSwitcher.svelte';
10
+ import NavMain from './NavMain.svelte';
11
+ import NavUser from './NavUser.svelte';
12
+ import type { SidebarData } from '../../../types/sidebar.js';
13
+ import type { ComponentProps } from 'svelte';
14
+
15
+ type Props = ComponentProps<typeof Sidebar> & {
16
+ data: SidebarData;
17
+ onSignOut?: () => void | Promise<void>;
18
+ };
19
+
20
+ let { data, onSignOut, ...restProps }: Props = $props();
21
+
22
+ // Convert navItems to the format expected by NavMain
23
+ const navMainItems = $derived(
24
+ data?.navItems?.map((item) => ({
25
+ title: item.label,
26
+ url: item.href,
27
+ icon: undefined, // We'll keep icons simple for now
28
+ isActive: false
29
+ })) || [
30
+ {
31
+ title: 'Content',
32
+ url: '/admin',
33
+ icon: undefined,
34
+ isActive: false
35
+ }
36
+ ]
37
+ );
38
+ </script>
39
+
40
+ <Sidebar collapsible="icon" {...restProps}>
41
+ <SidebarHeader>
42
+ <!-- Organization Switcher -->
43
+ {#if data?.organizations && data.organizations.length > 0}
44
+ <OrganizationSwitcher
45
+ organizations={data.organizations}
46
+ activeOrganization={data.activeOrganization}
47
+ canCreateOrganization={data.user?.role === 'super_admin'}
48
+ />
49
+ {/if}
50
+ </SidebarHeader>
51
+
52
+ <SidebarContent>
53
+ <NavMain items={navMainItems} />
54
+ </SidebarContent>
55
+
56
+ <SidebarFooter>
57
+ {#if data?.user}
58
+ <NavUser user={data.user} {onSignOut} />
59
+ {/if}
60
+ </SidebarFooter>
61
+
62
+ <SidebarRail />
63
+ </Sidebar>
@@ -0,0 +1,11 @@
1
+ import { Sidebar } from '@aphexcms/ui/shadcn/sidebar';
2
+ import type { SidebarData } from '../../../types/sidebar.js';
3
+ import type { ComponentProps } from 'svelte';
4
+ type Props = ComponentProps<typeof Sidebar> & {
5
+ data: SidebarData;
6
+ onSignOut?: () => void | Promise<void>;
7
+ };
8
+ declare const AppSidebar: import("svelte").Component<Props, {}, "">;
9
+ type AppSidebar = ReturnType<typeof AppSidebar>;
10
+ export default AppSidebar;
11
+ //# sourceMappingURL=AppSidebar.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"AppSidebar.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/layout/sidebar/AppSidebar.svelte.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,OAAO,EAKP,MAAM,6BAA6B,CAAC;AAItC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,QAAQ,CAAC;AAG5C,KAAK,KAAK,GAAG,cAAc,CAAC,OAAO,OAAO,CAAC,GAAG;IAC7C,IAAI,EAAE,WAAW,CAAC;IAClB,SAAS,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACvC,CAAC;AAqDH,QAAA,MAAM,UAAU,2CAAwC,CAAC;AACzD,KAAK,UAAU,GAAG,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC;AAChD,eAAe,UAAU,CAAC"}
@@ -0,0 +1,95 @@
1
+ <script lang="ts">
2
+ import { goto } from '$app/navigation';
3
+ import { page } from '$app/state';
4
+ import * as Collapsible from '@aphexcms/ui/shadcn/collapsible';
5
+ import {
6
+ SidebarGroup,
7
+ SidebarGroupLabel,
8
+ SidebarMenu,
9
+ SidebarMenuItem,
10
+ SidebarMenuButton,
11
+ SidebarMenuSub,
12
+ SidebarMenuSubItem,
13
+ SidebarMenuSubButton
14
+ } from '@aphexcms/ui/shadcn/sidebar';
15
+ import { ChevronRight, type Icon as IconType } from 'lucide-svelte';
16
+
17
+ type NavItem = {
18
+ title: string;
19
+ url: string;
20
+ icon?: typeof IconType;
21
+ isActive?: boolean;
22
+ items?: {
23
+ title: string;
24
+ url: string;
25
+ }[];
26
+ };
27
+
28
+ type Props = {
29
+ items: NavItem[];
30
+ label?: string;
31
+ };
32
+
33
+ let { items, label = 'Content' }: Props = $props();
34
+
35
+ let currentPath = $derived(page.url.pathname);
36
+ </script>
37
+
38
+ <SidebarGroup>
39
+ <SidebarGroupLabel>{label}</SidebarGroupLabel>
40
+ <SidebarMenu>
41
+ {#each items as item (item.title)}
42
+ {#if item.items && item.items.length > 0}
43
+ <Collapsible.Root open={item.isActive} class="group/collapsible">
44
+ {#snippet child({ props })}
45
+ <SidebarMenuItem {...props}>
46
+ <Collapsible.Trigger>
47
+ {#snippet child({ props })}
48
+ <SidebarMenuButton {...props} tooltipContent={item.title}>
49
+ {#if item.icon}
50
+ {@const Icon = item.icon}
51
+ <Icon class="h-4 w-4" />
52
+ {/if}
53
+ <span>{item.title}</span>
54
+ <ChevronRight
55
+ class="ml-auto h-4 w-4 transition-transform duration-200 group-data-[state=open]/collapsible:rotate-90"
56
+ />
57
+ </SidebarMenuButton>
58
+ {/snippet}
59
+ </Collapsible.Trigger>
60
+ <Collapsible.Content>
61
+ <SidebarMenuSub>
62
+ {#each item.items as subItem (subItem.title)}
63
+ <SidebarMenuSubItem>
64
+ <SidebarMenuSubButton>
65
+ {#snippet child({ props })}
66
+ <a href={subItem.url} {...props}>
67
+ <span>{subItem.title}</span>
68
+ </a>
69
+ {/snippet}
70
+ </SidebarMenuSubButton>
71
+ </SidebarMenuSubItem>
72
+ {/each}
73
+ </SidebarMenuSub>
74
+ </Collapsible.Content>
75
+ </SidebarMenuItem>
76
+ {/snippet}
77
+ </Collapsible.Root>
78
+ {:else}
79
+ <SidebarMenuItem>
80
+ <SidebarMenuButton
81
+ onclick={() => goto(item.url)}
82
+ isActive={currentPath.startsWith(item.url)}
83
+ tooltipContent={item.title}
84
+ >
85
+ {#if item.icon}
86
+ {@const Icon = item.icon}
87
+ <Icon class="h-4 w-4" />
88
+ {/if}
89
+ <span>{item.title}</span>
90
+ </SidebarMenuButton>
91
+ </SidebarMenuItem>
92
+ {/if}
93
+ {/each}
94
+ </SidebarMenu>
95
+ </SidebarGroup>
@@ -0,0 +1,19 @@
1
+ import { type Icon as IconType } from 'lucide-svelte';
2
+ type NavItem = {
3
+ title: string;
4
+ url: string;
5
+ icon?: typeof IconType;
6
+ isActive?: boolean;
7
+ items?: {
8
+ title: string;
9
+ url: string;
10
+ }[];
11
+ };
12
+ type Props = {
13
+ items: NavItem[];
14
+ label?: string;
15
+ };
16
+ declare const NavMain: import("svelte").Component<Props, {}, "">;
17
+ type NavMain = ReturnType<typeof NavMain>;
18
+ export default NavMain;
19
+ //# sourceMappingURL=NavMain.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavMain.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/layout/sidebar/NavMain.svelte.ts"],"names":[],"mappings":"AAgBA,OAAO,EAAgB,KAAK,IAAI,IAAI,QAAQ,EAAE,MAAM,eAAe,CAAC;AAGnE,KAAK,OAAO,GAAG;IACd,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,QAAQ,CAAC;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,KAAK,CAAC,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,GAAG,EAAE,MAAM,CAAC;KACZ,EAAE,CAAC;CACJ,CAAC;AAEF,KAAK,KAAK,GAAG;IACZ,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAsEH,QAAA,MAAM,OAAO,2CAAwC,CAAC;AACtD,KAAK,OAAO,GAAG,UAAU,CAAC,OAAO,OAAO,CAAC,CAAC;AAC1C,eAAe,OAAO,CAAC"}
@@ -0,0 +1,69 @@
1
+ <script lang="ts">
2
+ import {
3
+ SidebarGroup,
4
+ SidebarGroupContent,
5
+ SidebarMenu,
6
+ SidebarMenuItem,
7
+ SidebarMenuButton
8
+ } from '@aphexcms/ui/shadcn/sidebar';
9
+ import { Sun, Moon } from 'lucide-svelte';
10
+ import { toggleMode } from 'mode-watcher';
11
+
12
+ type Props = {
13
+ enableGraphiQL?: boolean;
14
+ activeTab?: 'structure' | 'vision';
15
+ onTabChange?: (tab: 'structure' | 'vision') => void;
16
+ };
17
+
18
+ let { enableGraphiQL = false, activeTab = $bindable('structure'), onTabChange }: Props = $props();
19
+
20
+ function handleTabClick(tab: 'structure' | 'vision') {
21
+ activeTab = tab;
22
+ if (onTabChange) {
23
+ onTabChange(tab);
24
+ }
25
+ }
26
+ </script>
27
+
28
+ <SidebarGroup class="mt-auto">
29
+ <SidebarGroupContent>
30
+ <SidebarMenu>
31
+ <!-- Structure Tab -->
32
+ <SidebarMenuItem>
33
+ <SidebarMenuButton
34
+ onclick={() => handleTabClick('structure')}
35
+ isActive={activeTab === 'structure'}
36
+ tooltipContent="Structure"
37
+ size="sm"
38
+ >
39
+ <span>Structure</span>
40
+ </SidebarMenuButton>
41
+ </SidebarMenuItem>
42
+
43
+ <!-- Vision Tab (if GraphiQL is enabled) -->
44
+ {#if enableGraphiQL}
45
+ <SidebarMenuItem>
46
+ <SidebarMenuButton
47
+ onclick={() => handleTabClick('vision')}
48
+ isActive={activeTab === 'vision'}
49
+ tooltipContent="Vision"
50
+ size="sm"
51
+ >
52
+ <span>Vision</span>
53
+ </SidebarMenuButton>
54
+ </SidebarMenuItem>
55
+ {/if}
56
+
57
+ <!-- Theme Toggle -->
58
+ <SidebarMenuItem>
59
+ <SidebarMenuButton onclick={toggleMode} tooltipContent="Toggle theme" size="sm">
60
+ <Sun class="h-4 w-4 rotate-0 scale-100 transition-all dark:-rotate-90 dark:scale-0" />
61
+ <Moon
62
+ class="absolute h-4 w-4 rotate-90 scale-0 transition-all dark:rotate-0 dark:scale-100"
63
+ />
64
+ <span>Theme</span>
65
+ </SidebarMenuButton>
66
+ </SidebarMenuItem>
67
+ </SidebarMenu>
68
+ </SidebarGroupContent>
69
+ </SidebarGroup>
@@ -0,0 +1,9 @@
1
+ type Props = {
2
+ enableGraphiQL?: boolean;
3
+ activeTab?: 'structure' | 'vision';
4
+ onTabChange?: (tab: 'structure' | 'vision') => void;
5
+ };
6
+ declare const NavSecondary: import("svelte").Component<Props, {}, "activeTab">;
7
+ type NavSecondary = ReturnType<typeof NavSecondary>;
8
+ export default NavSecondary;
9
+ //# sourceMappingURL=NavSecondary.svelte.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavSecondary.svelte.d.ts","sourceRoot":"","sources":["../../../../src/lib/components/layout/sidebar/NavSecondary.svelte.ts"],"names":[],"mappings":"AAcC,KAAK,KAAK,GAAG;IACZ,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,SAAS,CAAC,EAAE,WAAW,GAAG,QAAQ,CAAC;IACnC,WAAW,CAAC,EAAE,CAAC,GAAG,EAAE,WAAW,GAAG,QAAQ,KAAK,IAAI,CAAC;CACpD,CAAC;AAkDH,QAAA,MAAM,YAAY,oDAAwC,CAAC;AAC3D,KAAK,YAAY,GAAG,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;AACpD,eAAe,YAAY,CAAC"}