tinacms 0.66.4 → 0.66.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,16 @@
1
1
  # tinacms
2
2
 
3
+ ## 0.66.5
4
+
5
+ ### Patch Changes
6
+
7
+ - 43c834565: Adds an activity indicator throughout Admin
8
+ - 53a4550db: Allows RouteMapping to be dynamically imported
9
+ - 731451bee: Adjust the JWT token refresh logic to refresh tokens _before_ they expire.
10
+ - e102d7438: Updated auth modal to use toolkit button components
11
+ - Updated dependencies [43c834565]
12
+ - @tinacms/toolkit@0.56.15
13
+
3
14
  ## 0.66.4
4
15
 
5
16
  ### Patch Changes
@@ -12,7 +12,10 @@ limitations under the License.
12
12
  */
13
13
  import type { TinaCMS } from '@tinacms/toolkit';
14
14
  import type { Collection } from '../types';
15
- export declare const useGetCollection: (cms: TinaCMS, collectionName: string, includeDocuments?: boolean) => Collection;
15
+ export declare const useGetCollection: (cms: TinaCMS, collectionName: string, includeDocuments?: boolean) => {
16
+ collection: Collection;
17
+ loading: boolean;
18
+ };
16
19
  declare const GetCollection: ({ cms, collectionName, includeDocuments, children, }: {
17
20
  cms: TinaCMS;
18
21
  collectionName: string;
@@ -15,7 +15,6 @@ import type { Collection } from '../types';
15
15
  export declare const useGetCollections: (cms: TinaCMS) => {
16
16
  collections: Collection[];
17
17
  loading: boolean;
18
- error: boolean;
19
18
  };
20
19
  declare const GetCollections: ({ cms, children }: {
21
20
  cms: TinaCMS;
@@ -12,7 +12,10 @@ limitations under the License.
12
12
  */
13
13
  import type { TinaCMS } from '@tinacms/toolkit';
14
14
  import type { DocumentForm } from '../types';
15
- export declare const useGetDocument: (cms: TinaCMS, collectionName: string, relativePath: string) => DocumentForm;
15
+ export declare const useGetDocument: (cms: TinaCMS, collectionName: string, relativePath: string) => {
16
+ document: DocumentForm;
17
+ loading: boolean;
18
+ };
16
19
  declare const GetDocument: ({ cms, collectionName, relativePath, children, }: {
17
20
  cms: TinaCMS;
18
21
  collectionName: string;
@@ -20,7 +20,16 @@ export interface Info {
20
20
  includeTemplate: boolean;
21
21
  };
22
22
  }
23
- export declare const useGetDocumentFields: (cms: TinaCMS, collectionName: string, templateName: string) => Info;
23
+ export declare const useGetDocumentFields: (cms: TinaCMS, collectionName: string, templateName: string) => {
24
+ loading: boolean;
25
+ collection: Object | undefined;
26
+ template: Object | undefined;
27
+ fields: Object[] | undefined;
28
+ mutationInfo: {
29
+ includeCollection: boolean;
30
+ includeTemplate: boolean;
31
+ };
32
+ };
24
33
  declare const GetDocumentFields: ({ cms, collectionName, templateName, children, }: {
25
34
  cms: TinaCMS;
26
35
  collectionName: string;
@@ -0,0 +1,14 @@
1
+ /**
2
+ Copyright 2021 Forestry.io Holdings, Inc.
3
+ Licensed under the Apache License, Version 2.0 (the "License");
4
+ you may not use this file except in compliance with the License.
5
+ You may obtain a copy of the License at
6
+ http://www.apache.org/licenses/LICENSE-2.0
7
+ Unless required by applicable law or agreed to in writing, software
8
+ distributed under the License is distributed on an "AS IS" BASIS,
9
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
10
+ See the License for the specific language governing permissions and
11
+ limitations under the License.
12
+ */
13
+ declare const LoadingPage: () => JSX.Element;
14
+ export default LoadingPage;
package/dist/index.es.js CHANGED
@@ -40,7 +40,7 @@ import * as yup from "yup";
40
40
  import { setEditing, TinaDataContext, useEditState } from "@tinacms/sharedctx";
41
41
  import { getIn, setIn } from "final-form";
42
42
  import UrlPattern from "url-pattern";
43
- import { NavLink, useParams, useNavigate, Link, BrowserRouter, Routes, Route } from "react-router-dom";
43
+ import { NavLink, useNavigate, useParams, Link, BrowserRouter, Routes, Route } from "react-router-dom";
44
44
  import { Menu, Transition } from "@headlessui/react";
45
45
  function popupWindow(url, title, window2, w, h) {
46
46
  const y = window2.top.outerHeight / 2 + window2.top.screenY - h / 2;
@@ -519,7 +519,7 @@ mutation addPendingDocumentMutation(
519
519
  async getRefreshedToken(tokens) {
520
520
  const { access_token, id_token, refresh_token } = JSON.parse(tokens);
521
521
  const { exp, iss, client_id } = this.parseJwt(access_token);
522
- if (Date.now() / 1e3 >= exp) {
522
+ if (Date.now() / 1e3 >= exp - 120) {
523
523
  const refreshResponse = await fetch(iss, {
524
524
  method: "POST",
525
525
  headers: {
@@ -877,6 +877,9 @@ const TinaCloudProvider = (props) => {
877
877
  if (!cms.api.tina) {
878
878
  cms.registerApi("tina", createClient(props));
879
879
  }
880
+ if (!cms.api.admin) {
881
+ cms.registerApi("admin", new TinaAdminApi(cms));
882
+ }
880
883
  const setupMedia = async () => {
881
884
  var _a;
882
885
  if (props.mediaStore) {
@@ -901,11 +904,6 @@ const TinaCloudProvider = (props) => {
901
904
  return newBranch;
902
905
  };
903
906
  setupMedia();
904
- React.useMemo(() => {
905
- if (cms.flags.get("tina-admin") === true) {
906
- cms.registerApi("admin", new TinaAdminApi(cms));
907
- }
908
- }, [cms, cms.flags.get("tina-admin")]);
909
907
  const [branchingEnabled, setBranchingEnabled] = React.useState(() => cms.flags.get("branch-switcher"));
910
908
  React.useEffect(() => {
911
909
  cms.events.subscribe("flag:set", ({ key, value }) => {
@@ -2112,6 +2110,10 @@ Document
2112
2110
  height: 20px !important;
2113
2111
  }
2114
2112
 
2113
+ .tina-tailwind .h-12 {
2114
+ height: 48px !important;
2115
+ }
2116
+
2115
2117
  .tina-tailwind .w-full {
2116
2118
  width: 100% !important;
2117
2119
  }
@@ -2156,6 +2158,14 @@ Document
2156
2158
  flex: 1 1 0% !important;
2157
2159
  }
2158
2160
 
2161
+ .tina-tailwind .flex-shrink-0 {
2162
+ flex-shrink: 0 !important;
2163
+ }
2164
+
2165
+ .tina-tailwind .flex-grow-0 {
2166
+ flex-grow: 0 !important;
2167
+ }
2168
+
2159
2169
  .tina-tailwind .table-auto {
2160
2170
  table-layout: auto !important;
2161
2171
  }
@@ -2195,6 +2205,10 @@ Document
2195
2205
  transform: var(--tw-transform) !important;
2196
2206
  }
2197
2207
 
2208
+ .tina-tailwind .cursor-pointer {
2209
+ cursor: pointer !important;
2210
+ }
2211
+
2198
2212
  .tina-tailwind .flex-col {
2199
2213
  flex-direction: column !important;
2200
2214
  }
@@ -2211,6 +2225,10 @@ Document
2211
2225
  align-items: stretch !important;
2212
2226
  }
2213
2227
 
2228
+ .tina-tailwind .justify-end {
2229
+ justify-content: flex-end !important;
2230
+ }
2231
+
2214
2232
  .tina-tailwind .justify-center {
2215
2233
  justify-content: center !important;
2216
2234
  }
@@ -2278,10 +2296,6 @@ Document
2278
2296
  border-color: rgba(225, 221, 236, var(--tw-border-opacity)) !important;
2279
2297
  }
2280
2298
 
2281
- .tina-tailwind .border-transparent {
2282
- border-color: transparent !important;
2283
- }
2284
-
2285
2299
  .tina-tailwind .bg-white {
2286
2300
  --tw-bg-opacity: 1 !important;
2287
2301
  background-color: rgba(255, 255, 255, var(--tw-bg-opacity)) !important;
@@ -2365,9 +2379,8 @@ Document
2365
2379
  padding-bottom: 12px !important;
2366
2380
  }
2367
2381
 
2368
- .tina-tailwind .px-8 {
2369
- padding-left: 32px !important;
2370
- padding-right: 32px !important;
2382
+ .tina-tailwind .pt-4 {
2383
+ padding-top: 16px !important;
2371
2384
  }
2372
2385
 
2373
2386
  .tina-tailwind .pb-4 {
@@ -2444,10 +2457,6 @@ Document
2444
2457
  line-height: 20px !important;
2445
2458
  }
2446
2459
 
2447
- .tina-tailwind .leading-4 {
2448
- line-height: 16px !important;
2449
- }
2450
-
2451
2460
  .tina-tailwind .tracking-wide {
2452
2461
  letter-spacing: 0.025em !important;
2453
2462
  }
@@ -2549,11 +2558,6 @@ Document
2549
2558
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow) !important;
2550
2559
  }
2551
2560
 
2552
- .tina-tailwind .shadow-sm {
2553
- --tw-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05) !important;
2554
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow) !important;
2555
- }
2556
-
2557
2561
  .tina-tailwind .ring-1 {
2558
2562
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color) !important;
2559
2563
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color) !important;
@@ -2648,11 +2652,6 @@ Document
2648
2652
  background-color: rgba(5, 116, 228, var(--tw-bg-opacity)) !important;
2649
2653
  }
2650
2654
 
2651
- .hover\\:bg-gray-50:hover {
2652
- --tw-bg-opacity: 1 !important;
2653
- background-color: rgba(246, 246, 249, var(--tw-bg-opacity)) !important;
2654
- }
2655
-
2656
2655
  .hover\\:text-blue-600:hover {
2657
2656
  --tw-text-opacity: 1 !important;
2658
2657
  color: rgba(5, 116, 228, var(--tw-text-opacity)) !important;
@@ -2667,10 +2666,6 @@ Document
2667
2666
  opacity: 1 !important;
2668
2667
  }
2669
2668
 
2670
- .hover\\:opacity-80:hover {
2671
- opacity: .8 !important;
2672
- }
2673
-
2674
2669
  .focus\\:text-blue-400:focus {
2675
2670
  --tw-text-opacity: 1 !important;
2676
2671
  color: rgba(34, 150, 254, var(--tw-text-opacity)) !important;
@@ -3157,41 +3152,29 @@ function ImFilesEmpty(props) {
3157
3152
  }
3158
3153
  const useGetCollections = (cms) => {
3159
3154
  const api = new TinaAdminApi(cms);
3160
- const [info, setInfo] = useState({ collections: [], loading: true, error: false });
3155
+ const [collections, setCollections] = useState([]);
3156
+ const [loading, setLoading] = useState(true);
3161
3157
  useEffect(() => {
3162
3158
  const fetchCollections = async () => {
3163
3159
  const response = await api.fetchCollections();
3164
- setInfo({
3165
- collections: response.getCollections,
3166
- loading: false,
3167
- error: false
3168
- });
3160
+ setCollections(response.getCollections);
3161
+ setLoading(false);
3169
3162
  };
3163
+ setLoading(true);
3170
3164
  fetchCollections();
3171
3165
  }, [cms]);
3172
- return info;
3173
- };
3174
- const GetCollections = ({ cms, children }) => {
3175
- const { collections, loading, error } = useGetCollections(cms);
3176
- if (!collections)
3177
- return null;
3178
- return /* @__PURE__ */ React.createElement(React.Fragment, null, children(collections, loading, error));
3166
+ return { collections, loading };
3179
3167
  };
3180
3168
  const slugify = (text) => {
3181
3169
  return text.toString().toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "_").replace(/^-+|-+$/g, "");
3182
3170
  };
3183
3171
  const Sidebar = ({ cms }) => {
3172
+ const collectionsInfo = useGetCollections(cms);
3184
3173
  const screens = cms.plugins.getType("screen").all();
3185
- return /* @__PURE__ */ React.createElement(GetCollections, {
3186
- cms
3187
- }, (collections, loading, error) => /* @__PURE__ */ React.createElement(Nav, {
3174
+ return /* @__PURE__ */ React.createElement(Nav, {
3188
3175
  sidebarWidth: 360,
3189
3176
  showCollections: true,
3190
- collectionsInfo: {
3191
- collections,
3192
- loading,
3193
- error
3194
- },
3177
+ collectionsInfo,
3195
3178
  screens,
3196
3179
  contentCreators: [],
3197
3180
  RenderNavSite: ({ view }) => /* @__PURE__ */ React.createElement(SidebarLink, {
@@ -3204,7 +3187,7 @@ const Sidebar = ({ cms }) => {
3204
3187
  to: `collections/${collection.name}`,
3205
3188
  Icon: ImFilesEmpty
3206
3189
  })
3207
- }));
3190
+ });
3208
3191
  };
3209
3192
  const SidebarLink = (props) => {
3210
3193
  const { to, label, Icon } = props;
@@ -3261,8 +3244,8 @@ const AuthTemplate = ({
3261
3244
  d: "M18.6466 14.5553C19.9018 13.5141 20.458 7.36086 21.0014 5.14903C21.5447 2.9372 23.7919 3.04938 23.7919 3.04938C23.7919 3.04938 23.2085 4.06764 23.4464 4.82751C23.6844 5.58738 25.3145 6.26662 25.3145 6.26662L24.9629 7.19622C24.9629 7.19622 24.2288 7.10204 23.7919 7.9785C23.355 8.85496 24.3392 17.4442 24.3392 17.4442C24.3392 17.4442 21.4469 22.7275 21.4469 24.9206C21.4469 27.1136 22.4819 28.9515 22.4819 28.9515H21.0296C21.0296 28.9515 18.899 26.4086 18.462 25.1378C18.0251 23.8669 18.1998 22.596 18.1998 22.596C18.1998 22.596 15.8839 22.4646 13.8303 22.596C11.7767 22.7275 10.4072 24.498 10.16 25.4884C9.91287 26.4787 9.81048 28.9515 9.81048 28.9515H8.66211C7.96315 26.7882 7.40803 26.0129 7.70918 24.9206C8.54334 21.8949 8.37949 20.1788 8.18635 19.4145C7.99321 18.6501 6.68552 17.983 6.68552 17.983C7.32609 16.6741 7.97996 16.0452 10.7926 15.9796C13.6052 15.914 17.3915 15.5965 18.6466 14.5553Z"
3262
3245
  }), /* @__PURE__ */ React.createElement("path", {
3263
3246
  d: "M11.1268 24.7939C11.1268 24.7939 11.4236 27.5481 13.0001 28.9516H14.3511C13.0001 27.4166 12.8527 23.4155 12.8527 23.4155C12.1656 23.6399 11.3045 24.3846 11.1268 24.7939Z"
3264
- })), /* @__PURE__ */ React.createElement("span", null, "Tina Admin"))), message && /* @__PURE__ */ React.createElement("div", {
3265
- className: "px-5 py-4 "
3247
+ })), /* @__PURE__ */ React.createElement("span", null, "Tina"))), message && /* @__PURE__ */ React.createElement("div", {
3248
+ className: "px-5 pt-4"
3266
3249
  }, /* @__PURE__ */ React.createElement("p", {
3267
3250
  className: "text-base font-sans leading-normal"
3268
3251
  }, message)), /* @__PURE__ */ React.createElement("div", {
@@ -3272,38 +3255,52 @@ const AuthTemplate = ({
3272
3255
  const LoginPage = () => {
3273
3256
  const { setEdit } = useEditState();
3274
3257
  const login = () => setEdit(true);
3275
- return /* @__PURE__ */ React.createElement(AuthTemplate, null, /* @__PURE__ */ React.createElement("a", {
3276
- href: "/",
3277
- className: "flex-1 text-center inline-flex justify-center items-center px-8 py-3 shadow-sm text-sm leading-4 font-medium rounded-full text-gray-600 border border-gray-150 hover:opacity-80 hover:bg-gray-50 focus:outline-none focus:shadow-outline-blue transition duration-150 ease-out"
3258
+ return /* @__PURE__ */ React.createElement(AuthTemplate, null, /* @__PURE__ */ React.createElement("div", {
3259
+ className: "flex w-full flex-1 gap-4 items-center justify-end"
3260
+ }, /* @__PURE__ */ React.createElement(Button, {
3261
+ onClick: () => {
3262
+ window.location.href = "/";
3263
+ },
3264
+ variant: "white",
3265
+ size: "custom",
3266
+ className: "text-base h-12 px-6 flex-shrink-0 flex-grow-0"
3278
3267
  }, /* @__PURE__ */ React.createElement(MdOutlineArrowBack, {
3279
3268
  className: "w-6 h-auto mr-1.5 opacity-80"
3280
- }), " Back to site"), /* @__PURE__ */ React.createElement("button", {
3281
- type: "submit",
3269
+ }), " Back To Site"), /* @__PURE__ */ React.createElement(Button, {
3282
3270
  onClick: () => login(),
3283
- className: "flex-1 justify-center text-center inline-flex items-center px-8 py-3 shadow-sm border border-transparent text-sm leading-4 font-medium rounded-full text-white hover:opacity-80 focus:outline-none focus:shadow-outline-blue transition duration-150 ease-out",
3284
- style: { background: "#0084FF" }
3271
+ variant: "primary",
3272
+ size: "custom",
3273
+ className: "text-base h-12 px-6 flex-1",
3274
+ type: "submit"
3285
3275
  }, /* @__PURE__ */ React.createElement(BiLogIn, {
3286
- className: "w-6 h-auto mr-1.5 opacity-80"
3287
- }), " Enter edit-mode"));
3276
+ className: "w-6 h-auto mr-2 opacity-80"
3277
+ }), " Edit With Tina")));
3288
3278
  };
3289
3279
  const logout = () => {
3290
3280
  setEditing(false);
3291
3281
  window.location.href = "/";
3292
3282
  };
3293
3283
  const LogoutPage = () => {
3294
- return /* @__PURE__ */ React.createElement(AuthTemplate, null, /* @__PURE__ */ React.createElement("a", {
3295
- href: "/",
3296
- className: "flex-1 text-center inline-flex justify-center items-center px-8 py-3 shadow-sm text-sm leading-4 font-medium rounded-full text-gray-600 border border-gray-150 hover:opacity-80 hover:bg-gray-50 focus:outline-none focus:shadow-outline-blue transition duration-150 ease-out"
3284
+ return /* @__PURE__ */ React.createElement(AuthTemplate, null, /* @__PURE__ */ React.createElement("div", {
3285
+ className: "flex w-full flex-1 gap-4 items-center justify-end"
3286
+ }, /* @__PURE__ */ React.createElement(Button, {
3287
+ onClick: () => {
3288
+ window.location.href = "/";
3289
+ },
3290
+ variant: "white",
3291
+ size: "custom",
3292
+ className: "text-base h-12 px-6 flex-shrink-0 flex-grow-0"
3297
3293
  }, /* @__PURE__ */ React.createElement(MdOutlineArrowBack, {
3298
3294
  className: "w-6 h-auto mr-1.5 opacity-80"
3299
- }), " Back to site"), /* @__PURE__ */ React.createElement("button", {
3300
- type: "submit",
3295
+ }), " Back To Site"), /* @__PURE__ */ React.createElement(Button, {
3301
3296
  onClick: () => logout(),
3302
- className: "flex-1 justify-center text-center inline-flex items-center px-8 py-3 shadow-sm border border-transparent text-sm leading-4 font-medium rounded-full text-white hover:opacity-80 focus:outline-none focus:shadow-outline-blue transition duration-150 ease-out",
3303
- style: { background: "#0084FF" }
3297
+ type: "submit",
3298
+ variant: "primary",
3299
+ size: "custom",
3300
+ className: "text-base h-12 px-6 flex-1"
3304
3301
  }, /* @__PURE__ */ React.createElement(BiLogOut, {
3305
3302
  className: "w-6 h-auto mr-1.5 opacity-80"
3306
- }), " Log out"));
3303
+ }), " Log Out of Tina")));
3307
3304
  };
3308
3305
  const PageWrapper = ({
3309
3306
  children
@@ -3344,17 +3341,119 @@ const DashboardPage = () => {
3344
3341
  }, "Welcome to Tina!")), /* @__PURE__ */ React.createElement(PageBodyNarrow, null, "This is your dashboard for editing or creating content. Select a collection on the left to begin.")));
3345
3342
  });
3346
3343
  };
3344
+ const LoadingPage = () => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", {
3345
+ style: {
3346
+ position: "absolute",
3347
+ top: 0,
3348
+ left: 0,
3349
+ width: "100%",
3350
+ height: "100%",
3351
+ zIndex: 200,
3352
+ opacity: "0.8",
3353
+ display: "flex",
3354
+ alignItems: "start",
3355
+ justifyContent: "center",
3356
+ padding: "120px 40px 40px 40px"
3357
+ }
3358
+ }, /* @__PURE__ */ React.createElement("div", {
3359
+ style: {
3360
+ background: "#FFF",
3361
+ border: "1px solid #EDECF3",
3362
+ boxShadow: "0px 2px 3px rgba(0, 0, 0, 0.05), 0 4px 12px rgba(0, 0, 0, 0.1)",
3363
+ borderRadius: "8px",
3364
+ padding: "32px 24px",
3365
+ width: "460px",
3366
+ maxWidth: "90%",
3367
+ display: "flex",
3368
+ alignItems: "center",
3369
+ justifyContent: "center",
3370
+ flexDirection: "column"
3371
+ }
3372
+ }, /* @__PURE__ */ React.createElement("svg", {
3373
+ style: {
3374
+ width: "64px",
3375
+ color: "#2296fe",
3376
+ marginTop: "-8px",
3377
+ marginBottom: "16px"
3378
+ },
3379
+ version: "1.1",
3380
+ id: "L5",
3381
+ xmlns: "http://www.w3.org/2000/svg",
3382
+ xmlnsXlink: "http://www.w3.org/1999/xlink",
3383
+ x: "0px",
3384
+ y: "0px",
3385
+ viewBox: "0 0 100 64",
3386
+ enableBackground: "new 0 0 0 0",
3387
+ xmlSpace: "preserve"
3388
+ }, /* @__PURE__ */ React.createElement("circle", {
3389
+ fill: "currentColor",
3390
+ stroke: "none",
3391
+ cx: 6,
3392
+ cy: 32,
3393
+ r: 6
3394
+ }, /* @__PURE__ */ React.createElement("animateTransform", {
3395
+ attributeName: "transform",
3396
+ dur: "1s",
3397
+ type: "translate",
3398
+ values: "0 15 ; 0 -15; 0 15",
3399
+ calcMode: "spline",
3400
+ keySplines: "0.8 0 0.4 1; 0.4 0 0.2 1",
3401
+ repeatCount: "indefinite",
3402
+ begin: "0.1"
3403
+ })), /* @__PURE__ */ React.createElement("circle", {
3404
+ fill: "currentColor",
3405
+ stroke: "none",
3406
+ cx: 30,
3407
+ cy: 32,
3408
+ r: 6
3409
+ }, /* @__PURE__ */ React.createElement("animateTransform", {
3410
+ attributeName: "transform",
3411
+ dur: "1s",
3412
+ type: "translate",
3413
+ values: "0 15 ; 0 -10; 0 15",
3414
+ calcMode: "spline",
3415
+ keySplines: "0.8 0 0.4 1; 0.4 0 0.2 1",
3416
+ repeatCount: "indefinite",
3417
+ begin: "0.2"
3418
+ })), /* @__PURE__ */ React.createElement("circle", {
3419
+ fill: "currentColor",
3420
+ stroke: "none",
3421
+ cx: 54,
3422
+ cy: 32,
3423
+ r: 6
3424
+ }, /* @__PURE__ */ React.createElement("animateTransform", {
3425
+ attributeName: "transform",
3426
+ dur: "1s",
3427
+ type: "translate",
3428
+ values: "0 15 ; 0 -5; 0 15",
3429
+ calcMode: "spline",
3430
+ keySplines: "0.8 0 0.4 1; 0.4 0 0.2 1",
3431
+ repeatCount: "indefinite",
3432
+ begin: "0.3"
3433
+ }))), /* @__PURE__ */ React.createElement("p", {
3434
+ style: {
3435
+ fontSize: "16px",
3436
+ color: "#716c7f",
3437
+ textAlign: "center",
3438
+ lineHeight: "1.3",
3439
+ fontFamily: "'Inter', sans-serif",
3440
+ fontWeight: "normal"
3441
+ }
3442
+ }, "Please wait, Tina is loading data..."))));
3347
3443
  const useGetCollection = (cms, collectionName, includeDocuments = true) => {
3348
3444
  const api = new TinaAdminApi(cms);
3349
3445
  const [collection, setCollection] = useState(void 0);
3446
+ const [loading, setLoading] = useState(true);
3350
3447
  useEffect(() => {
3351
3448
  const fetchCollection = async () => {
3352
3449
  const response = await api.fetchCollection(collectionName, includeDocuments);
3353
3450
  setCollection(response.getCollection);
3451
+ setLoading(false);
3354
3452
  };
3453
+ setLoading(true);
3355
3454
  fetchCollection();
3356
3455
  }, [cms, collectionName]);
3357
- return collection;
3456
+ return { collection, loading };
3358
3457
  };
