alinea 2.0.0-preview.4 → 2.0.0-preview.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 (164) hide show
  1. package/dist/.init/content/pages/welcome.json +1 -1
  2. package/dist/.init/src/cms.ts +1 -4
  3. package/dist/LICENSES.md +107 -107
  4. package/dist/adapter/next/cms.js +5 -1
  5. package/dist/adapter/next/handler.js +35 -6
  6. package/dist/adapter/next/previews.js +7 -1
  7. package/dist/adapter/next/syncCheck.d.ts +12 -0
  8. package/dist/adapter/next/syncCheck.js +59 -0
  9. package/dist/adapter/next/with-alinea.d.ts +0 -8
  10. package/dist/adapter/next/with-alinea.js +43 -19
  11. package/dist/adapter/vite/plugin.js +9 -4
  12. package/dist/backend/Handler.js +106 -0
  13. package/dist/backend/api/ProxyMedia.d.ts +3 -0
  14. package/dist/backend/api/ProxyMedia.js +39 -0
  15. package/dist/backend/api/S3Uploads.d.ts +1 -1
  16. package/dist/backend/router/Router.js +2 -0
  17. package/dist/backend/util/Syncable.js +1 -1
  18. package/dist/bundled.d.ts +164 -70
  19. package/dist/chunks/{chunk-XMOVGDFI.js → chunk-A6M3PNJT.js} +1 -1
  20. package/dist/cli/Generate.js +1 -3
  21. package/dist/cli/Serve.js +3 -2
  22. package/dist/cli/bin.js +1 -1
  23. package/dist/cli/generate/GenerateDashboard.js +1 -0
  24. package/dist/cli/serve/CreateLocalServer.d.ts +1 -1
  25. package/dist/cli/serve/CreateLocalServer.js +42 -34
  26. package/dist/cli/static/init/cms.js +1 -4
  27. package/dist/cli/util/ContentType.d.ts +1 -0
  28. package/dist/cli/util/ContentType.js +36 -0
  29. package/dist/cloud/CloudHandshake.d.ts +6 -0
  30. package/dist/cloud/CloudHandshake.js +67 -10
  31. package/dist/cloud/CloudRemote.js +24 -11
  32. package/dist/components/Calendar.js +4 -4
  33. package/dist/components/Checkbox.js +3 -3
  34. package/dist/components/ColorSwatchPicker.js +2 -2
  35. package/dist/components/ComboBox.js +9 -9
  36. package/dist/components/DateField.js +4 -4
  37. package/dist/components/DatePicker.js +3 -3
  38. package/dist/components/DateRangePicker.js +8 -8
  39. package/dist/components/Disclosure.js +7 -7
  40. package/dist/components/Label.js +4 -4
  41. package/dist/components/List.d.ts +1 -1
  42. package/dist/components/List.js +35 -34
  43. package/dist/components/Menu.js +4 -4
  44. package/dist/components/Modal.js +2 -2
  45. package/dist/components/MultipleSelect.js +23 -23
  46. package/dist/components/NumberField.js +6 -6
  47. package/dist/components/ProgressCircle.js +1 -1
  48. package/dist/components/SearchField.js +7 -7
  49. package/dist/components/Select.js +9 -9
  50. package/dist/components/Surface.js +2 -2
  51. package/dist/components/Table.js +7 -7
  52. package/dist/components/Tabs.js +2 -2
  53. package/dist/components/TagGroup.js +2 -2
  54. package/dist/components/TextField.js +6 -6
  55. package/dist/components/TimeField.js +3 -3
  56. package/dist/components/Toggle.js +2 -2
  57. package/dist/components/Toolbar.js +2 -2
  58. package/dist/components/Tooltip.js +2 -2
  59. package/dist/components/Tree.js +6 -6
  60. package/dist/core/Config.d.ts +10 -3
  61. package/dist/core/Config.js +16 -1
  62. package/dist/core/Graph.d.ts +2 -2
  63. package/dist/core/Role.js +16 -14
  64. package/dist/core/TextDoc.d.ts +2 -0
  65. package/dist/core/TextDoc.js +1 -0
  66. package/dist/core/Workspace.d.ts +6 -5
  67. package/dist/core/db/EntryIndex.d.ts +3 -0
  68. package/dist/core/db/EntryIndex.js +62 -0
  69. package/dist/core/db/EntryTransaction.js +33 -12
  70. package/dist/core/db/EntryUrlConflictError.js +1 -1
  71. package/dist/core/db/LinkResolver.d.ts +8 -2
  72. package/dist/core/db/LinkResolver.js +27 -5
  73. package/dist/core/field/RichTextField.js +16 -10
  74. package/dist/core/media/MediaLocation.d.ts +9 -15
  75. package/dist/core/media/MediaLocation.js +29 -19
  76. package/dist/core/media/MediaTypes.js +1 -2
  77. package/dist/dashboard/App.js +1 -1
  78. package/dist/dashboard/app/AccessDenied.js +2 -2
  79. package/dist/dashboard/app/ActivityStatus.js +14 -13
  80. package/dist/dashboard/app/AppShell.js +1 -1
  81. package/dist/dashboard/app/AuthView.js +9 -9
  82. package/dist/dashboard/app/Badge.js +2 -2
  83. package/dist/dashboard/app/CompactField.js +13 -13
  84. package/dist/dashboard/app/DashboardErrorBoundary.js +4 -4
  85. package/dist/dashboard/app/EntryFields.d.ts +3 -1
  86. package/dist/dashboard/app/EntryFields.js +11 -8
  87. package/dist/dashboard/app/EntryHeader.js +117 -85
  88. package/dist/dashboard/app/EntryHeaderActions.d.ts +21 -4
  89. package/dist/dashboard/app/EntryHeaderActions.js +48 -27
  90. package/dist/dashboard/app/EntryReferences.js +9 -9
  91. package/dist/dashboard/app/EntrySidebar.js +12 -12
  92. package/dist/dashboard/app/EntrySidebarPreview.js +11 -11
  93. package/dist/dashboard/app/EntryTranslationBanner.d.ts +3 -1
  94. package/dist/dashboard/app/EntryTranslationBanner.js +24 -21
  95. package/dist/dashboard/app/Explorer.d.ts +4 -2
  96. package/dist/dashboard/app/Explorer.js +50 -46
  97. package/dist/dashboard/app/ExplorerCards.js +28 -28
  98. package/dist/dashboard/app/ExplorerFileCard.js +19 -19
  99. package/dist/dashboard/app/ExplorerList.js +12 -13
  100. package/dist/dashboard/app/ExplorerModal.js +5 -5
  101. package/dist/dashboard/app/ExplorerTable.js +46 -46
  102. package/dist/dashboard/app/LinkPicker.js +5 -5
  103. package/dist/dashboard/app/LocaleMenu.d.ts +7 -0
  104. package/dist/dashboard/app/LocaleMenu.js +26 -10
  105. package/dist/dashboard/app/ReadOnlyBadge.d.ts +4 -0
  106. package/dist/dashboard/app/ReadOnlyBadge.js +33 -0
  107. package/dist/dashboard/app/SidebarTree.d.ts +3 -6
  108. package/dist/dashboard/app/SidebarTree.js +54 -49
  109. package/dist/dashboard/app/WorkspaceMenu.js +12 -12
  110. package/dist/dashboard/app/WorkspaceRoots.js +24 -24
  111. package/dist/dashboard/app/editor/FileEditor.d.ts +2 -3
  112. package/dist/dashboard/app/editor/FileEditor.js +31 -34
  113. package/dist/dashboard/app/editor/FilePreview.js +6 -6
  114. package/dist/dashboard/app/modals/CreateEntry.js +5 -5
  115. package/dist/dashboard/app/pages/EntryPage.js +73 -30
  116. package/dist/dashboard/app/pages/SplashPage.js +47 -47
  117. package/dist/dashboard/app/pages/UsersPage.js +34 -34
  118. package/dist/dashboard/app/ui/DashboardModal.js +18 -18
  119. package/dist/dashboard/app/ui/Rail.js +3 -3
  120. package/dist/dashboard/app/ui/Sidebar.js +2 -2
  121. package/dist/dashboard/atoms/activity.d.ts +0 -1
  122. package/dist/dashboard/atoms/activity.js +1 -2
  123. package/dist/dashboard/atoms/editor.d.ts +2 -1
  124. package/dist/dashboard/atoms/editor.js +4 -2
  125. package/dist/dashboard/atoms/entry.d.ts +2 -0
  126. package/dist/dashboard/atoms/entry.js +32 -14
  127. package/dist/dashboard/atoms/explorer.d.ts +4 -3
  128. package/dist/dashboard/atoms/explorer.js +61 -22
  129. package/dist/dashboard/atoms/link.d.ts +1 -1
  130. package/dist/dashboard/atoms/link.js +39 -55
  131. package/dist/dashboard/atoms/root.d.ts +7 -2
  132. package/dist/dashboard/atoms/root.js +51 -16
  133. package/dist/dashboard/atoms/upload.d.ts +1 -0
  134. package/dist/dashboard/atoms/upload.js +2 -1
  135. package/dist/dashboard/boot/DashboardWorker.js +1 -0
  136. package/dist/dashboard/fixture/cms.js +1 -4
  137. package/dist/dashboard/hook/UseSaveShortcut.d.ts +1 -0
  138. package/dist/dashboard/hook/UseSaveShortcut.js +24 -0
  139. package/dist/dashboard/hooks.d.ts +1 -1
  140. package/dist/dashboard/hooks.js +12 -3
  141. package/dist/field/code/CodeField.view.js +9 -9
  142. package/dist/field/link/ImageLink.js +1 -3
  143. package/dist/field/link/LinkField.view.js +84 -58
  144. package/dist/field/list/ListField.view.js +13 -13
  145. package/dist/field/metadata/MetadataField.d.ts +3 -3
  146. package/dist/field/metadata/MetadataField.view.js +24 -17
  147. package/dist/field/object/ObjectField.view.js +11 -4
  148. package/dist/field/richtext/PickTextLink.js +5 -2
  149. package/dist/field/richtext/ReferenceLink.d.ts +2 -0
  150. package/dist/field/richtext/ReferenceLink.js +5 -0
  151. package/dist/field/richtext/RichTextBlock.js +2 -2
  152. package/dist/field/richtext/RichTextExtensions.js +22 -22
  153. package/dist/field/richtext/RichTextField.view.js +4 -4
  154. package/dist/field/richtext/extensions/Link.d.ts +1 -0
  155. package/dist/field/richtext/extensions/Link.js +1 -0
  156. package/dist/field/time/TimeField.d.ts +0 -2
  157. package/dist/field/time/TimeField.view.js +1 -1
  158. package/dist/index.css +44 -38
  159. package/dist/next.cjs +96 -19
  160. package/dist/picker/entry/EntryPicker.js +10 -12
  161. package/dist/picker/entry/EntryReference.d.ts +2 -0
  162. package/dist/picker/entry/EntryReference.js +1 -0
  163. package/dist/types.d.ts +0 -1
  164. package/package.json +1 -1
