tinacms 3.8.3 → 3.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (26) hide show
  1. package/dist/index.d.ts +0 -4
  2. package/dist/index.js +1156 -567
  3. package/dist/internalClient/index.d.ts +30 -8
  4. package/dist/toolkit/components/media/index.d.ts +1 -1
  5. package/dist/toolkit/components/media/media-workflow-overlay.d.ts +2 -0
  6. package/dist/toolkit/components/media/utils.d.ts +8 -0
  7. package/dist/toolkit/core/event.d.ts +15 -1
  8. package/dist/toolkit/core/media-store.default.d.ts +31 -4
  9. package/dist/toolkit/fields/plugins/mdx-field-plugin/plate/components/plate-ui/command.d.ts +8 -8
  10. package/dist/toolkit/fields/plugins/mdx-field-plugin/plate/components/plate-ui/heading-items.d.ts +15 -0
  11. package/dist/toolkit/fields/plugins/mdx-field-plugin/plate/components/plate-ui/input.d.ts +1 -1
  12. package/dist/toolkit/fields/plugins/mdx-field-plugin/plate/plugins/core/autoformat/autoformat-block.d.ts +2 -0
  13. package/dist/toolkit/fields/plugins/mdx-field-plugin/plate/plugins/editor-plugins.d.ts +171 -165
  14. package/dist/toolkit/fields/plugins/mdx-field-plugin/plate/toolbar/toolbar-overrides.d.ts +3 -2
  15. package/dist/toolkit/fields/plugins/mdx-field-plugin/plate/toolbar/toolbar-provider.d.ts +10 -1
  16. package/dist/toolkit/form-builder/create-branch-modal.d.ts +9 -0
  17. package/dist/toolkit/form-builder/editorial-workflow-progress-modal.d.ts +15 -0
  18. package/dist/toolkit/form-builder/editorial-workflow-utils.d.ts +20 -0
  19. package/dist/toolkit/form-builder/use-editorial-workflow.d.ts +2 -0
  20. package/dist/toolkit/git-client/git-client.d.ts +0 -6
  21. package/dist/toolkit/git-client/git-file.d.ts +1 -1
  22. package/dist/toolkit/index.d.ts +2 -1
  23. package/dist/toolkit/plugin-branch-switcher/branch-switcher.d.ts +2 -1
  24. package/dist/toolkit/plugin-branch-switcher/format-branch-name.d.ts +8 -0
  25. package/dist/toolkit/react-core/use-cms-event.d.ts +1 -1
  26. package/package.json +4 -4
@@ -2,16 +2,20 @@ import { BranchData, EventBus } from '@tinacms/toolkit';
2
2
  import { DocumentNode, GraphQLSchema } from 'graphql';
3
3
  import { TokenObject } from '../auth/authenticate';
4
4
  import { AuthProvider, Schema, TinaSchema } from '@tinacms/schema-tools';
5
- import { SearchClient, SearchOptions, SearchQueryResponse, IndexableDocument, FuzzySearchOptions } from '@tinacms/search/index-client';
5
+ import { FuzzySearchOptions, IndexableDocument, SearchClient, SearchOptions, SearchQueryResponse } from '@tinacms/search/index-client';
6
+ import gql from 'graphql-tag';
7
+ import { EditorialWorkflowResult } from '../toolkit/form-builder/editorial-workflow-constants';
8
+ import { TinaCloudProject } from './types';
9
+ export * from './authProvider';
6
10
  interface TinaSearchConfig {
7
11
  stopwordLanguages?: string[];
8
12
  fuzzyEnabled?: boolean;
9
13
  fuzzyOptions?: FuzzySearchOptions;
10
14
  }
11
- import gql from 'graphql-tag';
12
- import { EditorialWorkflowResult } from '../toolkit/form-builder/editorial-workflow-constants';
13
- import { TinaCloudProject } from './types';
14
- export * from './authProvider';
15
+ type EditorialWorkflowStatusUpdate = {
16
+ status: string;
17
+ message?: string;
18
+ };
15
19
  export type OnLoginFunc = (args: {
16
20
  token?: TokenObject;
17
21
  }) => Promise<void>;
