tinacms 1.4.6 → 1.5.1

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
@@ -233,12 +233,16 @@ mutation addPendingDocumentMutation(
233
233
  this.contentApiUrl = this.options.customContentApiUrl || `${this.contentApiBase}/${this.tinaGraphQLVersion}/content/${this.options.clientId}/github/${encodedBranch}`;
234
234
  }
235
235
  async request(query, { variables }) {
236
+ const token = await this.getToken();
237
+ const headers = {
238
+ "Content-Type": "application/json"
239
+ };
240
+ if (token == null ? void 0 : token.id_token) {
241
+ headers["Authorization"] = "Bearer " + (token == null ? void 0 : token.id_token);
242
+ }
236
243
  const res = await fetch(this.contentApiUrl, {
237
244
  method: "POST",
238
- headers: {
239
- "Content-Type": "application/json",
240
- Authorization: "Bearer " + (await this.getToken()).id_token
241
- },
245
+ headers,
242
246
  body: JSON.stringify({
243
247
  query: typeof query === "function" ? graphql.print(query(gql__default["default"])) : query,
244
248
  variables
@@ -350,12 +354,13 @@ mutation addPendingDocumentMutation(
350
354
  }
351
355
  async fetchWithToken(input, init) {
352
356
  const headers = (init == null ? void 0 : init.headers) || {};
357
+ const token = await this.getToken();
358
+ if (token == null ? void 0 : token.id_token) {
359
+ headers["Authorization"] = "Bearer " + (token == null ? void 0 : token.id_token);
360
+ }
353
361
  return await fetch(input, {
354
362
  ...init,
355
- headers: new Headers({
356
- Authorization: "Bearer " + (await this.getToken()).id_token,
357
- ...headers
358
- })
363
+ headers: new Headers(headers)
359
364
  });
360
365
  }
361
366
  async getUser() {
@@ -632,7 +637,7 @@ mutation addPendingDocumentMutation(
632
637
  }
633
638
  }`, { variables: { collection, relativePath } });
634
639
  }
635
- async fetchCollection(collectionName, includeDocuments, after, sortKey, order, filterArgs) {
640
+ async fetchCollection(collectionName, includeDocuments, folder = "", after, sortKey, order, filterArgs) {
636
641
  let filter = null;
637
642
  const filterField = filterArgs == null ? void 0 : filterArgs.filterField;
638
643
  if (filterField) {
@@ -669,13 +674,13 @@ mutation addPendingDocumentMutation(
669
674
  if (includeDocuments === true) {
670
675
  const sort = sortKey || this.schema.getIsTitleFieldName(collectionName);
671
676
  const response = order === "asc" ? await this.api.request(`#graphql
672
- query($collection: String!, $includeDocuments: Boolean!, $sort: String, $limit: Float, $after: String, $filter: DocumentFilter){
677
+ query($collection: String!, $includeDocuments: Boolean!, $sort: String, $limit: Float, $after: String, $filter: DocumentFilter, $folder: String){
673
678
  collection(collection: $collection){
674
679
  name
675
680
  label
676
681
  format
677
682
  templates
678
- documents(sort: $sort, after: $after, first: $limit, filter: $filter) @include(if: $includeDocuments) {
683
+ documents(sort: $sort, after: $after, first: $limit, filter: $filter, folder: $folder) @include(if: $includeDocuments) {
679
684
  totalCount
680
685
  pageInfo {
681
686
  hasPreviousPage
@@ -685,6 +690,11 @@ mutation addPendingDocumentMutation(
685
690
  }
686
691
  edges {
687
692
  node {
693
+ __typename
694
+ ... on Folder {
695
+ name
696
+ path
697
+ }
688
698
  ... on Document {
689
699
  _sys {
690
700
  title
@@ -705,19 +715,20 @@ mutation addPendingDocumentMutation(
705
715
  variables: {
706
716
  collection: collectionName,
707
717
  includeDocuments,
718
+ folder,
708
719
  sort,
709
720
  limit: 50,
710
721
  after,
711
722
  filter
712
723
  }
713
724
  }) : await this.api.request(`#graphql
714
- query($collection: String!, $includeDocuments: Boolean!, $sort: String, $limit: Float, $after: String, $filter: DocumentFilter){
725
+ query($collection: String!, $includeDocuments: Boolean!, $sort: String, $limit: Float, $after: String, $filter: DocumentFilter, $folder: String) {
715
726
  collection(collection: $collection){
716
727
  name
717
728
  label
718
729
  format
719
730
  templates
720
- documents(sort: $sort, before: $after, last: $limit, filter: $filter) @include(if: $includeDocuments) {
731
+ documents(sort: $sort, before: $after, last: $limit, filter: $filter, folder: $folder) @include(if: $includeDocuments) {
721
732
  totalCount
722
733
  pageInfo {
723
734
  hasPreviousPage
@@ -727,6 +738,11 @@ mutation addPendingDocumentMutation(
727
738
  }
728
739
  edges {
729
740
  node {
741
+ __typename
742
+ ... on Folder {
743
+ name
744
+ path
745
+ }
730
746
  ... on Document {
731
747
  _sys {
732
748
  title
@@ -747,6 +763,7 @@ mutation addPendingDocumentMutation(
747
763
  variables: {
748
764
  collection: collectionName,
749
765
  includeDocuments,
766
+ folder,
750
767
  sort,
751
768
  limit: 50,
752
769
  after,
@@ -1479,6 +1496,9 @@ mutation addPendingDocumentMutation(
1479
1496
  .tina-tailwind .flex-shrink-0 {
1480
1497
  flex-shrink: 0;
1481
1498
  }
1499
+ .tina-tailwind .shrink-0 {
1500
+ flex-shrink: 0;
1501
+ }
1482
1502
  .tina-tailwind .flex-grow-0 {
1483
1503
  flex-grow: 0;
1484
1504
  }
@@ -1541,6 +1561,9 @@ mutation addPendingDocumentMutation(
1541
1561
  .tina-tailwind .items-stretch {
1542
1562
  align-items: stretch;
1543
1563
  }
1564
+ .tina-tailwind .justify-start {
1565
+ justify-content: flex-start;
1566
+ }
1544
1567
  .tina-tailwind .justify-end {
1545
1568
  justify-content: flex-end;
1546
1569
  }
@@ -1556,6 +1579,9 @@ mutation addPendingDocumentMutation(
1556
1579
  .tina-tailwind .gap-0\\.5 {
1557
1580
  gap: 2px;
1558
1581
  }
1582
+ .tina-tailwind .gap-1 {
1583
+ gap: 4px;
1584
+ }
1559
1585
  .tina-tailwind .gap-2 {
1560
1586
  gap: 8px;
1561
1587
  }
@@ -1616,9 +1642,15 @@ mutation addPendingDocumentMutation(
1616
1642
  .tina-tailwind .border {
1617
1643
  border-width: 1px;
1618
1644
  }
1645
+ .tina-tailwind .border-0 {
1646
+ border-width: 0;
1647
+ }
1619
1648
  .tina-tailwind .border-b {
1620
1649
  border-bottom-width: 1px;
1621
1650
  }
1651
+ .tina-tailwind .border-r {
1652
+ border-right-width: 1px;
1653
+ }
1622
1654
  .tina-tailwind .border-gray-100 {
1623
1655
  --tw-border-opacity: 1;
1624
1656
  border-color: rgb(237 236 243 / var(--tw-border-opacity));
@@ -1643,6 +1675,12 @@ mutation addPendingDocumentMutation(
1643
1675
  --tw-bg-opacity: 1;
1644
1676
  background-color: rgb(246 246 249 / var(--tw-bg-opacity));
1645
1677
  }
1678
+ .tina-tailwind .bg-gray-50\\/30 {
1679
+ background-color: rgb(246 246 249 / .3);
1680
+ }
1681
+ .tina-tailwind .bg-transparent {
1682
+ background-color: transparent;
1683
+ }
1646
1684
  .tina-tailwind .bg-white {
1647
1685
  --tw-bg-opacity: 1;
1648
1686
  background-color: rgb(255 255 255 / var(--tw-bg-opacity));
@@ -1684,6 +1722,9 @@ mutation addPendingDocumentMutation(
1684
1722
  .tina-tailwind .fill-current {
1685
1723
  fill: currentColor;
1686
1724
  }
1725
+ .tina-tailwind .p-0 {
1726
+ padding: 0px;
1727
+ }
1687
1728
  .tina-tailwind .px-12 {
1688
1729
  padding-left: 48px;
1689
1730
  padding-right: 48px;
@@ -1752,6 +1793,12 @@ mutation addPendingDocumentMutation(
1752
1793
  .tina-tailwind .pl-8 {
1753
1794
  padding-left: 32px;
1754
1795
  }
1796
+ .tina-tailwind .pr-0 {
1797
+ padding-right: 0px;
1798
+ }
1799
+ .tina-tailwind .pr-0\\.5 {
1800
+ padding-right: 2px;
1801
+ }
1755
1802
  .tina-tailwind .pr-3 {
1756
1803
  padding-right: 12px;
1757
1804
  }
@@ -1822,6 +1869,10 @@ mutation addPendingDocumentMutation(
1822
1869
  .tina-tailwind .tracking-wide {
1823
1870
  letter-spacing: 0.025em;
1824
1871
  }
1872
+ .tina-tailwind .text-blue-400 {
1873
+ --tw-text-opacity: 1;
1874
+ color: rgb(34 150 254 / var(--tw-text-opacity));
1875
+ }
1825
1876
  .tina-tailwind .text-blue-500 {
1826
1877
  --tw-text-opacity: 1;
1827
1878
  color: rgb(0 132 255 / var(--tw-text-opacity));
@@ -1833,6 +1884,10 @@ mutation addPendingDocumentMutation(
1833
1884
  .tina-tailwind .text-current {
1834
1885
  color: currentColor;
1835
1886
  }
1887
+ .tina-tailwind .text-gray-200 {
1888
+ --tw-text-opacity: 1;
1889
+ color: rgb(225 221 236 / var(--tw-text-opacity));
1890
+ }
1836
1891
  .tina-tailwind .text-gray-300 {
1837
1892
  --tw-text-opacity: 1;
1838
1893
  color: rgb(178 173 190 / var(--tw-text-opacity));
@@ -1872,6 +1927,15 @@ mutation addPendingDocumentMutation(
1872
1927
  .tina-tailwind .underline {
1873
1928
  text-decoration-line: underline;
1874
1929
  }
1930
+ .tina-tailwind .decoration-blue-200 {
1931
+ text-decoration-color: #85C5FE;
1932
+ }
1933
+ .tina-tailwind .decoration-1 {
1934
+ text-decoration-thickness: 1px;
1935
+ }
1936
+ .tina-tailwind .underline-offset-2 {
1937
+ text-underline-offset: 2px;
1938
+ }
1875
1939
  .tina-tailwind .opacity-0 {
1876
1940
  opacity: 0;
1877
1941
  }
@@ -1983,14 +2047,24 @@ mutation addPendingDocumentMutation(
1983
2047
  --tw-bg-opacity: 1;
1984
2048
  background-color: rgb(5 116 228 / var(--tw-bg-opacity));
1985
2049
  }
2050
+ .tina-tailwind .hover\\:bg-gray-50\\/50:hover {
2051
+ background-color: rgb(246 246 249 / .5);
2052
+ }
1986
2053
  .tina-tailwind .hover\\:text-blue-400:hover {
1987
2054
  --tw-text-opacity: 1;
1988
2055
  color: rgb(34 150 254 / var(--tw-text-opacity));
1989
2056
  }
2057
+ .tina-tailwind .hover\\:text-blue-500:hover {
2058
+ --tw-text-opacity: 1;
2059
+ color: rgb(0 132 255 / var(--tw-text-opacity));
2060
+ }
1990
2061
  .tina-tailwind .hover\\:text-blue-600:hover {
1991
2062
  --tw-text-opacity: 1;
1992
2063
  color: rgb(5 116 228 / var(--tw-text-opacity));
1993
2064
  }
2065
+ .tina-tailwind .hover\\:decoration-blue-400:hover {
2066
+ text-decoration-color: #2296fe;
2067
+ }
1994
2068
  .tina-tailwind .hover\\:opacity-100:hover {
1995
2069
  opacity: 1;
1996
2070
  }
@@ -2574,12 +2648,24 @@ This will work when developing locally but NOT when deployed to production.
2574
2648
  function IoMdClose(props) {
2575
2649
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 512 512" }, "child": [{ "tag": "path", "attr": { "d": "M405 136.798L375.202 107 256 226.202 136.798 107 107 136.798 226.202 256 107 375.202 136.798 405 256 285.798 375.202 405 405 375.202 285.798 256z" } }] })(props);
2576
2650
  }
2651
+ function BiArrowBack(props) {
2652
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M21 11H6.414l5.293-5.293-1.414-1.414L2.586 12l7.707 7.707 1.414-1.414L6.414 13H21z" } }] })(props);
2653
+ }
2654
+ function BiCopy(props) {
2655
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M20 2H10c-1.103 0-2 .897-2 2v4H4c-1.103 0-2 .897-2 2v10c0 1.103.897 2 2 2h10c1.103 0 2-.897 2-2v-4h4c1.103 0 2-.897 2-2V4c0-1.103-.897-2-2-2zM4 20V10h10l.002 10H4zm16-6h-4v-4c0-1.103-.897-2-2-2h-4V4h10v10z" } }] })(props);
2656
+ }
2577
2657
  function BiEdit(props) {
2578
2658
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "m7 17.013 4.413-.015 9.632-9.54c.378-.378.586-.88.586-1.414s-.208-1.036-.586-1.414l-1.586-1.586c-.756-.756-2.075-.752-2.825-.003L7 12.583v4.43zM18.045 4.458l1.589 1.583-1.597 1.582-1.586-1.585 1.594-1.58zM9 13.417l6.03-5.973 1.586 1.586-6.029 5.971L9 15.006v-1.589z" } }, { "tag": "path", "attr": { "d": "M5 21h14c1.103 0 2-.897 2-2v-8.668l-2 2V19H8.158c-.026 0-.053.01-.079.01-.033 0-.066-.009-.1-.01H5V5h6.847l2-2H5c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2z" } }] })(props);
2579
2659
  }
2580
2660
  function BiError(props) {
2581
2661
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M11.001 10h2v5h-2zM11 16h2v2h-2z" } }, { "tag": "path", "attr": { "d": "M13.768 4.2C13.42 3.545 12.742 3.138 12 3.138s-1.42.407-1.768 1.063L2.894 18.064a1.986 1.986 0 0 0 .054 1.968A1.984 1.984 0 0 0 4.661 21h14.678c.708 0 1.349-.362 1.714-.968a1.989 1.989 0 0 0 .054-1.968L13.768 4.2zM4.661 19 12 5.137 19.344 19H4.661z" } }] })(props);
2582
2662
  }
2663
+ function BiFile(props) {
2664
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M19.903 8.586a.997.997 0 0 0-.196-.293l-6-6a.997.997 0 0 0-.293-.196c-.03-.014-.062-.022-.094-.033a.991.991 0 0 0-.259-.051C13.04 2.011 13.021 2 13 2H6c-1.103 0-2 .897-2 2v16c0 1.103.897 2 2 2h12c1.103 0 2-.897 2-2V9c0-.021-.011-.04-.013-.062a.952.952 0 0 0-.051-.259c-.01-.032-.019-.063-.033-.093zM16.586 8H14V5.414L16.586 8zM6 20V4h6v5a1 1 0 0 0 1 1h5l.002 10H6z" } }, { "tag": "path", "attr": { "d": "M8 12h8v2H8zm0 4h8v2H8zm0-8h2v2H8z" } }] })(props);
2665
+ }
2666
+ function BiFolder(props) {
2667
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "M20 5h-8.586L9.707 3.293A.997.997 0 0 0 9 3H4c-1.103 0-2 .897-2 2v14c0 1.103.897 2 2 2h16c1.103 0 2-.897 2-2V7c0-1.103-.897-2-2-2zM4 19V7h16l.002 12H4z" } }] })(props);
2668
+ }
2583
2669
  function BiLogIn(props) {
2584
2670
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "d": "m13 16 5-4-5-4v3H4v2h9z" } }, { "tag": "path", "attr": { "d": "M20 3h-9c-1.103 0-2 .897-2 2v4h2V5h9v14h-9v-4H9v4c0 1.103.897 2 2 2h9c1.103 0 2-.897 2-2V5c0-1.103-.897-2-2-2z" } }] })(props);
2585
2671
  }
@@ -2638,7 +2724,7 @@ This will work when developing locally but NOT when deployed to production.
2638
2724
  }),
2639
2725
  RenderNavCollection: ({ collection }) => /* @__PURE__ */ React__default["default"].createElement(SidebarLink, {
2640
2726
  label: collection.label ? collection.label : collection.name,
2641
- to: `/collections/${collection.name}`,
2727
+ to: `/collections/${collection.name}/~`,
2642
2728
  Icon: ImFilesEmpty
2643
2729
  })
2644
2730
  }), !renderDesktopNav && /* @__PURE__ */ React__default["default"].createElement(react.Transition, {
@@ -2675,7 +2761,7 @@ This will work when developing locally but NOT when deployed to production.
2675
2761
  }),
2676
2762
  RenderNavCollection: ({ collection }) => /* @__PURE__ */ React__default["default"].createElement(SidebarLink, {
2677
2763
  label: collection.label ? collection.label : collection.name,
2678
- to: `/collections/${collection.name}`,
2764
+ to: `/collections/${collection.name}/~`,
2679
2765
  Icon: ImFilesEmpty,
2680
2766
  onClick: () => {
2681
2767
  setMenuIsOpen(false);
@@ -2913,6 +2999,9 @@ This will work when developing locally but NOT when deployed to production.
2913
2999
  }, "Welcome to Tina!")), /* @__PURE__ */ React__default["default"].createElement(PageBodyNarrow, null, "This is your dashboard for editing or creating content. Select a collection on the left to begin.")));
2914
3000
  });
2915
3001
  };
3002
+ function RiHome2Line(props) {
3003
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "g", "attr": {}, "child": [{ "tag": "path", "attr": { "fill": "none", "d": "M0 0h24v24H0z" } }, { "tag": "path", "attr": { "d": "M19 21H5a1 1 0 0 1-1-1v-9H1l10.327-9.388a1 1 0 0 1 1.346 0L23 11h-3v9a1 1 0 0 1-1 1zM6 19h12V9.157l-6-5.454-6 5.454V19z" } }] }] })(props);
3004
+ }
2916
3005
  const LoadingPage = () => /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, /* @__PURE__ */ React__default["default"].createElement("div", {
2917
3006
  style: {
2918
3007
  position: "absolute",
@@ -3031,7 +3120,7 @@ This will work when developing locally but NOT when deployed to production.
3031
3120
  className: "w-7 h-auto fill-current opacity-70 mr-1"
3032
3121
  }), " Reload"));
3033
3122
  };
3034
- const useGetCollection = (cms, collectionName, includeDocuments = true, after = "", sortKey, filterArgs) => {
3123
+ const useGetCollection = (cms, collectionName, includeDocuments = true, folder, after = "", sortKey, filterArgs) => {
3035
3124
  const api = new TinaAdminApi(cms);
3036
3125
  const schema = cms.api.tina.schema;
3037
3126
  const collectionExtra = schema.getCollection(collectionName);
@@ -3040,13 +3129,14 @@ This will work when developing locally but NOT when deployed to production.
3040
3129
  const [error, setError] = React.useState(void 0);
3041
3130
  const [resetState, setResetSate] = React.useState(0);
3042
3131
  React.useEffect(() => {
3132
+ let cancelled = false;
3043
3133
  const fetchCollection = async () => {
3044
3134
  var _a;
3045
- if (await api.isAuthenticated()) {
3135
+ if (await api.isAuthenticated() && !folder.loading && !cancelled) {
3046
3136
  const { name, order } = JSON.parse(sortKey || "{}");
3047
3137
  const validSortKey = ((_a = collectionExtra.fields) == null ? void 0 : _a.map((x) => x.name).includes(name)) ? name : void 0;
3048
3138
  try {
3049
- const collection2 = await api.fetchCollection(collectionName, includeDocuments, after, validSortKey, order, filterArgs);
3139
+ const collection2 = await api.fetchCollection(collectionName, includeDocuments, (filterArgs == null ? void 0 : filterArgs.filterField) ? "" : folder.fullyQualifiedName, after, validSortKey, order, filterArgs);
3050
3140
  setCollection(collection2);
3051
3141
  } catch (error2) {
3052
3142
  cms.alerts.error(`[${error2.name}] GetCollection failed: ${error2.message}`);
@@ -3057,15 +3147,29 @@ This will work when developing locally but NOT when deployed to production.
3057
3147
  setLoading(false);
3058
3148
  }
3059
3149
  };
3150
+ if (cancelled)
3151
+ return;
3060
3152
  setLoading(true);
3061
3153
  fetchCollection();
3062
- }, [cms, collectionName, resetState, after, sortKey]);
3154
+ return () => {
3155
+ cancelled = true;
3156
+ };
3157
+ }, [
3158
+ cms,
3159
+ collectionName,
3160
+ folder.loading,
3161
+ folder.fullyQualifiedName,
3162
+ resetState,
3163
+ after,
3164
+ sortKey
3165
+ ]);
3063
3166
  const reFetchCollection = () => setResetSate((x) => x + 1);
3064
3167
  return { collection, loading, error, reFetchCollection, collectionExtra };
3065
3168
  };
3066
3169
  const GetCollection = ({
3067
3170
  cms,
3068
3171
  collectionName,
3172
+ folder,
3069
3173
  includeDocuments = true,
3070
3174
  startCursor,
3071
3175
  sortKey,
@@ -3073,7 +3177,7 @@ This will work when developing locally but NOT when deployed to production.
3073
3177
  filterArgs
3074
3178
  }) => {
3075
3179
  const navigate = reactRouterDom.useNavigate();
3076
- const { collection, loading, error, reFetchCollection, collectionExtra } = useGetCollection(cms, collectionName, includeDocuments, startCursor || "", sortKey, filterArgs) || {};
3180
+ const { collection, loading, error, reFetchCollection, collectionExtra } = useGetCollection(cms, collectionName, includeDocuments, folder, startCursor || "", sortKey, filterArgs) || {};
3077
3181
  React.useEffect(() => {
3078
3182
  var _a, _b, _c, _d, _e, _f, _g, _h;
3079
3183
  if (loading)
@@ -3094,6 +3198,42 @@ This will work when developing locally but NOT when deployed to production.
3094
3198
  }
3095
3199
  return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, children(collection, loading, reFetchCollection, collectionExtra));
3096
3200
  };
3201
+ const folderRegex = /^.*\/~\/*(.*)$/;
3202
+ const parentFolder = (folder) => {
3203
+ return {
3204
+ ...folder,
3205
+ name: folder.name.split("/").slice(0, -1).join("/"),
3206
+ fullyQualifiedName: folder.fullyQualifiedName.split("/").slice(0, -1).join("/"),
3207
+ parentName: folder.parentName.split("/").slice(0, -1).join("/")
3208
+ };
3209
+ };
3210
+ const useCollectionFolder = () => {
3211
+ const [folder, setFolder] = React.useState({
3212
+ loading: true,
3213
+ name: "",
3214
+ fullyQualifiedName: "",
3215
+ parentName: ""
3216
+ });
3217
+ const loc = reactRouterDom.useLocation();
3218
+ React.useEffect(() => {
3219
+ const match = loc.pathname.match(folderRegex);
3220
+ const update = {
3221
+ name: match ? match[1] : "",
3222
+ fullyQualifiedName: match ? match[1] ? `~/${match[1]}` : "~" : "",
3223
+ loading: false,
3224
+ parentName: ""
3225
+ };
3226
+ if (update.fullyQualifiedName) {
3227
+ const pathParts = update.fullyQualifiedName.split("/");
3228
+ update.parentName = `/${pathParts.slice(0, pathParts.length - 1).join("/")}`;
3229
+ }
3230
+ setFolder({
3231
+ ...folder,
3232
+ ...update
3233
+ });
3234
+ }, [loc]);
3235
+ return folder;
3236
+ };
3097
3237
  const LOCAL_STORAGE_KEY = "tinacms.admin.collection.list.page";
3098
3238
  const isSSR = typeof window === "undefined";
3099
3239
  const TemplateMenu = ({ templates }) => {
@@ -3139,7 +3279,8 @@ This will work when developing locally but NOT when deployed to production.
3139
3279
  tinaPreview ? navigate(`/~/${routeOverride}`) : window.location.href = routeOverride;
3140
3280
  return null;
3141
3281
  } else {
3142
- navigate(document._sys.breadcrumbs.join("/"));
3282
+ const pathToDoc = document._sys.breadcrumbs;
3283
+ navigate(`/${["collections", "edit", collection.name, ...pathToDoc].join("/")}`, { replace: true });
3143
3284
  }
3144
3285
  };
3145
3286
  const CollectionListPage = () => {
@@ -3158,15 +3299,17 @@ This will work when developing locally but NOT when deployed to production.
3158
3299
  after: "",
3159
3300
  booleanEquals: null
3160
3301
  });
3302
+ const [activeSearch, setActiveSearch] = React__default["default"].useState(false);
3161
3303
  const [endCursor, setEndCursor] = React.useState("");
3162
3304
  const [prevCursors, setPrevCursors] = React.useState([]);
3163
3305
  const [sortKey, setSortKey] = React.useState(isSSR ? "" : window.localStorage.getItem(`${LOCAL_STORAGE_KEY}.${collectionName}`) || JSON.stringify({
3164
3306
  order: "asc",
3165
3307
  name: ""
3166
3308
  }));
3167
- const { order = "asc" } = JSON.parse(sortKey || "{}");
3309
+ const { order = "asc", name: sortName } = JSON.parse(sortKey || "{}");
3168
3310
  const [sortOrder, setSortOrder] = React.useState(order);
3169
3311
  const loc = reactRouterDom.useLocation();
3312
+ const folder = useCollectionFolder();
3170
3313
  React.useEffect(() => {
3171
3314
  setSortKey(window.localStorage.getItem(`${LOCAL_STORAGE_KEY}.${collectionName}`) || JSON.stringify({
3172
3315
  order: "asc",
@@ -3196,6 +3339,7 @@ This will work when developing locally but NOT when deployed to production.
3196
3339
  includeDocuments: true,
3197
3340
  startCursor: endCursor,
3198
3341
  sortKey,
3342
+ folder,
3199
3343
  filterArgs: collectionName === vars.collection ? vars : {
3200
3344
  collection: collectionName,
3201
3345
  relativePath: "",
@@ -3214,6 +3358,7 @@ This will work when developing locally but NOT when deployed to production.
3214
3358
  const admin = cms.api.admin;
3215
3359
  const pageInfo = collection.documents.pageInfo;
3216
3360
  const fields = (_a = collectionExtra.fields) == null ? void 0 : _a.filter((x) => ["string", "number", "datetime", "boolean"].includes(x.type));
3361
+ const sortField = fields.find((field) => field.name === sortName);
3217
3362
  const filterFields = (_b = collectionExtra.fields) == null ? void 0 : _b.filter((x) => {
3218
3363
  return ["string", "datetime", "boolean"].includes(x.type) && !x.list;
3219
3364
  });
@@ -3224,6 +3369,7 @@ This will work when developing locally but NOT when deployed to production.
3224
3369
  const collectionDefinition = cms.api.tina.schema.getCollection(collection.name);
3225
3370
  const allowCreate = (_e = (_d = (_c = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _c.allowedActions) == null ? void 0 : _d.create) != null ? _e : true;
3226
3371
  const allowDelete = (_h = (_g = (_f = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _f.allowedActions) == null ? void 0 : _g.delete) != null ? _h : true;
3372
+ const folderView = folder.fullyQualifiedName !== "";
3227
3373
  return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, deleteModalOpen && /* @__PURE__ */ React__default["default"].createElement(DeleteModal, {
3228
3374
  filename: vars.relativePath,
3229
3375
  deleteFunc: async () => {
@@ -3271,9 +3417,9 @@ This will work when developing locally but NOT when deployed to production.
3271
3417
  className: "flex flex-col gap-4"
3272
3418
  }, /* @__PURE__ */ React__default["default"].createElement("h3", {
3273
3419
  className: "font-sans text-2xl text-gray-700"
3274
- }, collection.label ? collection.label : collection.name), (fields == null ? void 0 : fields.length) > 0 && /* @__PURE__ */ React__default["default"].createElement("div", {
3420
+ }, collection.label ? collection.label : collection.name), /* @__PURE__ */ React__default["default"].createElement("div", {
3275
3421
  className: "flex gap-4 items-end flex-wrap"
3276
- }, /* @__PURE__ */ React__default["default"].createElement("div", {
3422
+ }, (fields == null ? void 0 : fields.length) > 0 && /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, /* @__PURE__ */ React__default["default"].createElement("div", {
3277
3423
  className: "flex flex-col gap-2 items-start"
3278
3424
  }, /* @__PURE__ */ React__default["default"].createElement("label", {
3279
3425
  htmlFor: "sort",
@@ -3436,6 +3582,7 @@ This will work when developing locally but NOT when deployed to production.
3436
3582
  className: "flex gap-3"
3437
3583
  }, /* @__PURE__ */ React__default["default"].createElement(toolkit.Button, {
3438
3584
  onClick: () => {
3585
+ setActiveSearch(true);
3439
3586
  setEndCursor("");
3440
3587
  setPrevCursors([]);
3441
3588
  reFetchCollection();
@@ -3446,8 +3593,10 @@ This will work when developing locally but NOT when deployed to production.
3446
3593
  className: "w-5 h-full ml-1.5 opacity-70"
3447
3594
  })), (vars.startsWith || vars.after || vars.before || vars.booleanEquals) && /* @__PURE__ */ React__default["default"].createElement(toolkit.Button, {
3448
3595
  onClick: () => {
3596
+ setActiveSearch(false);
3449
3597
  setVars((old) => ({
3450
3598
  ...old,
3599
+ filterField: "",
3451
3600
  startsWith: "",
3452
3601
  after: "",
3453
3602
  before: "",
@@ -3460,10 +3609,16 @@ This will work when developing locally but NOT when deployed to production.
3460
3609
  variant: "white"
3461
3610
  }, "Clear", " ", /* @__PURE__ */ React__default["default"].createElement(BiX, {
3462
3611
  className: "w-5 h-full ml-1 opacity-70"
3463
- })))))), /* @__PURE__ */ React__default["default"].createElement("div", {
3612
+ }))))))), /* @__PURE__ */ React__default["default"].createElement("div", {
3464
3613
  className: "flex self-end justify-self-end"
3465
3614
  }, !collection.templates && allowCreate && /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Link, {
3466
- to: `new`,
3615
+ to: `/${folder.fullyQualifiedName ? [
3616
+ "collections",
3617
+ "new",
3618
+ collectionName,
3619
+ "~",
3620
+ folder.name
3621
+ ].join("/") : ["collections", "new", collectionName].join("/")}`,
3467
3622
  className: "icon-parent inline-flex items-center font-medium focus:outline-none focus:ring-2 focus:shadow-outline text-center rounded-full justify-center transition-all duration-150 ease-out whitespace-nowrap shadow text-white bg-blue-500 hover:bg-blue-600 focus:ring-blue-500 text-sm h-10 px-6"
3468
3623
  }, "Create New", " ", /* @__PURE__ */ React__default["default"].createElement(BiPlus, {
3469
3624
  className: "w-5 h-full ml-1 opacity-70"
@@ -3471,25 +3626,73 @@ This will work when developing locally but NOT when deployed to production.
3471
3626
  templates: collection.templates
3472
3627
  })))), /* @__PURE__ */ React__default["default"].createElement(PageBody, null, /* @__PURE__ */ React__default["default"].createElement("div", {
3473
3628
  className: "w-full mx-auto max-w-screen-xl"
3474
- }, documents.length > 0 ? /* @__PURE__ */ React__default["default"].createElement("table", {
3629
+ }, sortField && !sortField.required && /* @__PURE__ */ React__default["default"].createElement("p", {
3630
+ className: "mb-4 text-gray-500"
3631
+ }, /* @__PURE__ */ React__default["default"].createElement("em", null, "Sorting on a non-required field. Some documents may be excluded (if they don't have a value for", " ", sortName, ")")), documents.length > 0 ? /* @__PURE__ */ React__default["default"].createElement("table", {
3475
3632
  className: "table-auto shadow bg-white border-b border-gray-200 w-full max-w-full rounded-lg"
3476
3633
  }, /* @__PURE__ */ React__default["default"].createElement("tbody", {
3477
3634
  className: "divide-y divide-gray-150"
3478
- }, documents.map((document) => {
3635
+ }, !activeSearch && folder.name && /* @__PURE__ */ React__default["default"].createElement("tr", null, /* @__PURE__ */ React__default["default"].createElement("td", {
3636
+ colSpan: 5
3637
+ }, /* @__PURE__ */ React__default["default"].createElement(Breadcrumb, {
3638
+ folder,
3639
+ navigate,
3640
+ collectionName
3641
+ }))), documents.map((document) => {
3479
3642
  var _a2;
3643
+ if (document.node.__typename === "Folder") {
3644
+ return /* @__PURE__ */ React__default["default"].createElement("tr", {
3645
+ key: `folder-${document.node.path}`
3646
+ }, /* @__PURE__ */ React__default["default"].createElement("td", {
3647
+ className: "pl-5 pr-3 py-3 truncate max-w-0"
3648
+ }, /* @__PURE__ */ React__default["default"].createElement("a", {
3649
+ className: "text-blue-600 hover:text-blue-400 flex items-center gap-3 cursor-pointer truncate",
3650
+ onClick: () => {
3651
+ navigate(`/${[
3652
+ "collections",
3653
+ collectionName,
3654
+ document.node.path
3655
+ ].join("/")}`, { replace: true });
3656
+ }
3657
+ }, /* @__PURE__ */ React__default["default"].createElement(BiFolder, {
3658
+ className: "inline-block h-6 w-auto flex-shrink-0 opacity-70"
3659
+ }), /* @__PURE__ */ React__default["default"].createElement("span", {
3660
+ className: "truncate block"
3661
+ }, /* @__PURE__ */ React__default["default"].createElement("span", {
3662
+ className: "block text-xs text-gray-400 mb-1 uppercase"
3663
+ }, "Name"), /* @__PURE__ */ React__default["default"].createElement("span", {
3664
+ className: "h-5 leading-5 block truncate"
3665
+ }, /* @__PURE__ */ React__default["default"].createElement("span", null, document.node.name))))), /* @__PURE__ */ React__default["default"].createElement("td", {
3666
+ className: "px-3 py-3 truncate max-w-0",
3667
+ colSpan: 4
3668
+ }, /* @__PURE__ */ React__default["default"].createElement("span", {
3669
+ className: "block text-xs text-gray-400 mb-1 uppercase"
3670
+ }, "Path"), /* @__PURE__ */ React__default["default"].createElement("span", {
3671
+ className: "leading-5 block text-sm font-medium text-gray-900 truncate"
3672
+ }, document.node.path.substring(2).split("/").map((node) => {
3673
+ return /* @__PURE__ */ React__default["default"].createElement("span", {
3674
+ key: node
3675
+ }, /* @__PURE__ */ React__default["default"].createElement("span", {
3676
+ className: "text-gray-300 pr-0.5"
3677
+ }, "/"), /* @__PURE__ */ React__default["default"].createElement("span", {
3678
+ className: "pr-0.5"
3679
+ }, node));
3680
+ }))));
3681
+ }
3480
3682
  const hasTitle = Boolean(document.node._sys.title);
3481
3683
  const subfolders = document.node._sys.breadcrumbs.slice(0, -1).join("/");
3482
3684
  return /* @__PURE__ */ React__default["default"].createElement("tr", {
3483
3685
  key: `document-${document.node._sys.relativePath}`,
3484
3686
  className: ""
3485
3687
  }, /* @__PURE__ */ React__default["default"].createElement("td", {
3486
- className: "pl-5 pr-3 py-2 truncate max-w-0"
3688
+ className: "pl-5 pr-3 py-3 truncate max-w-0",
3689
+ colSpan: hasTitle ? 1 : 2
3487
3690
  }, /* @__PURE__ */ React__default["default"].createElement("a", {
3488
3691
  className: "text-blue-600 hover:text-blue-400 flex items-center gap-3 cursor-pointer truncate",
3489
3692
  onClick: () => {
3490
3693
  handleNavigate(navigate, cms, collection, collectionDefinition, document.node);
3491
3694
  }
3492
- }, /* @__PURE__ */ React__default["default"].createElement(BiEdit, {
3695
+ }, /* @__PURE__ */ React__default["default"].createElement(BiFile, {
3493
3696
  className: "inline-block h-6 w-auto flex-shrink-0 opacity-70"
3494
3697
  }), /* @__PURE__ */ React__default["default"].createElement("span", {
3495
3698
  className: "truncate block"
@@ -3497,24 +3700,24 @@ This will work when developing locally but NOT when deployed to production.
3497
3700
  className: "block text-xs text-gray-400 mb-1 uppercase"
3498
3701
  }, hasTitle ? "Title" : "Filename"), /* @__PURE__ */ React__default["default"].createElement("span", {
3499
3702
  className: "h-5 leading-5 block truncate"
3500
- }, !hasTitle && subfolders && /* @__PURE__ */ React__default["default"].createElement("span", {
3703
+ }, !folderView && !hasTitle && subfolders && /* @__PURE__ */ React__default["default"].createElement("span", {
3501
3704
  className: "text-xs text-gray-400"
3502
3705
  }, `${subfolders}/`), /* @__PURE__ */ React__default["default"].createElement("span", null, hasTitle ? (_a2 = document.node._sys) == null ? void 0 : _a2.title : document.node._sys.filename))))), hasTitle && /* @__PURE__ */ React__default["default"].createElement("td", {
3503
- className: "px-3 py-4 truncate max-w-0 "
3706
+ className: "px-3 py-3 truncate max-w-0"
3504
3707
  }, /* @__PURE__ */ React__default["default"].createElement("span", {
3505
3708
  className: "block text-xs text-gray-400 mb-1 uppercase"
3506
3709
  }, "Filename"), /* @__PURE__ */ React__default["default"].createElement("span", {
3507
3710
  className: "h-5 leading-5 block text-sm font-medium text-gray-900 truncate"
3508
- }, subfolders && /* @__PURE__ */ React__default["default"].createElement("span", {
3711
+ }, !folderView && subfolders && /* @__PURE__ */ React__default["default"].createElement("span", {
3509
3712
  className: "text-xs text-gray-400"
3510
3713
  }, `${subfolders}/`), /* @__PURE__ */ React__default["default"].createElement("span", null, document.node._sys.filename))), /* @__PURE__ */ React__default["default"].createElement("td", {
3511
- className: "px-3 py-4 truncate w-[15%]"
3714
+ className: "px-3 py-3 truncate w-[15%]"
3512
3715
  }, /* @__PURE__ */ React__default["default"].createElement("span", {
3513
3716
  className: "block text-xs text-gray-400 mb-1 uppercase"
3514
3717
  }, "Extension"), /* @__PURE__ */ React__default["default"].createElement("span", {
3515
3718
  className: "h-5 leading-5 block text-sm font-medium text-gray-900"
3516
3719
  }, document.node._sys.extension)), /* @__PURE__ */ React__default["default"].createElement("td", {
3517
- className: "px-3 py-4 truncate w-[15%]"
3720
+ className: "px-3 py-3 truncate w-[15%]"
3518
3721
  }, /* @__PURE__ */ React__default["default"].createElement("span", {
3519
3722
  className: "block text-xs text-gray-400 mb-1 uppercase"
3520
3723
  }, "Template"), /* @__PURE__ */ React__default["default"].createElement("span", {
@@ -3530,7 +3733,35 @@ This will work when developing locally but NOT when deployed to production.
3530
3733
  size: "1.3rem"
3531
3734
  }),
3532
3735
  onMouseDown: () => {
3533
- navigate(`${document.node._sys.breadcrumbs.join("/")}`, { replace: true });
3736
+ const pathToDoc = document.node._sys.breadcrumbs;
3737
+ if (folder.fullyQualifiedName) {
3738
+ pathToDoc.unshift("~");
3739
+ }
3740
+ navigate(`/${[
3741
+ "collections",
3742
+ "edit",
3743
+ collectionName,
3744
+ ...pathToDoc
3745
+ ].join("/")}`, { replace: true });
3746
+ }
3747
+ },
3748
+ allowCreate && {
3749
+ name: "duplicate",
3750
+ label: "Duplicate",
3751
+ Icon: /* @__PURE__ */ React__default["default"].createElement(BiCopy, {
3752
+ size: "1.3rem"
3753
+ }),
3754
+ onMouseDown: () => {
3755
+ const pathToDoc = document.node._sys.breadcrumbs;
3756
+ if (folder.fullyQualifiedName) {
3757
+ pathToDoc.unshift("~");
3758
+ }
3759
+ navigate(`/${[
3760
+ "collections",
3761
+ "duplicate",
3762
+ collectionName,
3763
+ ...pathToDoc
3764
+ ].join("/")}`, { replace: true });
3534
3765
  }
3535
3766
  },
3536
3767
  allowDelete && {
@@ -3592,6 +3823,51 @@ This will work when developing locally but NOT when deployed to production.
3592
3823
  }));
3593
3824
  });
3594
3825
  };
3826
+ const Breadcrumb = ({ folder, navigate, collectionName }) => {
3827
+ const folderArray = folder.name.split("/");
3828
+ return /* @__PURE__ */ React__default["default"].createElement("div", {
3829
+ className: "w-full bg-gray-50/30 flex items-stretch"
3830
+ }, /* @__PURE__ */ React__default["default"].createElement("button", {
3831
+ onClick: () => {
3832
+ const folders = folder.fullyQualifiedName.split("/");
3833
+ navigate(`/${[
3834
+ "collections",
3835
+ collectionName,
3836
+ ...folders.slice(0, folders.length - 1)
3837
+ ].join("/")}`, { replace: true });
3838
+ },
3839
+ className: "px-3 py-2 bg-white hover:bg-gray-50/50 transition ease-out duration-100 border-r border-gray-100 text-blue-500 hover:text-blue-600"
3840
+ }, /* @__PURE__ */ React__default["default"].createElement(BiArrowBack, {
3841
+ className: "w-6 h-full opacity-70"
3842
+ })), /* @__PURE__ */ React__default["default"].createElement("span", {
3843
+ className: "px-3 py-2 text-gray-600 flex flex-wrap items-center justify-start gap-1"
3844
+ }, /* @__PURE__ */ React__default["default"].createElement("button", {
3845
+ onClick: () => {
3846
+ navigate(`/collections/${collectionName}/~`, {
3847
+ replace: true
3848
+ });
3849
+ },
3850
+ className: "shrink-0 bg-transparent p-0 border-0 text-blue-400 hover:text-blue-500 transition-all ease-out duration-100 opacity-70 hover:opacity-100"
3851
+ }, /* @__PURE__ */ React__default["default"].createElement(RiHome2Line, {
3852
+ className: "w-5 h-auto"
3853
+ })), folderArray.map((node, index) => {
3854
+ return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, /* @__PURE__ */ React__default["default"].createElement("span", {
3855
+ className: "text-gray-200 shrink-0"
3856
+ }, "/"), index < folderArray.length - 1 ? /* @__PURE__ */ React__default["default"].createElement("button", {
3857
+ className: "bg-transparent whitespace-nowrap truncate p-0 border-0 text-blue-500 hover:text-blue-600 transition-all ease-out duration-100 underline underline-offset-2 decoration-1 decoration-blue-200 hover:decoration-blue-400",
3858
+ onClick: () => {
3859
+ const folders = folder.fullyQualifiedName.split("/");
3860
+ navigate(`/${[
3861
+ "collections",
3862
+ collectionName,
3863
+ ...folders.slice(0, folders.length - (folders.length - (index + 2)))
3864
+ ].join("/")}`, { replace: true });
3865
+ }
3866
+ }, node) : /* @__PURE__ */ React__default["default"].createElement("span", {
3867
+ className: "whitespace-nowrap truncate"
3868
+ }, node));
3869
+ })));
3870
+ };
3595
3871
  const NoDocumentsPlaceholder = () => {
3596
3872
  return /* @__PURE__ */ React__default["default"].createElement("div", {
3597
3873
  className: "text-center px-5 py-3 flex flex-col items-center justify-center shadow border border-gray-100 bg-gray-50 border-b border-gray-200 w-full max-w-full rounded-lg"
@@ -3654,10 +3930,10 @@ This will work when developing locally but NOT when deployed to production.
3654
3930
  function FaUnlock(props) {
3655
3931
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 448 512" }, "child": [{ "tag": "path", "attr": { "d": "M400 256H152V152.9c0-39.6 31.7-72.5 71.3-72.9 40-.4 72.7 32.1 72.7 72v16c0 13.3 10.7 24 24 24h32c13.3 0 24-10.7 24-24v-16C376 68 307.5-.3 223.5 0 139.5.3 72 69.5 72 153.5V256H48c-26.5 0-48 21.5-48 48v160c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V304c0-26.5-21.5-48-48-48z" } }] })(props);
3656
3932
  }
3657
- const createDocument = async (cms, collection, template, mutationInfo, values) => {
3933
+ const createDocument = async (cms, collection, template, mutationInfo, folder, values) => {
3658
3934
  const api = new TinaAdminApi(cms);
3659
3935
  const { filename, ...leftover } = values;
3660
- const relativePath = `${filename}.${collection.format}`;
3936
+ const relativePath = `${folder ? `${folder}/` : ""}${filename}.${collection.format}`;
3661
3937
  const params = api.schema.transformPayload(collection.name, {
3662
3938
  _collection: collection.name,
3663
3939
  ...template && { _template: template.name },
@@ -3673,10 +3949,12 @@ This will work when developing locally but NOT when deployed to production.
3673
3949
  }
3674
3950
  };
3675
3951
  const CollectionCreatePage = () => {
3952
+ const folder = useCollectionFolder();
3676
3953
  const { collectionName, templateName } = reactRouterDom.useParams();
3677
3954
  return /* @__PURE__ */ React__default["default"].createElement(GetCMS, null, (cms) => /* @__PURE__ */ React__default["default"].createElement(GetCollection, {
3678
3955
  cms,
3679
3956
  collectionName,
3957
+ folder,
3680
3958
  includeDocuments: false
3681
3959
  }, (collection) => {
3682
3960
  const mutationInfo = {
@@ -3687,7 +3965,8 @@ This will work when developing locally but NOT when deployed to production.
3687
3965
  cms,
3688
3966
  collection,
3689
3967
  templateName,
3690
- mutationInfo
3968
+ mutationInfo,
3969
+ folder
3691
3970
  });
3692
3971
  }));
3693
3972
  };
@@ -3709,7 +3988,14 @@ This will work when developing locally but NOT when deployed to production.
3709
3988
  className: `text-blue-500 absolute top-1/2 left-2 -translate-y-1/2 pointer-events-none h-5 w-auto transition-opacity duration-150 ease-out ${!filenameTouched && !props.readonly ? "opacity-0 group-hover:opacity-80 group-active:opacity-80" : "opacity-0"}`
3710
3989
  }));
3711
3990
  };
3712
- const RenderForm$1 = ({ cms, collection, templateName, mutationInfo }) => {
3991
+ const RenderForm$1 = ({
3992
+ cms,
3993
+ collection,
3994
+ folder,
3995
+ templateName,
3996
+ mutationInfo,
3997
+ customDefaults
3998
+ }) => {
3713
3999
  var _a, _b, _c, _d, _e, _f;
3714
4000
  const navigate = reactRouterDom.useNavigate();
3715
4001
  const [formIsPristine, setFormIsPristine] = React.useState(true);
@@ -3735,7 +4021,7 @@ This will work when developing locally but NOT when deployed to production.
3735
4021
  };
3736
4022
  }
3737
4023
  }
3738
- const defaultItem = ((_d = template.ui) == null ? void 0 : _d.defaultItem) || (template == null ? void 0 : template.defaultItem);
4024
+ const defaultItem = customDefaults || ((_d = template.ui) == null ? void 0 : _d.defaultItem) || (template == null ? void 0 : template.defaultItem);
3739
4025
  const form = React.useMemo(() => {
3740
4026
  var _a2, _b2;
3741
4027
  return new toolkit.Form({
@@ -3792,9 +4078,12 @@ This will work when developing locally but NOT when deployed to production.
3792
4078
  ],
3793
4079
  onSubmit: async (values) => {
3794
4080
  try {
3795
- await createDocument(cms, collection, template, mutationInfo, values);
4081
+ const folderName = folder.fullyQualifiedName ? folder.name : "";
4082
+ await createDocument(cms, collection, template, mutationInfo, folderName, values);
3796
4083
  cms.alerts.success("Document created!");
3797
- navigate(`/collections/${collection.name}`);
4084
+ setTimeout(() => {
4085
+ navigate(`/collections/${collection.name}${folder.fullyQualifiedName ? `/${folder.fullyQualifiedName}` : ""}`);
4086
+ }, 10);
3798
4087
  } catch (error) {
3799
4088
  console.error(error);
3800
4089
  const defaultErrorText = "There was a problem saving your document.";
@@ -3821,7 +4110,7 @@ This will work when developing locally but NOT when deployed to production.
3821
4110
  }, /* @__PURE__ */ React__default["default"].createElement("span", {
3822
4111
  className: "block text-sm leading-tight uppercase text-gray-400 mb-1"
3823
4112
  }, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Link, {
3824
- to: `/collections/${collection.name}`,
4113
+ to: `/collections/${collection.name}${folder.fullyQualifiedName ? `/${folder.fullyQualifiedName}` : ""}`,
3825
4114
  className: "inline-block text-current hover:text-blue-400 focus:underline focus:outline-none focus:text-blue-400 font-medium transition-colors duration-150 ease-out"
3826
4115
  }, collection.label ? collection.label : collection.name), /* @__PURE__ */ React__default["default"].createElement(HiChevronRight, {
3827
4116
  className: "inline-block -mt-0.5 opacity-50"
@@ -3874,6 +4163,38 @@ This will work when developing locally but NOT when deployed to production.
3874
4163
  }
3875
4164
  return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, children(document, loading));
3876
4165
  };
4166
+ const CollectionDuplicatePage = () => {
4167
+ const folder = useCollectionFolder();
4168
+ const { collectionName, ...rest } = reactRouterDom.useParams();
4169
+ const { "*": filename } = rest;
4170
+ return /* @__PURE__ */ React__default["default"].createElement(GetCMS, null, (cms) => /* @__PURE__ */ React__default["default"].createElement(GetCollection, {
4171
+ cms,
4172
+ collectionName,
4173
+ folder,
4174
+ includeDocuments: false
4175
+ }, (collection) => {
4176
+ const relativePath = `${filename.startsWith("~/") ? filename.substring(2) : filename}.${collection.format}`;
4177
+ const mutationInfo = {
4178
+ includeCollection: true,
4179
+ includeTemplate: !!collection.templates
4180
+ };
4181
+ return /* @__PURE__ */ React__default["default"].createElement(GetDocument, {
4182
+ cms,
4183
+ collectionName: collection.name,
4184
+ relativePath
4185
+ }, (document) => {
4186
+ var _a;
4187
+ return /* @__PURE__ */ React__default["default"].createElement(RenderForm$1, {
4188
+ cms,
4189
+ collection,
4190
+ templateName: (_a = document._values) == null ? void 0 : _a._template,
4191
+ folder: parentFolder(folder),
4192
+ mutationInfo,
4193
+ customDefaults: document._values
4194
+ });
4195
+ });
4196
+ }));
4197
+ };
3877
4198
  const updateDocument = async (cms, relativePath, collection, mutationInfo, values) => {
3878
4199
  const api = new TinaAdminApi(cms);
3879
4200
  const params = api.schema.transformPayload(collection.name, values);
@@ -3888,13 +4209,16 @@ This will work when developing locally but NOT when deployed to production.
3888
4209
  };
3889
4210
  const CollectionUpdatePage = () => {
3890
4211
  const { collectionName, ...rest } = reactRouterDom.useParams();
4212
+ const folder = useCollectionFolder();
3891
4213
  const { "*": filename } = rest;
4214
+ const resolvedFile = folder.fullyQualifiedName ? folder.name : filename;
3892
4215
  return /* @__PURE__ */ React__default["default"].createElement(GetCMS, null, (cms) => /* @__PURE__ */ React__default["default"].createElement(GetCollection, {
3893
4216
  cms,
3894
4217
  collectionName,
4218
+ folder,
3895
4219
  includeDocuments: false
3896
4220
  }, (collection) => {
3897
- const relativePath = `${filename}.${collection.format}`;
4221
+ const relativePath = `${resolvedFile}.${collection.format}`;
3898
4222
  const mutationInfo = {
3899
4223
  includeCollection: true,
3900
4224
  includeTemplate: !!collection.templates
@@ -3906,7 +4230,7 @@ This will work when developing locally but NOT when deployed to production.
3906
4230
  }, (document) => /* @__PURE__ */ React__default["default"].createElement(RenderForm, {
3907
4231
  cms,
3908
4232
  document,
3909
- filename,
4233
+ filename: resolvedFile,
3910
4234
  relativePath,
3911
4235
  collection,
3912
4236
  mutationInfo
@@ -3924,6 +4248,7 @@ This will work when developing locally but NOT when deployed to production.
3924
4248
  var _a, _b;
3925
4249
  const [formIsPristine, setFormIsPristine] = React.useState(true);
3926
4250
  const schema = cms.api.tina.schema;
4251
+ const parentFolder2 = relativePath.split("/").slice(0, -1).join("/");
3927
4252
  const schemaCollection = schema.getCollection(collection.name);
3928
4253
  const template = schema.getTemplateForData({
3929
4254
  collection: schemaCollection,
@@ -3965,7 +4290,7 @@ This will work when developing locally but NOT when deployed to production.
3965
4290
  }, /* @__PURE__ */ React__default["default"].createElement("span", {
3966
4291
  className: "block text-sm leading-tight uppercase text-gray-400 mb-1"
3967
4292
  }, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Link, {
3968
- to: `/collections/${collection.name}`,
4293
+ to: `/collections/${collection.name}/~${parentFolder2}`,
3969
4294
  className: "inline-block text-current hover:text-blue-400 focus:underline focus:outline-none focus:text-blue-400 font-medium transition-colors duration-150 ease-out"
3970
4295
  }, collection.label ? collection.label : collection.name), /* @__PURE__ */ React__default["default"].createElement(HiChevronRight, {
3971
4296
  className: "inline-block -mt-0.5 opacity-50"
@@ -4126,22 +4451,42 @@ This will work when developing locally but NOT when deployed to production.
4126
4451
  path: "graphql",
4127
4452
  element: /* @__PURE__ */ React__default["default"].createElement(PlainLayout, null, /* @__PURE__ */ React__default["default"].createElement(Playground, null))
4128
4453
  }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
4129
- path: "collections/:collectionName/new",
4454
+ path: "collections/new/:collectionName",
4455
+ element: /* @__PURE__ */ React__default["default"].createElement(DefaultWrapper, {
4456
+ cms
4457
+ }, /* @__PURE__ */ React__default["default"].createElement(CollectionCreatePage, null))
4458
+ }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
4459
+ path: "collections/duplicate/:collectionName/~/*",
4460
+ element: /* @__PURE__ */ React__default["default"].createElement(DefaultWrapper, {
4461
+ cms
4462
+ }, /* @__PURE__ */ React__default["default"].createElement(CollectionDuplicatePage, null))
4463
+ }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
4464
+ path: "collections/duplicate/:collectionName/*",
4465
+ element: /* @__PURE__ */ React__default["default"].createElement(DefaultWrapper, {
4466
+ cms
4467
+ }, /* @__PURE__ */ React__default["default"].createElement(CollectionDuplicatePage, null))
4468
+ }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
4469
+ path: "collections/new/:collectionName/:templateName",
4130
4470
  element: /* @__PURE__ */ React__default["default"].createElement(DefaultWrapper, {
4131
4471
  cms
4132
4472
  }, /* @__PURE__ */ React__default["default"].createElement(CollectionCreatePage, null))
4133
4473
  }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
4134
- path: "collections/:collectionName/:templateName/new",
4474
+ path: "collections/new/:collectionName/:templateName/~/*",
4135
4475
  element: /* @__PURE__ */ React__default["default"].createElement(DefaultWrapper, {
4136
4476
  cms
4137
4477
  }, /* @__PURE__ */ React__default["default"].createElement(CollectionCreatePage, null))
4138
4478
  }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
4139
- path: "collections/:collectionName/*",
4479
+ path: "collections/new/:collectionName/~/*",
4480
+ element: /* @__PURE__ */ React__default["default"].createElement(DefaultWrapper, {
4481
+ cms
4482
+ }, /* @__PURE__ */ React__default["default"].createElement(CollectionCreatePage, null))
4483
+ }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
4484
+ path: "collections/edit/:collectionName/*",
4140
4485
  element: /* @__PURE__ */ React__default["default"].createElement(DefaultWrapper, {
4141
4486
  cms
4142
4487
  }, /* @__PURE__ */ React__default["default"].createElement(CollectionUpdatePage, null))
4143
4488
  }), /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
4144
- path: "collections/:collectionName",
4489
+ path: "collections/:collectionName/*",
4145
4490
  element: /* @__PURE__ */ React__default["default"].createElement(DefaultWrapper, {
4146
4491
  cms
4147
4492
  }, /* @__PURE__ */ React__default["default"].createElement(CollectionListPage, null))
@@ -4236,10 +4581,10 @@ This will work when developing locally but NOT when deployed to production.
4236
4581
  return schemaTools.NAMER;
4237
4582
  }
4238
4583
  });
4239
- Object.defineProperty(exports2, "resolveForm", {
4584
+ Object.defineProperty(exports2, "resolveField", {
4240
4585
  enumerable: true,
4241
4586
  get: function() {
4242
- return schemaTools.resolveForm;
4587
+ return schemaTools.resolveField;
4243
4588
  }
4244
4589
  });
4245
4590
  exports2.AuthWallInner = AuthWallInner;