alinea 2.0.0-preview.2 → 2.0.0-preview.4

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 (178) hide show
  1. package/dist/.init/content/pages/welcome.json +1 -1
  2. package/dist/LICENSES.md +157 -103
  3. package/dist/adapter/next/DevRemote.js +10 -2
  4. package/dist/adapter/next/previews.js +4 -1
  5. package/dist/adapter/next/previews.spec.d.ts +1 -0
  6. package/dist/backend/Handler.js +14 -7
  7. package/dist/backend/api/BasicAuth.d.ts +1 -1
  8. package/dist/backend/api/BasicAuth.js +14 -14
  9. package/dist/backend/api/OAuth2.d.ts +3 -3
  10. package/dist/backend/api/OAuth2.js +7 -4
  11. package/dist/bundled.d.ts +159 -42
  12. package/dist/chunks/{chunk-Y7XOMJOC.js → chunk-CFNRVI3Y.js} +220 -247
  13. package/dist/chunks/chunk-D6UJHBJJ.js +183 -0
  14. package/dist/chunks/chunk-TIJTT5ZI.js +228 -0
  15. package/dist/chunks/{chunk-UVOEM4AH.js → chunk-XMOVGDFI.js} +1 -1
  16. package/dist/cli/Serve.js +1 -1
  17. package/dist/cli/bin.js +1 -1
  18. package/dist/cli/serve/LocalAuth.js +1 -1
  19. package/dist/cloud/AuthResult.d.ts +2 -0
  20. package/dist/cloud/CloudHandshake.d.ts +7 -0
  21. package/dist/cloud/CloudHandshake.js +64 -0
  22. package/dist/cloud/CloudRemote.d.ts +4 -1
  23. package/dist/cloud/CloudRemote.js +21 -3
  24. package/dist/components/Breadcrumbs.js +2 -2
  25. package/dist/components/Calendar.js +6 -6
  26. package/dist/components/Checkbox.js +3 -3
  27. package/dist/components/ComboBox.js +11 -11
  28. package/dist/components/DateField.js +3 -3
  29. package/dist/components/DatePicker.js +4 -4
  30. package/dist/components/DateRangePicker.js +6 -6
  31. package/dist/components/Disclosure.js +8 -8
  32. package/dist/components/Label.js +5 -5
  33. package/dist/components/List.js +34 -34
  34. package/dist/components/Menu.js +4 -4
  35. package/dist/components/Modal.js +3 -3
  36. package/dist/components/MultipleSelect.js +25 -25
  37. package/dist/components/NumberField.js +6 -6
  38. package/dist/components/ProgressCircle.js +2 -2
  39. package/dist/components/RadioGroup.js +2 -2
  40. package/dist/components/SearchField.js +3 -3
  41. package/dist/components/Select.js +7 -7
  42. package/dist/components/Surface.js +2 -2
  43. package/dist/components/Table.js +7 -7
  44. package/dist/components/Tabs.js +4 -4
  45. package/dist/components/TagGroup.js +2 -2
  46. package/dist/components/TextField.js +6 -6
  47. package/dist/components/TimeField.js +2 -2
  48. package/dist/components/Toggle.d.ts +1 -1
  49. package/dist/components/Toggle.js +2 -2
  50. package/dist/components/Toolbar.js +2 -2
  51. package/dist/components/Tooltip.js +3 -3
  52. package/dist/components/Tree.d.ts +4 -2
  53. package/dist/components/Tree.js +18 -4
  54. package/dist/core/Connection.d.ts +7 -4
  55. package/dist/core/Entry.d.ts +6 -0
  56. package/dist/core/Entry.js +10 -0
  57. package/dist/core/Graph.d.ts +1 -1
  58. package/dist/core/Id.d.ts +1 -0
  59. package/dist/core/Id.js +8 -0
  60. package/dist/core/Infer.d.ts +8 -1
  61. package/dist/core/db/EntryAliases.js +1 -4
  62. package/dist/core/db/EntryResolver.js +6 -6
  63. package/dist/core/db/EntryTransaction.js +1 -0
  64. package/dist/core/db/Operation.d.ts +2 -2
  65. package/dist/core/db/Operation.js +15 -4
  66. package/dist/dashboard/App.js +37 -17
  67. package/dist/dashboard/StoryProvider.js +2 -2
  68. package/dist/dashboard/app/AccessDenied.d.ts +16 -1
  69. package/dist/dashboard/app/AccessDenied.js +21 -12
  70. package/dist/dashboard/app/ActivityStatus.js +19 -19
  71. package/dist/dashboard/app/AppearanceToggle.d.ts +1 -0
  72. package/dist/dashboard/app/AppearanceToggle.js +43 -0
  73. package/dist/dashboard/app/AuthView.d.ts +1 -1
  74. package/dist/dashboard/app/AuthView.js +16 -18
  75. package/dist/dashboard/app/Badge.js +2 -2
  76. package/dist/dashboard/app/CompactField.js +17 -17
  77. package/dist/dashboard/app/DashboardErrorBoundary.js +22 -10
  78. package/dist/dashboard/app/DashboardLayout.js +15 -8
  79. package/dist/dashboard/app/DashboardMeta.d.ts +2 -1
  80. package/dist/dashboard/app/DashboardMeta.js +20 -5
  81. package/dist/dashboard/app/EntryFields.js +6 -6
  82. package/dist/dashboard/app/EntryHeader.js +25 -25
  83. package/dist/dashboard/app/EntryReferences.js +16 -16
  84. package/dist/dashboard/app/EntrySidebar.js +26 -26
  85. package/dist/dashboard/app/EntrySidebarPreview.js +61 -34
  86. package/dist/dashboard/app/EntrySidebarPreview.story.d.ts +6 -1
  87. package/dist/dashboard/app/EntryTranslationBanner.js +8 -8
  88. package/dist/dashboard/app/Explorer.d.ts +2 -1
  89. package/dist/dashboard/app/Explorer.js +79 -67
  90. package/dist/dashboard/app/ExplorerCards.js +62 -66
  91. package/dist/dashboard/app/ExplorerFileCard.js +20 -20
  92. package/dist/dashboard/app/ExplorerList.js +22 -22
  93. package/dist/dashboard/app/ExplorerModal.js +3 -3
  94. package/dist/dashboard/app/ExplorerPickerContent.js +2 -2
  95. package/dist/dashboard/app/ExplorerTable.js +68 -68
  96. package/dist/dashboard/app/ImagePicker.js +7 -7
  97. package/dist/dashboard/app/LinkPicker.js +44 -24
  98. package/dist/dashboard/app/LocaleMenu.js +5 -7
  99. package/dist/dashboard/app/SidebarLayout.js +7 -7
  100. package/dist/dashboard/app/SidebarTree.js +66 -74
  101. package/dist/dashboard/app/WorkspaceMenu.d.ts +10 -3
  102. package/dist/dashboard/app/WorkspaceMenu.js +85 -64
  103. package/dist/dashboard/app/WorkspaceMenu.stories.d.ts +2 -0
  104. package/dist/dashboard/app/WorkspaceRoots.d.ts +3 -1
  105. package/dist/dashboard/app/WorkspaceRoots.js +82 -107
  106. package/dist/dashboard/app/editor/FileEditor.js +31 -31
  107. package/dist/dashboard/app/editor/FilePreview.js +4 -4
  108. package/dist/dashboard/app/editor/MediaAltField.view.js +4 -4
  109. package/dist/dashboard/app/modals/CreateEntry.js +14 -14
  110. package/dist/dashboard/app/pages/EntryPage.js +28 -30
  111. package/dist/dashboard/app/pages/RootPage.js +4 -4
  112. package/dist/dashboard/app/pages/SplashPage.d.ts +3 -0
  113. package/dist/dashboard/app/pages/SplashPage.js +414 -0
  114. package/dist/dashboard/app/pages/UsersPage.js +35 -35
  115. package/dist/dashboard/app/ui/DashboardModal.js +19 -19
  116. package/dist/dashboard/app/ui/Rail.js +3 -3
  117. package/dist/dashboard/atoms/ReactiveNode.js +1 -1
  118. package/dist/dashboard/atoms/activity.js +2 -3
  119. package/dist/dashboard/atoms/auth.d.ts +2 -0
  120. package/dist/dashboard/atoms/auth.js +6 -2
  121. package/dist/dashboard/atoms/config.js +1 -1
  122. package/dist/dashboard/atoms/core.js +2 -2
  123. package/dist/dashboard/atoms/create.js +1 -1
  124. package/dist/dashboard/atoms/dashboard.js +2 -2
  125. package/dist/dashboard/atoms/editor.js +1 -1
  126. package/dist/dashboard/atoms/entry.js +2 -2
  127. package/dist/dashboard/atoms/explorer.d.ts +1 -3
  128. package/dist/dashboard/atoms/explorer.js +7 -9
  129. package/dist/dashboard/atoms/graph.d.ts +1 -0
  130. package/dist/dashboard/atoms/graph.js +7 -2
  131. package/dist/dashboard/atoms/link.js +2 -2
  132. package/dist/dashboard/atoms/nav.d.ts +4 -3
  133. package/dist/dashboard/atoms/nav.js +10 -5
  134. package/dist/dashboard/atoms/preview.js +1 -1
  135. package/dist/dashboard/atoms/root.js +2 -2
  136. package/dist/dashboard/atoms/upload.js +1 -1
  137. package/dist/dashboard/atoms/user.d.ts +1 -1
  138. package/dist/dashboard/atoms/user.js +8 -6
  139. package/dist/dashboard/atoms/utils.js +2 -2
  140. package/dist/dashboard/boot/Boot.js +2 -4
  141. package/dist/dashboard/boot/DashboardWorker.js +34 -29
  142. package/dist/dashboard/editor/UseField.js +6 -6
  143. package/dist/dashboard/fixture/cms.d.ts +12 -0
  144. package/dist/dashboard/fixture/cms.js +53 -2
  145. package/dist/dashboard/hook/UseGraph.js +4 -4
  146. package/dist/dashboard/hook/UseRoot.js +4 -4
  147. package/dist/dashboard/hooks.js +16 -16
  148. package/dist/field/check/CheckField.view.js +2 -2
  149. package/dist/field/code/CodeField.view.js +15 -15
  150. package/dist/field/link/EntryLink.d.ts +1 -1
  151. package/dist/field/link/EntryLink.js +1 -0
  152. package/dist/field/link/Link.js +1 -0
  153. package/dist/field/link/LinkField.d.ts +5 -0
  154. package/dist/field/link/LinkField.view.js +81 -64
  155. package/dist/field/list/ListField.view.js +26 -26
  156. package/dist/field/localiser/LocalisedField.view.js +76 -5
  157. package/dist/field/metadata/MetadataField.d.ts +2 -0
  158. package/dist/field/metadata/MetadataField.js +2 -1
  159. package/dist/field/metadata/MetadataField.view.js +20 -20
  160. package/dist/field/richtext/PickTextLink.js +6 -6
  161. package/dist/field/richtext/RichTextBlock.js +6 -6
  162. package/dist/field/richtext/RichTextBlocks.js +1 -1
  163. package/dist/field/richtext/RichTextExtensions.js +23 -23
  164. package/dist/field/richtext/RichTextField.view.js +9 -9
  165. package/dist/field/richtext/RichTextState.js +1 -1
  166. package/dist/field/text/TextField.view.js +2 -2
  167. package/dist/index.css +436 -28
  168. package/dist/preview/PreviewMessage.d.ts +3 -0
  169. package/dist/preview/PreviewMessage.js +1 -0
  170. package/dist/preview/RegisterPreview.d.ts +1 -1
  171. package/dist/preview/RegisterPreview.js +28 -10
  172. package/dist/preview/react.d.ts +5 -1
  173. package/dist/preview/react.js +12 -9
  174. package/dist/preview/widget.js +6 -12
  175. package/dist/query.d.ts +7 -7
  176. package/package.json +1 -1
  177. package/dist/chunks/chunk-STAJCW4Z.js +0 -322
  178. package/dist/chunks/chunk-U4VOHNR2.js +0 -210