@@ -124,11 +128,12 @@ export declare class Client {
124
128
  getIndexStatus({ ref }: {
125
129
  ref: string;
126
130
  }): Promise<{
127
- status?: "unknown" | "complete" | "failed" | "inprogress";
131
+ status?: "complete" | "unknown" | "failed" | "inprogress";
128
132
  timestamp?: number;
129
133
  }>;
130
134
  listBranches(args?: {
131
135
  includeIndexStatus?: boolean;
136
+ signal?: AbortSignal;
132
137
  }): Promise<[{
133
138
  name?: string;
134
139
  protected?: boolean;
@@ -139,7 +144,7 @@ export declare class Client {
139
144
  githubPullRequestUrl?: string;
140
145
  }[]] | {
141
146
  indexStatus: {
142
- status?: "unknown" | "complete" | "failed" | "inprogress";
147
+ status?: "complete" | "unknown" | "failed" | "inprogress";
143
148
  timestamp?: number;
144
149
  };
145
150
  name?: string;
@@ -147,9 +152,14 @@ export declare class Client {
147
152
  githubPullRequestUrl?: string;
148
153
  }[]>;
149
154
  usingProtectedBranch(): boolean;
150
- branchExists(branchName: string): Promise<boolean>;
155
+ branchExists(branchName: string, args?: {
156
+ signal?: AbortSignal;
157
+ }): Promise<boolean>;
151
158
  createBranch({ baseBranch, branchName }: BranchData): Promise<string>;
152
159
  getLatestVersion(): Promise<LatestVersionResponse>;
160
+ private pollEditorialWorkflowStatus;
161
+ private toEditorialWorkflowError;
162
+ private postEditorialWorkflow;
153
163
  /**
154
164
  * Initiate and poll for the results of an editorial workflow operation
155
165
  *
@@ -169,6 +179,18 @@ export declare class Client {
169
179
  message?: string;
170
180
  }) => void;
171
181
  }): Promise<EditorialWorkflowResult>;
182
+ startMediaEditorialWorkflow(options: {
183
+ branchName: string;
184
+ baseBranch: string;
185
+ prTitle?: string;
186
+ operation: 'upload' | 'delete';
187
+ repoPath: string;
188
+ }): Promise<{
189
+ branchName: string;
190
+ requestId: string;
191
+ status?: string;
192
+ }>;
193
+ waitForEditorialWorkflowStatus(requestId: string, onStatusUpdate?: (status: EditorialWorkflowStatusUpdate) => void): Promise<EditorialWorkflowResult>;
172
194
  }
173
195
  export declare const DEFAULT_LOCAL_TINA_GQL_SERVER_URL = "http://localhost:4001/graphql";
174
196
  export declare class LocalClient extends Client {
@@ -3,4 +3,4 @@ export { ListMediaItem, GridMediaItem } from './media-item';
3
3
  export { Breadcrumb } from './breadcrumb';
4
4
  export { CursorPaginator } from './pagination';
5
5
  export type { MediaPaginatorProps } from './pagination';
6
- export { DEFAULT_MEDIA_UPLOAD_TYPES } from './utils';
6
+ export { DEFAULT_MEDIA_UPLOAD_TYPES, sanitizeFilename } from './utils';
@@ -0,0 +1,2 @@
1
+ import * as React from 'react';
2
+ export declare const MediaWorkflowOverlay: () => React.JSX.Element;
@@ -3,3 +3,11 @@ export declare const dropzoneAcceptFromString: (str: string) => any;
3
3
  export declare const isImage: (filename: string) => boolean;
4
4
  export declare const isVideo: (filename: string) => boolean;
5
5
  export declare const absoluteImgURL: (str: string) => string;
6
+ /**
7
+ * Normalizes filenames to NFC and replaces characters that are unsafe for
8
+ * URLs or common filesystems with a hyphen, while preserving the extension.
9
+ *
10
+ * Example: `image-a\u0308.jpg` becomes `image-ä.jpg`,
11
+ * so URLs use `%C3%A4` instead of the decomposed `%CC%88` sequence.
12
+ */
13
+ export declare const sanitizeFilename: (filename: string) => string;
@@ -6,12 +6,26 @@ export interface CMSEvent {
6
6
  export declare class EventBus {
7
7
  private listeners;
8
8
  subscribe<E extends CMSEvent = CMSEvent>(event: E['type'] | E['type'][], callback: Callback<E>): () => void;
9
- dispatch<E extends CMSEvent = CMSEvent>(event: E): void;
9
+ dispatch<E extends CMSEvent = CMSEvent>(event: E): boolean;
10
+ /**
11
+ * Whether any listener *explicitly* targets `eventType`. The catch-all `'*'`
12
+ * pattern does not count — callers use this to detect a purpose-built
13
+ * subscriber (e.g. a mounted UI overlay) without being misled by ambient
14
+ * `'*'` listeners such as the alerts bridge, which would otherwise make
15
+ * {@link dispatch} report every event as "handled".
16
+ */
17
+ hasExplicitListenerFor<E extends CMSEvent = CMSEvent>(eventType: E['type']): boolean;
10
18
  }
11
19
  export declare class Listener<E extends CMSEvent = CMSEvent> {
12
20
  private eventPattern;
13
21
  private callback;
14
22
  constructor(eventPattern: E['type'], callback: Callback<E>);
15
23
  handleEvent(event: E): boolean;
24
+ /**
25
+ * Whether this listener explicitly targets `eventType`. Unlike
26
+ * {@link watchesEvent}, the catch-all `'*'` pattern does NOT match, so this
27
+ * reflects a purpose-built subscription rather than an ambient one.
28
+ */
29
+ isExplicitListenerFor(eventType: E['type']): boolean;
16
30
  watchesEvent(currentEvent: E): boolean;
17
31
  }
@@ -1,4 +1,4 @@
1
- import { CMS } from './cms';
1
+ import type { TinaCMS } from '../tina-cms';
2
2
  import { Media, MediaList, MediaListOptions, MediaStore, MediaUploadOptions } from './media';
3
3
  export declare class DummyMediaStore implements MediaStore {
4
4
  accept: string;
@@ -30,14 +30,16 @@ export declare class TinaMediaStore implements MediaStore {
30
30
  private url;
31
31
  private staticMedia;
32
32
  isStatic?: boolean;
33
- constructor(cms: CMS, staticMedia?: StaticMedia);
33
+ private workflowBranchOverride;
34
+ private mediaWorkflowInProgress;
35
+ constructor(cms: TinaCMS, staticMedia?: StaticMedia);
34
36
  setup(): void;
35
37
  isAuthenticated(): Promise<boolean>;
36
38
  accept: string;
37
39
  maxSize: number;
38
40
  /**
39
- * Returns the current branch as a single-encoded query-param value, or
40
- * an empty string when no branch is set.
41
+ * Returns the workflow branch override or current branch as a single-encoded
42
+ * query-param value, or an empty string when no branch is set.
41
43
  *
42
44
  * `this.api.branch` is already URL-encoded by `Client.setBranch()`, so we
43
45
  * decode then re-encode here to defend against double-encoding when this
@@ -50,7 +52,32 @@ export declare class TinaMediaStore implements MediaStore {
50
52
  * assets-api (which would route the call to a non-existent staging path).
51
53
  */
52
54
  private encodedBranchParam;
55
+ private shortStableHash;
56
+ private trimEdges;
57
+ private branchSlugForMediaPath;
58
+ /** Joins a directory and filename into a normalized `dir/file` repo path. */
59
+ private joinMediaPath;
60
+ private branchQueryParam;
61
+ private requestMediaBranchChoice;
62
+ private prepareMediaBranch;
63
+ private resetWorkflowState;
64
+ private finalizeMediaWorkflow;
65
+ private dispatchMediaWorkflowError;
66
+ private runMediaOpWithWorkflow;
67
+ private prepareProtectedMediaBranch;
68
+ private waitForRequestStatus;
53
69
  private persist_cloud;
70
+ /**
71
+ * Uploads assets through the editorial workflow. The asset is staged, the
72
+ * server-side workflow catalogues it in the new branch's media index, and
73
+ * only then do we list it — while the branch override still routes list
74
+ * calls to the workflow branch, so the freshly uploaded item is returned to
75
+ * the caller (and added to the media manager) without needing a manual
76
+ * refresh.
77
+ */
78
+ private persistCloudViaWorkflow;
79
+ private uploadCloudMediaItem;
80
+ private groupMediaByDirectory;
54
81
  /**
55
82
  * Resolves the just-uploaded items to canonical `Media` entries by hitting
56
83
  * the assets-api `list` endpoint, which is the source of truth for the
@@ -6,7 +6,7 @@ export declare const Command: React.ForwardRefExoticComponent<Omit<Omit<{
6
6
  ref?: React.Ref<HTMLDivElement>;
7
7
  } & {
8
8
  asChild?: boolean;
9
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
9
+ }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>> & {
10
10
  label?: string;
11
11
  shouldFilter?: boolean;
12
12
  filter?: (value: string, search: string, keywords?: string[]) => number;
@@ -22,7 +22,7 @@ export declare const Command: React.ForwardRefExoticComponent<Omit<Omit<{
22
22
  ref?: React.Ref<HTMLDivElement>;
23
23
  } & {
24
24
  asChild?: boolean;
25
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
25
+ }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>> & {
26
26
  label?: string;
27
27
  shouldFilter?: boolean;
28
28
  filter?: (value: string, search: string, keywords?: string[]) => number;
@@ -58,7 +58,7 @@ export declare const InputCommand: React.ForwardRefExoticComponent<Omit<Omit<Omi
58
58
  }, "key" | keyof React.InputHTMLAttributes<HTMLInputElement> | "asChild">, "value" | "type" | "onChange"> & {
59
59
  value?: string;
60
60
  onValueChange?: (search: string) => void;
61
- } & React.RefAttributes<HTMLInputElement>, "h" | "variant"> & import("class-variance-authority").VariantProps<(props?: {
61
+ } & React.RefAttributes<HTMLInputElement>, "variant" | "h"> & import("class-variance-authority").VariantProps<(props?: {
62
62
  h?: "sm" | "md";
63
63
  variant?: "default" | "ghost";
64
64
  } & import("class-variance-authority/types").ClassProp) => string>, "ref"> & React.RefAttributes<HTMLInputElement>>;
@@ -68,7 +68,7 @@ export declare const CommandList: React.ForwardRefExoticComponent<Omit<{
68
68
  ref?: React.Ref<HTMLDivElement>;
69
69
  } & {
70
70
  asChild?: boolean;
71
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
71
+ }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>> & {
72
72
  label?: string;
73
73
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
74
74
  export declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
@@ -77,14 +77,14 @@ export declare const CommandEmpty: React.ForwardRefExoticComponent<Omit<{
77
77
  ref?: React.Ref<HTMLDivElement>;
78
78
  } & {
79
79
  asChild?: boolean;
80
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
80
+ }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>> & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
81
81
  export declare const CommandGroup: React.ForwardRefExoticComponent<Omit<{
82
82
  children?: React.ReactNode;
83
83
  } & Omit<Pick<Pick<React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, "key" | keyof React.HTMLAttributes<HTMLDivElement>> & {
84
84
  ref?: React.Ref<HTMLDivElement>;
85
85
  } & {
86
86
  asChild?: boolean;
87
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "value" | "heading"> & {
87
+ }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>>, "value" | "heading"> & {
88
88
  heading?: React.ReactNode;
89
89
  value?: string;
90
90
  forceMount?: boolean;
@@ -93,7 +93,7 @@ export declare const CommandSeparator: React.ForwardRefExoticComponent<Omit<Pick
93
93
  ref?: React.Ref<HTMLDivElement>;
94
94
  } & {
95
95
  asChild?: boolean;
96
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild"> & {
96
+ }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>> & {
97
97
  alwaysRender?: boolean;
98
98
  } & React.RefAttributes<HTMLDivElement>, "ref"> & React.RefAttributes<HTMLDivElement>>;
99
99
  export declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
@@ -102,7 +102,7 @@ export declare const CommandItem: React.ForwardRefExoticComponent<Omit<{
102
102
  ref?: React.Ref<HTMLDivElement>;
103
103
  } & {
104
104
  asChild?: boolean;
105
- }, "key" | keyof React.HTMLAttributes<HTMLDivElement> | "asChild">, "value" | "disabled" | "onSelect"> & {
105
+ }, "key" | "asChild" | keyof React.HTMLAttributes<HTMLDivElement>>, "value" | "disabled" | "onSelect"> & {
106
106
  disabled?: boolean;
107
107
  onSelect?: (value: string) => void;
108
108
  value?: string;
@@ -0,0 +1,15 @@
1
+ import type { ComponentType, SVGProps } from 'react';
2
+ import { type HeadingLevel } from '@tinacms/schema-tools';
3
+ export type HeadingItemIcon = ComponentType<SVGProps<SVGSVGElement>>;
4
+ export interface HeadingMenuItem {
5
+ description: string;
6
+ icon: HeadingItemIcon;
7
+ label: string;
8
+ value: string;
9
+ }
10
+ export declare const headingItemsByLevel: Record<HeadingLevel, HeadingMenuItem>;
11
+ export declare const paragraphItem: HeadingMenuItem;
12
+ /** Looks up the menu item for any block value. Returns `undefined`
13
+ * for non-heading values so callers can fall back as they see fit
14
+ * (e.g. to `paragraphItem` for the dropdown trigger label). */
15
+ export declare const getHeadingItem: (value: string) => HeadingMenuItem | undefined;
@@ -2,7 +2,7 @@ export declare const inputVariants: (props?: {
2
2
  h?: "sm" | "md";
3
3
  variant?: "default" | "ghost";
4
4
  } & import("class-variance-authority/types").ClassProp) => string;
5
- export declare const Input: import("react").ForwardRefExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & Omit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "h" | "variant"> & import("class-variance-authority").VariantProps<(props?: {
5
+ export declare const Input: import("react").ForwardRefExoticComponent<Omit<Omit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "ref"> & Omit<import("react").DetailedHTMLProps<import("react").InputHTMLAttributes<HTMLInputElement>, HTMLInputElement>, "variant" | "h"> & import("class-variance-authority").VariantProps<(props?: {
6
6
  h?: "sm" | "md";
7
7
  variant?: "default" | "ghost";
8
8
  } & import("class-variance-authority/types").ClassProp) => string>, "ref"> & import("react").RefAttributes<HTMLInputElement>>;
@@ -1,2 +1,4 @@
1
1
  import { AutoformatRule } from '@udecode/plate-autoformat';
2
+ import { type HeadingLevel } from '@tinacms/schema-tools';
3
+ export declare const getAutoformatBlocks: (headingLevels?: readonly HeadingLevel[]) => AutoformatRule[];
2
4
  export declare const autoformatBlocks: AutoformatRule[];