tinacms 1.5.8 → 1.5.10

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.
package/dist/index.js CHANGED
@@ -54,6 +54,152 @@
54
54
  authTab = popupWindow(`${frontendUrl}/signin?clientId=${clientId}&origin=${origin}`, "_blank", window, 1e3, 700);
55
55
  });
56
56
  };
57
+ class StringBuilder {
58
+ constructor(limit) {
59
+ this.length = 0;
60
+ this.buffer = [];
61
+ this.limit = limit;
62
+ }
63
+ append(str) {
64
+ if (this.length + str.length > this.limit) {
65
+ return true;
66
+ } else {
67
+ this.buffer.push(str);
68
+ this.length += str.length;
69
+ if (this.length > this.limit) {
70
+ return true;
71
+ }
72
+ return false;
73
+ }
74
+ }
75
+ toString() {
76
+ return this.buffer.join(" ");
77
+ }
78
+ }
79
+ const extractText = (data, acc, indexableNodeTypes) => {
80
+ var _a, _b;
81
+ if (data) {
82
+ if (indexableNodeTypes.indexOf(data.type) !== -1 && (data.text || data.value)) {
83
+ const tokens = tokenizeString(data.text || data.value);
84
+ for (const token of tokens) {
85
+ if (acc.append(token)) {
86
+ return;
87
+ }
88
+ }
89
+ }
90
+ (_b = (_a = data.children) == null ? void 0 : _a.forEach) == null ? void 0 : _b.call(_a, (child) => extractText(child, acc, indexableNodeTypes));
91
+ }
92
+ };
93
+ const relativePath = (path, collection) => {
94
+ return path.replace(/\\/g, "/").replace(collection.path, "").replace(/^\/|\/$/g, "");
95
+ };
96
+ const tokenizeString = (str) => {
97
+ return str.split(/[\s\.,]+/).map((s) => s.toLowerCase()).filter((s) => s);
98
+ };
99
+ const processTextFieldValue = (value, maxLen) => {
100
+ const tokens = tokenizeString(value);
101
+ const builder = new StringBuilder(maxLen);
102
+ for (const part of tokens) {
103
+ if (builder.append(part)) {
104
+ break;
105
+ }
106
+ }
107
+ return builder.toString();
108
+ };
109
+ const processDocumentForIndexing = (data, path, collection, textIndexLength, field) => {
110
+ if (!field) {
111
+ const relPath = relativePath(path, collection);
112
+ data["_id"] = `${collection.name}:${relPath}`;
113
+ data["_relativePath"] = relPath;
114
+ }
115
+ for (const f of collection.fields || (field == null ? void 0 : field.fields) || []) {
116
+ if (!f.searchable) {
117
+ delete data[f.name];
118
+ continue;
119
+ }
120
+ const isList = f.list;
121
+ if (data[f.name]) {
122
+ if (f.type === "object") {
123
+ if (isList) {
124
+ data[f.name] = data[f.name].map((obj) => processDocumentForIndexing(obj, path, collection, textIndexLength, f));
125
+ } else {
126
+ data[f.name] = processDocumentForIndexing(data[f.name], path, collection, textIndexLength, f);
127
+ }
128
+ } else if (f.type === "string") {
129
+ const fieldTextIndexLength = f.maxSearchIndexFieldLength || textIndexLength;
130
+ if (isList) {
131
+ data[f.name] = data[f.name].map((value) => processTextFieldValue(value, fieldTextIndexLength));
132
+ } else {
133
+ data[f.name] = processTextFieldValue(data[f.name], fieldTextIndexLength);
134
+ }
135
+ } else if (f.type === "rich-text") {
136
+ const fieldTextIndexLength = f.maxSearchIndexFieldLength || textIndexLength;
137
+ if (isList) {
138
+ data[f.name] = data[f.name].map((value) => {
139
+ const acc = new StringBuilder(fieldTextIndexLength);
140
+ extractText(value, acc, ["text", "code_block", "html"]);
141
+ return acc.toString();
142
+ });
143
+ } else {
144
+ const acc = new StringBuilder(fieldTextIndexLength);
145
+ extractText(data[f.name], acc, ["text", "code_block", "html"]);
146
+ data[f.name] = acc.toString();
147
+ }
148
+ }
149
+ }
150
+ }
151
+ return data;
152
+ };
153
+ const queryToSearchIndexQuery = (query) => {
154
+ let q;
155
+ const parts = query.split(" ");
156
+ if (parts.length === 1) {
157
+ q = { AND: [parts[0]] };
158
+ } else {
159
+ q = { AND: parts.filter((part) => part.toLowerCase() !== "and") };
160
+ }
161
+ return q;
162
+ };
163
+ const optionsToSearchIndexOptions = (options) => {
164
+ const opt = {};
165
+ if (options == null ? void 0 : options.limit) {
166
+ opt["PAGE"] = {
167
+ SIZE: options.limit,
168
+ NUMBER: (options == null ? void 0 : options.cursor) ? parseInt(options.cursor) : 0
169
+ };
170
+ }
171
+ return opt;
172
+ };
173
+ const parseSearchIndexResponse = (data, options) => {
174
+ const results = data["RESULT"];
175
+ const total = data["RESULT_LENGTH"];
176
+ if ((options == null ? void 0 : options.cursor) && (options == null ? void 0 : options.limit)) {
177
+ const prevCursor = options.cursor === "0" ? null : (parseInt(options.cursor) - 1).toString();
178
+ const nextCursor = total <= (parseInt(options.cursor) + 1) * options.limit ? null : (parseInt(options.cursor) + 1).toString();
179
+ return {
180
+ results,
181
+ total,
182
+ prevCursor,
183
+ nextCursor
184
+ };
185
+ } else if (!(options == null ? void 0 : options.cursor) && (options == null ? void 0 : options.limit)) {
186
+ const prevCursor = null;
187
+ const nextCursor = total <= options.limit ? null : "1";
188
+ return {
189
+ results,
190
+ total,
191
+ prevCursor,
192
+ nextCursor
193
+ };
194
+ } else {
195
+ return {
196
+ results,
197
+ total,
198
+ prevCursor: null,
199
+ nextCursor: null
200
+ };
201
+ }
202
+ };
57
203
  const captureBranchName = /^refs\/heads\/(.*)/;