@@ -1,7 +1,7 @@
1
1
  import {
2
- useAtomValue
3
- } from "../../../chunks/chunk-U4VOHNR2.js";
4
- import "../../../chunks/chunk-Y7XOMJOC.js";
2
+ useAtomValueRaw
3
+ } from "../../../chunks/chunk-D6UJHBJJ.js";
4
+ import "../../../chunks/chunk-CFNRVI3Y.js";
5
5
  import "../../../chunks/chunk-CQ52GEHY.js";
6
6
 
7
7
  // src/dashboard/app/editor/MediaAltField.view.tsx
@@ -21,7 +21,7 @@ import { useState } from "react";
21
21
  import { jsx } from "react/jsx-runtime";
22
22
  function MediaAltFieldView({ field }) {
23
23
  const { entry } = useEntryAtoms();
24
- const i18n = useAtomValue(entry.mediaI18n);
24
+ const i18n = useAtomValueRaw(entry.mediaI18n);
25
25
  const [value, setValue] = useField(field);
26
26
  const options = useFieldOptions(field);
27
27
  const error = useFieldError(field);
@@ -1,10 +1,10 @@
1
1
  import {
2
- useAtomValue,
2
+ useAtomValueRaw,
3
3
  useSetAtom
4
- } from "../../../chunks/chunk-U4VOHNR2.js";
4
+ } from "../../../chunks/chunk-D6UJHBJJ.js";
5
5
  import {
6
6
  atom
7
- } from "../../../chunks/chunk-Y7XOMJOC.js";
7
+ } from "../../../chunks/chunk-CFNRVI3Y.js";
8
8
  import {
9
9
  dist_default
10
10
  } from "../../../chunks/chunk-I4OYYAX5.js";
