alinea 2.0.0-preview.4 → 2.0.0-preview.6

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 (187) 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 +137 -137
  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/GithubApi.js +16 -7
  14. package/dist/backend/api/ProxyMedia.d.ts +3 -0
  15. package/dist/backend/api/ProxyMedia.js +39 -0
  16. package/dist/backend/api/S3Uploads.d.ts +1 -1
  17. package/dist/backend/router/Router.js +2 -0
  18. package/dist/backend/util/Syncable.js +1 -1
  19. package/dist/bundled.d.ts +166 -73
  20. package/dist/chunks/{chunk-XMOVGDFI.js → chunk-7IOKMUKO.js} +1 -1
  21. package/dist/chunks/{chunk-O7XWTMCB.js → chunk-D6RGFNUW.js} +73 -72
  22. package/dist/chunks/{chunk-VXZM6V4P.js → chunk-OFEKTDRF.js} +41 -41
  23. package/dist/cli/Generate.js +3 -4
  24. package/dist/cli/Serve.js +3 -2
  25. package/dist/cli/bin.js +1 -1
  26. package/dist/cli/generate/FillCache.d.ts +1 -1
  27. package/dist/cli/generate/FillCache.js +20 -9
  28. package/dist/cli/generate/GenerateDashboard.js +1 -0
  29. package/dist/cli/serve/CreateLocalServer.d.ts +1 -1
  30. package/dist/cli/serve/CreateLocalServer.js +42 -34
  31. package/dist/cli/serve/DevServer.js +1 -0
  32. package/dist/cli/static/init/cms.js +1 -4
  33. package/dist/cli/util/ContentType.d.ts +1 -0
  34. package/dist/cli/util/ContentType.js +36 -0
  35. package/dist/cli/util/Emitter.js +1 -1
  36. package/dist/cloud/CloudHandshake.d.ts +6 -0
  37. package/dist/cloud/CloudHandshake.js +67 -10
  38. package/dist/cloud/CloudRemote.js +24 -11
  39. package/dist/components/Breadcrumbs.js +7 -7
  40. package/dist/components/Button.js +5 -5
  41. package/dist/components/Calendar.js +7 -7
  42. package/dist/components/Checkbox.js +8 -8
  43. package/dist/components/CheckboxGroup.js +5 -5
  44. package/dist/components/ColorSwatch.js +5 -5
  45. package/dist/components/ColorSwatchPicker.js +7 -7
  46. package/dist/components/ComboBox.js +14 -14
  47. package/dist/components/DateField.js +8 -8
  48. package/dist/components/DatePicker.js +10 -10
  49. package/dist/components/DateRangePicker.js +11 -11
  50. package/dist/components/Dialog.js +5 -5
  51. package/dist/components/Disclosure.js +11 -11
  52. package/dist/components/DropZone.js +5 -5
  53. package/dist/components/Label.js +9 -9
  54. package/dist/components/Link.js +5 -5
  55. package/dist/components/List.d.ts +1 -1
  56. package/dist/components/List.js +37 -36
  57. package/dist/components/Menu.js +9 -9
  58. package/dist/components/Modal.js +8 -8
  59. package/dist/components/MultipleSelect.js +33 -33
  60. package/dist/components/NumberField.js +11 -11
  61. package/dist/components/Popover.js +5 -5
  62. package/dist/components/ProgressCircle.js +8 -8
  63. package/dist/components/RadioGroup.js +7 -7
  64. package/dist/components/SearchField.js +10 -10
  65. package/dist/components/Select.js +12 -12
  66. package/dist/components/Surface.js +3 -3
  67. package/dist/components/Switch.js +7 -7
  68. package/dist/components/Table.js +11 -11
  69. package/dist/components/Tabs.js +9 -9
  70. package/dist/components/TagGroup.js +7 -7
  71. package/dist/components/TextField.js +10 -10
  72. package/dist/components/TimeField.js +5 -5
  73. package/dist/components/Toggle.js +5 -5
  74. package/dist/components/Toolbar.js +6 -6
  75. package/dist/components/Tooltip.js +8 -8
  76. package/dist/components/Tree.js +13 -13
  77. package/dist/core/Config.d.ts +10 -3
  78. package/dist/core/Config.js +16 -1
  79. package/dist/core/Graph.d.ts +2 -2
  80. package/dist/core/Role.js +16 -14
  81. package/dist/core/TextDoc.d.ts +2 -0
  82. package/dist/core/TextDoc.js +1 -0
  83. package/dist/core/Workspace.d.ts +6 -5
  84. package/dist/core/db/EntryIndex.d.ts +3 -0
  85. package/dist/core/db/EntryIndex.js +55 -0
  86. package/dist/core/db/EntryTransaction.js +34 -32
  87. package/dist/core/db/EntryUrlConflictError.js +1 -1
  88. package/dist/core/db/LinkResolver.d.ts +8 -2
  89. package/dist/core/db/LinkResolver.js +27 -5
  90. package/dist/core/field/RichTextField.js +16 -10
  91. package/dist/core/media/MediaLocation.d.ts +9 -15
  92. package/dist/core/media/MediaLocation.js +29 -19
  93. package/dist/core/media/MediaTypes.js +1 -2
  94. package/dist/dashboard/App.js +4 -4
  95. package/dist/dashboard/app/ActivityStatus.js +31 -37
  96. package/dist/dashboard/app/AppShell.js +2 -2
  97. package/dist/dashboard/app/AuthView.js +12 -12
  98. package/dist/dashboard/app/Badge.js +2 -2
  99. package/dist/dashboard/app/CompactField.js +9 -9
  100. package/dist/dashboard/app/DashboardErrorBoundary.js +6 -6
  101. package/dist/dashboard/app/EntryFields.d.ts +3 -1
  102. package/dist/dashboard/app/EntryFields.js +11 -8
  103. package/dist/dashboard/app/EntryHeader.js +116 -84
  104. package/dist/dashboard/app/EntryHeaderActions.d.ts +21 -4
  105. package/dist/dashboard/app/EntryHeaderActions.js +48 -27
  106. package/dist/dashboard/app/EntryReferences.js +6 -6
  107. package/dist/dashboard/app/EntrySidebar.js +15 -15
  108. package/dist/dashboard/app/EntrySidebarPreview.js +4 -4
  109. package/dist/dashboard/app/EntryTranslationBanner.d.ts +3 -1
  110. package/dist/dashboard/app/EntryTranslationBanner.js +23 -20
  111. package/dist/dashboard/app/Explorer.d.ts +4 -2
  112. package/dist/dashboard/app/Explorer.js +53 -49
  113. package/dist/dashboard/app/ExplorerCards.js +31 -31
  114. package/dist/dashboard/app/ExplorerFileCard.js +16 -16
  115. package/dist/dashboard/app/ExplorerList.js +14 -15
  116. package/dist/dashboard/app/ExplorerModal.js +4 -4
  117. package/dist/dashboard/app/ExplorerTable.js +54 -54
  118. package/dist/dashboard/app/LinkPicker.js +5 -5
  119. package/dist/dashboard/app/LocaleMenu.d.ts +7 -0
  120. package/dist/dashboard/app/LocaleMenu.js +34 -18
  121. package/dist/dashboard/app/ReadOnlyBadge.d.ts +4 -0
  122. package/dist/dashboard/app/ReadOnlyBadge.js +33 -0
  123. package/dist/dashboard/app/SidebarTree.d.ts +3 -6
  124. package/dist/dashboard/app/SidebarTree.js +62 -57
  125. package/dist/dashboard/app/WorkspaceMenu.js +16 -16
  126. package/dist/dashboard/app/WorkspaceRoots.js +21 -21
  127. package/dist/dashboard/app/editor/FileEditor.d.ts +2 -3
  128. package/dist/dashboard/app/editor/FileEditor.js +24 -27
  129. package/dist/dashboard/app/editor/FilePreview.js +4 -4
  130. package/dist/dashboard/app/modals/CreateEntry.js +5 -5
  131. package/dist/dashboard/app/pages/EntryPage.js +72 -29
  132. package/dist/dashboard/app/pages/RootPage.js +3 -3
  133. package/dist/dashboard/app/pages/SplashPage.js +45 -45
  134. package/dist/dashboard/app/pages/UsersPage.js +36 -36
  135. package/dist/dashboard/app/ui/DashboardModal.js +21 -21
  136. package/dist/dashboard/app/ui/Rail.js +5 -5
  137. package/dist/dashboard/app/ui/Sidebar.js +2 -2
  138. package/dist/dashboard/atoms/activity.d.ts +0 -2
  139. package/dist/dashboard/atoms/activity.js +4 -10
  140. package/dist/dashboard/atoms/editor.d.ts +2 -1
  141. package/dist/dashboard/atoms/editor.js +4 -2
  142. package/dist/dashboard/atoms/entry.d.ts +2 -0
  143. package/dist/dashboard/atoms/entry.js +32 -14
  144. package/dist/dashboard/atoms/explorer.d.ts +4 -3
  145. package/dist/dashboard/atoms/explorer.js +61 -22
  146. package/dist/dashboard/atoms/link.d.ts +1 -1
  147. package/dist/dashboard/atoms/link.js +39 -55
  148. package/dist/dashboard/atoms/root.d.ts +7 -2
  149. package/dist/dashboard/atoms/root.js +51 -16
  150. package/dist/dashboard/atoms/upload.d.ts +1 -0
  151. package/dist/dashboard/atoms/upload.js +2 -1
  152. package/dist/dashboard/boot/ActivityEvent.d.ts +1 -1
  153. package/dist/dashboard/boot/DashboardWorker.js +2 -28
  154. package/dist/dashboard/fixture/cms.js +1 -4
  155. package/dist/dashboard/hook/UseSaveShortcut.d.ts +1 -0
  156. package/dist/dashboard/hook/UseSaveShortcut.js +24 -0
  157. package/dist/dashboard/hooks.d.ts +1 -1
  158. package/dist/dashboard/hooks.js +12 -3
  159. package/dist/field/check/CheckField.view.js +2 -2
  160. package/dist/field/code/CodeField.view.js +11 -11
  161. package/dist/field/date/DateField.view.js +5 -5
  162. package/dist/field/link/ImageLink.js +1 -3
  163. package/dist/field/link/LinkField.view.js +88 -62
  164. package/dist/field/list/ListField.view.js +25 -25
  165. package/dist/field/metadata/MetadataField.d.ts +3 -3
  166. package/dist/field/metadata/MetadataField.view.js +27 -20
  167. package/dist/field/object/ObjectField.view.js +11 -4
  168. package/dist/field/richtext/PickTextLink.js +5 -2
  169. package/dist/field/richtext/ReferenceLink.d.ts +2 -0
  170. package/dist/field/richtext/ReferenceLink.js +5 -0
  171. package/dist/field/richtext/RichTextBlock.js +2 -2
  172. package/dist/field/richtext/RichTextExtensions.js +24 -24
  173. package/dist/field/richtext/RichTextField.view.js +2 -2
  174. package/dist/field/richtext/RichTextInsertMenu.js +3 -3
  175. package/dist/field/richtext/extensions/Link.d.ts +1 -0
  176. package/dist/field/richtext/extensions/Link.js +1 -0
  177. package/dist/field/select/SelectField.view.js +1 -1
  178. package/dist/field/time/TimeField.d.ts +0 -2
  179. package/dist/field/time/TimeField.view.js +1 -1
  180. package/dist/index.css +44 -38
  181. package/dist/next.cjs +96 -19
  182. package/dist/picker/entry/EntryPicker.js +10 -12
  183. package/dist/picker/entry/EntryReference.d.ts +2 -0
  184. package/dist/picker/entry/EntryReference.js +1 -0
  185. package/dist/types.d.ts +0 -1
  186. package/package.json +1 -1
  187. package/dist/chunks/{chunk-6V4TAD2N.js → chunk-DNJX6CRV.js} +4 -4