3359
3458
  const GetCollection = ({
3360
3459
  cms,
@@ -3362,11 +3461,11 @@ const GetCollection = ({
3362
3461
  includeDocuments = true,
3363
3462
  children
3364
3463
  }) => {
3365
- const collection = useGetCollection(cms, collectionName, includeDocuments);
3366
- if (!collection) {
3367
- return null;
3464
+ const { collection, loading } = useGetCollection(cms, collectionName, includeDocuments);
3465
+ if (!collection || loading === true) {
3466
+ return /* @__PURE__ */ React.createElement(LoadingPage, null);
3368
3467
  }
3369
- return /* @__PURE__ */ React.createElement(React.Fragment, null, children(collection));
3468
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, children(collection, loading));
3370
3469
  };
3371
3470
  const TemplateMenu = ({ templates }) => {
3372
3471
  return /* @__PURE__ */ React.createElement(Menu, {
@@ -3395,12 +3494,21 @@ const TemplateMenu = ({ templates }) => {
3395
3494
  className: `w-full text-md px-4 py-2 tracking-wide flex items-center opacity-80 text-gray-600 ${active && "text-gray-800 opacity-100"}`
3396
3495
  }, template.label))))))));
3397
3496
  };
3497
+ const handleNavigate = (navigate, cms, collection, document) => {
3498
+ const plugins = cms.plugins.all("tina-admin");
3499
+ const routeMapping = plugins.find(({ name }) => name === "route-mapping");
3500
+ const routeOverride = routeMapping ? routeMapping.mapper(collection, document) : void 0;
3501
+ if (routeOverride) {
3502
+ window.location.href = routeOverride;
3503
+ return null;
3504
+ } else {
3505
+ navigate(document.sys.filename);
3506
+ }
3507
+ };
3398
3508
  const CollectionListPage = () => {
3509
+ const navigate = useNavigate();
3399
3510
  const { collectionName } = useParams();
3400
- useNavigate();
3401
3511
  return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => {
3402
- const plugins = cms.plugins.all("tina-admin");
3403
- const routeMapping = plugins.find(({ name }) => name === "route-mapping");
3404
3512
  return /* @__PURE__ */ React.createElement(GetCollection, {
3405
3513
  cms,
3406
3514
  collectionName,
@@ -3427,24 +3535,16 @@ const CollectionListPage = () => {
3427
3535
  }, /* @__PURE__ */ React.createElement("tbody", {
3428
3536
  className: "divide-y divide-gray-150"
3429
3537
  }, documents.map((document) => {
3430
- const overrideRoute = routeMapping ? routeMapping.mapper(collection, document.node) : void 0;
3431
3538
  return /* @__PURE__ */ React.createElement("tr", {
3432
3539
  key: `document-${document.node.sys.filename}`,
3433
3540
  className: ""
3434
3541
  }, /* @__PURE__ */ React.createElement("td", {
3435
3542
  className: "px-6 py-2 whitespace-nowrap"
3436
- }, overrideRoute && /* @__PURE__ */ React.createElement("a", {
3437
- className: "text-blue-600 hover:text-blue-400 flex items-center gap-3",
3438
- href: `${overrideRoute}`
3439
- }, /* @__PURE__ */ React.createElement(BiEdit, {
3440
- className: "inline-block h-6 w-auto opacity-70"
3441
- }), /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement("span", {
3442
- className: "block text-xs text-gray-400 mb-1 uppercase"
3443
- }, "Filename"), /* @__PURE__ */ React.createElement("span", {
3444
- className: "h-5 leading-5 block whitespace-nowrap"
3445
- }, document.node.sys.filename))), !overrideRoute && /* @__PURE__ */ React.createElement(Link, {
3446
- className: "text-blue-600 hover:text-blue-400 flex items-center gap-3",
3447
- to: `${document.node.sys.filename}`
3543
+ }, /* @__PURE__ */ React.createElement("a", {
3544
+ className: "text-blue-600 hover:text-blue-400 flex items-center gap-3 cursor-pointer",
3545
+ onClick: () => {
3546
+ handleNavigate(navigate, cms, collection, document.node);
3547
+ }
3448
3548
  }, /* @__PURE__ */ React.createElement(BiEdit, {
3449
3549
  className: "inline-block h-6 w-auto opacity-70"
3450
3550
  }), /* @__PURE__ */ React.createElement("span", null, /* @__PURE__ */ React.createElement("span", {
@@ -3479,6 +3579,7 @@ const useGetDocumentFields = (cms, collectionName, templateName) => {
3479
3579
  fields: void 0,
3480
3580
  mutationInfo: void 0
3481
3581
  });
3582
+ const [loading, setLoading] = useState(true);
3482
3583
  useEffect(() => {
3483
3584
  const fetchDocumentFields = async () => {
3484
3585
  const response = await api.fetchDocumentFields();
@@ -3499,10 +3600,12 @@ const useGetDocumentFields = (cms, collectionName, templateName) => {
3499
3600
  fields,
3500
3601
  mutationInfo
3501
3602
  });
3603
+ setLoading(false);
3502
3604
  };
3605
+ setLoading(true);
3503
3606
  fetchDocumentFields();
3504
3607
  }, [cms, collectionName]);
3505
- return info;
3608
+ return __spreadProps(__spreadValues({}, info), { loading });
3506
3609
  };
3507
3610
  const GetDocumentFields = ({
3508
3611
  cms,
@@ -3510,11 +3613,11 @@ const GetDocumentFields = ({
3510
3613
  templateName,
3511
3614
  children
3512
3615
  }) => {
3513
- const { collection, template, fields, mutationInfo } = useGetDocumentFields(cms, collectionName, templateName);
3514
- if (!collection) {
3515
- return null;
3616
+ const { collection, template, fields, mutationInfo, loading } = useGetDocumentFields(cms, collectionName, templateName);
3617
+ if (!collection || loading) {
3618
+ return /* @__PURE__ */ React.createElement(LoadingPage, null);
3516
3619
  }
3517
- return /* @__PURE__ */ React.createElement(React.Fragment, null, children({ collection, template, fields, mutationInfo }));
3620
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, children({ collection, template, fields, mutationInfo, loading }));
3518
3621
  };
3519
3622
  const createDocument = async (cms, collection, template, mutationInfo, values) => {
3520
3623
  const api = new TinaAdminApi(cms);
@@ -3604,14 +3707,17 @@ const RenderForm$1 = ({ cms, collection, template, fields, mutationInfo }) => {
3604
3707
  const useGetDocument = (cms, collectionName, relativePath) => {
3605
3708
  const api = new TinaAdminApi(cms);
3606
3709
  const [document, setDocument] = useState(void 0);
3710
+ const [loading, setLoading] = useState(true);
3607
3711
  useEffect(() => {
3608
3712
  const fetchDocument = async () => {
3609
3713
  const response = await api.fetchDocument(collectionName, relativePath);
3610
3714
  setDocument(response.getDocument);
3715
+ setLoading(false);
3611
3716
  };
3717
+ setLoading(true);
3612
3718
  fetchDocument();
3613
3719
  }, [cms, collectionName, relativePath]);
3614
- return document;
3720
+ return { document, loading };
3615
3721
  };
3616
3722
  const GetDocument = ({
3617
3723
  cms,
@@ -3619,11 +3725,11 @@ const GetDocument = ({
3619
3725
  relativePath,
3620
3726
  children
3621
3727
  }) => {
3622
- const document = useGetDocument(cms, collectionName, relativePath);
3623
- if (!document) {
3624
- return null;
3728
+ const { document, loading } = useGetDocument(cms, collectionName, relativePath);
3729
+ if (!document || loading) {
3730
+ return /* @__PURE__ */ React.createElement(LoadingPage, null);
3625
3731
  }
3626
- return /* @__PURE__ */ React.createElement(React.Fragment, null, children(document));
3732
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, children(document, loading));
3627
3733
  };
3628
3734
  const updateDocument = async (cms, relativePath, collection, mutationInfo, values) => {
3629
3735
  const api = new TinaAdminApi(cms);
@@ -3743,7 +3849,7 @@ const TinaAdmin = () => {
3743
3849
  }, /* @__PURE__ */ React.createElement(Sidebar, {
3744
3850
  cms
3745
3851
  }), /* @__PURE__ */ React.createElement("div", {
3746
- className: "flex-1"
3852
+ className: "flex-1 relative"
3747
3853
  }, /* @__PURE__ */ React.createElement(Routes, null, /* @__PURE__ */ React.createElement(Route, {
3748
3854
  path: "collections/:collectionName/new",
3749
3855
  element: /* @__PURE__ */ React.createElement(CollectionCreatePage, null)
package/dist/index.js CHANGED
@@ -539,7 +539,7 @@ mutation addPendingDocumentMutation(
539
539
  async getRefreshedToken(tokens) {
540
540
  const { access_token, id_token, refresh_token } = JSON.parse(tokens);
541
541
  const { exp, iss, client_id } = this.parseJwt(access_token);
542
- if (Date.now() / 1e3 >= exp) {
542
+ if (Date.now() / 1e3 >= exp - 120) {
543
543
  const refreshResponse = await fetch(iss, {
544
544
  method: "POST",
545
545
  headers: {
@@ -897,6 +897,9 @@ mutation addPendingDocumentMutation(
897
897
  if (!cms.api.tina) {
898
898
  cms.registerApi("tina", createClient(props));
899
899
  }
900
+ if (!cms.api.admin) {
901
+ cms.registerApi("admin", new TinaAdminApi(cms));
902
+ }
900
903
  const setupMedia = async () => {
901
904
  var _a;
902
905
  if (props.mediaStore) {
@@ -921,11 +924,6 @@ mutation addPendingDocumentMutation(
921
924
  return newBranch;
922
925
  };
923
926
  setupMedia();
924
- React__default["default"].useMemo(() => {
925
- if (cms.flags.get("tina-admin") === true) {
926
- cms.registerApi("admin", new TinaAdminApi(cms));
927
- }
928
- }, [cms, cms.flags.get("tina-admin")]);
929
927
  const [branchingEnabled, setBranchingEnabled] = React__default["default"].useState(() => cms.flags.get("branch-switcher"));
930
928
  React__default["default"].useEffect(() => {
931
929
  cms.events.subscribe("flag:set", ({ key, value }) => {
@@ -2132,6 +2130,10 @@ Document
2132
2130
  height: 20px !important;
2133
2131
  }
2134
2132
 
2133
+ .tina-tailwind .h-12 {
2134
+ height: 48px !important;
2135
+ }
2136
+
2135
2137
  .tina-tailwind .w-full {
2136
2138
  width: 100% !important;
2137
2139
  }
@@ -2176,6 +2178,14 @@ Document
2176
2178
  flex: 1 1 0% !important;
2177
2179
  }
2178
2180
 
2181
+ .tina-tailwind .flex-shrink-0 {
2182
+ flex-shrink: 0 !important;
2183
+ }
2184
+
2185
+ .tina-tailwind .flex-grow-0 {
2186
+ flex-grow: 0 !important;
2187
+ }
2188
+
2179
2189
  .tina-tailwind .table-auto {
2180
2190
  table-layout: auto !important;
2181
2191
  }
@@ -2215,6 +2225,10 @@ Document
2215
2225
  transform: var(--tw-transform) !important;
2216
2226
  }
2217
2227
 
2228
+ .tina-tailwind .cursor-pointer {
2229
+ cursor: pointer !important;
2230
+ }
2231
+
2218
2232
  .tina-tailwind .flex-col {
2219
2233
  flex-direction: column !important;
2220
2234
  }
@@ -2231,6 +2245,10 @@ Document
2231
2245
  align-items: stretch !important;
2232
2246
  }
2233
2247
 
2248
+ .tina-tailwind .justify-end {
2249
+ justify-content: flex-end !important;
2250
+ }
2251
+
2234
2252
  .tina-tailwind .justify-center {
2235
2253
  justify-content: center !important;
2236
2254
  }
@@ -2298,10 +2316,6 @@ Document
2298
2316
  border-color: rgba(225, 221, 236, var(--tw-border-opacity)) !important;
2299
2317
  }
2300
2318
 
2301
- .tina-tailwind .border-transparent {
2302
- border-color: transparent !important;
2303
- }
2304
-
2305
2319
  .tina-tailwind .bg-white {
2306
2320
  --tw-bg-opacity: 1 !important;
2307
2321
  background-color: rgba(255, 255, 255, var(--tw-bg-opacity)) !important;
@@ -2385,9 +2399,8 @@ Document
2385
2399
  padding-bottom: 12px !important;
2386
2400
  }
2387
2401
 
2388
- .tina-tailwind .px-8 {
2389
- padding-left: 32px !important;
2390
- padding-right: 32px !important;
2402
+ .tina-tailwind .pt-4 {
2403
+ padding-top: 16px !important;
2391
2404
  }
2392
2405
 
2393
2406
  .tina-tailwind .pb-4 {
@@ -2464,10 +2477,6 @@ Document
2464
2477
  line-height: 20px !important;
2465
2478
  }
2466
2479
 
2467
- .tina-tailwind .leading-4 {
2468
- line-height: 16px !important;
2469
- }
2470
-
2471
2480
  .tina-tailwind .tracking-wide {
2472
2481
  letter-spacing: 0.025em !important;
2473
2482
  }
@@ -2569,11 +2578,6 @@ Document
2569
2578
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow) !important;
2570
2579
  }
2571
2580
 
2572
- .tina-tailwind .shadow-sm {
2573
- --tw-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05) !important;
2574
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow) !important;
2575
- }
2576
-
2577
2581
  .tina-tailwind .ring-1 {
2578
2582
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color) !important;
2579
2583
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color) !important;
@@ -2668,11 +2672,6 @@ Document
2668
2672
  background-color: rgba(5, 116, 228, var(--tw-bg-opacity)) !important;
2669
2673
  }
2670
2674
 
2671
- .hover\\:bg-gray-50:hover {
2672
- --tw-bg-opacity: 1 !important;
2673
- background-color: rgba(246, 246, 249, var(--tw-bg-opacity)) !important;
2674
- }
2675
-
2676
2675
  .hover\\:text-blue-600:hover {
2677
2676
  --tw-text-opacity: 1 !important;
2678
2677
  color: rgba(5, 116, 228, var(--tw-text-opacity)) !important;
@@ -2687,10 +2686,6 @@ Document
2687
2686
  opacity: 1 !important;
2688
2687
  }
2689
2688
 
2690
- .hover\\:opacity-80:hover {
2691
- opacity: .8 !important;
2692
- }
2693
-
2694
2689
  .focus\\:text-blue-400:focus {
2695
2690
  --tw-text-opacity: 1 !important;
2696
2691
  color: rgba(34, 150, 254, var(--tw-text-opacity)) !important;
@@ -3177,41 +3172,29 @@ This will work when developing locally but NOT when deployed to production.
3177
3172
  }
3178
3173
  const useGetCollections = (cms) => {
3179
3174
  const api = new TinaAdminApi(cms);
3180
- const [info, setInfo] = React.useState({ collections: [], loading: true, error: false });
3175
+ const [collections, setCollections] = React.useState([]);
3176
+ const [loading, setLoading] = React.useState(true);
3181
3177
  React.useEffect(() => {
3182
3178
  const fetchCollections = async () => {
3183
3179
  const response = await api.fetchCollections();
3184
- setInfo({
3185
- collections: response.getCollections,
3186
- loading: false,
3187
- error: false
3188
- });
3180
+ setCollections(response.getCollections);
3181
+ setLoading(false);
3189
3182
  };
3183
+ setLoading(true);
3190
3184
  fetchCollections();
3191
3185
  }, [cms]);
3192
- return info;
3193
- };
3194
- const GetCollections = ({ cms, children }) => {
3195
- const { collections, loading, error } = useGetCollections(cms);
3196
- if (!collections)
3197
- return null;
3198
- return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, children(collections, loading, error));
3186
+ return { collections, loading };
3199
3187
  };
3200
3188
  const slugify = (text) => {
3201
3189
  return text.toString().toLowerCase().trim().replace(/[^\w\s-]/g, "").replace(/[\s_-]+/g, "_").replace(/^-+|-+$/g, "");
3202
3190
  };
3203
3191
  const Sidebar = ({ cms }) => {
3192
+ const collectionsInfo = useGetCollections(cms);
3204
3193
  const screens = cms.plugins.getType("screen").all();
3205
- return /* @__PURE__ */ React__default["default"].createElement(GetCollections, {
3206
- cms
3207
- }, (collections, loading, error) => /* @__PURE__ */ React__default["default"].createElement(toolkit.Nav, {
3194
+ return /* @__PURE__ */ React__default["default"].createElement(toolkit.Nav, {
3208
3195
  sidebarWidth: 360,
3209
3196
  showCollections: true,
3210
- collectionsInfo: {
3211
- collections,
3212
- loading,
3213
- error
3214
- },
3197
+ collectionsInfo,
3215
3198
  screens,
3216
3199
  contentCreators: [],
3217
3200
  RenderNavSite: ({ view }) => /* @__PURE__ */ React__default["default"].createElement(SidebarLink, {
@@ -3224,7 +3207,7 @@ This will work when developing locally but NOT when deployed to production.
3224
3207
  to: `collections/${collection.name}`,
3225
3208
  Icon: ImFilesEmpty
3226
3209
  })
3227
- }));
3210
+ });
3228
3211
  };
3229
3212
  const SidebarLink = (props) => {
3230
3213
  const { to, label, Icon } = props;
@@ -3281,8 +3264,8 @@ This will work when developing locally but NOT when deployed to production.
3281
3264
  d: "M18.6466 14.5553C19.9018 13.5141 20.458 7.36086 21.0014 5.14903C21.5447 2.9372 23.7919 3.04938 23.7919 3.04938C23.7919 3.04938 23.2085 4.06764 23.4464 4.82751C23.6844 5.58738 25.3145 6.26662 25.3145 6.26662L24.9629 7.19622C24.9629 7.19622 24.2288 7.10204 23.7919 7.9785C23.355 8.85496 24.3392 17.4442 24.3392 17.4442C24.3392 17.4442 21.4469 22.7275 21.4469 24.9206C21.4469 27.1136 22.4819 28.9515 22.4819 28.9515H21.0296C21.0296 28.9515 18.899 26.4086 18.462 25.1378C18.0251 23.8669 18.1998 22.596 18.1998 22.596C18.1998 22.596 15.8839 22.4646 13.8303 22.596C11.7767 22.7275 10.4072 24.498 10.16 25.4884C9.91287 26.4787 9.81048 28.9515 9.81048 28.9515H8.66211C7.96315 26.7882 7.40803 26.0129 7.70918 24.9206C8.54334 21.8949 8.37949 20.1788 8.18635 19.4145C7.99321 18.6501 6.68552 17.983 6.68552 17.983C7.32609 16.6741 7.97996 16.0452 10.7926 15.9796C13.6052 15.914 17.3915 15.5965 18.6466 14.5553Z"
3282
3265
  }), /* @__PURE__ */ React__default["default"].createElement("path", {
3283
3266
  d: "M11.1268 24.7939C11.1268 24.7939 11.4236 27.5481 13.0001 28.9516H14.3511C13.0001 27.4166 12.8527 23.4155 12.8527 23.4155C12.1656 23.6399 11.3045 24.3846 11.1268 24.7939Z"
3284
- })), /* @__PURE__ */ React__default["default"].createElement("span", null, "Tina Admin"))), message && /* @__PURE__ */ React__default["default"].createElement("div", {
3285
- className: "px-5 py-4 "
3267
+ })), /* @__PURE__ */ React__default["default"].createElement("span", null, "Tina"))), message && /* @__PURE__ */ React__default["default"].createElement("div", {
3268
+ className: "px-5 pt-4"
3286
3269
  }, /* @__PURE__ */ React__default["default"].createElement("p", {
3287
3270
  className: "text-base font-sans leading-normal"
3288
3271
  }, message)), /* @__PURE__ */ React__default["default"].createElement("div", {
@@ -3292,38 +3275,52 @@ This will work when developing locally but NOT when deployed to production.
3292
3275
  const LoginPage = () => {
3293
3276
  const { setEdit } = sharedctx.useEditState();
3294
3277
  const login = () => setEdit(true);
3295
- return /* @__PURE__ */ React__default["default"].createElement(AuthTemplate, null, /* @__PURE__ */ React__default["default"].createElement("a", {
3296
- href: "/",
3297
- className: "flex-1 text-center inline-flex justify-center items-center px-8 py-3 shadow-sm text-sm leading-4 font-medium rounded-full text-gray-600 border border-gray-150 hover:opacity-80 hover:bg-gray-50 focus:outline-none focus:shadow-outline-blue transition duration-150 ease-out"
3278
+ return /* @__PURE__ */ React__default["default"].createElement(AuthTemplate, null, /* @__PURE__ */ React__default["default"].createElement("div", {
3279
+ className: "flex w-full flex-1 gap-4 items-center justify-end"
3280
+ }, /* @__PURE__ */ React__default["default"].createElement(toolkit.Button, {
3281
+ onClick: () => {
3282
+ window.location.href = "/";
3283
+ },
3284
+ variant: "white",
3285
+ size: "custom",
3286
+ className: "text-base h-12 px-6 flex-shrink-0 flex-grow-0"
3298
3287
  }, /* @__PURE__ */ React__default["default"].createElement(MdOutlineArrowBack, {
3299
3288
  className: "w-6 h-auto mr-1.5 opacity-80"
3300
- }), " Back to site"), /* @__PURE__ */ React__default["default"].createElement("button", {
3301
- type: "submit",
3289
+ }), " Back To Site"), /* @__PURE__ */ React__default["default"].createElement(toolkit.Button, {
3302
3290
  onClick: () => login(),
3303
- className: "flex-1 justify-center text-center inline-flex items-center px-8 py-3 shadow-sm border border-transparent text-sm leading-4 font-medium rounded-full text-white hover:opacity-80 focus:outline-none focus:shadow-outline-blue transition duration-150 ease-out",
3304
- style: { background: "#0084FF" }
3291
+ variant: "primary",
3292
+ size: "custom",
3293
+ className: "text-base h-12 px-6 flex-1",
3294
+ type: "submit"
3305
3295
  }, /* @__PURE__ */ React__default["default"].createElement(BiLogIn, {
3306
- className: "w-6 h-auto mr-1.5 opacity-80"
3307
- }), " Enter edit-mode"));
3296
+ className: "w-6 h-auto mr-2 opacity-80"
3297
+ }), " Edit With Tina")));
3308
3298
  };
3309
3299
  const logout = () => {
3310
3300
  sharedctx.setEditing(false);
3311
3301
  window.location.href = "/";
3312
3302
  };
3313
3303
  const LogoutPage = () => {
3314
- return /* @__PURE__ */ React__default["default"].createElement(AuthTemplate, null, /* @__PURE__ */ React__default["default"].createElement("a", {
3315
- href: "/",
3316
- className: "flex-1 text-center inline-flex justify-center items-center px-8 py-3 shadow-sm text-sm leading-4 font-medium rounded-full text-gray-600 border border-gray-150 hover:opacity-80 hover:bg-gray-50 focus:outline-none focus:shadow-outline-blue transition duration-150 ease-out"
3304
+ return /* @__PURE__ */ React__default["default"].createElement(AuthTemplate, null, /* @__PURE__ */ React__default["default"].createElement("div", {
3305
+ className: "flex w-full flex-1 gap-4 items-center justify-end"
3306
+ }, /* @__PURE__ */ React__default["default"].createElement(toolkit.Button, {
3307
+ onClick: () => {
3308
+ window.location.href = "/";
3309
+ },
3310
+ variant: "white",
3311
+ size: "custom",
3312
+ className: "text-base h-12 px-6 flex-shrink-0 flex-grow-0"
3317
3313
  }, /* @__PURE__ */ React__default["default"].createElement(MdOutlineArrowBack, {
3318
3314
  className: "w-6 h-auto mr-1.5 opacity-80"
3319
- }), " Back to site"), /* @__PURE__ */ React__default["default"].createElement("button", {
3320
- type: "submit",
3315
+ }), " Back To Site"), /* @__PURE__ */ React__default["default"].createElement(toolkit.Button, {
3321
3316
  onClick: () => logout(),
3322
- className: "flex-1 justify-center text-center inline-flex items-center px-8 py-3 shadow-sm border border-transparent text-sm leading-4 font-medium rounded-full text-white hover:opacity-80 focus:outline-none focus:shadow-outline-blue transition duration-150 ease-out",
3323
- style: { background: "#0084FF" }
3317
+ type: "submit",
3318
+ variant: "primary",
3319
+ size: "custom",
3320
+ className: "text-base h-12 px-6 flex-1"
3324
3321
  }, /* @__PURE__ */ React__default["default"].createElement(BiLogOut, {
3325
3322
  className: "w-6 h-auto mr-1.5 opacity-80"
3326
- }), " Log out"));
3323
+ }), " Log Out of Tina")));
3327
3324
  };
3328
3325
  const PageWrapper = ({
3329
3326
  children
@@ -3364,17 +3361,119 @@ This will work when developing locally but NOT when deployed to production.
3364
3361
  }, "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.")));
3365
3362
  });
3366
3363
  };
3364
+ const LoadingPage = () => /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, /* @__PURE__ */ React__default["default"].createElement("div", {
3365
+ style: {
3366
+ position: "absolute",
3367
+ top: 0,
3368
+ left: 0,
3369
+ width: "100%",
3370
+ height: "100%",
3371
+ zIndex: 200,
3372
+ opacity: "0.8",
3373
+ display: "flex",
3374
+ alignItems: "start",
3375
+ justifyContent: "center",
3376
+ padding: "120px 40px 40px 40px"
3377
+ }
3378
+ }, /* @__PURE__ */ React__default["default"].createElement("div", {
3379
+ style: {
3380
+ background: "#FFF",
3381
+ border: "1px solid #EDECF3",
3382
+ boxShadow: "0px 2px 3px rgba(0, 0, 0, 0.05), 0 4px 12px rgba(0, 0, 0, 0.1)",
3383
+ borderRadius: "8px",
3384
+ padding: "32px 24px",
3385
+ width: "460px",
3386
+ maxWidth: "90%",
3387
+ display: "flex",
3388
+ alignItems: "center",
3389
+ justifyContent: "center",
3390
+ flexDirection: "column"
3391
+ }
3392
+ }, /* @__PURE__ */ React__default["default"].createElement("svg", {
3393
+ style: {
3394
+ width: "64px",
3395
+ color: "#2296fe",
3396
+ marginTop: "-8px",
3397
+ marginBottom: "16px"
3398
+ },
3399
+ version: "1.1",
3400
+ id: "L5",
3401
+ xmlns: "http://www.w3.org/2000/svg",
3402
+ xmlnsXlink: "http://www.w3.org/1999/xlink",
3403
+ x: "0px",
3404
+ y: "0px",
3405
+ viewBox: "0 0 100 64",
3406
+ enableBackground: "new 0 0 0 0",
3407
+ xmlSpace: "preserve"
3408
+ }, /* @__PURE__ */ React__default["default"].createElement("circle", {
3409
+ fill: "currentColor",
3410
+ stroke: "none",
3411
+ cx: 6,
3412
+ cy: 32,
3413
+ r: 6
3414
+ }, /* @__PURE__ */ React__default["default"].createElement("animateTransform", {
3415
+ attributeName: "transform",
3416
+ dur: "1s",
3417
+ type: "translate",
3418
+ values: "0 15 ; 0 -15; 0 15",
3419
+ calcMode: "spline",
3420
+ keySplines: "0.8 0 0.4 1; 0.4 0 0.2 1",
3421
+ repeatCount: "indefinite",
3422
+ begin: "0.1"
3423
+ })), /* @__PURE__ */ React__default["default"].createElement("circle", {
3424
+ fill: "currentColor",
3425
+ stroke: "none",
3426
+ cx: 30,
3427
+ cy: 32,
3428
+ r: 6
3429
+ }, /* @__PURE__ */ React__default["default"].createElement("animateTransform", {
3430
+ attributeName: "transform",
3431
+ dur: "1s",
3432
+ type: "translate",
3433
+ values: "0 15 ; 0 -10; 0 15",
3434
+ calcMode: "spline",
3435
+ keySplines: "0.8 0 0.4 1; 0.4 0 0.2 1",
3436
+ repeatCount: "indefinite",
3437
+ begin: "0.2"
3438
+ })), /* @__PURE__ */ React__default["default"].createElement("circle", {
3439
+ fill: "currentColor",
3440
+ stroke: "none",
3441
+ cx: 54,
3442
+ cy: 32,
3443
+ r: 6
3444
+ }, /* @__PURE__ */ React__default["default"].createElement("animateTransform", {
3445
+ attributeName: "transform",
3446
+ dur: "1s",
3447
+ type: "translate",
3448
+ values: "0 15 ; 0 -5; 0 15",
3449
+ calcMode: "spline",
3450
+ keySplines: "0.8 0 0.4 1; 0.4 0 0.2 1",
3451
+ repeatCount: "indefinite",
3452
+ begin: "0.3"
3453
+ }))), /* @__PURE__ */ React__default["default"].createElement("p", {
3454
+ style: {
3455
+ fontSize: "16px",
3456
+ color: "#716c7f",
3457
+ textAlign: "center",
3458
+ lineHeight: "1.3",
3459
+ fontFamily: "'Inter', sans-serif",
3460
+ fontWeight: "normal"
3461
+ }
3462
+ }, "Please wait, Tina is loading data..."))));
3367
3463
  const useGetCollection = (cms, collectionName, includeDocuments = true) => {
3368
3464
  const api = new TinaAdminApi(cms);
3369
3465
  const [collection, setCollection] = React.useState(void 0);
3466
+ const [loading, setLoading] = React.useState(true);
3370
3467
  React.useEffect(() => {
3371
3468
  const fetchCollection = async () => {
3372
3469
  const response = await api.fetchCollection(collectionName, includeDocuments);
3373
3470
  setCollection(response.getCollection);
3471
+ setLoading(false);
3374
3472
  };
3473
+ setLoading(true);
3375
3474
  fetchCollection();
3376
3475
  }, [cms, collectionName]);
3377
- return collection;
3476
+ return { collection, loading };
3378
3477
  };
3379
3478
  const GetCollection = ({
3380
3479
  cms,
@@ -3382,11 +3481,11 @@ This will work when developing locally but NOT when deployed to production.
3382
3481
  includeDocuments = true,
3383
3482
  children
3384
3483
  }) => {
3385
- const collection = useGetCollection(cms, collectionName, includeDocuments);
3386
- if (!collection) {
3387
- return null;
3484
+ const { collection, loading } = useGetCollection(cms, collectionName, includeDocuments);
3485
+ if (!collection || loading === true) {
3486
+ return /* @__PURE__ */ React__default["default"].createElement(LoadingPage, null);
3388
3487
  }
3389
- return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, children(collection));
3488
+ return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, children(collection, loading));
3390
3489
  };
3391
3490
  const TemplateMenu = ({ templates }) => {
3392
3491
  return /* @__PURE__ */ React__default["default"].createElement(react.Menu, {
@@ -3415,12 +3514,21 @@ This will work when developing locally but NOT when deployed to production.
3415
3514
  className: `w-full text-md px-4 py-2 tracking-wide flex items-center opacity-80 text-gray-600 ${active && "text-gray-800 opacity-100"}`
3416
3515
  }, template.label))))))));
3417
3516
  };
3517
+ const handleNavigate = (navigate, cms, collection, document) => {
3518
+ const plugins = cms.plugins.all("tina-admin");
3519
+ const routeMapping = plugins.find(({ name }) => name === "route-mapping");
3520
+ const routeOverride = routeMapping ? routeMapping.mapper(collection, document) : void 0;
3521
+ if (routeOverride) {
3522
+ window.location.href = routeOverride;
3523
+ return null;
3524
+ } else {
3525
+ navigate(document.sys.filename);
3526
+ }
3527
+ };
3418
3528
  const CollectionListPage = () => {
3529
+ const navigate = reactRouterDom.useNavigate();
3419
3530
  const { collectionName } = reactRouterDom.useParams();
3420
- reactRouterDom.useNavigate();
3421
3531
  return /* @__PURE__ */ React__default["default"].createElement(GetCMS, null, (cms) => {
3422
- const plugins = cms.plugins.all("tina-admin");
3423
- const routeMapping = plugins.find(({ name }) => name === "route-mapping");
3424
3532
  return /* @__PURE__ */ React__default["default"].createElement(GetCollection, {
3425
3533
  cms,
3426
3534
  collectionName,
@@ -3447,24 +3555,16 @@ This will work when developing locally but NOT when deployed to production.
3447
3555
  }, /* @__PURE__ */ React__default["default"].createElement("tbody", {
3448
3556
  className: "divide-y divide-gray-150"
3449
3557
  }, documents.map((document) => {
3450
- const overrideRoute = routeMapping ? routeMapping.mapper(collection, document.node) : void 0;
3451
3558
  return /* @__PURE__ */ React__default["default"].createElement("tr", {
3452
3559
  key: `document-${document.node.sys.filename}`,
3453
3560
  className: ""
3454
3561
  }, /* @__PURE__ */ React__default["default"].createElement("td", {
3455
3562
  className: "px-6 py-2 whitespace-nowrap"
3456
- }, overrideRoute && /* @__PURE__ */ React__default["default"].createElement("a", {
3457
- className: "text-blue-600 hover:text-blue-400 flex items-center gap-3",
3458
- href: `${overrideRoute}`
3459
- }, /* @__PURE__ */ React__default["default"].createElement(BiEdit, {
3460
- className: "inline-block h-6 w-auto opacity-70"
3461
- }), /* @__PURE__ */ React__default["default"].createElement("span", null, /* @__PURE__ */ React__default["default"].createElement("span", {
3462
- className: "block text-xs text-gray-400 mb-1 uppercase"
3463
- }, "Filename"), /* @__PURE__ */ React__default["default"].createElement("span", {
3464
- className: "h-5 leading-5 block whitespace-nowrap"
3465
- }, document.node.sys.filename))), !overrideRoute && /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Link, {
3466
- className: "text-blue-600 hover:text-blue-400 flex items-center gap-3",
3467
- to: `${document.node.sys.filename}`
3563
+ }, /* @__PURE__ */ React__default["default"].createElement("a", {
3564
+ className: "text-blue-600 hover:text-blue-400 flex items-center gap-3 cursor-pointer",
3565
+ onClick: () => {
3566
+ handleNavigate(navigate, cms, collection, document.node);
3567
+ }
3468
3568
  }, /* @__PURE__ */ React__default["default"].createElement(BiEdit, {
3469
3569
  className: "inline-block h-6 w-auto opacity-70"
3470
3570
  }), /* @__PURE__ */ React__default["default"].createElement("span", null, /* @__PURE__ */ React__default["default"].createElement("span", {
@@ -3499,6 +3599,7 @@ This will work when developing locally but NOT when deployed to production.
3499
3599
  fields: void 0,
3500
3600
  mutationInfo: void 0
3501
3601
  });
3602
+ const [loading, setLoading] = React.useState(true);
3502
3603
  React.useEffect(() => {
3503
3604
  const fetchDocumentFields = async () => {
3504
3605
  const response = await api.fetchDocumentFields();
@@ -3519,10 +3620,12 @@ This will work when developing locally but NOT when deployed to production.
3519
3620
  fields,
3520
3621
  mutationInfo
3521
3622
  });
3623
+ setLoading(false);
3522
3624
  };
3625
+ setLoading(true);
3523
3626
  fetchDocumentFields();
3524
3627
  }, [cms, collectionName]);
3525
- return info;
3628
+ return __spreadProps(__spreadValues({}, info), { loading });
3526
3629
  };
3527
3630
  const GetDocumentFields = ({
3528
3631
  cms,
@@ -3530,11 +3633,11 @@ This will work when developing locally but NOT when deployed to production.
3530
3633
  templateName,
3531
3634
  children
3532
3635
  }) => {
3533
- const { collection, template, fields, mutationInfo } = useGetDocumentFields(cms, collectionName, templateName);
3534
- if (!collection) {
3535
- return null;
3636
+ const { collection, template, fields, mutationInfo, loading } = useGetDocumentFields(cms, collectionName, templateName);
3637
+ if (!collection || loading) {
3638
+ return /* @__PURE__ */ React__default["default"].createElement(LoadingPage, null);
3536
3639
  }
3537
- return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, children({ collection, template, fields, mutationInfo }));
3640
+ return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, children({ collection, template, fields, mutationInfo, loading }));
3538
3641
  };
3539
3642
  const createDocument = async (cms, collection, template, mutationInfo, values) => {
3540
3643
  const api = new TinaAdminApi(cms);
@@ -3624,14 +3727,17 @@ This will work when developing locally but NOT when deployed to production.
3624
3727
  const useGetDocument = (cms, collectionName, relativePath) => {
3625
3728
  const api = new TinaAdminApi(cms);
3626
3729
  const [document, setDocument] = React.useState(void 0);
3730
+ const [loading, setLoading] = React.useState(true);
3627
3731
  React.useEffect(() => {
3628
3732
  const fetchDocument = async () => {
3629
3733
  const response = await api.fetchDocument(collectionName, relativePath);
3630
3734
  setDocument(response.getDocument);
3735
+ setLoading(false);
3631
3736
  };
3737
+ setLoading(true);
3632
3738
  fetchDocument();
3633
3739
  }, [cms, collectionName, relativePath]);
3634
- return document;
3740
+ return { document, loading };
3635
3741
  };
3636
3742
  const GetDocument = ({
3637
3743
  cms,
@@ -3639,11 +3745,11 @@ This will work when developing locally but NOT when deployed to production.
3639
3745
  relativePath,
3640
3746
  children
3641
3747
  }) => {
3642
- const document = useGetDocument(cms, collectionName, relativePath);
3643
- if (!document) {
3644
- return null;
3748
+ const { document, loading } = useGetDocument(cms, collectionName, relativePath);
3749
+ if (!document || loading) {
3750
+ return /* @__PURE__ */ React__default["default"].createElement(LoadingPage, null);
3645
3751
  }
3646
- return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, children(document));
3752
+ return /* @__PURE__ */ React__default["default"].createElement(React__default["default"].Fragment, null, children(document, loading));
3647
3753
  };
3648
3754
  const updateDocument = async (cms, relativePath, collection, mutationInfo, values) => {
3649
3755
  const api = new TinaAdminApi(cms);
@@ -3763,7 +3869,7 @@ This will work when developing locally but NOT when deployed to production.
3763
3869
  }, /* @__PURE__ */ React__default["default"].createElement(Sidebar, {
3764
3870
  cms
3765
3871
  }), /* @__PURE__ */ React__default["default"].createElement("div", {
3766
- className: "flex-1"
3872
+ className: "flex-1 relative"
3767
3873
  }, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Routes, null, /* @__PURE__ */ React__default["default"].createElement(reactRouterDom.Route, {
3768
3874
  path: "collections/:collectionName/new",
3769
3875
  element: /* @__PURE__ */ React__default["default"].createElement(CollectionCreatePage, null)
package/dist/style.css CHANGED
@@ -725,6 +725,10 @@ Document
725
725
  height: 20px !important;
726
726
  }
727
727
 
728
+ .tina-tailwind .h-12 {
729
+ height: 48px !important;
730
+ }
731
+
728
732
  .tina-tailwind .w-full {
729
733
  width: 100% !important;
730
734
  }
@@ -769,6 +773,14 @@ Document
769
773
  flex: 1 1 0% !important;
770
774
  }
771
775
 
776
+ .tina-tailwind .flex-shrink-0 {
777
+ flex-shrink: 0 !important;
778
+ }
779
+
780
+ .tina-tailwind .flex-grow-0 {
781
+ flex-grow: 0 !important;
782
+ }
783
+
772
784
  .tina-tailwind .table-auto {
773
785
  table-layout: auto !important;
774
786
  }
@@ -808,6 +820,10 @@ Document
808
820
  transform: var(--tw-transform) !important;
809
821
  }
810
822
 
823
+ .tina-tailwind .cursor-pointer {
824
+ cursor: pointer !important;
825
+ }
826
+
811
827
  .tina-tailwind .flex-col {
812
828
  flex-direction: column !important;
813
829
  }
@@ -824,6 +840,10 @@ Document
824
840
  align-items: stretch !important;
825
841
  }
826
842
 
843
+ .tina-tailwind .justify-end {
844
+ justify-content: flex-end !important;
845
+ }
846
+
827
847
  .tina-tailwind .justify-center {
828
848
  justify-content: center !important;
829
849
  }
@@ -891,10 +911,6 @@ Document
891
911
  border-color: rgba(225, 221, 236, var(--tw-border-opacity)) !important;
892
912
  }
893
913
 
894
- .tina-tailwind .border-transparent {
895
- border-color: transparent !important;
896
- }
897
-
898
914
  .tina-tailwind .bg-white {
899
915
  --tw-bg-opacity: 1 !important;
900
916
  background-color: rgba(255, 255, 255, var(--tw-bg-opacity)) !important;
@@ -978,9 +994,8 @@ Document
978
994
  padding-bottom: 12px !important;
979
995
  }
980
996
 
981
- .tina-tailwind .px-8 {
982
- padding-left: 32px !important;
983
- padding-right: 32px !important;
997
+ .tina-tailwind .pt-4 {
998
+ padding-top: 16px !important;
984
999
  }
985
1000
 
986
1001
  .tina-tailwind .pb-4 {
@@ -1057,10 +1072,6 @@ Document
1057
1072
  line-height: 20px !important;
1058
1073
  }
1059
1074
 
1060
- .tina-tailwind .leading-4 {
1061
- line-height: 16px !important;
1062
- }
1063
-
1064
1075
  .tina-tailwind .tracking-wide {
1065
1076
  letter-spacing: 0.025em !important;
1066
1077
  }
@@ -1162,11 +1173,6 @@ Document
1162
1173
  box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow) !important;
1163
1174
  }
1164
1175
 
1165
- .tina-tailwind .shadow-sm {
1166
- --tw-shadow: 0 1px 2px 0 rgba(0, 0, 0, 0.05) !important;
1167
- box-shadow: var(--tw-ring-offset-shadow, 0 0 #0000), var(--tw-ring-shadow, 0 0 #0000), var(--tw-shadow) !important;
1168
- }
1169
-
1170
1176
  .tina-tailwind .ring-1 {
1171
1177
  --tw-ring-offset-shadow: var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color) !important;
1172
1178
  --tw-ring-shadow: var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color) !important;
@@ -1261,11 +1267,6 @@ Document
1261
1267
  background-color: rgba(5, 116, 228, var(--tw-bg-opacity)) !important;
1262
1268
  }
1263
1269
 
1264
- .hover\:bg-gray-50:hover {
1265
- --tw-bg-opacity: 1 !important;
1266
- background-color: rgba(246, 246, 249, var(--tw-bg-opacity)) !important;
1267
- }
1268
-
1269
1270
  .hover\:text-blue-600:hover {
1270
1271
  --tw-text-opacity: 1 !important;
1271
1272
  color: rgba(5, 116, 228, var(--tw-text-opacity)) !important;
@@ -1280,10 +1281,6 @@ Document
1280
1281
  opacity: 1 !important;
1281
1282
  }
1282
1283
 
1283
- .hover\:opacity-80:hover {
1284
- opacity: .8 !important;
1285
- }
1286
-
1287
1284
  .focus\:text-blue-400:focus {
1288
1285
  --tw-text-opacity: 1 !important;
1289
1286
  color: rgba(34, 150, 254, var(--tw-text-opacity)) !important;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tinacms",
3
- "version": "0.66.4",
3
+ "version": "0.66.5",
4
4
  "main": "dist/index.js",
5
5
  "files": [
6
6
  "dist"
@@ -24,7 +24,7 @@
24
24
  "@headlessui/react": "^1.4.1",
25
25
  "@heroicons/react": "^1.0.4",
26
26
  "@tinacms/sharedctx": "0.1.0",
27
- "@tinacms/toolkit": "0.56.14",
27
+ "@tinacms/toolkit": "0.56.15",
28
28
  "crypto-js": "^4.0.0",
29
29
  "final-form": "4.20.1",
30
30
  "graphql": "^15.1.0",