58
204
  const parseRefForBranchName = (ref) => {
59
205
  const matches = ref.match(captureBranchName);
@@ -232,6 +378,9 @@ mutation addPendingDocumentMutation(
232
378
  this.contentApiBase = ((_d = this.options.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://content.tinajs.io`;
233
379
  this.contentApiUrl = this.options.customContentApiUrl || `${this.contentApiBase}/${this.tinaGraphQLVersion}/content/${this.options.clientId}/github/${encodedBranch}`;
234
380
  }
381
+ getBranch() {
382
+ return this.branch;
383
+ }
235
384
  async request(query, { variables }) {
236
385
  const token = await this.getToken();
237
386
  const headers = {
@@ -517,6 +666,62 @@ mutation addPendingDocumentMutation(
517
666
  return localStorage.getItem(LOCAL_CLIENT_KEY) === "true";
518
667
  }
519
668
  }
669
+ class TinaCMSSearchClient {
670
+ constructor(client) {
671
+ this.client = client;
672
+ }
673
+ async query(query, options) {
674
+ const q = queryToSearchIndexQuery(query);
675
+ const opt = optionsToSearchIndexOptions(options);
676
+ const optionsParam = opt["PAGE"] ? `&options=${JSON.stringify(opt)}` : "";
677
+ const res = await this.client.fetchWithToken(`${this.client.contentApiBase}/searchIndex/${this.client.clientId}/${this.client.getBranch()}?q=${JSON.stringify(q)}${optionsParam}`);
678
+ return parseSearchIndexResponse(await res.json(), options);
679
+ }
680
+ async del(ids) {
681
+ const res = await this.client.fetchWithToken(`${this.client.contentApiBase}/searchIndex/${this.client.clientId}/${this.client.getBranch()}?ids=${ids.join(",")}`, {
682
+ method: "DELETE"
683
+ });
684
+ if (res.status !== 200) {
685
+ throw new Error("Failed to update search index");
686
+ }
687
+ }
688
+ async put(docs) {
689
+ const res = await this.client.fetchWithToken(`${this.client.contentApiBase}/searchIndex/${this.client.clientId}/${this.client.getBranch()}`, {
690
+ method: "POST",
691
+ body: JSON.stringify({ docs }),
692
+ headers: {
693
+ "Content-Type": "application/json"
694
+ }
695
+ });
696
+ if (res.status !== 200) {
697
+ throw new Error("Failed to update search index");
698
+ }
699
+ }
700
+ supportsClientSideIndexing() {
701
+ return true;
702
+ }
703
+ }
704
+ class LocalSearchClient {
705
+ constructor(client) {
706
+ this.client = client;
707
+ }
708
+ async query(query, options) {
709
+ const q = queryToSearchIndexQuery(query);
710
+ const opt = optionsToSearchIndexOptions(options);
711
+ const optionsParam = opt["PAGE"] ? `&options=${JSON.stringify(opt)}` : "";
712
+ const res = await this.client.fetchWithToken(`http://localhost:4001/searchIndex?q=${JSON.stringify(q)}${optionsParam}`);
713
+ return parseSearchIndexResponse(await res.json(), options);
714
+ }
715
+ del(ids) {
716
+ return Promise.resolve(void 0);
717
+ }
718
+ put(docs) {
719
+ return Promise.resolve(void 0);
720
+ }
721
+ supportsClientSideIndexing() {
722
+ return false;
723
+ }
724
+ }
520
725
  function ModalBuilder(modalProps) {
521
726
  return /* @__PURE__ */ React__default["default"].createElement(toolkit.Modal, null, /* @__PURE__ */ React__default["default"].createElement(toolkit.ModalPopup, null, /* @__PURE__ */ React__default["default"].createElement(toolkit.ModalHeader, null, modalProps.title), /* @__PURE__ */ React__default["default"].createElement(toolkit.ModalBody, {
522
727
  padded: true
@@ -601,8 +806,14 @@ mutation addPendingDocumentMutation(
601
806
  }
602
807
  class TinaAdminApi {
603
808
  constructor(cms) {
809
+ var _a, _b, _c, _d;
810
+ this.maxSearchIndexFieldLength = 100;
604
811
  this.api = cms.api.tina;
605
812
  this.schema = cms.api.tina.schema;
813
+ if (cms.api.search && ((_a = cms.api.search) == null ? void 0 : _a.supportsClientSideIndexing())) {
814
+ this.searchClient = cms.api.searchClient;
815
+ this.maxSearchIndexFieldLength = ((_d = (_c = (_b = this.schema.config) == null ? void 0 : _b.config) == null ? void 0 : _c.search) == null ? void 0 : _d.maxSearchIndexFieldLength) || 100;
816
+ }
606
817
  }
607
818
  async isAuthenticated() {
608
819
  return await this.api.isAuthenticated();
@@ -621,25 +832,33 @@ mutation addPendingDocumentMutation(
621
832
  fetchCollections() {
622
833
  return this.schema.getCollections();
623
834
  }
624
- async renameDocument({ collection, relativePath, newRelativePath }) {
835
+ async renameDocument({ collection, relativePath: relativePath2, newRelativePath }) {
625
836
  await this.api.request(`#graphql
626
837
  mutation RenameDocument($collection: String!, $relativePath: String! $newRelativePath: String!) {
627
838
  updateDocument(collection: $collection, relativePath: $relativePath, params: {relativePath: $newRelativePath}){
628
839
  __typename
629
840
  }
630
841
  }
631
- `, { variables: { collection, relativePath, newRelativePath } });
842
+ `, { variables: { collection, relativePath: relativePath2, newRelativePath } });
843
+ if (this.searchClient) {
844
+ const { document: doc } = await this.fetchDocument(collection.name, newRelativePath);
845
+ const processed = processDocumentForIndexing(doc["_values"], `${collection.path}/${newRelativePath}`, collection, this.maxSearchIndexFieldLength);
846
+ await this.searchClient.put([processed]);
847
+ await this.searchClient.del([`${collection.name}:${relativePath2}`]);
848
+ }
632
849
  }
633
850
  async deleteDocument({
634
851
  collection,
635
- relativePath
852
+ relativePath: relativePath2
636
853
  }) {
854
+ var _a;
637
855
  await this.api.request(`#graphql
638
856
  mutation DeleteDocument($collection: String!, $relativePath: String! ){
639
857
  deleteDocument(collection: $collection, relativePath: $relativePath){
640
858
  __typename
641
859
  }
642
- }`, { variables: { collection, relativePath } });
860
+ }`, { variables: { collection, relativePath: relativePath2 } });
861
+ await ((_a = this.searchClient) == null ? void 0 : _a.del([`${collection}:${relativePath2}`]));
643
862
  }
644
863
  async fetchCollection(collectionName, includeDocuments, folder = "", after, sortKey, order, filterArgs) {
645
864
  let filter = null;
@@ -785,18 +1004,43 @@ mutation addPendingDocumentMutation(
785
1004
  }
786
1005
  }
787
1006
  }
788
- async fetchDocument(collectionName, relativePath) {
789
- const response = await this.api.request(`#graphql
790
- query($collection: String!, $relativePath: String!) {
791
- document(collection:$collection, relativePath:$relativePath) {
792
- ... on Document {
793
- _values
1007
+ async fetchDocument(collectionName, relativePath2, values = true) {
1008
+ let query;
1009
+ if (values) {
1010
+ query = `#graphql
1011
+ query($collection: String!, $relativePath: String!) {
1012
+ document(collection:$collection, relativePath:$relativePath) {
1013
+ ... on Document {
1014
+ _values
1015
+ }
794
1016
  }
795
- }
796
- }`, { variables: { collection: collectionName, relativePath } });
1017
+ }`;
1018
+ } else {
1019
+ query = `#graphql
1020
+ query($collection: String!, $relativePath: String!) {
1021
+ document(collection:$collection, relativePath:$relativePath) {
1022
+ __typename
1023
+ ... on Document {
1024
+ _sys {
1025
+ title
1026
+ template
1027
+ breadcrumbs
1028
+ path
1029
+ basename
1030
+ relativePath
1031
+ filename
1032
+ extension
1033
+ }
1034
+ }
1035
+ }
1036
+ }`;
1037
+ }
1038
+ const response = await this.api.request(query, {
1039
+ variables: { collection: collectionName, relativePath: relativePath2 }
1040
+ });
797
1041
  return response;
798
1042
  }
799
- async createDocument(collectionName, relativePath, params) {
1043
+ async createDocument(collection, relativePath2, params) {
800
1044
  const response = await this.api.request(`#graphql
801
1045
  mutation($collection: String!, $relativePath: String!, $params: DocumentMutation!) {
802
1046
  createDocument(
@@ -806,14 +1050,19 @@ mutation addPendingDocumentMutation(
806
1050
  ){__typename}
807
1051
  }`, {
808
1052
  variables: {
809
- collection: collectionName,
810
- relativePath,
1053
+ collection: collection.name,
1054
+ relativePath: relativePath2,
811
1055
  params
812
1056
  }
813
1057
  });
1058
+ if (this.searchClient) {
1059
+ const { document: doc } = await this.fetchDocument(collection.name, relativePath2);
1060
+ const processed = processDocumentForIndexing(doc["_values"], `${collection.path}/${relativePath2}`, collection, this.maxSearchIndexFieldLength);
1061
+ await this.searchClient.put([processed]);
1062
+ }
814
1063
  return response;
815
1064
  }
816
- async updateDocument(collectionName, relativePath, params) {
1065
+ async updateDocument(collection, relativePath2, params) {
817
1066
  const response = await this.api.request(`#graphql
818
1067
  mutation($collection: String!, $relativePath: String!, $params: DocumentUpdateMutation!) {
819
1068
  updateDocument(
@@ -823,11 +1072,16 @@ mutation addPendingDocumentMutation(
823
1072
  ){__typename}
824
1073
  }`, {
825
1074
  variables: {
826
- collection: collectionName,
827
- relativePath,
1075
+ collection: collection.name,
1076
+ relativePath: relativePath2,
828
1077
  params
829
1078
  }
830
1079
  });
1080
+ if (this.searchClient) {
1081
+ const { document: doc } = await this.fetchDocument(collection.name, relativePath2);
1082
+ const processed = processDocumentForIndexing(doc["_values"], `${collection.path}/${relativePath2}`, collection, this.maxSearchIndexFieldLength);
1083
+ await this.searchClient.put([processed]);
1084
+ }
831
1085
  return response;
832
1086
  }
833
1087
  }
@@ -913,6 +1167,23 @@ mutation addPendingDocumentMutation(
913
1167
  } else {
914
1168
  cms.api.tina.setBranch(currentBranch);
915
1169
  }
1170
+ React.useEffect(() => {
1171
+ var _a, _b, _c, _d;
1172
+ let searchClient;
1173
+ if (props.isLocalClient) {
1174
+ searchClient = new LocalSearchClient(cms.api.tina);
1175
+ } else {
1176
+ const hasTinaSearch = Boolean((_b = (_a = props.schema.config) == null ? void 0 : _a.search) == null ? void 0 : _b.tina);
1177
+ if (hasTinaSearch) {
1178
+ searchClient = new TinaCMSSearchClient(cms.api.tina);
1179
+ } else {
1180
+ searchClient = (_d = (_c = props.schema.config) == null ? void 0 : _c.search) == null ? void 0 : _d.searchClient;
1181
+ }
1182
+ }
1183
+ if (searchClient) {
1184
+ cms.registerApi("search", searchClient);
1185
+ }
1186
+ }, [props]);
916
1187
  if (!cms.api.admin) {
917
1188
  cms.registerApi("admin", new TinaAdminApi(cms));
918
1189
  }
@@ -1479,6 +1750,9 @@ mutation addPendingDocumentMutation(
1479
1750
  .tina-tailwind .w-full {
1480
1751
  width: 100%;
1481
1752
  }
1753
+ .tina-tailwind .min-w-\\[200px\\] {
1754
+ min-width: 200px;
1755
+ }
1482
1756
  .tina-tailwind .max-w-0 {
1483
1757
  max-width: 0rem;
1484
1758
  }
@@ -2146,16 +2420,16 @@ mutation addPendingDocumentMutation(
2146
2420
  this.onChange = options.onChange;
2147
2421
  this.initialValues = options.initialValues;
2148
2422
  }
2149
- async onSubmit({ collection, template, relativePath }, cms) {
2423
+ async onSubmit({ collection, template, relativePath: relativePath2 }, cms) {
2150
2424
  try {
2151
2425
  const selectedCollection = this.collections.find((collectionItem) => collectionItem.slug === collection);
2152
2426
  const collectionFormat = selectedCollection.format;
2153
2427
  const extensionLength = -1 * (collectionFormat.length + 1);
2154
- let relativePathWithExt = relativePath;
2155
- if (relativePath.slice(extensionLength).toLocaleLowerCase() === `.${collectionFormat}`) {
2156
- relativePathWithExt = `${relativePath.slice(0, -3)}.${collectionFormat}`;
2428
+ let relativePathWithExt = relativePath2;
2429
+ if (relativePath2.slice(extensionLength).toLocaleLowerCase() === `.${collectionFormat}`) {
2430
+ relativePathWithExt = `${relativePath2.slice(0, -3)}.${collectionFormat}`;
2157
2431
  } else {
2158
- relativePathWithExt = `${relativePath}.${collectionFormat}`;
2432
+ relativePathWithExt = `${relativePath2}.${collectionFormat}`;
2159
2433
  }
2160
2434
  const payload = {
2161
2435
  relativePath: relativePathWithExt,
@@ -3173,6 +3447,75 @@ This will work when developing locally but NOT when deployed to production.
3173
3447
  const reFetchCollection = () => setResetSate((x) => x + 1);
3174
3448
  return { collection, loading, error, reFetchCollection, collectionExtra };
3175
3449
  };
3450
+ const useSearchCollection = (cms, collectionName, includeDocuments = true, folder, after = "", search) => {
3451
+ const api = new TinaAdminApi(cms);
3452
+ const schema = cms.api.tina.schema;
3453
+ const collectionExtra = schema.getCollection(collectionName);
3454
+ const [collection, setCollection] = React.useState(void 0);
3455
+ const [loading, setLoading] = React.useState(true);
3456
+ const [error, setError] = React.useState(void 0);
3457
+ const [resetState, setResetSate] = React.useState(0);
3458
+ React.useEffect(() => {
3459
+ let cancelled = false;
3460
+ const searchCollection = async () => {
3461
+ if (await api.isAuthenticated() && !folder.loading && !cancelled) {
3462
+ try {
3463
+ const response = await cms.api.search.query(`${search} AND _collection:${collectionName}`, {
3464
+ limit: 15,
3465
+ cursor: after
3466
+ });
3467
+ const docs = await Promise.allSettled(response.results.map((result) => {
3468
+ const [collection2, relativePath2] = result._id.split(":");
3469
+ return api.fetchDocument(collection2, relativePath2, false);
3470
+ }));
3471
+ const edges = docs.filter((p) => {
3472
+ var _a;
3473
+ return p.status === "fulfilled" && !!((_a = p.value) == null ? void 0 : _a.document);
3474
+ }).map((result) => ({ node: result.value.document }));
3475
+ const c = await api.fetchCollection(collectionName, false, "");
3476
+ setCollection({
3477
+ format: collection.format,
3478
+ label: collection.label,
3479
+ name: collectionName,
3480
+ templates: collection.templates,
3481
+ documents: {
3482
+ pageInfo: {
3483
+ hasNextPage: !!response.nextCursor,
3484
+ hasPreviousPage: !!response.prevCursor,
3485
+ startCursor: "",
3486
+ endCursor: response.nextCursor || ""
3487
+ },
3488
+ edges
3489
+ }
3490
+ });
3491
+ } catch (error2) {
3492
+ cms.alerts.error(`[${error2.name}] GetCollection failed: ${error2.message}`);
3493
+ console.error(error2);
3494
+ setCollection(void 0);
3495
+ setError(error2);
3496
+ }
3497
+ setLoading(false);
3498
+ }
3499
+ };
3500
+ if (cancelled)
3501
+ return;
3502
+ setLoading(true);
3503
+ searchCollection();
3504
+ return () => {
3505
+ cancelled = true;
3506
+ };
3507
+ }, [
3508
+ cms,
3509
+ collectionName,
3510
+ folder.loading,
3511
+ folder.fullyQualifiedName,
3512
+ resetState,
3513
+ after,
3514
+ search
3515
+ ]);
3516
+ const reFetchCollection = () => setResetSate((x) => x + 1);
3517
+ return { collection, loading, error, reFetchCollection, collectionExtra };
3518
+ };
3176
3519
  const GetCollection = ({
3177
3520
  cms,
3178
3521
  collectionName,
@@ -3181,10 +3524,11 @@ This will work when developing locally but NOT when deployed to production.
3181
3524
  startCursor,
3182
3525
  sortKey,
3183
3526
  children,
3184
- filterArgs
3527
+ filterArgs,
3528
+ search
3185
3529
  }) => {
3186
3530
  const navigate = reactRouterDom.useNavigate();
3187
- const { collection, loading, error, reFetchCollection, collectionExtra } = useGetCollection(cms, collectionName, includeDocuments, folder, startCursor || "", sortKey, filterArgs) || {};
3531
+ const { collection, loading, error, reFetchCollection, collectionExtra } = search ? useSearchCollection(cms, collectionName, includeDocuments, folder, startCursor || "", search) : useGetCollection(cms, collectionName, includeDocuments, folder, startCursor || "", sortKey, filterArgs) || {};
3188
3532
  React.useEffect(() => {
3189
3533
  var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
3190
3534
  if (loading)
@@ -3192,9 +3536,10 @@ This will work when developing locally but NOT when deployed to production.
3192
3536
  const collectionDefinition = cms.api.tina.schema.getCollection(collection.name);
3193
3537
  const allowCreate = (_c = (_b = (_a = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _a.allowedActions) == null ? void 0 : _b.create) != null ? _c : true;
3194
3538
  const allowDelete = (_f = (_e = (_d = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _d.allowedActions) == null ? void 0 : _e.delete) != null ? _f : true;
3195
- if (!allowCreate && !allowDelete && ((_h = (_g = collection.documents) == null ? void 0 : _g.edges) == null ? void 0 : _h.length) === 1 && ((_k = (_j = (_i = collection.documents) == null ? void 0 : _i.edges[0]) == null ? void 0 : _j.node) == null ? void 0 : _k.__typename) !== "Folder") {
3196
- const doc = collection.documents.edges[0].node;
3197
- handleNavigate(navigate, cms, collection, collectionDefinition, doc);
3539
+ const collectionResponse = collection;
3540
+ if (!allowCreate && !allowDelete && ((_h = (_g = collectionResponse.documents) == null ? void 0 : _g.edges) == null ? void 0 : _h.length) === 1 && ((_k = (_j = (_i = collectionResponse.documents) == null ? void 0 : _i.edges[0]) == null ? void 0 : _j.node) == null ? void 0 : _k.__typename) !== "Folder") {
3541
+ const doc = collectionResponse.documents.edges[0].node;
3542
+ handleNavigate(navigate, cms, collectionResponse, collectionDefinition, doc);
3198
3543
  }
3199
3544
  }, [(collection == null ? void 0 : collection.name) || "", loading]);
3200
3545
  if (error) {
@@ -3323,13 +3668,14 @@ This will work when developing locally but NOT when deployed to production.
3323
3668
  after: "",
3324
3669
  booleanEquals: null
3325
3670
  });
3326
- const [activeSearch, setActiveSearch] = React__default["default"].useState(false);
3327
3671
  const [endCursor, setEndCursor] = React.useState("");
3328
3672
  const [prevCursors, setPrevCursors] = React.useState([]);
3329
3673
  const [sortKey, setSortKey] = React.useState(isSSR ? "" : window.localStorage.getItem(`${LOCAL_STORAGE_KEY}.${collectionName}`) || JSON.stringify({
3330
3674
  order: "asc",
3331
3675
  name: ""
3332
3676
  }));
3677
+ const [search, setSearch] = React.useState("");
3678
+ const [searchInput, setSearchInput] = React.useState("");
3333
3679
  const { order = "asc", name: sortName } = JSON.parse(sortKey || "{}");
3334
3680
  const [sortOrder, setSortOrder] = React.useState(order);
3335
3681
  const loc = reactRouterDom.useLocation();
@@ -3374,25 +3720,20 @@ This will work when developing locally but NOT when deployed to production.
3374
3720
  before: "",
3375
3721
  after: "",
3376
3722
  booleanEquals: null
3377
- }
3723
+ },
3724
+ search
3378
3725
  }, (collection, _loading, reFetchCollection, collectionExtra) => {
3379
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
3726
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l;
3380
3727
  collection.documents.totalCount;
3381
3728
  const documents = collection.documents.edges;
3382
3729
  const admin = cms.api.admin;
3383
3730
  const pageInfo = collection.documents.pageInfo;
3384
3731
  const fields = (_a = collectionExtra.fields) == null ? void 0 : _a.filter((x) => ["string", "number", "datetime", "boolean"].includes(x.type));
3385
3732
  const sortField = fields == null ? void 0 : fields.find((field) => field.name === sortName);
3386
- const filterFields = (_b = collectionExtra.fields) == null ? void 0 : _b.filter((x) => {
3387
- return ["string", "datetime", "boolean"].includes(x.type) && !x.list;
3388
- });
3389
- const filterField = filterFields == null ? void 0 : filterFields.find((x) => x.name === vars.filterField);
3390
- const showStartsWith = (filterField == null ? void 0 : filterField.type) === "string" && !filterField.list;
3391
- const showDateFilter = (filterField == null ? void 0 : filterField.type) === "datetime";
3392
- const showBooleanToggle = (filterField == null ? void 0 : filterField.type) === "boolean" && !filterField.list;
3733
+ const searchEnabled = !!((_d = (_c = (_b = cms.api.tina.schema) == null ? void 0 : _b.config) == null ? void 0 : _c.config) == null ? void 0 : _d.search);
3393
3734
  const collectionDefinition = cms.api.tina.schema.getCollection(collection.name);
3394
- const allowCreate = (_e = (_d = (_c = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _c.allowedActions) == null ? void 0 : _d.create) != null ? _e : true;
3395
- const allowDelete = (_h = (_g = (_f = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _f.allowedActions) == null ? void 0 : _g.delete) != null ? _h : true;
3735
+ const allowCreate = (_g = (_f = (_e = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _e.allowedActions) == null ? void 0 : _f.create) != null ? _g : true;
3736
+ const allowDelete = (_j = (_i = (_h = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _h.allowedActions) == null ? void 0 : _i.delete) != null ? _j : true;
3396
3737
  const folderView = folder.fullyQualifiedName !== "";
3397
3738
  return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, deleteModalOpen && /* @__PURE__ */ React__default["default"].createElement(DeleteModal, {
3398
3739
  filename: vars.relativePath,
@@ -3434,7 +3775,7 @@ This will work when developing locally but NOT when deployed to production.
3434
3775
  },
3435
3776
  close: () => setRenameModalOpen(false)
3436
3777
  }), /* @__PURE__ */ React__default["default"].createElement(PageHeader, {
3437
- isLocalMode: (_j = (_i = cms == null ? void 0 : cms.api) == null ? void 0 : _i.tina) == null ? void 0 : _j.isLocalMode
3778
+ isLocalMode: (_l = (_k = cms == null ? void 0 : cms.api) == null ? void 0 : _k.tina) == null ? void 0 : _l.isLocalMode
3438
3779
  }, /* @__PURE__ */ React__default["default"].createElement("div", {
3439
3780
  className: "w-full grid grid-flow-col items-end gap-4"
3440
3781
  }, /* @__PURE__ */ React__default["default"].createElement("div", {
@@ -3442,8 +3783,8 @@ This will work when developing locally but NOT when deployed to production.
3442
3783
  }, /* @__PURE__ */ React__default["default"].createElement("h3", {
3443
3784
  className: "font-sans text-2xl text-gray-700"
3444
3785
  }, collection.label ? collection.label : collection.name), /* @__PURE__ */ React__default["default"].createElement("div", {
3445
- className: "flex gap-4 items-end flex-wrap"
3446
- }, (fields == null ? void 0 : fields.length) > 0 && /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, /* @__PURE__ */ React__default["default"].createElement("div", {
3786
+ className: "flex gap-4 items-start flex-wrap"
3787
+ }, (fields == null ? void 0 : fields.length) > 0 && /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, !search && /* @__PURE__ */ React__default["default"].createElement("div", {
3447
3788
  className: "flex flex-col gap-2 items-start"
3448
3789
  }, /* @__PURE__ */ React__default["default"].createElement("label", {
3449
3790
  htmlFor: "sort",
@@ -3488,152 +3829,22 @@ This will work when developing locally but NOT when deployed to production.
3488
3829
  setSortOrder(val.order);
3489
3830
  }
3490
3831
  }
3491
- })), /* @__PURE__ */ React__default["default"].createElement("form", {
3492
- className: "flex flex-wrap gap-4 items-end"
3493
- }, /* @__PURE__ */ React__default["default"].createElement("div", {
3494
- className: "flex flex-shrink-0 flex-col gap-2 items-start"
3495
- }, /* @__PURE__ */ React__default["default"].createElement("label", {
3496
- htmlFor: "filter",
3497
- className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
3498
- }, "Filter by"), /* @__PURE__ */ React__default["default"].createElement(toolkit.Select, {
3499
- name: "filter",
3500
- options: [
3501
- {
3502
- label: "None",
3503
- value: ""
3504
- },
3505
- ...filterFields.map((x) => ({
3506
- label: typeof x.label === "string" && x.label || x.name,
3507
- value: x.name
3508
- }))
3509
- ],
3510
- input: {
3511
- id: "filter",
3512
- name: "filter",
3513
- value: vars.filterField,
3514
- onChange: (e) => {
3515
- const val = e.target.value;
3516
- setEndCursor("");
3517
- setPrevCursors([]);
3518
- setVars((old) => ({
3519
- ...old,
3520
- filterField: val
3521
- }));
3522
- if (!val) {
3523
- reFetchCollection();
3524
- }
3525
- }
3526
- }
3527
- })), showStartsWith && /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, /* @__PURE__ */ React__default["default"].createElement("div", {
3528
- className: "flex flex-shrink-0 flex-col gap-2 items-start"
3529
- }, /* @__PURE__ */ React__default["default"].createElement("label", {
3530
- htmlFor: "startsWith",
3531
- className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
3532
- }, "Starts with"), /* @__PURE__ */ React__default["default"].createElement(toolkit.Input, {
3533
- name: "startsWith",
3534
- id: "startsWith",
3535
- value: vars.startsWith,
3536
- onChange: (e) => {
3537
- const val = e.target.value;
3538
- setVars((old) => ({
3539
- ...old,
3540
- startsWith: val,
3541
- after: "",
3542
- before: "",
3543
- booleanEquals: null
3544
- }));
3545
- }
3546
- }))), showDateFilter && /* @__PURE__ */ React__default["default"].createElement("div", {
3547
- className: "flex flex-shrink-0 gap-4"
3548
- }, /* @__PURE__ */ React__default["default"].createElement("div", {
3549
- className: "flex flex-col gap-2 items-start"
3550
- }, /* @__PURE__ */ React__default["default"].createElement("label", {
3551
- htmlFor: "dateAfter",
3552
- className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
3553
- }, "After"), /* @__PURE__ */ React__default["default"].createElement(toolkit.ReactDateTimeWithStyles, {
3554
- inputProps: {
3555
- className: toolkit.textFieldClasses
3556
- },
3557
- value: vars.after,
3558
- onChange: (e) => {
3559
- setVars((old) => ({
3560
- ...old,
3561
- after: typeof e.format === "function" ? e.format() : "",
3562
- booleanEquals: null,
3563
- startsWith: ""
3564
- }));
3565
- }
3566
3832
  })), /* @__PURE__ */ React__default["default"].createElement("div", {
3567
- className: "flex flex-col gap-2 items-start"
3568
- }, /* @__PURE__ */ React__default["default"].createElement("label", {
3569
- htmlFor: "dateBefore",
3570
- className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
3571
- }, "Before"), /* @__PURE__ */ React__default["default"].createElement(toolkit.ReactDateTimeWithStyles, {
3572
- inputProps: {
3573
- className: toolkit.textFieldClasses
3574
- },
3575
- value: vars.before,
3576
- onChange: (e) => {
3577
- setVars((old) => ({
3578
- ...old,
3579
- before: typeof e.format === "function" ? e.format() : "",
3580
- booleanEquals: null,
3581
- startsWith: ""
3582
- }));
3583
- }
3584
- }))), showBooleanToggle && /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, /* @__PURE__ */ React__default["default"].createElement("div", {
3585
- className: "flex flex-col gap-2 items-start"
3586
- }, /* @__PURE__ */ React__default["default"].createElement("label", {
3587
- htmlFor: "toggle",
3833
+ className: "flex flex-1 flex-col gap-2 items-start w-full"
3834
+ }, searchEnabled ? /* @__PURE__ */ React__default["default"].createElement(SearchInput, {
3835
+ loading: _loading,
3836
+ search,
3837
+ setSearch,
3838
+ searchInput,
3839
+ setSearchInput
3840
+ }) : /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, /* @__PURE__ */ React__default["default"].createElement("label", {
3588
3841
  className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
3589
- }, filterField.label || filterField.name), /* @__PURE__ */ React__default["default"].createElement(toolkit.Toggle, {
3590
- field: filterField,
3591
- input: {
3592
- name: "toggle",
3593
- value: (_k = vars.booleanEquals) != null ? _k : false,
3594
- onChange: () => {
3595
- setVars((old) => ({
3596
- ...old,
3597
- booleanEquals: !old.booleanEquals,
3598
- after: "",
3599
- before: "",
3600
- startsWith: ""
3601
- }));
3602
- }
3603
- },
3604
- name: "toggle"
3605
- }))), (showStartsWith || showDateFilter || showBooleanToggle) && /* @__PURE__ */ React__default["default"].createElement("div", {
3606
- className: "flex gap-3"
3607
- }, /* @__PURE__ */ React__default["default"].createElement(toolkit.Button, {
3608
- onClick: () => {
3609
- setActiveSearch(true);
3610
- setEndCursor("");
3611
- setPrevCursors([]);
3612
- reFetchCollection();
3613
- },
3614
- variant: "primary",
3615
- type: "submit"
3616
- }, "Search", " ", /* @__PURE__ */ React__default["default"].createElement(BiSearch, {
3617
- className: "w-5 h-full ml-1.5 opacity-70"
3618
- })), (vars.startsWith || vars.after || vars.before || vars.booleanEquals) && /* @__PURE__ */ React__default["default"].createElement(toolkit.Button, {
3619
- onClick: () => {
3620
- setActiveSearch(false);
3621
- setVars((old) => ({
3622
- ...old,
3623
- filterField: "",
3624
- startsWith: "",
3625
- after: "",
3626
- before: "",
3627
- booleanEquals: null
3628
- }));
3629
- setEndCursor("");
3630
- setPrevCursors([]);
3631
- reFetchCollection();
3632
- },
3633
- variant: "white"
3634
- }, "Clear", " ", /* @__PURE__ */ React__default["default"].createElement(BiX, {
3635
- className: "w-5 h-full ml-1 opacity-70"
3636
- }))))))), /* @__PURE__ */ React__default["default"].createElement("div", {
3842
+ }, "Search"), /* @__PURE__ */ React__default["default"].createElement(toolkit.Message, {
3843
+ link: "https://tina.io/docs/reference/search/overview",
3844
+ linkLabel: "Read The Docs",
3845
+ type: "info",
3846
+ size: "small"
3847
+ }, "Search not configured.")))))), /* @__PURE__ */ React__default["default"].createElement("div", {
3637
3848
  className: "flex self-end justify-self-end"
3638
3849
  }, !collection.templates && allowCreate && /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Link, {
3639
3850
  to: `/${folder.fullyQualifiedName ? [
@@ -3658,7 +3869,7 @@ This will work when developing locally but NOT when deployed to production.
3658
3869
  className: "table-auto shadow bg-white border-b border-gray-200 w-full max-w-full rounded-lg"
3659
3870
  }, /* @__PURE__ */ React__default["default"].createElement("tbody", {
3660
3871
  className: "divide-y divide-gray-150"
3661
- }, !activeSearch && folder.name && /* @__PURE__ */ React__default["default"].createElement("tr", null, /* @__PURE__ */ React__default["default"].createElement("td", {
3872
+ }, folder.name && !search && /* @__PURE__ */ React__default["default"].createElement("tr", null, /* @__PURE__ */ React__default["default"].createElement("td", {
3662
3873
  colSpan: 5
3663
3874
  }, /* @__PURE__ */ React__default["default"].createElement(Breadcrumb, {
3664
3875
  folder,
@@ -3849,6 +4060,59 @@ This will work when developing locally but NOT when deployed to production.
3849
4060
  }));
3850
4061
  });
3851
4062
  };
4063
+ const SearchInput = ({
4064
+ loading,
4065
+ search,
4066
+ setSearch,
4067
+ searchInput,
4068
+ setSearchInput
4069
+ }) => {
4070
+ const [searchLoaded, setSearchLoaded] = React.useState(false);
4071
+ React.useEffect(() => {
4072
+ if (loading) {
4073
+ setSearchLoaded(false);
4074
+ } else {
4075
+ setSearchLoaded(true);
4076
+ }
4077
+ }, [loading]);
4078
+ return /* @__PURE__ */ React__default["default"].createElement("form", {
4079
+ className: "flex flex-1 flex-col gap-2 items-start w-full"
4080
+ }, /* @__PURE__ */ React__default["default"].createElement("label", {
4081
+ htmlFor: "search",
4082
+ className: "block font-sans text-xs font-semibold text-gray-500 whitespace-normal"
4083
+ }, "Search"), /* @__PURE__ */ React__default["default"].createElement("div", {
4084
+ className: "flex flex-wrap items-center gap-3"
4085
+ }, /* @__PURE__ */ React__default["default"].createElement("div", {
4086
+ className: "flex-1 min-w-[200px]"
4087
+ }, /* @__PURE__ */ React__default["default"].createElement(toolkit.Input, {
4088
+ type: "text",
4089
+ name: "search",
4090
+ placeholder: "Search",
4091
+ value: searchInput,
4092
+ onChange: (e) => {
4093
+ setSearchInput(e.target.value);
4094
+ }
4095
+ })), /* @__PURE__ */ React__default["default"].createElement("div", {
4096
+ className: "flex gap-3"
4097
+ }, /* @__PURE__ */ React__default["default"].createElement(toolkit.Button, {
4098
+ onClick: () => {
4099
+ setSearch(searchInput);
4100
+ setSearchLoaded(false);
4101
+ },
4102
+ variant: "primary",
4103
+ type: "submit"
4104
+ }, "Search ", /* @__PURE__ */ React__default["default"].createElement(BiSearch, {
4105
+ className: "w-5 h-full ml-1.5 opacity-70"
4106
+ })), search && searchLoaded && /* @__PURE__ */ React__default["default"].createElement(toolkit.Button, {
4107
+ onClick: () => {
4108
+ setSearch("");
4109
+ setSearchInput("");
4110
+ },
4111
+ variant: "white"
4112
+ }, "Clear ", /* @__PURE__ */ React__default["default"].createElement(BiX, {
4113
+ className: "w-5 h-full ml-1 opacity-70"
4114
+ })))));
4115
+ };
3852
4116
  const Breadcrumb = ({ folder, navigate, collectionName }) => {
3853
4117
  const folderArray = folder.name.split("/");
3854
4118
  return /* @__PURE__ */ React__default["default"].createElement("div", {
@@ -3959,14 +4223,14 @@ This will work when developing locally but NOT when deployed to production.
3959
4223
  const createDocument = async (cms, collection, template, mutationInfo, folder, values) => {
3960
4224
  const api = new TinaAdminApi(cms);
3961
4225
  const { filename, ...leftover } = values;
3962
- const relativePath = `${folder ? `${folder}/` : ""}${filename}.${collection.format}`;
4226
+ const relativePath2 = `${folder ? `${folder}/` : ""}${filename}.${collection.format}`;
3963
4227
  const params = api.schema.transformPayload(collection.name, {
3964
4228
  _collection: collection.name,
3965
4229
  ...template && { _template: template.name },
3966
4230
  ...leftover
3967
4231
  });
3968
4232
  if (await api.isAuthenticated()) {
3969
- await api.createDocument(collection.name, relativePath, params);
4233
+ await api.createDocument(collection, relativePath2, params);
3970
4234
  } else {
3971
4235
  const authMessage = `CreateDocument failed: User is no longer authenticated; please login and try again.`;
3972
4236
  cms.alerts.error(authMessage);
@@ -4161,7 +4425,7 @@ This will work when developing locally but NOT when deployed to production.
4161
4425
  onPristineChange: setFormIsPristine
4162
4426
  })));
4163
4427
  };
4164
- const useGetDocument = (cms, collectionName, relativePath) => {
4428
+ const useGetDocument = (cms, collectionName, relativePath2) => {
4165
4429
  const api = new TinaAdminApi(cms);
4166
4430
  const [document, setDocument] = React.useState(void 0);
4167
4431
  const [loading, setLoading] = React.useState(true);
@@ -4170,7 +4434,7 @@ This will work when developing locally but NOT when deployed to production.
4170
4434
  const fetchDocument = async () => {
4171
4435
  if (api.isAuthenticated()) {
4172
4436
  try {
4173
- const response = await api.fetchDocument(collectionName, relativePath);
4437
+ const response = await api.fetchDocument(collectionName, relativePath2);
4174
4438
  setDocument(response.document);
4175
4439
  } catch (error2) {
4176
4440
  cms.alerts.error(`[${error2.name}] GetDocument failed: ${error2.message}`);
@@ -4183,16 +4447,16 @@ This will work when developing locally but NOT when deployed to production.
4183
4447
  };
4184
4448
  setLoading(true);
4185
4449
  fetchDocument();
4186
- }, [cms, collectionName, relativePath]);
4450
+ }, [cms, collectionName, relativePath2]);
4187
4451
  return { document, loading, error };
4188
4452
  };
4189
4453
  const GetDocument = ({
4190
4454
  cms,
4191
4455
  collectionName,
4192
- relativePath,
4456
+ relativePath: relativePath2,
4193
4457
  children
4194
4458
  }) => {
4195
- const { document, loading, error } = useGetDocument(cms, collectionName, relativePath);
4459
+ const { document, loading, error } = useGetDocument(cms, collectionName, relativePath2);
4196
4460
  if (error) {
4197
4461
  return /* @__PURE__ */ React__default["default"].createElement(FullscreenError, null);
4198
4462
  }
@@ -4211,7 +4475,7 @@ This will work when developing locally but NOT when deployed to production.
4211
4475
  folder,
4212
4476
  includeDocuments: false
4213
4477
  }, (collection) => {
4214
- const relativePath = `${filename.startsWith("~/") ? filename.substring(2) : filename}.${collection.format}`;
4478
+ const relativePath2 = `${filename.startsWith("~/") ? filename.substring(2) : filename}.${collection.format}`;
4215
4479
  const mutationInfo = {
4216
4480
  includeCollection: true,
4217
4481
  includeTemplate: !!collection.templates
@@ -4219,7 +4483,7 @@ This will work when developing locally but NOT when deployed to production.
4219
4483
  return /* @__PURE__ */ React__default["default"].createElement(GetDocument, {
4220
4484
  cms,
4221
4485
  collectionName: collection.name,
4222
- relativePath
4486
+ relativePath: relativePath2
4223
4487
  }, (document) => {
4224
4488
  var _a;
4225
4489
  return /* @__PURE__ */ React__default["default"].createElement(RenderForm$1, {
@@ -4233,11 +4497,11 @@ This will work when developing locally but NOT when deployed to production.
4233
4497
  });
4234
4498
  }));
4235
4499
  };
4236
- const updateDocument = async (cms, relativePath, collection, mutationInfo, values) => {
4500
+ const updateDocument = async (cms, relativePath2, collection, mutationInfo, values) => {
4237
4501
  const api = new TinaAdminApi(cms);
4238
4502
  const params = api.schema.transformPayload(collection.name, values);
4239
4503
  if (await api.isAuthenticated()) {
4240
- await api.updateDocument(collection.name, relativePath, params);
4504
+ await api.updateDocument(collection, relativePath2, params);
4241
4505
  } else {
4242
4506
  const authMessage = `UpdateDocument failed: User is no longer authenticated; please login and try again.`;
4243
4507
  cms.alerts.error(authMessage);
@@ -4256,7 +4520,7 @@ This will work when developing locally but NOT when deployed to production.
4256
4520
  folder,
4257
4521
  includeDocuments: false
4258
4522
  }, (collection) => {
4259
- const relativePath = `${resolvedFile}.${collection.format}`;
4523
+ const relativePath2 = `${resolvedFile}.${collection.format}`;
4260
4524
  const mutationInfo = {
4261
4525
  includeCollection: true,
4262
4526
  includeTemplate: !!collection.templates
@@ -4264,12 +4528,12 @@ This will work when developing locally but NOT when deployed to production.
4264
4528
  return /* @__PURE__ */ React__default["default"].createElement(PageWrapper, null, /* @__PURE__ */ React__default["default"].createElement(GetDocument, {
4265
4529
  cms,
4266
4530
  collectionName: collection.name,
4267
- relativePath
4531
+ relativePath: relativePath2
4268
4532
  }, (document) => /* @__PURE__ */ React__default["default"].createElement(RenderForm, {
4269
4533
  cms,
4270
4534
  document,
4271
4535
  filename: resolvedFile,
4272
- relativePath,
4536
+ relativePath: relativePath2,
4273
4537
  collection,
4274
4538
  mutationInfo
4275
4539
  })));
@@ -4279,14 +4543,14 @@ This will work when developing locally but NOT when deployed to production.
4279
4543
  cms,
4280
4544
  document,
4281
4545
  filename,
4282
- relativePath,
4546
+ relativePath: relativePath2,
4283
4547
  collection,
4284
4548
  mutationInfo
4285
4549
  }) => {
4286
4550
  var _a, _b;
4287
4551
  const [formIsPristine, setFormIsPristine] = React.useState(true);
4288
4552
  const schema = cms.api.tina.schema;
4289
- const parentFolder2 = relativePath.split("/").slice(0, -1).join("/");
4553
+ const parentFolder2 = relativePath2.split("/").slice(0, -1).join("/");
4290
4554
  const schemaCollection = schema.getCollection(collection.name);
4291
4555
  const template = schema.getTemplateForData({
4292
4556
  collection: schemaCollection,
@@ -4306,7 +4570,7 @@ This will work when developing locally but NOT when deployed to production.
4306
4570
  initialValues: document._values,
4307
4571
  onSubmit: async (values) => {
4308
4572
  try {
4309
- await updateDocument(cms, relativePath, collection, mutationInfo, values);
4573
+ await updateDocument(cms, relativePath2, collection, mutationInfo, values);
4310
4574
  cms.alerts.success("Document updated!");
4311
4575
  } catch (error) {
4312
4576
  console.error(error);
@@ -4314,7 +4578,7 @@ This will work when developing locally but NOT when deployed to production.
4314
4578
  }
4315
4579
  }
4316
4580
  });
4317
- }, [cms, document, relativePath, collection, mutationInfo]);
4581
+ }, [cms, document, relativePath2, collection, mutationInfo]);
4318
4582
  const navBreakpoint = 1e3;
4319
4583
  const windowWidth = windowSize.useWindowWidth();
4320
4584
  const renderNavToggle = windowWidth < navBreakpoint + 1;
@@ -4641,10 +4905,12 @@ This will work when developing locally but NOT when deployed to production.
4641
4905
  exports2.Client = Client;
4642
4906
  exports2.DEFAULT_LOCAL_TINA_GQL_SERVER_URL = DEFAULT_LOCAL_TINA_GQL_SERVER_URL;
4643
4907
  exports2.LocalClient = LocalClient;
4908
+ exports2.LocalSearchClient = LocalSearchClient;
4644
4909
  exports2.RouteMappingPlugin = RouteMappingPlugin;
4645
4910
  exports2.TinaAdmin = TinaAdmin;
4646
4911
  exports2.TinaAdminApi = TinaAdminApi;
4647
4912
  exports2.TinaCMSProvider2 = TinaCMSProvider2;
4913
+ exports2.TinaCMSSearchClient = TinaCMSSearchClient;
4648
4914
  exports2.TinaCloudAuthWall = TinaCloudAuthWall;
4649
4915
  exports2.TinaCloudProvider = TinaCloudProvider;
4650
4916
  exports2.assertShape = assertShape;