package/dist/bundled.d.ts CHANGED
@@ -133,17 +133,26 @@ declare module 'alinea/adapter/next/previews.spec' {
133
133
 
134
134
  }
135
135
 
136
+ declare module 'alinea/adapter/next/syncCheck' {
137
+
138
+ import type { Client } from 'alinea/core/Client';
139
+ import type { LocalDB } from 'alinea/core/db/LocalDB';
140
+ export const CONTENT_SHA_TAG = "alinea-content-sha";
141
+ export function revalidateContentSha(): Promise<void>;
142
+ /**
143
+ * Sync the isolate-local db only when it is behind the shared content sha.
144
+ * Returns true when the freshness question is settled here (synced, forced,
145
+ * or explicitly disabled) and the caller can skip its throttled sync.
146
+ * Returns false when the sha could not be determined, so the caller falls
147
+ * back to its existing throttle behavior.
148
+ */
149
+ export function syncIfStale(db: LocalDB, client: Client, syncInterval?: number): Promise<boolean>;
150
+
151
+ }
152
+
136
153
  declare module 'alinea/adapter/next/with-alinea' {
137
154
 
138
155
  import type { NextConfig } from 'next/dist/types.js';
139
- export interface WithAlineaOptions {
140
- /**
141
- * Base path where the dashboard is mounted.
142
- *
143
- * @default '/admin'
144
- */
145
- adminPath?: string;
146
- }
147
156
  export function createCMS(): void;
148
157
  export function withAlinea(config?: NextConfig): NextConfig;
149
158
 
@@ -345,6 +354,14 @@ declare module 'alinea/backend/api/OAuth2' {
345
354
 
346
355
  }
347
356
 
357
+ declare module 'alinea/backend/api/ProxyMedia' {
358
+
359
+ import { type Request, Response } from '@alinea/iso';
360
+ export function proxyMediaUrl(request: Request, source: URL, isAllowed?: (url: URL) => boolean): Promise<Response>;
361
+ export function isRedirectStatus(status: number): boolean;
362
+
363
+ }
364
+
348
365
  declare module 'alinea/backend/api/S3Uploads' {
349
366
 
350
367
  import type { UploadMetadata, UploadResponse, UploadsApi } from 'alinea/core/Connection';
@@ -362,7 +379,7 @@ declare module 'alinea/backend/api/S3Uploads' {
362
379
  previewExpiresIn?: number;
363
380
  }
364
381
  interface S3PresignOptions {
365
- method: 'GET' | 'PUT';
382
+ method: 'GET' | 'HEAD' | 'PUT';
366
383
  url: URL;
367
384
  region: string;
368
385
  accessKeyId: string;
@@ -887,7 +904,7 @@ declare module 'alinea/cli/generate/FillCache' {
887
904
 
888
905
  import { type Emitter } from 'alinea/cli/util/Emitter';
889
906
  import type { DevDB } from 'alinea/cli/generate/DevDB';
890
- export function fillCache(db: DevDB, fix?: boolean): Emitter<DevDB>;
907
+ export function fillCache(db: DevDB, fix?: boolean, watch?: boolean): Emitter<DevDB>;
891
908
 
892
909
  }
893
910
 
@@ -957,7 +974,7 @@ declare module 'alinea/cli/serve/CreateLocalServer' {
957
974
  import type { Handler } from 'alinea/backend/Handler';
958
975
  import type { CMS } from 'alinea/core/CMS';
959
976
  import type { User } from 'alinea/core/User';
960
- import { type Request, Response } from '@alinea/iso';
977
+ import { Request, Response } from '@alinea/iso';
961
978
  import type { ServeContext } from 'alinea/cli/serve/ServeContext';
962
979
  export function createLocalServer({ cmd, configLocation, rootDir, staticDir, alineaDev, buildOptions, production, liveReload, buildId, apiKey }: ServeContext, cms: CMS, handleApi: Handler, user: User): {
963
980
  close(): void;
@@ -1100,6 +1117,12 @@ declare module 'alinea/cli/util/CommitSha' {
1100
1117
 
1101
1118
  }
1102
1119
 
1120
+ declare module 'alinea/cli/util/ContentType' {
1121
+
1122
+ export function contentType(extension: string): string;
1123
+
1124
+ }
1125
+
1103
1126
  declare module 'alinea/cli/util/Dirname' {
1104
1127
 
1105
1128
  export function dirname(url?: string): string;
@@ -1279,6 +1302,12 @@ declare module 'alinea/cloud/CloudHandshake' {
1279
1302
  handshakeId: string;
1280
1303
  origin: string;
1281
1304
  }
1305
+ export class CloudHandshakeError extends Error {
1306
+ name: string;
1307
+ }
1308
+ export class CloudHandshakeServiceError extends Error {
1309
+ name: string;
1310
+ }
1282
1311
  export function verifyCloudHandshake(token: string, options: VerifyCloudHandshakeOptions): Promise<void>;
1283
1312
  export {};
1284
1313
 
@@ -1648,7 +1677,7 @@ declare module 'alinea/components/List' {
1648
1677
  description?: ReactNode;
1649
1678
  inline?: boolean;
1650
1679
  }
1651
- export function ListLabel({ children, expanded, hasRows, shared, showFold, className, description, inline, ...props }: ListLabelProps): import("react").JSX.Element;
1680
+ export function ListLabel({ children, expanded, hasRows, shared, showFold, className, description, inline, ...props }: ListLabelProps): import("react").JSX.Element | null;
1652
1681
  export interface ListErrorProps extends ComponentPropsWithoutRef<'div'> {
1653
1682
  }
1654
1683
  export function ListError({ className, ...props }: ListErrorProps): import("react").JSX.Element;
@@ -2172,7 +2201,7 @@ declare module 'alinea/core/Config' {
2172
2201
  preview?: Preview;
2173
2202
  /** Every edit will pass through a draft status before being published */
2174
2203
  enableDrafts?: boolean;
2175
- /** The interval in seconds at which the frontend will poll for updates */
2204
+ /** Fallback interval in seconds for polling content updates (freshness is primarily sha-driven) */
2176
2205
  syncInterval?: number;
2177
2206
  /** Maximum file upload size in bytes */
2178
2207
  maxUploadSize?: number;
@@ -2183,9 +2212,14 @@ declare module 'alinea/core/Config' {
2183
2212
  };
2184
2213
  /** The url of the handler endpoint */
2185
2214
  handlerUrl?: string;
2186
- /** The folder where public assets are stored, defaults to /public */
2215
+ /** The public path where Alinea is mounted, defaults to /admin */
2216
+ adminPath?: string;
2217
+ /** The folder where public assets are stored, defaults to /public. */
2187
2218
  publicDir?: string;
2188
- /** Filename of the generated dashboard, defaults to admin.html */
2219
+ /**
2220
+ * Filename of the generated dashboard, defaults to admin.html.
2221
+ * @deprecated Use adminPath instead.
2222
+ */
2189
2223
  dashboardFile?: string;
2190
2224
  /** Optional application-owned instrumentation for Alinea operations. */
2191
2225
  tracer?: Tracer;
@@ -2195,6 +2229,8 @@ declare module 'alinea/core/Config' {
2195
2229
  function baseUrl(config: Config, env?: string): string | undefined;
2196
2230
  function handlerUrl(config: Config): string;
2197
2231
  function adminPath(config: Config): string;
2232
+ function filePathname(config: Config, file: string): string;
2233
+ function dashboardFile(config: Config): string;
2198
2234
  function mainWorkspace(config: Config): WorkspaceInternal;
2199
2235
  function type(config: Config, name: string): Type | undefined;
2200
2236
  function rootContains(config: Config, root: Root, childType: Type): boolean;
@@ -2487,6 +2523,8 @@ declare module 'alinea/core/db/EntryIndex' {
2487
2523
  constructor(config: Config, versionData: Map<string, EntryVersionData>, seeds: Map<string, Seed>);
2488
2524
  byId(id: string): EntryNode | undefined;
2489
2525
  candidateNodes(query: EntryNodeQuery): Array<EntryNode> | undefined;
2526
+ byUrl(url: string): Iterable<Entry>;
2527
+ byAlias(alias: string): Iterable<Entry>;
2490
2528
  get config(): Config;
2491
2529
  byDir(dir: string): EntryNode | undefined;
2492
2530
  entryByFilePath(filePath: string): Entry | undefined;
@@ -2504,6 +2542,7 @@ declare module 'alinea/core/db/EntryIndex' {
2504
2542
  filter(filter: EntryCondition): Iterable<Entry>;
2505
2543
  findFirst<T extends Record<string, unknown>>(filter: (entry: Entry) => boolean): Entry<T> | undefined;
2506
2544
  findMany(filter: (entry: Entry) => boolean): Iterable<Entry>;
2545
+ findByUrl(url: string, filter: (entry: Entry) => boolean): Entry | undefined;
2507
2546
  referencesTo(query: EntryReferenceQuery): Promise<EntryReferenceResult>;
2508
2547
  referencesFrom(sourceId: string): Promise<import("alinea/core/db/EntryReference").EntryReference[]>;
2509
2548
  get references(): Promise<EntryReferenceIndex>;
@@ -2754,13 +2793,19 @@ declare module 'alinea/core/db/LinkResolver' {
2754
2793
 
2755
2794
  import type { InferProjection, Projection } from 'alinea/core/Graph';
2756
2795
  import type { EntryResolver, ResolveContext } from 'alinea/core/db/EntryResolver';
2796
+ export interface LinkTarget {
2797
+ entryId: string;
2798
+ locale?: string;
2799
+ }
2757
2800
  export class LinkResolver {
2758
2801
  resolver: EntryResolver;
2759
2802
  private ctx;
2760
2803
  locale: string | null;
2761
2804
  constructor(resolver: EntryResolver, ctx: ResolveContext, locale: string | null);
2762
- includedAtBuild(filePath: string): boolean;
2763
- resolveLinks<P extends Projection>(projection: P, entryIds: ReadonlyArray<string>): Promise<Array<InferProjection<P>>>;
2805
+ resolveLinks<P extends Projection>(projection: P, entryIds: ReadonlyArray<string>, locale?: string | null | undefined): Promise<Array<InferProjection<P>>>;
2806
+ resolveTargets<P extends Projection & {
2807
+ id: unknown;
2808
+ }>(projection: P, targets: ReadonlyArray<LinkTarget>): Promise<Array<InferProjection<P> | undefined>>;
2764
2809
  }
2765
2810
 
2766
2811
  }
@@ -3719,9 +3764,9 @@ declare module 'alinea/core/Graph' {
3719
3764
  filter?: Filter<EntryFields>;
3720
3765
  /** Filter by search terms */
3721
3766
  search?: string | Array<string>;
3722
- /** The time in seconds to poll for updates to content */
3767
+ /** Fallback interval in seconds for polling content updates (freshness is primarily sha-driven) */
3723
3768
  syncInterval?: number;
3724
- /** Disable polling for updates to content */
3769
+ /** Disable syncing content updates */
3725
3770
  disableSync?: boolean;
3726
3771
  /** Skip the first N results */
3727
3772
  skip?: number;
@@ -3977,35 +4022,25 @@ declare module 'alinea/core/media/MediaAltField' {
3977
4022
 
3978
4023
  declare module 'alinea/core/media/MediaLocation' {
3979
4024
 
3980
- import type { Config } from 'alinea/core/Config';
4025
+ import { Config } from 'alinea/core/Config';
3981
4026
  export const MEDIA_LOCATION = "@alinea.location";
3982
- export interface MediaUrlMeta {
4027
+ export interface MediaPublicUrlMeta {
3983
4028
  /** The media entry path without its extension. */
3984
4029
  path: string;
3985
4030
  /** The paths of parent media directories. */
3986
4031
  parentPaths: Array<string>;
3987
4032
  /** The file extension, including its leading dot. */
3988
4033
  extension: string;
3989
- /** The location stored in the media entry, excluding mediaDir. */
3990
- location: string;
4034
+ /** The workspace holding the media entry. */
3991
4035
  workspace: string;
3992
- root: string;
3993
- }
3994
- export interface MediaUrlResolver {
3995
- (meta: MediaUrlMeta): string;
3996
- }
3997
- export interface MediaPublicUrlMeta extends Omit<MediaUrlMeta, 'parentPaths'> {
3998
- /** @deprecated Pass parentPaths directly when available. */
3999
- entryUrl?: string;
4000
- parentPaths?: Array<string>;
4001
4036
  }
4002
4037
  export interface MediaEntryUrlMeta {
4003
4038
  defaultUrl: string;
4004
4039
  parentPaths: Array<string>;
4005
4040
  path: string;
4006
- workspace: string;
4007
- root: string;
4008
4041
  data: Record<string, unknown>;
4042
+ /** The workspace holding the media entry. */
4043
+ workspace: string;
4009
4044
  }
4010
4045
  /** Maps media entry locations between storage and public URLs. */
4011
4046
  export namespace MediaLocation {
@@ -4015,8 +4050,12 @@ declare module 'alinea/core/media/MediaLocation' {
4015
4050
  function storagePath(config: Config, workspace: string, location: string): string;
4016
4051
  /** Remove the workspace storage directory from a prepared upload location. */
4017
4052
  function entryLocation(config: Config, workspace: string, location: string): string;
4053
+ /** Resolve the deployed public location of a stored media file. */
4054
+ function sourceUrl(config: Config, workspace: string, location: string): string | undefined;
4018
4055
  /** Resolve the public URL used to serve a media entry. */
4019
4056
  function publicUrl(config: Config, meta: MediaPublicUrlMeta): string;
4057
+ /** Add an immutable media version without changing its canonical path. */
4058
+ function versionedUrl(url: string, version: string | undefined): string;
4020
4059
  /** Resolve a media entry URL, falling back to its regular entry URL. */
4021
4060
  function entryUrl(config: Config, meta: MediaEntryUrlMeta): string;
4022
4061
  }
@@ -5024,6 +5063,7 @@ declare module 'alinea/core/TextDoc' {
5024
5063
  _id: string;
5025
5064
  _link: 'entry' | 'file' | 'url';
5026
5065
  _entry?: string;
5066
+ _locale?: string;
5027
5067
  _anchor?: string;
5028
5068
  _suffix?: string;
5029
5069
  }
@@ -5031,6 +5071,7 @@ declare module 'alinea/core/TextDoc' {
5031
5071
  const id = "_id";
5032
5072
  const link = "_link";
5033
5073
  const entry = "_entry";
5074
+ const locale = "_locale";
5034
5075
  const anchor = "_anchor";
5035
5076
  const suffix = "_suffix";
5036
5077
  }
@@ -5857,23 +5898,23 @@ declare module 'alinea/core/Workspace' {
5857
5898
 
5858
5899
  import type { Preview } from 'alinea/core/Preview';
5859
5900
  import type { ComponentType } from 'react';
5860
- import type { MediaUrlResolver } from 'alinea/core/media/MediaLocation';
5861
5901
  import { type HasWorkspace } from 'alinea/core/Internal';
5862
5902
  import { Root } from 'alinea/core/Root';
5863
5903
  import type { Schema } from 'alinea/core/Schema';
5864
5904
  export interface WorkspaceMeta {
5865
5905
  /** A directory which contains the json entry files */
5866
5906
  source: string;
5867
- /** The directory where media files are placed in case a file backend is used */
5907
+ /**
5908
+ * The directory where media files are placed
5909
+ */
5868
5910
  mediaDir?: string;
5869
- /** Prepare the public URL used when querying media files */
5870
- mediaUrl?: string | MediaUrlResolver;
5911
+ /** The public URL prefix used when querying media files */
5912
+ mediaUrl?: string;
5871
5913
  /** The main theme color used in the dashboard */
5872
5914
  color?: string;
5873
5915
  icon?: ComponentType;
5874
5916
  preview?: Preview;
5875
5917
  }
5876
- export type { MediaUrlMeta, MediaUrlResolver } from 'alinea/core/media/MediaLocation';
5877
5918
  type Roots = Record<string, Root>;
5878
5919
  export interface RootsDefinition {
5879
5920
  [key: string]: Root;
@@ -5901,6 +5942,7 @@ declare module 'alinea/core/Workspace' {
5901
5942
  export function workspace<Roots extends RootsDefinition>(
5902
5943
  /** The name of the workspace */
5903
5944
  label: string, config: WorkspaceConfig<Roots>): Workspace<Roots>;
5945
+ export {};
5904
5946
 
5905
5947
  }
5906
5948
 
@@ -6086,12 +6128,11 @@ declare module 'alinea/dashboard/app/DashboardMeta' {
6086
6128
 
6087
6129
  declare module 'alinea/dashboard/app/editor/FileEditor' {
6088
6130
 
6089
- import type { Entry } from 'alinea/core/Entry';
6090
6131
  export interface FileEditorProps {
6091
- entry: Pick<Entry, 'root' | 'url' | 'workspace'>;
6092
6132
  parentPaths: Array<string>;
6133
+ workspace: string;
6093
6134
  }
6094
- export function FileEditor({ entry, parentPaths }: FileEditorProps): import("react").JSX.Element;
6135
+ export function FileEditor({ parentPaths, workspace }: FileEditorProps): import("react").JSX.Element;
6095
6136
 
6096
6137
  }
6097
6138
 
@@ -6142,9 +6183,10 @@ declare module 'alinea/dashboard/app/EntryFields' {
6142
6183
  import type { EditorNode } from 'alinea/dashboard/atoms/editor';
6143
6184
  interface NodeEditorProps extends PropsWithChildren {
6144
6185
  node: EditorNode;
6186
+ readOnly?: boolean;
6145
6187
  type: Type;
6146
6188
  }
6147
- export function NodeEditor({ children, node, type }: NodeEditorProps): import("react").JSX.Element;
6189
+ export function NodeEditor({ children, node, readOnly, type }: NodeEditorProps): import("react").JSX.Element;
6148
6190
  export function FieldsEditor(): import("react").JSX.Element[];
6149
6191
  export function EntryFields(): import("react").JSX.Element[];
6150
6192
  export interface EditFieldsProps {
@@ -6155,6 +6197,7 @@ declare module 'alinea/dashboard/app/EntryFields' {
6155
6197
  field: Field;
6156
6198
  }
6157
6199
  export const EditField: import("react").MemoExoticComponent<({ field }: EditFieldProps) => import("react").JSX.Element | null>;
6200
+ export function fieldWidth(width?: number): string;
6158
6201
  export {};
6159
6202
 
6160
6203
  }
@@ -6182,8 +6225,6 @@ declare module 'alinea/dashboard/app/EntryHeader' {
6182
6225
  declare module 'alinea/dashboard/app/EntryHeaderActions' {
6183
6226
 
6184
6227
  import type { EntryStatus } from 'alinea/core/Entry';
6185
- export type EntryHeaderActionId = 'remove-draft' | 'replace' | 'unpublish' | 'archive' | 'publish' | 'delete';
6186
- export type EntryHeaderPrimaryActionId = 'create-draft' | 'save-translation' | 'discard-changes' | 'publish-edits' | 'save-draft' | 'publish-draft';
6187
6228
  interface EntryHeaderAccess {
6188
6229
  archive: boolean;
6189
6230
  delete: boolean;
@@ -6215,8 +6256,27 @@ declare module 'alinea/dashboard/app/EntryHeaderActions' {
6215
6256
  parentNeedsTranslation: boolean;
6216
6257
  untranslated: boolean;
6217
6258
  }
6218
- export function entryHeaderPrimaryActionIds({ access, activeStatus, canPublishParents, canSaveDraft, isDirty, isRevision, parentNeedsTranslation, untranslated }: EntryHeaderPrimaryActionState): Array<EntryHeaderPrimaryActionId>;
6219
- export function entryHeaderActionIds({ access, activeStatus, canDelete, canPublishParents, draftsEnabled, isDirty, isMediaFile, isMediaLibrary, isParentUnpublished, isRevision, isUnpublished, untranslated }: EntryHeaderActionState): Array<EntryHeaderActionId>;
6259
+ export interface EntryDirtyActions {
6260
+ publish: boolean;
6261
+ saveDraft: boolean;
6262
+ }
6263
+ export interface EntryHeaderPrimaryActions {
6264
+ createDraft: boolean;
6265
+ dirty: EntryDirtyActions | undefined;
6266
+ publishDraft: boolean;
6267
+ saveTranslation: boolean;
6268
+ }
6269
+ export interface EntryHeaderActions {
6270
+ archive: boolean;
6271
+ delete: boolean;
6272
+ publish: boolean;
6273
+ removeDraft: boolean;
6274
+ replace: boolean;
6275
+ unpublish: boolean;
6276
+ }
6277
+ export function entryDirtyActions(canPublish: boolean, canSaveDraft: boolean): EntryDirtyActions;
6278
+ export function entryHeaderPrimaryActions({ access, activeStatus, canPublishParents, canSaveDraft, isDirty, isRevision, parentNeedsTranslation, untranslated }: EntryHeaderPrimaryActionState): EntryHeaderPrimaryActions;
6279
+ export function entryHeaderActions({ access, activeStatus, canDelete, canPublishParents, draftsEnabled, isDirty, isMediaFile, isMediaLibrary, isParentUnpublished, isRevision, isUnpublished, untranslated }: EntryHeaderActionState): EntryHeaderActions;
6220
6280
  export {};
6221
6281
 
6222
6282
  }
@@ -6308,12 +6368,14 @@ declare module 'alinea/dashboard/app/EntrySidebarToggle' {
6308
6368
  declare module 'alinea/dashboard/app/EntryTranslationBanner' {
6309
6369
 
6310
6370
  export interface EntryTranslationBannerProps {
6371
+ copyFromSource: boolean;
6311
6372
  parentNeedsTranslation: boolean;
6312
6373
  sourceLocale: string | null;
6313
6374
  sourceLocales: ReadonlyArray<string>;
6375
+ onCopyFromSourceChange: (copyFromSource: boolean) => void;
6314
6376
  onSourceLocaleChange: (locale: string) => void;
6315
6377
  }
6316
- export const EntryTranslationBanner: import("react").MemoExoticComponent<({ parentNeedsTranslation, sourceLocale, sourceLocales, onSourceLocaleChange }: EntryTranslationBannerProps) => import("react").JSX.Element>;
6378
+ export const EntryTranslationBanner: import("react").MemoExoticComponent<({ copyFromSource, parentNeedsTranslation, sourceLocale, sourceLocales, onCopyFromSourceChange, onSourceLocaleChange }: EntryTranslationBannerProps) => import("react").JSX.Element>;
6317
6379
 
6318
6380
  }
6319
6381
 
@@ -6327,6 +6389,7 @@ declare module 'alinea/dashboard/app/Explorer' {
6327
6389
  explorer: DashboardExplorer;
6328
6390
  headerEntry?: ExplorerHeaderEntry;
6329
6391
  page: ExplorerReadyPage;
6392
+ readOnly?: boolean;
6330
6393
  titleControls?: ReactNode;
6331
6394
  }
6332
6395
  export interface ExplorerHeaderEntry {
@@ -6342,6 +6405,7 @@ declare module 'alinea/dashboard/app/Explorer' {
6342
6405
  headerEntry?: ExplorerHeaderEntry;
6343
6406
  navigate?: boolean;
6344
6407
  page: ExplorerReadyPage;
6408
+ readOnly?: boolean;
6345
6409
  titleControls?: ReactNode;
6346
6410
  }
6347
6411
  export interface ExplorerBodyProps {
@@ -6357,9 +6421,9 @@ declare module 'alinea/dashboard/app/Explorer' {
6357
6421
  page: ExplorerReadyPage;
6358
6422
  }
6359
6423
  export function ExplorerSearch({ autoFocus, explorer, onEntryAction, page }: ExplorerSearchProps): import("react").JSX.Element;
6360
- export function ExplorerHeader({ canBrowse, autoFocusSearch, controls, explorer, headerEntry, navigate, page, titleControls }: ExplorerHeaderProps): import("react").JSX.Element;
6424
+ export function ExplorerHeader({ canBrowse, autoFocusSearch, controls, explorer, headerEntry, navigate, page, readOnly, titleControls }: ExplorerHeaderProps): import("react").JSX.Element;
6361
6425
  export function ExplorerBody({ compactTable, explorer, onSelectionChange, page }: ExplorerBodyProps): import("react").JSX.Element;
6362
- export function Explorer({ controls, explorer, headerEntry, page: loadedPage, titleControls }: ExplorerProps): import("react").JSX.Element;
6426
+ export function Explorer({ controls, explorer, headerEntry, page: loadedPage, readOnly, titleControls }: ExplorerProps): import("react").JSX.Element;
6363
6427
  export {};
6364
6428
 
6365
6429
  }
@@ -6518,7 +6582,14 @@ declare module 'alinea/dashboard/app/LocaleMenu' {
6518
6582
  locale: string | null;
6519
6583
  onLocaleChange(locale: string): void;
6520
6584
  }
6585
+ export interface LocaleMenuSelectProps {
6586
+ ariaLabel?: string;
6587
+ locale: string | null;
6588
+ locales: ReadonlyArray<string>;
6589
+ onLocaleChange(locale: string): void;
6590
+ }
6521
6591
  export function LocaleMenu({ root, locale, onLocaleChange }: LocaleMenuProps): import("react").JSX.Element | null;
6592
+ export function LocaleMenuSelect({ ariaLabel, locale, locales, onLocaleChange }: LocaleMenuSelectProps): import("react").JSX.Element | null;
6522
6593
  export {};
6523
6594
 
6524
6595
  }
@@ -6592,6 +6663,15 @@ declare module 'alinea/dashboard/app/pages/UsersPage' {
6592
6663
 
6593
6664
  }
6594
6665
 
6666
+ declare module 'alinea/dashboard/app/ReadOnlyBadge' {
6667
+
6668
+ import type { ComponentPropsWithoutRef } from 'react';
6669
+ export interface ReadOnlyBadgeProps extends ComponentPropsWithoutRef<'span'> {
6670
+ }
6671
+ export function ReadOnlyBadge(props: ReadOnlyBadgeProps): import("react").JSX.Element;
6672
+
6673
+ }
6674
+
6595
6675
  declare module 'alinea/dashboard/app/SidebarLayout' {
6596
6676
 
6597
6677
  import { type ReactNode } from 'react';
@@ -6609,7 +6689,7 @@ declare module 'alinea/dashboard/app/SidebarTree' {
6609
6689
 
6610
6690
  import { type Page } from 'alinea/dashboard/atoms/nav';
6611
6691
  import type { RootAtoms, RootTreeItem, RootTreeNode, TreeAtoms } from 'alinea/dashboard/atoms/root';
6612
- import { type Atom, type WritableAtom } from 'jotai';
6692
+ import { type WritableAtom } from 'jotai';
6613
6693
  import { type ReactNode } from 'react';
6614
6694
  import { type Selection } from 'react-aria-components';
6615
6695
  export interface SidebarTreeProps {
@@ -6628,16 +6708,13 @@ declare module 'alinea/dashboard/app/SidebarTree' {
6628
6708
  }
6629
6709
  interface SidebarTreeItemProps {
6630
6710
  children?: ReactNode;
6711
+ data: RootTreeItem;
6631
6712
  entryLink?: (entry: RootTreeItem) => SidebarTreeLink;
6632
6713
  item: RootTreeNode;
6633
6714
  locale: string | null;
6634
6715
  selectedItem?: RootTreeItem;
6635
- tree: SidebarTreeItemSource;
6636
6716
  }
6637
- interface SidebarTreeItemSource {
6638
- item(id: string): Atom<RootTreeItem>;
6639
- }
6640
- export const SidebarTreeItem: import("react").MemoExoticComponent<({ children, entryLink, item, locale, selectedItem, tree }: SidebarTreeItemProps) => import("react").JSX.Element>;
6717
+ export const SidebarTreeItem: import("react").MemoExoticComponent<({ children, data, entryLink, item, locale, selectedItem }: SidebarTreeItemProps) => import("react").JSX.Element>;
6641
6718
  interface SidebarTreeLink {
6642
6719
  href: string;
6643
6720
  }
@@ -6825,10 +6902,8 @@ declare module 'alinea/dashboard/atoms/activity' {
6825
6902
  import { type Activity } from 'alinea/dashboard/boot/ActivityEvent';
6826
6903
  export interface DashboardActivity {
6827
6904
  items: Array<Activity>;
6828
- isFetchingUpdates: boolean;
6829
6905
  isMutating: boolean;
6830
6906
  hasFailed: boolean;
6831
- hasFailedMutations: boolean;
6832
6907
  hasBlocked: boolean;
6833
6908
  canRetry: boolean;
6834
6909
  canDiscard: boolean;
@@ -7069,9 +7144,10 @@ declare module 'alinea/dashboard/atoms/editor' {
7069
7144
  policy?: Policy | undefined;
7070
7145
  resolvedImages: ReadonlyMap<string, ResolvedEditorImage>;
7071
7146
  anchors: Atom<Array<EntryAnchorTarget>>;
7147
+ readonly readOnly: boolean;
7072
7148
  value: Atom<object>;
7073
7149
  sections: Array<EntryEditorSection>;
7074
- constructor(type: Type, node: EditorNode, parent?: EntryEditor | undefined, resource?: Resource | undefined, policy?: Policy | undefined, resolvedImages?: ReadonlyMap<string, ResolvedEditorImage>);
7150
+ constructor(type: Type, node: EditorNode, parent?: EntryEditor | undefined, resource?: Resource | undefined, policy?: Policy | undefined, resolvedImages?: ReadonlyMap<string, ResolvedEditorImage>, readOnly?: boolean);
7075
7151
  field: (key: string) => EntryEditorField | undefined;
7076
7152
  get(field: Field): EntryEditorField | undefined;
7077
7153
  }
@@ -7166,6 +7242,7 @@ declare module 'alinea/dashboard/atoms/entry' {
7166
7242
  init: ReactiveNode<object> | undefined;
7167
7243
  };
7168
7244
  untranslated: Atom<boolean>;
7245
+ copyTranslationSource: import("jotai").WritableAtom<boolean, [next: boolean], void>;
7169
7246
  translationSourceLocale: import("jotai").WritableAtom<string, [next: string], void>;
7170
7247
  parentNeedsTranslation: Atom<Promise<boolean>>;
7171
7248
  selectedVersion: import("jotai").PrimitiveAtom<SelectedVersion | null> & {
@@ -7173,6 +7250,7 @@ declare module 'alinea/dashboard/atoms/entry' {
7173
7250
  };
7174
7251
  versions: Atom<Map<EntryStatus, Entry<Record<string, unknown>>>>;
7175
7252
  availableStatuses: Atom<EntryStatus[]>;
7253
+ preferredEntry: Atom<Entry<Record<string, unknown>>>;
7176
7254
  selectedEntry: Atom<Promise<Entry<Record<string, unknown>>>>;
7177
7255
  historyReady: Atom<Promise<import("alinea/core/Connection").Revision[]>>;
7178
7256
  history: Atom<import("alinea/core/Connection").Revision[]>;
@@ -7438,7 +7516,7 @@ declare module 'alinea/dashboard/atoms/explorer' {
7438
7516
  initialSelection?: Array<string>;
7439
7517
  searchDepth?: 'current' | 'all';
7440
7518
  onAction?: (entry: ExplorerEntry) => void;
7441
- onConfirm?: (selection: Array<string>) => void;
7519
+ onConfirm?: (selection: Array<string>, locale: string | null) => void;
7442
7520
  preselect?: boolean;
7443
7521
  }
7444
7522
  export interface ExplorerTreeItem {
@@ -7450,6 +7528,7 @@ declare module 'alinea/dashboard/atoms/explorer' {
7450
7528
  }
7451
7529
  export type ExplorerResultMode = 'browse' | 'matches';
7452
7530
  export interface ExplorerReadyPage {
7531
+ canUpload: boolean;
7453
7532
  isMedia: boolean;
7454
7533
  items: Array<ExplorerEntry>;
7455
7534
  locale: string | null;
@@ -7604,7 +7683,7 @@ declare module 'alinea/dashboard/atoms/explorer' {
7604
7683
  get limitLocations(): ExplorerLimitLocation[] | undefined;
7605
7684
  canUpload: Atom<boolean>;
7606
7685
  uploadsInCurrentFolder: Atom<import("alinea/dashboard/boot/ActivityEvent").Activity[]>;
7607
- upload: WritableAtom<null, [files: ArrayLike<File> | Iterable<File>], void> & {
7686
+ upload: WritableAtom<null, [files: ArrayLike<File> | Iterable<File>], Promise<void>> & {
7608
7687
  init: null;
7609
7688
  };
7610
7689
  getItems: WritableAtom<null, [keys: Set<Key>], DragItem[]> & {
@@ -7622,7 +7701,7 @@ declare module 'alinea/dashboard/atoms/explorer' {
7622
7701
  openLocation: WritableAtom<null, [entry: ExplorerEntry], void> & {
7623
7702
  init: null;
7624
7703
  };
7625
- onConfirm: WritableAtom<null, [], void> & {
7704
+ onConfirm: WritableAtom<null, [locale?: string | null | undefined], void> & {
7626
7705
  init: null;
7627
7706
  };
7628
7707
  isExpanded: (entry: ExplorerEntry) => Atom<boolean>;
@@ -7674,7 +7753,7 @@ declare module 'alinea/dashboard/atoms/link' {
7674
7753
  state: 'hasError';
7675
7754
  error: Error;
7676
7755
  };
7677
- export const linkEntryAtoms: (id: string) => import("jotai").Atom<LinkEntryState>;
7756
+ export const linkEntryAtoms: (id: string, locale?: string | undefined) => import("jotai").Atom<LinkEntryState>;
7678
7757
 
7679
7758
  }
7680
7759
 
@@ -7798,7 +7877,7 @@ declare module 'alinea/dashboard/atoms/root' {
7798
7877
  import { type Atom, type PrimitiveAtom } from 'jotai';
7799
7878
  import type { ComponentType } from 'react';
7800
7879
  import type { DroppableCollectionInsertDropEvent, DroppableCollectionOnItemDropEvent, DroppableCollectionReorderEvent, Key } from 'react-aria-components';
7801
- import { LucideFile } from 'alinea/dashboard/icons';
7880
+ import { IcOutlineDescription } from 'alinea/dashboard/icons';
7802
7881
  import { type TreeEntryAtoms } from 'alinea/dashboard/atoms/entry';
7803
7882
  export interface RootViewProps {
7804
7883
  root: RootData;
@@ -7824,6 +7903,10 @@ declare module 'alinea/dashboard/atoms/root' {
7824
7903
  items: Array<RootTreeNode>;
7825
7904
  selectedKeys: Set<string>;
7826
7905
  }
7906
+ export interface TreeView {
7907
+ entries: Map<string, RootTreeItem>;
7908
+ snapshot: TreeSnapshot;
7909
+ }
7827
7910
  interface TreeCollapseState {
7828
7911
  selectedId: string | undefined;
7829
7912
  keys: Set<string>;
@@ -7837,6 +7920,7 @@ declare module 'alinea/dashboard/atoms/root' {
7837
7920
  expandedKeys: PrimitiveAtom<Set<string>>;
7838
7921
  collapsedKeys: PrimitiveAtom<TreeCollapseState>;
7839
7922
  constructor(root: RootAtoms, locale: string | null, selectedKeys: Atom<Set<Key>>, viewState?: TreeViewState);
7923
+ view: Atom<TreeView>;
7840
7924
  snapshot: Atom<TreeSnapshot>;
7841
7925
  items: Atom<RootTreeItem[]>;
7842
7926
  children: (id: string) => Atom<Promise<TreeEntryAtoms[]>>;
@@ -7860,7 +7944,7 @@ declare module 'alinea/dashboard/atoms/root' {
7860
7944
  treeEntries: (locale: string | null) => Atom<Promise<TreeEntryAtoms[]>>;
7861
7945
  children: (parentId: string | null) => ExplorerAtoms;
7862
7946
  label: Atom<string>;
7863
- icon: Atom<typeof LucideFile | ComponentType>;
7947
+ icon: Atom<typeof IcOutlineDescription | ComponentType>;
7864
7948
  i18n: Atom<RootI18n | undefined>;
7865
7949
  isMedia: Atom<boolean>;
7866
7950
  canCreate: Atom<boolean>;
@@ -7892,6 +7976,7 @@ declare module 'alinea/dashboard/atoms/upload' {
7892
7976
  workspace: string;
7893
7977
  root: string;
7894
7978
  parentId?: string;
7979
+ parents?: Array<string>;
7895
7980
  }
7896
7981
  export const uploadFilesAtom: import("jotai").WritableAtom<null, [request: UploadFilesRequest], Promise<void>> & {
7897
7982
  init: null;
@@ -7937,7 +8022,7 @@ declare module 'alinea/dashboard/atoms/utils' {
7937
8022
 
7938
8023
  declare module 'alinea/dashboard/boot/ActivityEvent' {
7939
8024
 
7940
- export type ActivityType = 'mutation' | 'fetch' | 'upload';
8025
+ export type ActivityType = 'mutation' | 'upload';
7941
8026
  export type ActivityStatus = 'pending' | 'running' | 'succeeded' | 'failed' | 'blocked' | 'discarded' | 'cancelled';
7942
8027
  export interface Activity {
7943
8028
  id: string;
@@ -8314,6 +8399,12 @@ declare module 'alinea/dashboard/hook/UseRoot' {
8314
8399
 
8315
8400
  }
8316
8401
 
8402
+ declare module 'alinea/dashboard/hook/UseSaveShortcut' {
8403
+
8404
+ export function useSaveShortcut(action: (() => void) | undefined, disabled: boolean): void;
8405
+
8406
+ }
8407
+
8317
8408
  declare module 'alinea/dashboard/hook/UseWorkspace' {
8318
8409
 
8319
8410
  import type { WorkspaceInternal } from 'alinea/core/Workspace';
@@ -8429,7 +8520,7 @@ declare module 'alinea/dashboard/hooks' {
8429
8520
  /**
8430
8521
  * Creates an editor for a nested reactive node.
8431
8522
  */
8432
- export function useNodeEditor(node: EditorNode, type: Type): EntryEditor;
8523
+ export function useNodeEditor(node: EditorNode, type: Type, readOnly?: boolean): EntryEditor;
8433
8524
  /**
8434
8525
  * Returns the reactive node backing a field in the active editor.
8435
8526
  */
@@ -9555,10 +9646,10 @@ declare module 'alinea/field/metadata/MetadataField' {
9555
9646
  updatedAt: number | null;
9556
9647
  updatedBy: MetadataAuditUser;
9557
9648
  }
9558
- export class MetadataField extends RecordField<Metadata, {
9559
- label: string;
9649
+ export interface MetadataOptions extends FieldOptions<Metadata> {
9560
9650
  fields: Type<MetadataFields>;
9561
- }> {
9651
+ }
9652
+ export class MetadataField extends RecordField<Metadata, MetadataOptions> {
9562
9653
  }
9563
9654
  export interface MetadataField extends MetadataFields {
9564
9655
  }
@@ -9767,6 +9858,7 @@ declare module 'alinea/field/richtext/extensions/Link' {
9767
9858
  interface LinkAttributes {
9768
9859
  'data-id'?: string;
9769
9860
  'data-entry'?: string;
9861
+ 'data-locale'?: string;
9770
9862
  'data-anchor'?: string;
9771
9863
  'data-link'?: string;
9772
9864
  'data-suffix'?: string;
@@ -9880,9 +9972,11 @@ declare module 'alinea/field/richtext/ReferenceLink' {
9880
9972
  interface Anchor extends HTMLProps<HTMLAnchorElement> {
9881
9973
  _id?: string;
9882
9974
  _entry?: string;
9975
+ _locale?: string;
9883
9976
  _link?: 'entry' | 'file' | 'image' | 'url';
9884
9977
  'data-id'?: string;
9885
9978
  'data-entry'?: string;
9979
+ 'data-locale'?: string;
9886
9980
  'data-anchor'?: string;
9887
9981
  'data-link'?: 'entry' | 'file' | 'image' | 'url';
9888
9982
  'data-suffix'?: string;
@@ -10586,8 +10680,6 @@ declare module 'alinea/field/time/TimeField' {
10586
10680
  minValue?: string;
10587
10681
  /** A maximum value */
10588
10682
  maxValue?: string;
10589
- /** Specifies the legal time intervals */
10590
- step?: number;
10591
10683
  }
10592
10684
  /** Internal representation of a date field */
10593
10685
  export class TimeField extends ScalarField<string, TimeOptions> {
@@ -10736,11 +10828,13 @@ declare module 'alinea/picker/entry/EntryReference' {
10736
10828
  export interface EntryReference extends Reference {
10737
10829
  _type: 'entry' | 'image' | 'file';
10738
10830
  _entry: string;
10831
+ _locale?: string;
10739
10832
  _anchor?: string;
10740
10833
  _suffix?: string;
10741
10834
  }
10742
10835
  export namespace EntryReference {
10743
10836
  const entry = "_entry";
10837
+ const locale = "_locale";
10744
10838
  const anchor = "_anchor";
10745
10839
  const suffix = "_suffix";
10746
10840
  function isEntryReference(value: any): value is EntryReference;
@@ -11152,7 +11246,6 @@ declare module 'alinea/types' {
11152
11246
  export type { Schema } from 'alinea/core/Schema';
11153
11247
  export type { TextDoc } from 'alinea/core/TextDoc';
11154
11248
  export type { Type } from 'alinea/core/Type';
11155
- export type { MediaUrlMeta, MediaUrlResolver } from 'alinea/core/media/MediaLocation';
11156
11249
  export type { Workspace } from 'alinea/core/Workspace';
11157
11250
  export type { EntryLink } from 'alinea/field/link/EntryLink';
11158
11251
  export type { FileLink } from 'alinea/field/link/FileLink';