@@ -8,9 +8,9 @@ import { Icon } from "../../components/Icon.js";
8
8
 
9
9
  // src/dashboard/app/Badge.module.css
10
10
  var Badge_default = {
11
+ "Badge": "alinea-Badge",
11
12
  "Badge-label": "alinea-Badge-label",
12
- "BadgeLabel": "alinea-Badge-label",
13
- "Badge": "alinea-Badge"
13
+ "BadgeLabel": "alinea-Badge-label"
14
14
  };
15
15
 
16
16
  // src/dashboard/app/Badge.tsx
@@ -19,25 +19,25 @@ import { Badge } from "./Badge.js";
19
19
 
20
20
  // src/dashboard/app/CompactField.module.css
21
21
  var CompactField_default = {
22
- "CompactField-json": "alinea-CompactField-json",
23
- "CompactFieldJson": "alinea-CompactField-json",
22
+ "CompactField": "alinea-CompactField",
23
+ "CompactField-list-count": "alinea-CompactField-list-count",
24
+ "CompactFieldListCount": "alinea-CompactField-list-count",
25
+ "CompactField-record-field": "alinea-CompactField-record-field",
26
+ "CompactFieldRecordField": "alinea-CompactField-record-field",
24
27
  "CompactField-record": "alinea-CompactField-record",
25
28
  "CompactFieldRecord": "alinea-CompactField-record",
26
- "CompactField": "alinea-CompactField",
27
- "CompactField-record-value": "alinea-CompactField-record-value",
28
- "CompactFieldRecordValue": "alinea-CompactField-record-value",
29
- "CompactField-record-label": "alinea-CompactField-record-label",
30
- "CompactFieldRecordLabel": "alinea-CompactField-record-label",
31
- "CompactField-items": "alinea-CompactField-items",
32
- "CompactFieldItems": "alinea-CompactField-items",
33
29
  "CompactField-muted": "alinea-CompactField-muted",
34
30
  "CompactFieldMuted": "alinea-CompactField-muted",
35
- "CompactField-list-count": "alinea-CompactField-list-count",
36
- "CompactFieldListCount": "alinea-CompactField-list-count",
31
+ "CompactField-json": "alinea-CompactField-json",
32
+ "CompactFieldJson": "alinea-CompactField-json",
37
33
  "CompactField-text": "alinea-CompactField-text",
38
34
  "CompactFieldText": "alinea-CompactField-text",
39
- "CompactField-record-field": "alinea-CompactField-record-field",
40
- "CompactFieldRecordField": "alinea-CompactField-record-field"
35
+ "CompactField-items": "alinea-CompactField-items",
36
+ "CompactFieldItems": "alinea-CompactField-items",
37
+ "CompactField-record-label": "alinea-CompactField-record-label",
38
+ "CompactFieldRecordLabel": "alinea-CompactField-record-label",
39
+ "CompactField-record-value": "alinea-CompactField-record-value",
40
+ "CompactFieldRecordValue": "alinea-CompactField-record-value"
41
41
  };