@@ -47,14 +47,14 @@ import {
47
47
 
48
48
  // src/dashboard/app/modals/CreateEntry.module.css
49
49
  var CreateEntry_default = {
50
+ "CreateEntry-message": "alinea-CreateEntry-message",
51
+ "CreateEntryMessage": "alinea-CreateEntry-message",
50
52
  "CreateEntry-parentRow": "alinea-CreateEntry-parentRow",
51
53
  "CreateEntryParentRow": "alinea-CreateEntry-parentRow",
52
- "CreateEntry-insertOrder": "alinea-CreateEntry-insertOrder",
53
- "CreateEntryInsertOrder": "alinea-CreateEntry-insertOrder",
54
54
  "CreateEntry-parentField": "alinea-CreateEntry-parentField",
55
55
  "CreateEntryParentField": "alinea-CreateEntry-parentField",
56
- "CreateEntry-message": "alinea-CreateEntry-message",
57
- "CreateEntryMessage": "alinea-CreateEntry-message"
56
+ "CreateEntry-insertOrder": "alinea-CreateEntry-insertOrder",
57
+ "CreateEntryInsertOrder": "alinea-CreateEntry-insertOrder"
58
58
  };
59
59
 
60
60
  // src/dashboard/app/modals/CreateEntry.tsx
@@ -102,12 +102,12 @@ function CreateEntryForm() {
102
102
  const modal = useDashboardModal();
103
103
  const { page, root } = useDashboardContext();
104
104
  const createEntry = useSetAtom(createEntryAtom);
105
- const config = useAtomValue(configAtom).schema;
106
- const policy = useAtomValue(policyAtom);
105
+ const config = useAtomValueRaw(configAtom).schema;
106
+ const policy = useAtomValueRaw(policyAtom);
107
107
  const { locale } = page;
108
108
  const tree = root.tree(locale);
109
- const selectedItem = useAtomValue(tree.selectedItem);
110
- const rootData = useAtomValue(root.data);
109
+ const selectedItem = useAtomValueRaw(tree.selectedItem);
110
+ const rootData = useAtomValueRaw(root.data);
111
111
  const initialParentId = useMemo(() => {
112
112
  if (!page.entry || !selectedItem) return void 0;
113
113
  const type = config[selectedItem.type];
@@ -134,7 +134,7 @@ function CreateEntryForm() {
134
134
  initialParentId ? entryReference(initialParentId, "parent") : null
135
135
  );
136
136
  }, [containerTypes, initialParentId, root.key, root.workspace]);
137
- const parentValue = useAtomValue(parent.value);
137
+ const parentValue = useAtomValueRaw(parent.value);
138
138
  const parentId = entryIdOf(parentValue);
139
139
  const parentItemAtom = useMemo(
140
140
  () => atom((get) => {
@@ -143,7 +143,7 @@ function CreateEntryForm() {
143
143
  }),
144
144
  [parent.value, tree]
145
145
  );
146
- const parentItem = useAtomValue(parentItemAtom);
146
+ const parentItem = useAtomValueRaw(parentItemAtom);
147
147
  const parentType = parentItem ? config[parentItem.type] : void 0;
148
148
  const allowed = parentType ? Schema.contained(config, Type.contains(parentType)) : Schema.contained(config, rootData.contains ?? []);
149
149
  const parentIds = parentItem ? [parentItem.id, ...parentItem.parents] : [];
@@ -166,7 +166,7 @@ function CreateEntryForm() {
166
166
  });
167
167
  return createLinkEditor("copyFrom", field);
168
168
  }, [root.key, root.workspace, selectedType]);
169
- const copyFromValue = useAtomValue(copyFrom.value);
169
+ const copyFromValue = useAtomValueRaw(copyFrom.value);
170
170
  const copyFromId = entryIdOf(copyFromValue);
171
171
  const showInsertOrder = parentType ? Type.insertOrder(parentType) === "free" : true;