42
42
 
43
43
  // src/dashboard/app/CompactField.tsx
@@ -69,13 +69,13 @@ var DashboardErrorBoundary_default = {
69
69
  "DashboardErrorBoundaryTitle": "alinea-DashboardErrorBoundary-title",
70
70
  "DashboardErrorBoundary-actions": "alinea-DashboardErrorBoundary-actions",
71
71
  "DashboardErrorBoundaryActions": "alinea-DashboardErrorBoundary-actions",
72
- "DashboardErrorBoundary-message": "alinea-DashboardErrorBoundary-message",
73
- "DashboardErrorBoundaryMessage": "alinea-DashboardErrorBoundary-message",
72
+ "DashboardErrorBoundary-heading": "alinea-DashboardErrorBoundary-heading",
73
+ "DashboardErrorBoundaryHeading": "alinea-DashboardErrorBoundary-heading",
74
74
  "DashboardErrorBoundary": "alinea-DashboardErrorBoundary",
75
75
  "DashboardErrorBoundary-card": "alinea-DashboardErrorBoundary-card",
76
76
  "DashboardErrorBoundaryCard": "alinea-DashboardErrorBoundary-card",
77
- "DashboardErrorBoundary-heading": "alinea-DashboardErrorBoundary-heading",
78
- "DashboardErrorBoundaryHeading": "alinea-DashboardErrorBoundary-heading"
77
+ "DashboardErrorBoundary-message": "alinea-DashboardErrorBoundary-message",
78
+ "DashboardErrorBoundaryMessage": "alinea-DashboardErrorBoundary-message"
79
79
  };
80
80
 
81
81
  // src/dashboard/app/DashboardErrorBoundary.tsx
@@ -5,9 +5,10 @@ import { type PropsWithChildren } from 'react';
5
5
  import type { EditorNode } from '../atoms/editor.js';
6
6
  interface NodeEditorProps extends PropsWithChildren {
7
7
  node: EditorNode;
8
+ readOnly?: boolean;
8
9
  type: Type;
9
10
  }
10
- export declare function NodeEditor({ children, node, type }: NodeEditorProps): import("react").JSX.Element;
11
+ export declare function NodeEditor({ children, node, readOnly, type }: NodeEditorProps): import("react").JSX.Element;
11
12
  export declare function FieldsEditor(): import("react").JSX.Element[];
12
13
  export declare function EntryFields(): import("react").JSX.Element[];