172
172
  async function onSubmit(event) {
@@ -1,9 +1,9 @@
1
1
  import {
2
2
  useAtom,
3
- useAtomValue,
3
+ useAtomValueRaw,
4
4
  useSetAtom
5
- } from "../../../chunks/chunk-U4VOHNR2.js";
6
- import "../../../chunks/chunk-Y7XOMJOC.js";
5
+ } from "../../../chunks/chunk-D6UJHBJJ.js";
6
+ import "../../../chunks/chunk-CFNRVI3Y.js";
7
7
  import {
8
8
  styler
9
9
  } from "../../../chunks/chunk-I4OYYAX5.js";
@@ -26,7 +26,7 @@ import {
26
26
  routeGuardAtom
27
27
  } from "alinea/dashboard/atoms/nav";
28
28
  import { rootAtoms } from "alinea/dashboard/atoms/root";
29
- import { useEffect, useLayoutEffect, useRef, useTransition } from "react";
29
+ import { useEffect, useLayoutEffect, useRef } from "react";
30
30
  import { EntryScope } from "../../hooks.js";
31
31
  import {
32
32
  IcBaselineErrorOutline,
@@ -56,31 +56,31 @@ import { Rail, RailBody, RailContent } from "./../ui/Rail.js";
56
56
 
57
57
  // src/dashboard/app/pages/EntryPage.module.css
58
58
  var EntryPage_default = {
59
- "EntryEditor-fields": "alinea-EntryEditor-fields",
60
- "EntryEditorFields": "alinea-EntryEditor-fields",
61
- "EntryEditor-title": "alinea-EntryEditor-title",
62
- "EntryEditorTitle": "alinea-EntryEditor-title",
59
+ "MissingEntry-icon": "alinea-MissingEntry-icon",
60
+ "MissingEntryIcon": "alinea-MissingEntry-icon",
61
+ "MissingEntry-title": "alinea-MissingEntry-title",
62
+ "MissingEntryTitle": "alinea-MissingEntry-title",
63
+ "MissingEntry-id": "alinea-MissingEntry-id",
64
+ "MissingEntryId": "alinea-MissingEntry-id",
65
+ "MissingEntry-message": "alinea-MissingEntry-message",
66
+ "MissingEntryMessage": "alinea-MissingEntry-message",
63
67
  "EntryEditor-toolbar": "alinea-EntryEditor-toolbar",
64
68
  "EntryEditorToolbar": "alinea-EntryEditor-toolbar",
65
69
  "EntryOverview-mobileActions": "alinea-EntryOverview-mobileActions",
66
70
  "EntryOverviewMobileActions": "alinea-EntryOverview-mobileActions",
67
- "EntryEditor-header": "alinea-EntryEditor-header",
68
- "EntryEditorHeader": "alinea-EntryEditor-header",
71
+ "EntryEditor-title": "alinea-EntryEditor-title",
72
+ "EntryEditorTitle": "alinea-EntryEditor-title",
73
+ "EntryEditor-fields": "alinea-EntryEditor-fields",
74
+ "EntryEditorFields": "alinea-EntryEditor-fields",
69
75
  "MissingEntry-card": "alinea-MissingEntry-card",
70
76
  "MissingEntryCard": "alinea-MissingEntry-card",
71
- "MissingEntry": "alinea-MissingEntry",
72
77
  "EntryEditor-body": "alinea-EntryEditor-body",
73
78
  "EntryEditorBody": "alinea-EntryEditor-body",
74
- "MissingEntry-icon": "alinea-MissingEntry-icon",
75
- "MissingEntryIcon": "alinea-MissingEntry-icon",
76
- "MissingEntry-title": "alinea-MissingEntry-title",
77
- "MissingEntryTitle": "alinea-MissingEntry-title",
78
- "MissingEntry-message": "alinea-MissingEntry-message",
79
- "MissingEntryMessage": "alinea-MissingEntry-message",
80
- "MissingEntry-id": "alinea-MissingEntry-id",
81
- "MissingEntryId": "alinea-MissingEntry-id",
82
79
  "EntryEditor-banner": "alinea-EntryEditor-banner",
83
- "EntryEditorBanner": "alinea-EntryEditor-banner"
80
+ "EntryEditorBanner": "alinea-EntryEditor-banner",
81
+ "MissingEntry": "alinea-MissingEntry",
82
+ "EntryEditor-header": "alinea-EntryEditor-header",
83
+ "EntryEditorHeader": "alinea-EntryEditor-header"
84
84
  };
85
85
 
86
86
  // src/dashboard/app/pages/EntryPage.tsx
@@ -136,7 +136,7 @@ var entryPage = page(async (page2, get) => {
136
136
  });
137
137
  function MissingEntry({ page: page2 }) {
138
138
  assert(page2.workspace && page2.root && page2.entry);
139
- const root = useAtomValue(rootAtoms(page2.workspace, page2.root).data);
139
+ const root = useAtomValueRaw(rootAtoms(page2.workspace, page2.root).data);
140
140
  const setRoute = useSetAtom(routeAtom);
141
141
  return /* @__PURE__ */ jsx(
142
142
  NotFoundPanel,
@@ -176,10 +176,9 @@ function NotFoundPanel({
176
176
  ] }) }) });
177
177
  }