13
14
  export interface EditFieldsProps {
@@ -18,4 +19,5 @@ interface EditFieldProps {
18
19
  field: Field;
19
20
  }
20
21
  export declare const EditField: import("react").MemoExoticComponent<({ field }: EditFieldProps) => import("react").JSX.Element | null>;
22
+ export declare function fieldWidth(width?: number): string;
21
23
  export {};
@@ -32,8 +32,8 @@ var EntryFields_default = {
32
32
  // src/dashboard/app/EntryFields.tsx
33
33
  import { jsx, jsxs } from "react/jsx-runtime";
34
34
  var styles = styler(EntryFields_default);
35
- function NodeEditor({ children, node, type }) {
36
- const editor = useNodeEditor(node, type);
35
+ function NodeEditor({ children, node, readOnly, type }) {
36
+ const editor = useNodeEditor(node, type, readOnly);
37
37
  return /* @__PURE__ */ jsx(EditorScope, { editor, children: children ?? /* @__PURE__ */ jsx(FieldsEditor, {}) });
38
38
  }
39
39
  function FieldsEditor() {
@@ -64,7 +64,7 @@ var EditFields = memo(function EditFields2({ fields }) {
64
64
  "div",
65
65
  {
66
66
  className: styles.EditField.slot(),
67
- style: { gridColumn: `span ${fieldSpan()}` },
67
+ style: { flexBasis: fieldWidth() },
68
68
  children: /* @__PURE__ */ jsx(FormSection, { section: new EntryEditorSection(value) })
69
69
  },
70
70
  name
@@ -83,19 +83,22 @@ var EditField = memo(function EditField2({ field }) {
83
83
  "div",
84
84
  {
85
85
  className: styles.EditField.slot(),
86
- style: { gridColumn: `span ${fieldSpan(options.width)}` },
86
+ style: { flexBasis: fieldWidth(options.width) },
87
87
  children: /* @__PURE__ */ jsx(View, { field })
88
88
  }
89
89
  );
90
90
  });
91
- function fieldSpan(width = 1) {
92
- const columns = 12;
93
- return Math.max(1, Math.min(columns, Math.round(width * columns)));
91
+ function fieldWidth(width = 1) {
92
+ const fraction = Math.max(0, Math.min(1, width));
93
+ if (fraction === 0) return "0px";
94
+ if (fraction === 1) return "100%";
95
+ return `calc(${fraction * 100}% - var(--alinea-field-gap) * ${1 - fraction})`;
94
96
  }
95
97
  export {
96
98
  EditField,
97
99
  EditFields,
98
100
  EntryFields,
99
101
  FieldsEditor,
100
- NodeEditor
102
+ NodeEditor,
103
+ fieldWidth
101
104
  };
@@ -18,10 +18,11 @@ import { getType } from "alinea/core/Internal";
18
18
  import { MediaFile, MediaLibrary } from "alinea/core/media/MediaTypes";
19
19
  import { assert } from "alinea/core/util/Assert";
20
20
  import { isRecord } from "alinea/core/util/Objects";
21
- import { configAtom } from "alinea/dashboard/atoms/core";
22
21
  import { activityAtom } from "alinea/dashboard/atoms/activity";
22
+ import { configAtom } from "alinea/dashboard/atoms/core";
23
23
  import { routeAtom } from "alinea/dashboard/atoms/nav";
24
24
  import { policyAtom } from "alinea/dashboard/atoms/user";
25
+ import { useSaveShortcut } from "alinea/dashboard/hook/UseSaveShortcut";
25
26
  import { useState, useTransition } from "react";
26
27
  import {
27
28
  IcOutlineArchive,
@@ -30,6 +31,7 @@ import {
30
31
  IcRoundDelete,
31
32
  IcRoundEdit,
32
33
  IcRoundFlashOn,
34
+ IcRoundLanguage,
33
35
  IcRoundMoreHoriz,
34
36
  IcRoundPublishedWithChanges,
35
37
  IcRoundSave,
@@ -41,15 +43,6 @@ import { EditorBackButton } from "./EditorBackButton.js";
41
43
 
42
44
  // src/dashboard/app/EntryHeader.module.css
43
45
  var EntryHeader_default = {
44
- "EntryHeader": "alinea-EntryHeader",
45
- "EntryHeader-actions": "alinea-EntryHeader-actions",
46
- "EntryHeaderActions": "alinea-EntryHeader-actions",
47
- "EntryHeader-status": "alinea-EntryHeader-status",
48
- "EntryHeaderStatus": "alinea-EntryHeader-status",
49
- "is-dirty": "alinea-is-dirty",
50
- "isDirty": "alinea-is-dirty",
51
- "EntryHeader-content": "alinea-EntryHeader-content",
52
- "EntryHeaderContent": "alinea-EntryHeader-content",
53
46
  "EntryHeader-sidebarToggle": "alinea-EntryHeader-sidebarToggle",
54
47
  "EntryHeaderSidebarToggle": "alinea-EntryHeader-sidebarToggle",
55
48
  "EntryHeader-main": "alinea-EntryHeader-main",
@@ -57,15 +50,25 @@ var EntryHeader_default = {
57
50
  "EntryHeader-type": "alinea-EntryHeader-type",
58
51
  "EntryHeaderType": "alinea-EntryHeader-type",
59
52
  "EntryHeader-title": "alinea-EntryHeader-title",
60
- "EntryHeaderTitle": "alinea-EntryHeader-title"
53
+ "EntryHeaderTitle": "alinea-EntryHeader-title",
54
+ "EntryHeader-actions": "alinea-EntryHeader-actions",
55
+ "EntryHeaderActions": "alinea-EntryHeader-actions",
56
+ "EntryHeader-status": "alinea-EntryHeader-status",
57
+ "EntryHeaderStatus": "alinea-EntryHeader-status",
58
+ "EntryHeader": "alinea-EntryHeader",
59
+ "EntryHeader-content": "alinea-EntryHeader-content",
60
+ "EntryHeaderContent": "alinea-EntryHeader-content",
61
+ "is-dirty": "alinea-is-dirty",
62
+ "isDirty": "alinea-is-dirty"
61
63
  };
62
64
 
63
65
  // src/dashboard/app/EntryHeader.tsx
64
66
  import {
65
- entryHeaderActionIds,
66
- entryHeaderPrimaryActionIds
67
+ entryHeaderActions,
68
+ entryHeaderPrimaryActions
67
69
  } from "./EntryHeaderActions.js";
68
70
  import { EntrySidebarToggle } from "./EntrySidebarToggle.js";
71
+ import { ReadOnlyBadge } from "./ReadOnlyBadge.js";
69
72
  import {
70
73
  DashboardModal,
71
74
  DashboardModalContent,
@@ -82,16 +85,22 @@ function UrlConflictModal({ conflict, onClose }) {
82
85
  onOpenChange: (isOpen) => {
83
86
  if (!isOpen) onClose();
84
87
  },
85
- children: conflict && /* @__PURE__ */ jsxs(DashboardModalDialog, { label: "URL alias already in use", children: [
88
+ children: conflict && /* @__PURE__ */ jsxs(DashboardModalDialog, { label: "URL already in use", children: [
86
89
  /* @__PURE__ */ jsxs(DashboardModalContent, { children: [
87
90
  /* @__PURE__ */ jsxs("p", { children: [
88
- "The URL alias ",
91
+ "The URL ",
89
92
  /* @__PURE__ */ jsx("strong", { children: conflict.url }),
90
93
  " is already defined on entry ",
91
94
  /* @__PURE__ */ jsx("strong", { children: conflict.entryId }),
95
+ " in workspace",
96
+ " ",
97
+ /* @__PURE__ */ jsx("strong", { children: conflict.workspace }),
98
+ ", root",
99
+ " ",
100
+ /* @__PURE__ */ jsx("strong", { children: conflict.root }),
92
101
  "."
93
102
  ] }),
94
- /* @__PURE__ */ jsx("p", { children: "Remove or change this alias, then publish again." })
103
+ /* @__PURE__ */ jsx("p", { children: "Change the entry path or remove this alias, then try again." })
95
104
  ] }),
96
105
  /* @__PURE__ */ jsx(DashboardModalFooter, { children: /* @__PURE__ */ jsx(Button, { intent: "primary", onPress: onClose, children: "OK" }) })
97
106
  ] })
@@ -117,19 +126,22 @@ var variantDescription = {
117
126
  published: "Published",
118
127
  unpublished: "Unpublished",
119
128
  archived: "Archived",
120
- draft: "Draft"
129
+ draft: "Draft",
130
+ untranslated: "Untranslated"
121
131
  };
122
132
  var badgeStatus = {
123
133
  published: "published",
124
134
  unpublished: "unpublished",
125
135
  archived: "archived",
126
- draft: "draft"
136
+ draft: "draft",
137
+ untranslated: "untranslated"
127
138
  };
128
139
  var badgeIcon = {
129
140
  published: IcRoundCheck,
130
141
  unpublished: IcRoundFlashOn,
131
142
  archived: IcOutlineArchive,
132
- draft: IcRoundEdit
143
+ draft: IcRoundEdit,
144
+ untranslated: IcRoundLanguage
133
145
  };
134
146
  function EntryHeader({
135
147
  controls,
@@ -142,6 +154,7 @@ function EntryHeader({
142
154
  selectedEntry
143
155
  }) {
144
156
  const config = useAtomValueRaw(configAtom);
157
+ const activity = useAtomValueRaw(activityAtom);
145
158
  const policy = useAtomValueRaw(policyAtom);
146
159
  const route = useAtomValueRaw(routeAtom);
147
160
  const setRoute = useSetAtom(routeAtom);
@@ -168,7 +181,6 @@ function EntryHeader({
168
181
  const replaceFile = useSetAtom(localeData.replaceFile);
169
182
  const reset = useSetAtom(node.reset);
170
183
  const isDirty = useAtomValueRaw(node.isDirty);
171
- const activity = useAtomValueRaw(activityAtom);
172
184
  const activeVersion = Array.from(versions.values()).find(
173
185
  (version) => version.active
174
186
  );
@@ -184,12 +196,12 @@ function EntryHeader({
184
196
  const isRevision = selectedVersion?.type === "history";
185
197
  const isUnpublished = activeStatus === "draft" && activeVersion.main;
186
198
  const viewedStatus = selectedEntry.status;
187
- const status = viewedStatus === "draft" && selectedEntry.main ? "unpublished" : viewedStatus;
199
+ const status = untranslated ? "untranslated" : viewedStatus === "draft" && selectedEntry.main ? "unpublished" : viewedStatus;
200
+ const showStatus = isRevision || status !== "published";
188
201
  const [isPending, startTransition] = useTransition();
189
- const isActionDisabled = isPending || activity.hasFailedMutations;
202
+ const isActionDisabled = isPending || activity.isMutating;
190
203
  const [urlConflict, setUrlConflict] = useState();
191
204
  function runAction(action) {
192
- if (activity.hasFailedMutations) return;
193
205
  startTransition(async () => {
194
206
  try {
195
207
  await action();
@@ -221,7 +233,7 @@ function EntryHeader({
221
233
  input.click();
222
234
  }
223
235
  const canSaveDraft = !isMedia && config.enableDrafts && access.update;
224
- const primaryActionIds = entryHeaderPrimaryActionIds({
236
+ const primaryActions = entryHeaderPrimaryActions({
225
237
  access,
226
238
  activeStatus,
227
239
  canPublishParents,
@@ -231,8 +243,33 @@ function EntryHeader({
231
243
  parentNeedsTranslation,
232
244
  untranslated
233
245
  });
246
+ function createDraft() {
247
+ runAction(async () => {
248
+ await saveDraft(node);
249
+ setSelectedVersion({ type: "status", status: "draft" });
250
+ });
251
+ }
252
+ function saveTranslationChanges() {
253
+ runAction(() => saveTranslation(node));
254
+ }
255
+ function publishChanges() {
256
+ runAction(() => publishEdits(node));
257
+ }
258
+ function saveDraftChanges() {
259
+ runAction(() => saveDraft(node));
260
+ }
261
+ function publishCurrentDraft() {
262
+ runAction(publishDraft);
263
+ }
264
+ let saveShortcut;
265
+ if (primaryActions.dirty?.saveDraft) saveShortcut = saveDraftChanges;
266
+ else if (primaryActions.dirty?.publish) saveShortcut = publishChanges;
267
+ else if (primaryActions.saveTranslation) saveShortcut = saveTranslationChanges;
268
+ else if (primaryActions.createDraft) saveShortcut = createDraft;
269
+ else if (primaryActions.publishDraft) saveShortcut = publishCurrentDraft;
270
+ useSaveShortcut(saveShortcut, isActionDisabled);
234
271
  let primaryAction = null;
235
- if (primaryActionIds.includes("create-draft")) {
272
+ if (primaryActions.createDraft) {
236
273
  primaryAction = /* @__PURE__ */ jsx(
237
274
  Button,
238
275
  {
@@ -240,14 +277,11 @@ function EntryHeader({
240
277
  intent: "primary",
241
278
  isDisabled: isActionDisabled,
242
279
  isPending,
243
- onPress: () => runAction(async () => {
244
- await saveDraft(node);
245
- setSelectedVersion({ type: "status", status: "draft" });
246
- }),
280
+ onPress: createDraft,
247
281
  children: "Create draft"
248
282
  }
249
283
  );
250
- } else if (primaryActionIds.includes("save-translation")) {
284
+ } else if (primaryActions.saveTranslation) {
251
285
  primaryAction = /* @__PURE__ */ jsx(
252
286
  Button,
253
287
  {
@@ -255,11 +289,11 @@ function EntryHeader({
255
289
  intent: "primary",
256
290
  isDisabled: isActionDisabled,
257
291
  isPending,
258
- onPress: () => runAction(() => saveTranslation(node)),
292
+ onPress: saveTranslationChanges,
259
293
  children: "Save translation"
260
294
  }
261
295
  );
262
- } else if (primaryActionIds.includes("discard-changes")) {
296
+ } else if (primaryActions.dirty) {
263
297
  primaryAction = /* @__PURE__ */ jsxs(Fragment, { children: [
264
298
  /* @__PURE__ */ jsx(
265
299
  Button,
@@ -270,30 +304,30 @@ function EntryHeader({
270
304
  children: "Discard my changes"
271
305
  }
272
306
  ),
273
- primaryActionIds.includes("publish-edits") && /* @__PURE__ */ jsx(
307
+ primaryActions.dirty.publish && /* @__PURE__ */ jsx(
274
308
  Button,
275
309
  {
276
310
  icon: IcRoundCheck,
277
311
  intent: canSaveDraft ? "secondary" : "primary",
278
312
  isDisabled: isActionDisabled,
279
313
  isPending,
280
- onPress: () => runAction(() => publishEdits(node)),
314
+ onPress: publishChanges,
281
315
  children: "Publish"
282
316
  }
283
317
  ),
284
- primaryActionIds.includes("save-draft") && /* @__PURE__ */ jsx(
318
+ primaryActions.dirty.saveDraft && /* @__PURE__ */ jsx(
285
319
  Button,
286
320
  {
287
321
  icon: IcRoundSave,
288
322
  intent: "primary",
289
323
  isDisabled: isActionDisabled,
290
324
  isPending,
291
- onPress: () => runAction(() => saveDraft(node)),
325
+ onPress: saveDraftChanges,
292
326
  children: "Save draft"
293
327
  }
294
328
  )
295
329
  ] });
296
- } else if (primaryActionIds.includes("publish-draft")) {
330
+ } else if (primaryActions.publishDraft) {
297
331
  primaryAction = /* @__PURE__ */ jsx(
298
332
  Button,
299
333
  {
@@ -301,13 +335,13 @@ function EntryHeader({
301
335
  intent: "primary",
302
336
  isDisabled: isActionDisabled,
303
337
  isPending,
304
- onPress: () => runAction(publishDraft),
338
+ onPress: publishCurrentDraft,
305
339
  children: "Publish"
306
340
  }
307
341
  );
308
342
  }
309
343
  const menuItems = [];
310
- const actionIds = entryHeaderActionIds({
344
+ const actions = entryHeaderActions({
311
345
  access,
312
346
  activeStatus,
313
347
  canDelete: activeVersion.seeded === null,
@@ -321,51 +355,48 @@ function EntryHeader({
321
355
  isUnpublished,
322
356
  untranslated
323
357
  });
324
- for (const actionId of actionIds) {
325
- if (actionId === "remove-draft") {
326
- menuItems.push({
327
- id: "remove-draft",
328
- label: "Remove draft",
329
- action: discardDraft,
330
- icon: IcRoundDelete
331
- });
332
- } else if (actionId === "replace") {
333
- menuItems.push({
334
- id: "replace",
335
- label: "Replace",
336
- action: replaceMediaFile,
337
- icon: IcRoundSync
338
- });
339
- } else if (actionId === "unpublish") {
340
- menuItems.push({
341
- id: "unpublish",
342
- label: "Unpublish",
343
- action: unpublish,
344
- icon: IcRoundVisibilityOff
345
- });
346
- } else if (actionId === "archive") {
347
- menuItems.push({
348
- id: "archive",
349
- label: "Archive",
350
- action: archive,
351
- icon: IcRoundArchive
352
- });
353
- } else if (actionId === "publish") {
354
- menuItems.push({
355
- id: "publish",
356
- label: "Publish",
357
- action: publishArchived,
358
- icon: IcRoundCheck
359
- });
360
- } else {
361
- menuItems.push({
362
- id: "delete",
363
- label: "Delete",
364
- action: deleteAndNavigate,
365
- icon: IcRoundDelete
366
- });
367
- }
368
- }
358
+ if (actions.removeDraft)
359
+ menuItems.push({
360
+ id: "remove-draft",
361
+ label: "Remove draft",
362
+ action: discardDraft,
363
+ icon: IcRoundDelete
364
+ });
365
+ if (actions.replace)
366
+ menuItems.push({
367
+ id: "replace",
368
+ label: "Replace",
369
+ action: replaceMediaFile,
370
+ icon: IcRoundSync
371
+ });
372
+ if (actions.unpublish)
373
+ menuItems.push({
374
+ id: "unpublish",
375
+ label: "Unpublish",
376
+ action: unpublish,
377
+ icon: IcRoundVisibilityOff
378
+ });
379
+ if (actions.archive)
380
+ menuItems.push({
381
+ id: "archive",
382
+ label: "Archive",
383
+ action: archive,
384
+ icon: IcRoundArchive
385
+ });
386
+ if (actions.publish)
387
+ menuItems.push({
388
+ id: "publish",
389
+ label: "Publish",
390
+ action: publishArchived,
391
+ icon: IcRoundCheck
392
+ });
393
+ if (actions.delete)
394
+ menuItems.push({
395
+ id: "delete",
396
+ label: "Delete",
397
+ action: deleteAndNavigate,
398
+ icon: IcRoundDelete
399
+ });
369
400
  return /* @__PURE__ */ jsxs("header", { className: styles.EntryHeader({ dirty: isDirty }), children: [
370
401
  /* @__PURE__ */ jsxs("div", { className: styles.EntryHeader.content(), children: [
371
402
  /* @__PURE__ */ jsxs("div", { className: styles.EntryHeader.main(), children: [
@@ -383,7 +414,7 @@ function EntryHeader({
383
414
  ),
384
415
  /* @__PURE__ */ jsx("h1", { className: styles.EntryHeader.title(), children: selectedEntry.title }),
385
416
  controls,
386
- /* @__PURE__ */ jsx(
417
+ showStatus && /* @__PURE__ */ jsx(
387
418
  Badge,
388
419
  {
389
420
  className: styles.EntryHeader.status(),
@@ -393,6 +424,7 @@ function EntryHeader({
393
424
  }
394
425
  ),
395
426
  /* @__PURE__ */ jsx(Badge, { className: styles.EntryHeader.type(), icon: typeData.icon, children: typeData.label }),
427
+ !access.update && /* @__PURE__ */ jsx(ReadOnlyBadge, {}),
396
428
  menuItems.length > 0 && /* @__PURE__ */ jsx(
397
429
  Menu,
398
430
  {
@@ -1,6 +1,4 @@
1
1
  import type { EntryStatus } from 'alinea/core/Entry';
2
- export type EntryHeaderActionId = 'remove-draft' | 'replace' | 'unpublish' | 'archive' | 'publish' | 'delete';
3
- export type EntryHeaderPrimaryActionId = 'create-draft' | 'save-translation' | 'discard-changes' | 'publish-edits' | 'save-draft' | 'publish-draft';
4
2
  interface EntryHeaderAccess {
5
3
  archive: boolean;
6
4
  delete: boolean;
@@ -32,6 +30,25 @@ export interface EntryHeaderPrimaryActionState {
32
30
  parentNeedsTranslation: boolean;
33
31
  untranslated: boolean;
34
32
  }
35
- export declare function entryHeaderPrimaryActionIds({ access, activeStatus, canPublishParents, canSaveDraft, isDirty, isRevision, parentNeedsTranslation, untranslated }: EntryHeaderPrimaryActionState): Array<EntryHeaderPrimaryActionId>;
36
- export declare function entryHeaderActionIds({ access, activeStatus, canDelete, canPublishParents, draftsEnabled, isDirty, isMediaFile, isMediaLibrary, isParentUnpublished, isRevision, isUnpublished, untranslated }: EntryHeaderActionState): Array<EntryHeaderActionId>;
33
+ export interface EntryDirtyActions {
34
+ publish: boolean;
35
+ saveDraft: boolean;
36
+ }
37
+ export interface EntryHeaderPrimaryActions {
38
+ createDraft: boolean;
39
+ dirty: EntryDirtyActions | undefined;
40
+ publishDraft: boolean;
41
+ saveTranslation: boolean;
42
+ }
43
+ export interface EntryHeaderActions {
44
+ archive: boolean;
45
+ delete: boolean;
46
+ publish: boolean;
47
+ removeDraft: boolean;
48
+ replace: boolean;
49
+ unpublish: boolean;
50
+ }
51
+ export declare function entryDirtyActions(canPublish: boolean, canSaveDraft: boolean): EntryDirtyActions;
52
+ export declare function entryHeaderPrimaryActions({ access, activeStatus, canPublishParents, canSaveDraft, isDirty, isRevision, parentNeedsTranslation, untranslated }: EntryHeaderPrimaryActionState): EntryHeaderPrimaryActions;
53
+ export declare function entryHeaderActions({ access, activeStatus, canDelete, canPublishParents, draftsEnabled, isDirty, isMediaFile, isMediaLibrary, isParentUnpublished, isRevision, isUnpublished, untranslated }: EntryHeaderActionState): EntryHeaderActions;
37
54
  export {};
@@ -1,7 +1,10 @@
1
1
  import "../../chunks/chunk-CQ52GEHY.js";
2
2
 
3
3
  // src/dashboard/app/EntryHeaderActions.ts
4
- function entryHeaderPrimaryActionIds({
4
+ function entryDirtyActions(canPublish, canSaveDraft) {
5
+ return { publish: canPublish, saveDraft: canSaveDraft };
6
+ }
7
+ function entryHeaderPrimaryActions({
5
8
  access,
6
9
  activeStatus,
7
10
  canPublishParents,
@@ -11,21 +14,29 @@ function entryHeaderPrimaryActionIds({
11
14
  parentNeedsTranslation,
12
15
  untranslated
13
16
  }) {
14
- if (isRevision) return canSaveDraft ? ["create-draft"] : [];
17
+ const actions = {
18
+ createDraft: false,
19
+ dirty: void 0,
20
+ publishDraft: false,
21
+ saveTranslation: false
22
+ };
23
+ if (isRevision) {
24
+ actions.createDraft = canSaveDraft;
25
+ return actions;
26
+ }
15
27
  if (untranslated) {
16
- return !parentNeedsTranslation && access.update ? ["save-translation"] : [];
28
+ actions.saveTranslation = !parentNeedsTranslation && access.update;
29
+ return actions;
17
30
  }
18
31
  if (isDirty) {
19
- const actions = ["discard-changes"];
20
- if (access.publish) actions.push("publish-edits");
21
- if (canSaveDraft) actions.push("save-draft");
32
+ actions.dirty = entryDirtyActions(access.publish, canSaveDraft);
22
33
  return actions;
23
34
  }
24
35
  if (activeStatus === "draft" && canPublishParents && access.publish)
25
- return ["publish-draft"];
26
- return [];
36
+ actions.publishDraft = true;
37
+ return actions;
27
38
  }
28
- function entryHeaderActionIds({
39
+ function entryHeaderActions({
29
40
  access,
30
41
  activeStatus,
31
42
  canDelete,
@@ -39,33 +50,43 @@ function entryHeaderActionIds({
39
50
  isUnpublished,
40
51
  untranslated
41
52
  }) {
42
- if (isRevision || isDirty || untranslated) return [];
53
+ const actions = {
54
+ archive: false,
55
+ delete: false,
56
+ publish: false,
57
+ removeDraft: false,
58
+ replace: false,
59
+ unpublish: false
60
+ };
61
+ if (isRevision || isDirty || untranslated) return actions;
43
62
  if (activeStatus === "draft") {
44
- if (!isUnpublished) return access.update ? ["remove-draft"] : [];
63
+ if (!isUnpublished) {
64
+ actions.removeDraft = access.update;
65
+ return actions;
66
+ }
45
67
  if (isParentUnpublished) {
46
- return canDelete && access.delete ? ["delete"] : [];
68
+ actions.delete = canDelete && access.delete;
69
+ return actions;
47
70
  }
48
- return access.archive ? ["archive"] : [];
71
+ actions.archive = access.archive;
72
+ return actions;
49
73
  }
50
74
  if (activeStatus === "published") {
51
75
  if (isMediaFile) {
52
- const actions3 = [];
53
- if (access.update && access.upload) actions3.push("replace");
54
- if (canDelete && access.delete) actions3.push("delete");
55
- return actions3;
76
+ actions.replace = access.update && access.upload;
77
+ actions.delete = canDelete && access.delete;
78
+ return actions;
56
79
  }
57
- const actions2 = [];
58
- if (!isMediaLibrary && draftsEnabled && access.publish)
59
- actions2.push("unpublish");
60
- if (canDelete && access.archive) actions2.push("archive");
61
- return actions2;
80
+ actions.unpublish = !isMediaLibrary && draftsEnabled && access.publish;
81
+ actions.archive = canDelete && access.archive;
82
+ return actions;
62
83
  }
63
- const actions = [];
64
- if (canPublishParents && access.publish) actions.push("publish");
65
- if (canDelete && access.delete) actions.push("delete");
84
+ actions.publish = canPublishParents && access.publish;
85
+ actions.delete = canDelete && access.delete;
66
86
  return actions;
67
87
  }
68
88
  export {
69
- entryHeaderActionIds,
70
- entryHeaderPrimaryActionIds
89
+ entryDirtyActions,
90
+ entryHeaderActions,
91
+ entryHeaderPrimaryActions
71
92
  };