178
178
  function EntryViewToggle({ entry, page: page2 }) {
179
- const entryView = useAtomValue(entry.view);
179
+ const entryView = useAtomValueRaw(entry.view);
180
180
  const view = page2.view ?? entryView;
181
181
  const setRoute = useSetAtom(routeAtom);
182
- const [isPending, startTransition] = useTransition();
183
182
  const nextView = view === "overview" ? "edit" : "overview";
184
183
  const label = nextView === "overview" ? "Show overview" : "Edit entry";
185
184
  const tooltip = nextView === "overview" ? "Overview view" : "Edit view";
@@ -190,7 +189,6 @@ function EntryViewToggle({ entry, page: page2 }) {
190
189
  "aria-label": label,
191
190
  appearance: "plain",
192
191
  icon: ViewIcon,
193
- isDisabled: isPending,
194
192
  size: "icon",
195
193
  onPress: () => setRoute({
196
194
  workspace: page2.workspace,
@@ -245,12 +243,12 @@ function EntryEditorContent({
245
243
  sourceLocale,
246
244
  node
247
245
  }) {
248
- const typeName = useAtomValue(entry.type);
249
- const type = useAtomValue(typeAtoms(typeName));
250
- const hasChildren = useAtomValue(entry.hasChildren);
251
- const defaultView = useAtomValue(entry.view);
252
- const sourceLocales = useAtomValue(entry.translationSourceLocales);
253
- const parentPaths = useAtomValue(entry.parentPaths);
246
+ const typeName = useAtomValueRaw(entry.type);
247
+ const type = useAtomValueRaw(typeAtoms(typeName));
248
+ const hasChildren = useAtomValueRaw(entry.hasChildren);
249
+ const defaultView = useAtomValueRaw(entry.view);
250
+ const sourceLocales = useAtomValueRaw(entry.translationSourceLocales);
251
+ const parentPaths = useAtomValueRaw(entry.parentPaths);
254
252
  const View = type.customView;
255
253
  const { locale } = page2;
256
254
  const isUntranslated = selectedEntry.locale !== locale;
@@ -1,8 +1,8 @@
1
1
  import {
2
- useAtomValue,
2
+ useAtomValueRaw,
3
3
  useSetAtom
4
- } from "../../../chunks/chunk-U4VOHNR2.js";
5
- import "../../../chunks/chunk-Y7XOMJOC.js";
4
+ } from "../../../chunks/chunk-D6UJHBJJ.js";
5
+ import "../../../chunks/chunk-CFNRVI3Y.js";
6
6
  import {
7
7
  styler
8
8
  } from "../../../chunks/chunk-I4OYYAX5.js";
@@ -66,7 +66,7 @@ function RootBrowser({ page: page2, root }) {
66
66
  ) });
67
67
  }
68
68
  function MissingRoot({ page: page2, requestedRoot, root }) {
69
- const label = useAtomValue(root.label);
69
+ const label = useAtomValueRaw(root.label);
70
70
  const setRoute = useSetAtom(routeAtom);
71
71
  return /* @__PURE__ */ jsx(
72
72
  NotFoundPanel,
@@ -0,0 +1,3 @@
1
+ import { type Getter } from 'jotai';
2
+ import type { ReactNode } from 'react';
3
+ export declare function splashPage(get: Getter): Promise<ReactNode>;
@@ -0,0 +1,414 @@
1
+ import {
2
+ useSetAtom
3
+ } from "../../../chunks/chunk-D6UJHBJJ.js";
4
+ import "../../../chunks/chunk-CFNRVI3Y.js";
5
+ import {
6
+ styler
7
+ } from "../../../chunks/chunk-I4OYYAX5.js";
8
+ import "../../../chunks/chunk-CQ52GEHY.js";
9
+
10
+ // src/dashboard/app/pages/SplashPage.tsx
11
+ import { Button, Icon, Menu, MenuItem, Surface } from "alinea/components";
12
+ import { Entry } from "alinea/core/Entry";
13
+ import { timestampFromId } from "alinea/core/Id";
14
+ import { getRoot, getType } from "alinea/core/Internal";
15
+ import { configAtom, graphAtom } from "alinea/dashboard/atoms/core";
16
+ import { shaAtom } from "alinea/dashboard/atoms/graph";
17
+ import { routeAtom } from "alinea/dashboard/atoms/nav";
18
+ import { rootAtoms } from "alinea/dashboard/atoms/root";
19
+ import { workspaceAtom, workspacesAtom } from "alinea/dashboard/atoms/config";
20
+ import { canManageMembersAtom, policyAtom } from "alinea/dashboard/atoms/user";
21
+ import { useUser } from "alinea/dashboard/hooks";
22
+ import {
23
+ IcBaselineAccountCircle,
24
+ IcOutlineSettings,
25
+ IcRoundSearch,
26
+ LucideFile
27
+ } from "../../icons.js";
28
+ import { AppearanceToggle } from "../AppearanceToggle.js";
29
+ import { GlobalSearch, WorkspaceAvatar } from "../WorkspaceMenu.js";
30
+
31
+ // src/dashboard/app/pages/SplashPage.module.css
32
+ var SplashPage_default = {
33
+ "SplashPage-appearance": "alinea-SplashPage-appearance",
34
+ "SplashPageAppearance": "alinea-SplashPage-appearance",
35
+ "SplashPage": "alinea-SplashPage",
36
+ "SplashPage-card-header-title": "alinea-SplashPage-card-header-title",
37
+ "SplashPageCardHeaderTitle": "alinea-SplashPage-card-header-title",
38
+ "SplashPage-entries": "alinea-SplashPage-entries",
39
+ "SplashPageEntries": "alinea-SplashPage-entries",
40
+ "SplashPage-root-menuIcon": "alinea-SplashPage-root-menuIcon",
41
+ "SplashPageRootMenuIcon": "alinea-SplashPage-root-menuIcon",
42
+ "SplashPage-card-header": "alinea-SplashPage-card-header",
43
+ "SplashPageCardHeader": "alinea-SplashPage-card-header",
44
+ "SplashPage-search-label": "alinea-SplashPage-search-label",
45
+ "SplashPageSearchLabel": "alinea-SplashPage-search-label",
46
+ "SplashPage-sidebar": "alinea-SplashPage-sidebar",
47
+ "SplashPageSidebar": "alinea-SplashPage-sidebar",
48
+ "SplashPage-entry-visual-icon": "alinea-SplashPage-entry-visual-icon",
49
+ "SplashPageEntryVisualIcon": "alinea-SplashPage-entry-visual-icon",
50
+ "SplashPage-card-header-content": "alinea-SplashPage-card-header-content",
51
+ "SplashPageCardHeaderContent": "alinea-SplashPage-card-header-content",
52
+ "SplashPage-entry-user": "alinea-SplashPage-entry-user",
53
+ "SplashPageEntryUser": "alinea-SplashPage-entry-user",
54
+ "SplashPage-grid": "alinea-SplashPage-grid",
55
+ "SplashPageGrid": "alinea-SplashPage-grid",
56
+ "SplashPage-entry": "alinea-SplashPage-entry",
57
+ "SplashPageEntry": "alinea-SplashPage-entry",
58
+ "SplashPage-entry-content": "alinea-SplashPage-entry-content",
59
+ "SplashPageEntryContent": "alinea-SplashPage-entry-content",
60
+ "SplashPage-entry-visual": "alinea-SplashPage-entry-visual",
61
+ "SplashPageEntryVisual": "alinea-SplashPage-entry-visual",
62
+ "SplashPage-root": "alinea-SplashPage-root",
63
+ "SplashPageRoot": "alinea-SplashPage-root",
64
+ "SplashPage-user": "alinea-SplashPage-user",
65
+ "SplashPageUser": "alinea-SplashPage-user",
66
+ "SplashPage-content": "alinea-SplashPage-content",
67
+ "SplashPageContent": "alinea-SplashPage-content",
68
+ "SplashPage-card-header-button": "alinea-SplashPage-card-header-button",
69
+ "SplashPageCardHeaderButton": "alinea-SplashPage-card-header-button",
70
+ "SplashPage-card-header-label": "alinea-SplashPage-card-header-label",
71
+ "SplashPageCardHeaderLabel": "alinea-SplashPage-card-header-label",
72
+ "SplashPage-card-footer": "alinea-SplashPage-card-footer",
73
+ "SplashPageCardFooter": "alinea-SplashPage-card-footer",
74
+ "SplashPage-actionIcon": "alinea-SplashPage-actionIcon",
75
+ "SplashPageActionIcon": "alinea-SplashPage-actionIcon",
76
+ "SplashPage-card": "alinea-SplashPage-card",
77
+ "SplashPageCard": "alinea-SplashPage-card",
78
+ "SplashPage-entry-meta": "alinea-SplashPage-entry-meta",
79
+ "SplashPageEntryMeta": "alinea-SplashPage-entry-meta",
80
+ "SplashPage-entry-title": "alinea-SplashPage-entry-title",
81
+ "SplashPageEntryTitle": "alinea-SplashPage-entry-title",
82
+ "SplashPage-entry-primary": "alinea-SplashPage-entry-primary",
83
+ "SplashPageEntryPrimary": "alinea-SplashPage-entry-primary",
84
+ "SplashPage-appearance-label": "alinea-SplashPage-appearance-label",
85
+ "SplashPageAppearanceLabel": "alinea-SplashPage-appearance-label",
86
+ "SplashPage-entry-time": "alinea-SplashPage-entry-time",
87
+ "SplashPageEntryTime": "alinea-SplashPage-entry-time",
88
+ "SplashPage-action": "alinea-SplashPage-action",
89
+ "SplashPageAction": "alinea-SplashPage-action",
90
+ "SplashPage-sidebar-content": "alinea-SplashPage-sidebar-content",
91
+ "SplashPageSidebarContent": "alinea-SplashPage-sidebar-content",
92
+ "SplashPage-user-label": "alinea-SplashPage-user-label",
93
+ "SplashPageUserLabel": "alinea-SplashPage-user-label"
94
+ };
95
+
96
+ // src/dashboard/app/pages/SplashPage.tsx
97
+ import { jsx, jsxs } from "react/jsx-runtime";
98
+ var styles = styler(SplashPage_default);
99
+ var recentEntryCount = 3;
100
+ var recentCandidateWindowSize = recentEntryCount;
101
+ var visibleRootCount = 2;
102
+ var futureTimestampTolerance = 24 * 60 * 60 * 1e3;
103
+ var relativeTimeFormatter = new Intl.RelativeTimeFormat(void 0, {
104
+ numeric: "auto",
105
+ style: "narrow"
106
+ });
107
+ var shortDateFormatter = new Intl.DateTimeFormat(void 0, {
108
+ day: "numeric",
109
+ month: "short"
110
+ });
111
+ var changedAtFormatter = new Intl.DateTimeFormat(void 0, {
112
+ dateStyle: "medium",
113
+ timeStyle: "short"
114
+ });
115
+ async function splashPage(get) {
116
+ const canManageMembers = await get(canManageMembersAtom);
117
+ await get(shaAtom);
118
+ const graph = get(graphAtom);
119
+ const config = get(configAtom);
120
+ const policy = get(policyAtom);
121
+ const summaries = await Promise.all(
122
+ get(workspacesAtom).map(async (key) => {
123
+ const workspace = get(workspaceAtom(key));
124
+ const roots = Object.entries(workspace.roots).flatMap(
125
+ ([rootKey, root]) => {
126
+ if (!policy.canRead({ workspace: key, root: rootKey })) return [];
127
+ const { icon, label } = getRoot(root);
128
+ return [{ icon: icon ?? LucideFile, key: rootKey, label }];
129
+ }
130
+ );
131
+ const candidates = await Promise.all(
132
+ roots.flatMap(({ key: root }) => [
133
+ graph.find({
134
+ workspace: key,
135
+ root,
136
+ status: "preferDraft",
137
+ groupBy: Entry.id,
138
+ orderBy: { desc: Entry.updatedAt },
139
+ take: recentCandidateWindowSize,
140
+ select: recentEntrySelection
141
+ }),
142
+ graph.find({
143
+ workspace: key,
144
+ root,
145
+ status: "preferDraft",
146
+ groupBy: Entry.id,
147
+ orderBy: { desc: Entry.id, caseSensitive: true },
148
+ take: recentCandidateWindowSize,
149
+ select: recentEntrySelection
150
+ })
151
+ ])
152
+ );
153
+ const readableCandidates = candidates.flat().filter((entry) => policy.canRead(entry));
154
+ const now = Date.now();
155
+ const trustsIdTimestamps = readableCandidates.every((entry) => {
156
+ const timestamp = timestampFromId(entry.id);
157
+ return timestamp === void 0 || timestamp <= now + futureTimestampTolerance;
158
+ });
159
+ const recentEntries = Array.from(
160
+ new Map(
161
+ readableCandidates.map((entry) => [
162
+ entry.id,
163
+ toRecentEntry(entry, trustsIdTimestamps)
164
+ ])
165
+ ).values()
166
+ ).filter((entry) => Boolean(entry)).sort((a, b) => b.changedAt - a.changedAt).slice(0, recentEntryCount);
167
+ const entries = recentEntries.map((entry) => {
168
+ const type = config.schema[entry.type];
169
+ return {
170
+ ...entry,
171
+ icon: type ? getType(type).icon ?? LucideFile : LucideFile
172
+ };
173
+ });
174
+ return {
175
+ entries,
176
+ key,
177
+ openRoute: { workspace: key, root: roots[0]?.key },
178
+ roots,
179
+ workspace
180
+ };
181
+ })
182
+ );
183
+ const searchLocation = summaries.flatMap(
184
+ (summary) => summary.roots.map((root) => ({ root: root.key, workspace: summary.key }))
185
+ ).at(0);
186
+ const searchRoot = searchLocation ? rootAtoms(searchLocation.workspace, searchLocation.root) : void 0;
187
+ return /* @__PURE__ */ jsx(
188
+ SplashPage,
189
+ {
190
+ canManageMembers,
191
+ searchRoot,
192
+ summaries
193
+ }
194
+ );
195
+ }
196
+ var recentEntrySelection = {
197
+ createdBy: Entry.createdBy,
198
+ id: Entry.id,
199
+ locale: Entry.locale,
200
+ root: Entry.root,
201
+ title: Entry.title,
202
+ type: Entry.type,
203
+ updatedAt: Entry.updatedAt,
204
+ updatedBy: Entry.updatedBy,
205
+ workspace: Entry.workspace
206
+ };
207
+ function toRecentEntry(entry, trustsIdTimestamps) {
208
+ const changedAt = typeof entry.updatedAt === "number" ? entry.updatedAt * 1e3 : trustsIdTimestamps ? timestampFromId(entry.id) : void 0;
209
+ if (changedAt === void 0) return void 0;
210
+ const auditUser = entry.updatedBy ?? entry.createdBy;
211
+ const actor = auditUser?.name || auditUser?.email || void 0;
212
+ return { ...entry, actor, changedAt };
213
+ }
214
+ function SplashPage({
215
+ canManageMembers,
216
+ searchRoot,
217
+ summaries
218
+ }) {
219
+ const user = useUser();
220
+ const setRoute = useSetAtom(routeAtom);
221
+ const userName = user ? user.name ?? user.sub : void 0;
222
+ return /* @__PURE__ */ jsx("main", { className: styles.SplashPage(), children: /* @__PURE__ */ jsxs("div", { className: styles.SplashPage.content(), children: [
223
+ /* @__PURE__ */ jsx(
224
+ "aside",
225
+ {
226
+ "aria-label": "Dashboard tools",
227
+ className: styles.SplashPage.sidebar(),
228
+ children: /* @__PURE__ */ jsxs("div", { className: styles.SplashPage.sidebar.content(), children: [
229
+ userName && /* @__PURE__ */ jsxs("div", { className: styles.SplashPage.user(), children: [
230
+ /* @__PURE__ */ jsx(
231
+ Icon,
232
+ {
233
+ icon: IcBaselineAccountCircle,
234
+ className: styles.SplashPage.actionIcon()
235
+ }
236
+ ),
237
+ /* @__PURE__ */ jsx("span", { className: styles.SplashPage.user.label(), children: userName })
238
+ ] }),
239
+ searchRoot && /* @__PURE__ */ jsx(GlobalSearch, { initialSearchScope: "everything", root: searchRoot, children: /* @__PURE__ */ jsxs(
240
+ Button,
241
+ {
242
+ appearance: "plain",
243
+ className: styles.SplashPage.action(),
244
+ "aria-label": "Search content",
245
+ children: [
246
+ /* @__PURE__ */ jsx(
247
+ Icon,
248
+ {
249
+ icon: IcRoundSearch,
250
+ className: styles.SplashPage.actionIcon()
251
+ }
252
+ ),
253
+ /* @__PURE__ */ jsx("span", { className: styles.SplashPage.search.label(), children: "Search content" })
254
+ ]
255
+ }
256
+ ) }),
257
+ canManageMembers && /* @__PURE__ */ jsxs(
258
+ Button,
259
+ {
260
+ appearance: "plain",
261
+ className: styles.SplashPage.action(),
262
+ onPress: () => setRoute({ page: "users" }),
263
+ children: [
264
+ /* @__PURE__ */ jsx(
265
+ Icon,
266
+ {
267
+ icon: IcOutlineSettings,
268
+ className: styles.SplashPage.actionIcon()
269
+ }
270
+ ),
271
+ "Manage users"
272
+ ]
273
+ }
274
+ ),
275
+ /* @__PURE__ */ jsxs(
276
+ "div",
277
+ {
278
+ "aria-label": "Appearance",
279
+ className: styles.SplashPage.appearance(),
280
+ children: [
281
+ /* @__PURE__ */ jsx("span", { className: styles.SplashPage.appearance.label(), children: "Appearance" }),
282
+ /* @__PURE__ */ jsx(AppearanceToggle, {})
283
+ ]
284
+ }
285
+ )
286
+ ] })
287
+ }
288
+ ),
289
+ /* @__PURE__ */ jsx("div", { className: styles.SplashPage.grid(), children: summaries.map((summary) => /* @__PURE__ */ jsx(WorkspaceCard, { summary }, summary.key)) })
290
+ ] }) });
291
+ }
292
+ function WorkspaceCard({ summary }) {
293
+ const setRoute = useSetAtom(routeAtom);
294
+ const { entries, key, openRoute, roots, workspace } = summary;
295
+ const visibleRoots = roots.slice(0, visibleRootCount);
296
+ const remainingRoots = roots.slice(visibleRootCount);
297
+ function onCardClick(event) {
298
+ const target = event.target;
299
+ if (target instanceof Element && target.closest('a, button, [role="menuitem"]'))
300
+ return;
301
+ setRoute(openRoute);
302
+ }
303
+ return /* @__PURE__ */ jsxs(Surface, { className: styles.SplashPage.card(), onClick: onCardClick, children: [
304
+ /* @__PURE__ */ jsxs("header", { className: styles.SplashPage.card.header(), children: [
305
+ /* @__PURE__ */ jsx("h2", { className: styles.SplashPage.card.header.title(), children: /* @__PURE__ */ jsxs(
306
+ Button,
307
+ {
308
+ appearance: "plain",
309
+ className: styles.SplashPage.card.header.button(),
310
+ onPress: () => setRoute(openRoute),
311
+ children: [
312
+ /* @__PURE__ */ jsx(WorkspaceAvatar, { color: workspace.color, icon: workspace.icon }),
313
+ /* @__PURE__ */ jsx("span", { className: styles.SplashPage.card.header.content(), children: /* @__PURE__ */ jsx("span", { className: styles.SplashPage.card.header.label(), children: workspace.label }) })
314
+ ]
315
+ }
316
+ ) }),
317
+ /* @__PURE__ */ jsxs("div", { className: styles.SplashPage.card.footer(), children: [
318
+ visibleRoots.map((root) => /* @__PURE__ */ jsx(
319
+ Button,
320
+ {
321
+ appearance: "plain",
322
+ className: styles.SplashPage.root(),
323
+ icon: root.icon,
324
+ onPress: () => setRoute({ workspace: key, root: root.key }),
325
+ children: root.label
326
+ },
327
+ root.key
328
+ )),
329
+ remainingRoots.length > 0 && /* @__PURE__ */ jsx(
330
+ Menu,
331
+ {
332
+ "aria-label": `More roots in ${workspace.label}`,
333
+ onAction: (rootKey) => setRoute({ workspace: key, root: String(rootKey) }),
334
+ popoverProps: { placement: "bottom start" },
335
+ label: /* @__PURE__ */ jsxs(Button, { appearance: "plain", className: styles.SplashPage.root(), children: [
336
+ "+",
337
+ remainingRoots.length,
338
+ " more"
339
+ ] }),
340
+ children: remainingRoots.map((root) => /* @__PURE__ */ jsxs(MenuItem, { id: root.key, textValue: root.label, children: [
341
+ /* @__PURE__ */ jsx(
342
+ Icon,
343
+ {
344
+ icon: root.icon,
345
+ className: styles.SplashPage.root.menuIcon()
346
+ }
347
+ ),
348
+ root.label
349
+ ] }, root.key))
350
+ }
351
+ )
352
+ ] })
353
+ ] }),
354
+ entries.length > 0 && /* @__PURE__ */ jsx("div", { className: styles.SplashPage.entries(), children: entries.map((entry) => /* @__PURE__ */ jsx(
355
+ Button,
356
+ {
357
+ appearance: "plain",
358
+ className: styles.SplashPage.entry(),
359
+ onPress: () => setRoute({
360
+ workspace: entry.workspace,
361
+ root: entry.root,
362
+ entry: entry.id,
363
+ locale: entry.locale ?? void 0,
364
+ view: "edit"
365
+ }),
366
+ children: /* @__PURE__ */ jsxs("span", { className: styles.SplashPage.entry.content(), children: [
367
+ /* @__PURE__ */ jsxs("span", { className: styles.SplashPage.entry.primary(), children: [
368
+ /* @__PURE__ */ jsx("span", { className: styles.SplashPage.entry.visual(), children: /* @__PURE__ */ jsx(
369
+ Icon,
370
+ {
371
+ className: styles.SplashPage.entry.visual.icon(),
372
+ icon: entry.icon
373
+ }
374
+ ) }),
375
+ /* @__PURE__ */ jsx("span", { className: styles.SplashPage.entry.title(), children: /* @__PURE__ */ jsx("span", { title: entry.title, children: entry.title }) })
376
+ ] }),
377
+ /* @__PURE__ */ jsxs("span", { className: styles.SplashPage.entry.meta(), children: [
378
+ entry.actor && /* @__PURE__ */ jsx("span", { className: styles.SplashPage.entry.user(), children: entry.actor }),
379
+ entry.actor && /* @__PURE__ */ jsx("span", { "aria-hidden": "true", children: "\xB7" }),
380
+ /* @__PURE__ */ jsx(
381
+ "time",
382
+ {
383
+ className: styles.SplashPage.entry.time(),
384
+ dateTime: new Date(entry.changedAt).toISOString(),
385
+ title: formatChangedAt(entry.changedAt),
386
+ children: formatRelativeTime(entry.changedAt)
387
+ }
388
+ )
389
+ ] })
390
+ ] })
391
+ },
392
+ entry.id
393
+ )) })
394
+ ] });
395
+ }
396
+ function formatChangedAt(timestamp) {
397
+ return changedAtFormatter.format(timestamp);
398
+ }
399
+ function formatRelativeTime(timestamp) {
400
+ const seconds = Math.round((timestamp - Date.now()) / 1e3);
401
+ if (Math.abs(seconds) < 60)
402
+ return relativeTimeFormatter.format(seconds, "second");
403
+ const minutes = Math.round(seconds / 60);
404
+ if (Math.abs(minutes) < 60)
405
+ return relativeTimeFormatter.format(minutes, "minute");
406
+ const hours = Math.round(minutes / 60);
407
+ if (Math.abs(hours) < 24) return relativeTimeFormatter.format(hours, "hour");
408
+ const days = Math.round(hours / 24);
409
+ if (Math.abs(days) < 7) return relativeTimeFormatter.format(days, "day");
410
+ return shortDateFormatter.format(timestamp);
411
+ }
412
+ export {
413
+ splashPage
414
+ };