tinacms 1.5.22 → 1.5.24

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
@@ -1,6 +1,6 @@
1
1
  (function(global, factory) {
2
- typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("zod"), require("react"), require("react-dom"), require("@udecode/plate-headless"), require("@monaco-editor/react"), require("slate-react"), require("@headlessui/react"), require("slate"), require("final-form-arrays"), require("final-form-set-field-data"), require("final-form"), require("react-final-form"), require("prop-types"), require("react-beautiful-dnd"), require("@radix-ui/react-popover"), require("react-color"), require("color-string"), require("react-dropzone"), require("@tinacms/sharedctx"), require("is-hotkey"), require("@floating-ui/dom"), require("moment"), require("date-fns"), require("@react-hook/window-size"), require("graphql"), require("graphql-tag"), require("@tinacms/schema-tools"), require("yup"), require("@graphql-inspector/core"), require("react-router-dom"), require("@tinacms/mdx")) : typeof define === "function" && define.amd ? define(["exports", "zod", "react", "react-dom", "@udecode/plate-headless", "@monaco-editor/react", "slate-react", "@headlessui/react", "slate", "final-form-arrays", "final-form-set-field-data", "final-form", "react-final-form", "prop-types", "react-beautiful-dnd", "@radix-ui/react-popover", "react-color", "color-string", "react-dropzone", "@tinacms/sharedctx", "is-hotkey", "@floating-ui/dom", "moment", "date-fns", "@react-hook/window-size", "graphql", "graphql-tag", "@tinacms/schema-tools", "yup", "@graphql-inspector/core", "react-router-dom", "@tinacms/mdx"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.tinacms = {}, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP));
3
- })(this, function(exports2, zod, React, reactDom, plateHeadless, MonacoEditor, slateReact, react, slate, arrayMutators, setFieldData, finalForm, reactFinalForm, PropTypes, reactBeautifulDnd, Popover$1, pkg$1, pkg, dropzone, sharedctx, isHotkey, dom, moment, dateFns, windowSize, graphql, gql$1, schemaTools, yup, core, reactRouterDom, mdx) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("zod"), require("react"), require("react-dom"), require("@udecode/plate-headless"), require("@monaco-editor/react"), require("slate-react"), require("@headlessui/react"), require("slate"), require("final-form-arrays"), require("final-form-set-field-data"), require("final-form"), require("react-final-form"), require("prop-types"), require("react-beautiful-dnd"), require("@radix-ui/react-popover"), require("react-color"), require("color-string"), require("react-dropzone"), require("@tinacms/sharedctx"), require("lodash.get"), require("moment"), require("date-fns"), require("@react-hook/window-size"), require("is-hotkey"), require("@floating-ui/dom"), require("graphql"), require("graphql-tag"), require("@tinacms/schema-tools"), require("yup"), require("@graphql-inspector/core"), require("react-router-dom"), require("@tinacms/mdx")) : typeof define === "function" && define.amd ? define(["exports", "zod", "react", "react-dom", "@udecode/plate-headless", "@monaco-editor/react", "slate-react", "@headlessui/react", "slate", "final-form-arrays", "final-form-set-field-data", "final-form", "react-final-form", "prop-types", "react-beautiful-dnd", "@radix-ui/react-popover", "react-color", "color-string", "react-dropzone", "@tinacms/sharedctx", "lodash.get", "moment", "date-fns", "@react-hook/window-size", "is-hotkey", "@floating-ui/dom", "graphql", "graphql-tag", "@tinacms/schema-tools", "yup", "@graphql-inspector/core", "react-router-dom", "@tinacms/mdx"], factory) : (global = typeof globalThis !== "undefined" ? globalThis : global || self, factory(global.tinacms = {}, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP, global.NOOP));
3
+ })(this, function(exports2, zod, React, reactDom, plateHeadless, MonacoEditor, slateReact, react, slate, arrayMutators, setFieldData, finalForm, reactFinalForm, PropTypes, reactBeautifulDnd, Popover$1, pkg$1, pkg, dropzone, sharedctx, get, moment, dateFns, windowSize, isHotkey, dom, graphql, gql$1, schemaTools, yup, core, reactRouterDom, mdx) {
4
4
  "use strict";var __defProp = Object.defineProperty;
5
5
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
6
6
  var __publicField = (obj, key, value) => {
@@ -30,42 +30,6 @@ var __publicField = (obj, key, value) => {
30
30
  const pkg__namespace = /* @__PURE__ */ _interopNamespaceDefault(pkg);
31
31
  const dropzone__namespace = /* @__PURE__ */ _interopNamespaceDefault(dropzone);
32
32
  const yup__namespace = /* @__PURE__ */ _interopNamespaceDefault(yup);
33
- function popupWindow(url, title, window2, w, h) {
34
- const y = window2.top.outerHeight / 2 + window2.top.screenY - h / 2;
35
- const x = window2.top.outerWidth / 2 + window2.top.screenX - w / 2;
36
- return window2.open(
37
- url,
38
- title,
39
- "toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=no, width=" + w + ", height=" + h + ", top=" + y + ", left=" + x
40
- );
41
- }
42
- const TINA_LOGIN_EVENT = "tinaCloudLogin";
43
- const AUTH_TOKEN_KEY = "tinacms-auth";
44
- const authenticate = (clientId, frontendUrl) => {
45
- return new Promise((resolve) => {
46
- let authTab;
47
- window.addEventListener("message", function(e) {
48
- if (e.data.source === TINA_LOGIN_EVENT) {
49
- if (authTab) {
50
- authTab.close();
51
- }
52
- resolve({
53
- id_token: e.data.id_token,
54
- access_token: e.data.access_token,
55
- refresh_token: e.data.refresh_token
56
- });
57
- }
58
- });
59
- const origin = `${window.location.protocol}//${window.location.host}`;
60
- authTab = popupWindow(
61
- `${frontendUrl}/signin?clientId=${clientId}&origin=${origin}`,
62
- "_blank",
63
- window,
64
- 1e3,
65
- 700
66
- );
67
- });
68
- };
69
33
  const ModalProvider = ({ children }) => {
70
34
  const [modalRootContainerRef, setModalRootContainerRef] = React.useState(
71
35
  null
@@ -1810,8 +1774,15 @@ var __publicField = (obj, key, value) => {
1810
1774
  return this.finalForm.subscribe(cb, options2);
1811
1775
  };
1812
1776
  this.handleSubmit = async (values, form, cb) => {
1777
+ var _a;
1813
1778
  try {
1814
- const response = await this.onSubmit(values, form, cb);
1779
+ const valOverride = await ((_a = this.beforeSubmit) == null ? void 0 : _a.call(this, values));
1780
+ if (valOverride) {
1781
+ for (const [key, value] of Object.entries(valOverride)) {
1782
+ form.change(key, value);
1783
+ }
1784
+ }
1785
+ const response = await this.onSubmit(valOverride || values, form, cb);
1815
1786
  form.initialize(values);
1816
1787
  return response;
1817
1788
  } catch (error) {
@@ -2349,6 +2320,7 @@ var __publicField = (obj, key, value) => {
2349
2320
  {
2350
2321
  name: field.name,
2351
2322
  key: field.name,
2323
+ isEqual: (a, b) => isEqual(field, a, b),
2352
2324
  type,
2353
2325
  parse: parse2 ? (value, name) => parse2(value, name, field) : void 0,
2354
2326
  format: format2 ? (value, name) => format2(value, name, field) : void 0,
@@ -2406,6 +2378,18 @@ var __publicField = (obj, key, value) => {
2406
2378
  }
2407
2379
  return prop;
2408
2380
  }
2381
+ const isEqual = (field, a, b) => {
2382
+ const replacer = (key, value) => {
2383
+ if (key === "id") {
2384
+ return void 0;
2385
+ }
2386
+ return value;
2387
+ };
2388
+ if (field.type === "rich-text") {
2389
+ return JSON.stringify(a, replacer) === JSON.stringify(b, replacer);
2390
+ }
2391
+ return a === b;
2392
+ };
2409
2393
  const FF = reactFinalForm.Form;
2410
2394
  const FormLegacy = ({ form, children }) => {
2411
2395
  const [i, setI] = React__namespace.useState(0);
@@ -2450,7 +2434,7 @@ var __publicField = (obj, key, value) => {
2450
2434
  disabled,
2451
2435
  rounded = "full",
2452
2436
  children,
2453
- className,
2437
+ className = "",
2454
2438
  ...props
2455
2439
  }) => {
2456
2440
  const baseClasses = "icon-parent inline-flex items-center font-medium focus:outline-none focus:ring-2 focus:shadow-outline text-center inline-flex justify-center transition-all duration-150 ease-out ";
@@ -3066,6 +3050,9 @@ var __publicField = (obj, key, value) => {
3066
3050
  function IoMdRefresh(props) {
3067
3051
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 512 512" }, "child": [{ "tag": "path", "attr": { "d": "M256 388c-72.597 0-132-59.405-132-132 0-72.601 59.403-132 132-132 36.3 0 69.299 15.4 92.406 39.601L278 234h154V80l-51.698 51.702C348.406 99.798 304.406 80 256 80c-96.797 0-176 79.203-176 176s78.094 176 176 176c81.045 0 148.287-54.134 169.401-128H378.85c-18.745 49.561-67.138 84-122.85 84z" } }] })(props);
3068
3052
  }
3053
+ function MdVpnKey(props) {
3054
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "fill": "none", "d": "M0 0h24v24H0z" } }, { "tag": "path", "attr": { "d": "M12.65 10A5.99 5.99 0 007 6c-3.31 0-6 2.69-6 6s2.69 6 6 6a5.99 5.99 0 005.65-4H17v4h4v-4h2v-4H12.65zM7 14c-1.1 0-2-.9-2-2s.9-2 2-2 2 .9 2 2-.9 2-2 2z" } }] })(props);
3055
+ }
3069
3056
  function MdKeyboardArrowDown(props) {
3070
3057
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "fill": "none", "d": "M0 0h24v24H0V0z" } }, { "tag": "path", "attr": { "d": "M7.41 8.59L12 13.17l4.59-4.58L18 10l-6 6-6-6 1.41-1.41z" } }] })(props);
3071
3058
  }
@@ -3127,14 +3114,14 @@ var __publicField = (obj, key, value) => {
3127
3114
  return branchData;
3128
3115
  };
3129
3116
  const textFieldClasses = "shadow-inner focus:shadow-outline focus:border-blue-500 focus:outline-none block text-base placeholder:text-gray-300 px-3 py-2 text-gray-600 w-full bg-white border border-gray-200 transition-all ease-out duration-150 focus:text-gray-900 rounded-md";
3130
- const disabledClasses = "opacity-50 pointer-events-none cursor-not-allowed";
3117
+ const disabledClasses$1 = "opacity-50 pointer-events-none cursor-not-allowed";
3131
3118
  const BaseTextField = React__namespace.forwardRef(({ className, disabled, ...rest }, ref) => {
3132
3119
  return /* @__PURE__ */ React__namespace.createElement(
3133
3120
  "input",
3134
3121
  {
3135
3122
  ref,
3136
3123
  type: "text",
3137
- className: `${textFieldClasses} ${disabled ? disabledClasses : ""} ${className}`,
3124
+ className: `${textFieldClasses} ${disabled ? disabledClasses$1 : ""} ${className}`,
3138
3125
  ...rest
3139
3126
  }
3140
3127
  );
@@ -3953,6 +3940,20 @@ var __publicField = (obj, key, value) => {
3953
3940
  return option;
3954
3941
  return { value: option, label: option };
3955
3942
  }
3943
+ const passwordFieldClasses = "shadow-inner focus:shadow-outline focus:border-blue-500 focus:outline-none block text-base placeholder:text-gray-300 px-3 py-2 text-gray-600 w-full bg-white border border-gray-200 transition-all ease-out duration-150 focus:text-gray-900 rounded-md";
3944
+ const disabledClasses = "opacity-50 pointer-events-none cursor-not-allowed";
3945
+ const errorClasses = "border-red-500 focus:border-red-500 focus:shadow-outline-red";
3946
+ const BasePasswordField = React__namespace.forwardRef(({ className, disabled, error, ...rest }, ref) => {
3947
+ return /* @__PURE__ */ React__namespace.createElement(
3948
+ "input",
3949
+ {
3950
+ ref,
3951
+ type: "password",
3952
+ className: `${passwordFieldClasses} ${disabled ? disabledClasses : ""} ${className} ${error ? errorClasses : ""}`,
3953
+ ...rest
3954
+ }
3955
+ );
3956
+ });
3956
3957
  const Group$1 = wrapFieldWithError(({ tinaForm, field }) => {
3957
3958
  const cms = useCMS$1();
3958
3959
  React__namespace.useState(false);
@@ -5039,9 +5040,19 @@ var __publicField = (obj, key, value) => {
5039
5040
  const TextFieldPlugin = {
5040
5041
  name: "text",
5041
5042
  Component: TextField,
5042
- validate(value, values, meta, field) {
5043
+ validate(value, allValues, meta, field) {
5044
+ var _a;
5043
5045
  if (field.required && !value)
5044
5046
  return "Required";
5047
+ if (field.uid) {
5048
+ const path = field.name.split(".");
5049
+ const fieldName = path[path.length - 1];
5050
+ const parent = path.slice(0, path.length - 2);
5051
+ const items = get(allValues, parent);
5052
+ if (((_a = items == null ? void 0 : items.filter((item) => item[fieldName] === value)) == null ? void 0 : _a.length) > 1) {
5053
+ return `Item with this unique id already exists`;
5054
+ }
5055
+ }
5045
5056
  },
5046
5057
  parse: parse$2
5047
5058
  };
@@ -5704,7 +5715,7 @@ var __publicField = (obj, key, value) => {
5704
5715
  }
5705
5716
  var passive = false;
5706
5717
  var options = Object.defineProperty({}, "passive", {
5707
- get: function get() {
5718
+ get: function get2() {
5708
5719
  passive = true;
5709
5720
  }
5710
5721
  });
@@ -6552,6 +6563,111 @@ var __publicField = (obj, key, value) => {
6552
6563
  Component: HiddenField,
6553
6564
  parse: parse$2
6554
6565
  };
6566
+ const PasswordMask = "********";
6567
+ const PasswordFieldComponent = wrapFieldsWithMeta(({ field, form, meta, input, children }) => {
6568
+ const ref1 = React__namespace.useRef(null);
6569
+ const ref2 = React__namespace.useRef(null);
6570
+ const [error, setError] = React__namespace.useState(false);
6571
+ const [password, setPassword] = React__namespace.useState();
6572
+ const [confirmPassword, setConfirmPassword] = React__namespace.useState();
6573
+ const [passwordChangeRequired, setPasswordChangeRequired] = React__namespace.useState(input.value.passwordChangeRequired);
6574
+ React__namespace.useEffect(() => {
6575
+ if (password) {
6576
+ if (password === confirmPassword) {
6577
+ setError(false);
6578
+ form.change(field.name, { value: password, passwordChangeRequired });
6579
+ } else {
6580
+ setError(true);
6581
+ form.change(field.name, void 0);
6582
+ }
6583
+ } else {
6584
+ setError(false);
6585
+ form.change(field.name, { passwordChangeRequired });
6586
+ }
6587
+ }, [password, confirmPassword, passwordChangeRequired]);
6588
+ return /* @__PURE__ */ React__namespace.createElement("div", { className: "flex flex-col" }, /* @__PURE__ */ React__namespace.createElement("div", { className: "flex flex-row space-x-4" }, /* @__PURE__ */ React__namespace.createElement(
6589
+ BasePasswordField,
6590
+ {
6591
+ autoComplete: "off",
6592
+ value: password ?? PasswordMask,
6593
+ ref: ref1,
6594
+ disabled: (field == null ? void 0 : field.disabled) ?? false,
6595
+ error,
6596
+ placeholder: field.placeholder || "Password",
6597
+ onKeyDown: (_) => {
6598
+ if (password === void 0) {
6599
+ setPassword("");
6600
+ }
6601
+ if (confirmPassword === void 0) {
6602
+ setConfirmPassword("");
6603
+ }
6604
+ },
6605
+ onChange: (event) => {
6606
+ setPassword(event.target.value);
6607
+ }
6608
+ }
6609
+ ), /* @__PURE__ */ React__namespace.createElement(
6610
+ BasePasswordField,
6611
+ {
6612
+ autoComplete: "off",
6613
+ ref: ref2,
6614
+ value: confirmPassword ?? PasswordMask,
6615
+ disabled: (field == null ? void 0 : field.disabled) ?? false,
6616
+ error,
6617
+ placeholder: field.confirmPlaceholder || "Confirm Password",
6618
+ onKeyDown: (_) => {
6619
+ setPasswordChangeRequired(true);
6620
+ if (password === void 0) {
6621
+ setPassword("");
6622
+ }
6623
+ if (confirmPassword === void 0) {
6624
+ setConfirmPassword("");
6625
+ }
6626
+ },
6627
+ onChange: (event) => {
6628
+ setConfirmPassword(event.target.value);
6629
+ }
6630
+ }
6631
+ ), /* @__PURE__ */ React__namespace.createElement(
6632
+ Button,
6633
+ {
6634
+ variant: "secondary",
6635
+ disabled: password === void 0 && confirmPassword === void 0,
6636
+ onClick: () => {
6637
+ setError(false);
6638
+ setPassword(void 0);
6639
+ setConfirmPassword(void 0);
6640
+ setPasswordChangeRequired(void 0);
6641
+ form.change(field.name, void 0);
6642
+ }
6643
+ },
6644
+ "Reset"
6645
+ )), /* @__PURE__ */ React__namespace.createElement("div", { className: "flex w-full items-center pl-1 pt-3" }, /* @__PURE__ */ React__namespace.createElement(
6646
+ Toggle,
6647
+ {
6648
+ field: { name: "passwordChangeRequired", component: "toggle" },
6649
+ input: {
6650
+ value: passwordChangeRequired ?? true,
6651
+ onChange: () => setPasswordChangeRequired(!passwordChangeRequired)
6652
+ },
6653
+ name: "passwordChangeRequired"
6654
+ }
6655
+ ), /* @__PURE__ */ React__namespace.createElement("div", null, /* @__PURE__ */ React__namespace.createElement("label", { className: "block font-sans text-xs font-semibold text-gray-700 whitespace-normal h-full items-center ml-1" }, "Require Password Change on Next Login"))));
6656
+ });
6657
+ const PasswordFieldPlugin = {
6658
+ name: "password",
6659
+ Component: PasswordFieldComponent,
6660
+ validate(value, values, meta, field) {
6661
+ let password = value;
6662
+ if (Array.isArray(value)) {
6663
+ password = value[0];
6664
+ }
6665
+ if (field.required && (password == null ? void 0 : password.passwordChangeRequired) === void 0) {
6666
+ return "Required";
6667
+ }
6668
+ },
6669
+ parse: parse$2
6670
+ };
6555
6671
  function GrCircleQuestion(props) {
6556
6672
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "fill": "none", "stroke": "#000", "strokeWidth": "2", "d": "M12,22 C17.5228475,22 22,17.5228475 22,12 C22,6.4771525 17.5228475,2 12,2 C6.4771525,2 2,6.4771525 2,12 C2,17.5228475 6.4771525,22 12,22 Z M12,15 L12,14 C12,13 12,12.5 13,12 C14,11.5 15,11 15,9.5 C15,8.5 14,7 12,7 C10,7 9,8.26413718 9,10 M12,16 L12,18" } }] })(props);
6557
6673
  }
@@ -7113,7 +7229,7 @@ var __publicField = (obj, key, value) => {
7113
7229
  toolbarItems: [
7114
7230
  branch.githubPullRequestUrl && {
7115
7231
  name: "github-pr",
7116
- label: "View in Github",
7232
+ label: "View in GitHub",
7117
7233
  Icon: /* @__PURE__ */ React__namespace.createElement(BiLinkExternal, { className: "w-5 h-auto text-blue-500 opacity-70" }),
7118
7234
  onMouseDown: () => {
7119
7235
  window.open(branch.githubPullRequestUrl, "_blank");
@@ -7506,14 +7622,19 @@ var __publicField = (obj, key, value) => {
7506
7622
  if (!this.api) {
7507
7623
  this.api = (_b = (_a = this.cms) == null ? void 0 : _a.api) == null ? void 0 : _b.tina;
7508
7624
  this.isLocal = !!this.api.isLocalMode;
7509
- const contentApiUrl = new URL(this.api.contentApiUrl);
7510
- this.url = `${contentApiUrl.origin}/media`;
7511
- if (!this.isLocal) {
7512
- if ((_d = (_c = this.api.options) == null ? void 0 : _c.tinaioConfig) == null ? void 0 : _d.assetsApiUrlOverride) {
7513
- const url = new URL(this.api.assetsApiUrl);
7514
- this.url = `${url.origin}/v1/${this.api.clientId}`;
7515
- } else {
7516
- this.url = `${contentApiUrl.origin.replace("content", "assets")}/v1/${this.api.clientId}`;
7625
+ if (!this.isStatic) {
7626
+ const contentApiUrl = new URL(this.api.contentApiUrl);
7627
+ this.url = `${contentApiUrl.origin}/media`;
7628
+ if (!this.isLocal) {
7629
+ if ((_d = (_c = this.api.options) == null ? void 0 : _c.tinaioConfig) == null ? void 0 : _d.assetsApiUrlOverride) {
7630
+ const url = new URL(this.api.assetsApiUrl);
7631
+ this.url = `${url.origin}/v1/${this.api.clientId}`;
7632
+ } else {
7633
+ this.url = `${contentApiUrl.origin.replace(
7634
+ "content",
7635
+ "assets"
7636
+ )}/v1/${this.api.clientId}`;
7637
+ }
7517
7638
  }
7518
7639
  }
7519
7640
  }
@@ -7535,6 +7656,10 @@ var __publicField = (obj, key, value) => {
7535
7656
  `${this.url}/upload_url/${path}`,
7536
7657
  { method: "GET" }
7537
7658
  );
7659
+ if (res.status === 412) {
7660
+ const { message = "Unexpected error generating upload url" } = await res.json();
7661
+ throw new Error(message);
7662
+ }
7538
7663
  const { signedUrl } = await res.json();
7539
7664
  if (!signedUrl) {
7540
7665
  throw new Error("Unexpected error generating upload url");
@@ -7649,6 +7774,38 @@ var __publicField = (obj, key, value) => {
7649
7774
  }
7650
7775
  async list(options) {
7651
7776
  this.setup();
7777
+ if (this.staticMedia) {
7778
+ const offset = options.offset || 0;
7779
+ const media = this.staticMedia[String(offset)];
7780
+ let hasMore = false;
7781
+ if (this.staticMedia[String(Number(offset) + 20)]) {
7782
+ hasMore = true;
7783
+ }
7784
+ if (options.directory) {
7785
+ let depth = 0;
7786
+ const pathToDirectory = options.directory.split("/");
7787
+ let currentFolder = media;
7788
+ let hasMore2 = false;
7789
+ while (depth < pathToDirectory.length) {
7790
+ const nextFolder = currentFolder.find(
7791
+ (item) => item.type === "dir" && item.filename === pathToDirectory[depth]
7792
+ );
7793
+ if (nextFolder) {
7794
+ const offset2 = options.offset || 0;
7795
+ currentFolder = nextFolder.children[String(offset2)];
7796
+ if (nextFolder.children[String(Number(offset2) + 20)]) {
7797
+ hasMore2 = true;
7798
+ }
7799
+ }
7800
+ depth++;
7801
+ }
7802
+ return {
7803
+ items: currentFolder,
7804
+ nextOffset: hasMore2 ? Number(offset) + 20 : null
7805
+ };
7806
+ }
7807
+ return { items: media, nextOffset: hasMore ? Number(offset) + 20 : null };
7808
+ }
7652
7809
  let res;
7653
7810
  if (!this.isLocal) {
7654
7811
  if (await this.isAuthenticated()) {
@@ -7701,38 +7858,6 @@ var __publicField = (obj, key, value) => {
7701
7858
  filename: dir
7702
7859
  });
7703
7860
  }
7704
- if (this.staticMedia) {
7705
- const offset = options.offset || 0;
7706
- const media = this.staticMedia[String(offset)];
7707
- let hasMore = false;
7708
- if (this.staticMedia[String(Number(offset) + 20)]) {
7709
- hasMore = true;
7710
- }
7711
- if (options.directory) {
7712
- let depth = 0;
7713
- const pathToDirectory = options.directory.split("/");
7714
- let currentFolder = media;
7715
- let hasMore2 = false;
7716
- while (depth < pathToDirectory.length) {
7717
- const nextFolder = currentFolder.find(
7718
- (item) => item.type === "dir" && item.filename === pathToDirectory[depth]
7719
- );
7720
- if (nextFolder) {
7721
- const offset2 = options.offset || 0;
7722
- currentFolder = nextFolder.children[String(offset2)];
7723
- if (nextFolder.children[String(Number(offset2) + 20)]) {
7724
- hasMore2 = true;
7725
- }
7726
- }
7727
- depth++;
7728
- }
7729
- return {
7730
- items: currentFolder,
7731
- nextOffset: hasMore2 ? Number(offset) + 20 : null
7732
- };
7733
- }
7734
- return { items: media, nextOffset: hasMore ? Number(offset) + 20 : null };
7735
- }
7736
7861
  return {
7737
7862
  items,
7738
7863
  nextOffset: cursor || 0
@@ -8398,6 +8523,9 @@ var __publicField = (obj, key, value) => {
8398
8523
  function ImFilesEmpty(props) {
8399
8524
  return GenIcon({ "tag": "svg", "attr": { "version": "1.1", "viewBox": "0 0 16 16" }, "child": [{ "tag": "path", "attr": { "d": "M14.341 5.579c-0.347-0.473-0.831-1.027-1.362-1.558s-1.085-1.015-1.558-1.362c-0.806-0.591-1.197-0.659-1.421-0.659h-5.75c-0.689 0-1.25 0.561-1.25 1.25v11.5c0 0.689 0.561 1.25 1.25 1.25h9.5c0.689 0 1.25-0.561 1.25-1.25v-7.75c0-0.224-0.068-0.615-0.659-1.421zM12.271 4.729c0.48 0.48 0.856 0.912 1.134 1.271h-2.406v-2.405c0.359 0.278 0.792 0.654 1.271 1.134v0zM14 14.75c0 0.136-0.114 0.25-0.25 0.25h-9.5c-0.136 0-0.25-0.114-0.25-0.25v-11.5c0-0.135 0.114-0.25 0.25-0.25 0 0 5.749-0 5.75 0v3.5c0 0.276 0.224 0.5 0.5 0.5h3.5v7.75z" } }, { "tag": "path", "attr": { "d": "M9.421 0.659c-0.806-0.591-1.197-0.659-1.421-0.659h-5.75c-0.689 0-1.25 0.561-1.25 1.25v11.5c0 0.604 0.43 1.109 1 1.225v-12.725c0-0.135 0.115-0.25 0.25-0.25h7.607c-0.151-0.124-0.297-0.238-0.437-0.341z" } }] })(props);
8400
8525
  }
8526
+ function ImUsers(props) {
8527
+ return GenIcon({ "tag": "svg", "attr": { "version": "1.1", "viewBox": "0 0 18 16" }, "child": [{ "tag": "path", "attr": { "d": "M12 12.041v-0.825c1.102-0.621 2-2.168 2-3.716 0-2.485 0-4.5-3-4.5s-3 2.015-3 4.5c0 1.548 0.898 3.095 2 3.716v0.825c-3.392 0.277-6 1.944-6 3.959h14c0-2.015-2.608-3.682-6-3.959z" } }, { "tag": "path", "attr": { "d": "M5.112 12.427c0.864-0.565 1.939-0.994 3.122-1.256-0.235-0.278-0.449-0.588-0.633-0.922-0.475-0.863-0.726-1.813-0.726-2.748 0-1.344 0-2.614 0.478-3.653 0.464-1.008 1.299-1.633 2.488-1.867-0.264-1.195-0.968-1.98-2.841-1.98-3 0-3 2.015-3 4.5 0 1.548 0.898 3.095 2 3.716v0.825c-3.392 0.277-6 1.944-6 3.959h4.359c0.227-0.202 0.478-0.393 0.753-0.573z" } }] })(props);
8528
+ }
8401
8529
  const LocalWarning = () => {
8402
8530
  return /* @__PURE__ */ React__namespace.createElement(
8403
8531
  "a",
@@ -8485,10 +8613,10 @@ var __publicField = (obj, key, value) => {
8485
8613
  const [error, setError] = React.useState(void 0);
8486
8614
  React__namespace.useEffect(() => {
8487
8615
  const fetchEvents = async () => {
8488
- var _a, _b, _c, _d;
8616
+ var _a, _b, _c, _d, _e;
8489
8617
  let doFetchEvents = false;
8490
8618
  if (!((_b = (_a = cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isCustomContentApi)) {
8491
- doFetchEvents = await ((_d = (_c = cms.api) == null ? void 0 : _c.tina) == null ? void 0 : _d.isAuthenticated());
8619
+ doFetchEvents = await ((_e = (_d = (_c = cms.api) == null ? void 0 : _c.tina) == null ? void 0 : _d.authProvider) == null ? void 0 : _e.isAuthenticated());
8492
8620
  }
8493
8621
  if (doFetchEvents) {
8494
8622
  try {
@@ -8647,17 +8775,40 @@ var __publicField = (obj, key, value) => {
8647
8775
  RenderNavSite,
8648
8776
  RenderNavCloud,
8649
8777
  RenderNavCollection,
8778
+ AuthRenderNavCollection,
8650
8779
  ...props
8651
8780
  }) => {
8652
8781
  const cms = useCMS$1();
8653
8782
  const { setEdit } = sharedctx.useEditState();
8654
8783
  const [eventsOpen, setEventsOpen] = React__namespace.useState(false);
8784
+ const { contentCollections, authCollection } = collectionsInfo.collections.reduce(
8785
+ (acc, collection) => {
8786
+ if (collection.isAuthCollection) {
8787
+ acc.authCollection = collection;
8788
+ } else {
8789
+ acc.contentCollections.push(collection);
8790
+ }
8791
+ return acc;
8792
+ },
8793
+ {
8794
+ contentCollections: []
8795
+ }
8796
+ );
8655
8797
  function closeEventsModal() {
8656
8798
  setEventsOpen(false);
8657
8799
  }
8658
8800
  const WrappedSyncStatus = React__namespace.forwardRef(
8659
8801
  (props2, ref) => /* @__PURE__ */ React__namespace.createElement(SyncStatus, { ...props2 })
8660
8802
  );
8803
+ const screenCategories = screens.reduce(
8804
+ (acc, screen) => {
8805
+ const category = screen.navCategory || "Site";
8806
+ acc[category] = acc[category] || [];
8807
+ acc[category].push(screen);
8808
+ return acc;
8809
+ },
8810
+ { Site: [] }
8811
+ );
8661
8812
  return /* @__PURE__ */ React__namespace.createElement(
8662
8813
  "div",
8663
8814
  {
@@ -8703,18 +8854,21 @@ var __publicField = (obj, key, value) => {
8703
8854
  {
8704
8855
  className: `text-lg px-4 py-2 first:pt-3 last:pb-3 tracking-wide whitespace-nowrap flex items-center opacity-80 text-gray-600 hover:text-blue-400 hover:bg-gray-50 hover:opacity-100`,
8705
8856
  onClick: async () => {
8706
- var _a, _b, _c, _d, _e, _f;
8857
+ var _a, _b, _c, _d, _e, _f, _g, _h;
8707
8858
  updateBodyDisplacement({
8708
8859
  displayState: "closed",
8709
8860
  sidebarWidth: null,
8710
8861
  resizingSidebar: false
8711
8862
  });
8712
8863
  try {
8713
- if ((_b = (_a = cms == null ? void 0 : cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.logout) {
8714
- await cms.api.tina.logout();
8715
- if ((_d = (_c = cms == null ? void 0 : cms.api) == null ? void 0 : _c.tina) == null ? void 0 : _d.onLogout) {
8716
- await ((_f = (_e = cms == null ? void 0 : cms.api) == null ? void 0 : _e.tina) == null ? void 0 : _f.onLogout());
8864
+ if ((_c = (_b = (_a = cms == null ? void 0 : cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.authProvider) == null ? void 0 : _c.logout) {
8865
+ await ((_d = cms.api.tina) == null ? void 0 : _d.authProvider.logout());
8866
+ if ((_f = (_e = cms == null ? void 0 : cms.api) == null ? void 0 : _e.tina) == null ? void 0 : _f.onLogout) {
8867
+ await ((_h = (_g = cms == null ? void 0 : cms.api) == null ? void 0 : _g.tina) == null ? void 0 : _h.onLogout());
8717
8868
  }
8869
+ window.location.href = new URL(
8870
+ window.location.href
8871
+ ).pathname;
8718
8872
  }
8719
8873
  setEdit(false);
8720
8874
  } catch (e) {
@@ -8747,13 +8901,25 @@ var __publicField = (obj, key, value) => {
8747
8901
  CollectionsList,
8748
8902
  {
8749
8903
  RenderNavCollection,
8750
- ...collectionsInfo
8904
+ collections: contentCollections
8751
8905
  }
8752
- )), (screens.length > 0 || contentCreators.length) > 0 && /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement("h4", { className: "uppercase font-sans font-bold text-sm mb-3 mt-8 text-gray-700" }, "Site"), /* @__PURE__ */ React__namespace.createElement("ul", { className: "flex flex-col gap-4" }, screens.map((view) => {
8906
+ )), (screenCategories.Site.length > 0 || contentCreators.length) > 0 && /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement("h4", { className: "uppercase font-sans font-bold text-sm mb-3 mt-8 text-gray-700" }, "Site"), /* @__PURE__ */ React__namespace.createElement("ul", { className: "flex flex-col gap-4" }, screenCategories.Site.map((view) => {
8753
8907
  return /* @__PURE__ */ React__namespace.createElement("li", { key: `nav-site-${view.name}` }, /* @__PURE__ */ React__namespace.createElement(RenderNavSite, { view }));
8754
8908
  }), contentCreators.map((plugin, idx) => {
8755
8909
  return /* @__PURE__ */ React__namespace.createElement(CreateContentNavItem, { key: `plugin-${idx}`, plugin });
8756
- }))), !!(cloudConfigs == null ? void 0 : cloudConfigs.length) && /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement("h4", { className: "uppercase font-sans font-bold text-sm mb-3 mt-8 text-gray-700" }, "Cloud"), /* @__PURE__ */ React__namespace.createElement("ul", { className: "flex flex-col gap-4" }, cloudConfigs.map((config) => {
8910
+ }), authCollection && /* @__PURE__ */ React__namespace.createElement(
8911
+ CollectionsList,
8912
+ {
8913
+ RenderNavCollection: AuthRenderNavCollection,
8914
+ collections: [authCollection]
8915
+ }
8916
+ ))), Object.entries(screenCategories).map(([category, screens2]) => {
8917
+ if (category !== "Site") {
8918
+ return /* @__PURE__ */ React__namespace.createElement("div", { key: category }, /* @__PURE__ */ React__namespace.createElement("h4", { className: "uppercase font-sans font-bold text-sm mb-3 mt-8 text-gray-700" }, category), /* @__PURE__ */ React__namespace.createElement("ul", { className: "flex flex-col gap-4" }, screens2.map((view) => {
8919
+ return /* @__PURE__ */ React__namespace.createElement("li", { key: `nav-site-${view.name}` }, /* @__PURE__ */ React__namespace.createElement(RenderNavSite, { view }));
8920
+ })));
8921
+ }
8922
+ }), !!(cloudConfigs == null ? void 0 : cloudConfigs.length) && /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, /* @__PURE__ */ React__namespace.createElement("h4", { className: "uppercase font-sans font-bold text-sm mb-3 mt-8 text-gray-700" }, "Cloud"), /* @__PURE__ */ React__namespace.createElement("ul", { className: "flex flex-col gap-4" }, cloudConfigs.map((config) => {
8757
8923
  return /* @__PURE__ */ React__namespace.createElement("li", { key: `nav-site-${config.name}` }, /* @__PURE__ */ React__namespace.createElement(RenderNavCloud, { config }));
8758
8924
  }))))
8759
8925
  );
@@ -8910,6 +9076,12 @@ var __publicField = (obj, key, value) => {
8910
9076
  const [activeScreen, setActiveView] = React.useState(null);
8911
9077
  const [sidebarWidth, setSidebarWidth] = React__namespace.useState(defaultWidth);
8912
9078
  const [formIsPristine, setFormIsPristine] = React__namespace.useState(true);
9079
+ const activeScreens = allScreens.filter(
9080
+ (screen) => {
9081
+ var _a2, _b2;
9082
+ return screen.navCategory !== "Account" || ((_b2 = (_a2 = cms.api.tina) == null ? void 0 : _a2.authProvider) == null ? void 0 : _b2.getLoginStrategy()) === "UsernamePassword";
9083
+ }
9084
+ );
8913
9085
  const setDisplayState = (value) => cms.dispatch({ type: "sidebar:set-display-state", value });
8914
9086
  const displayState = cms.state.sidebarDisplayState;
8915
9087
  React__namespace.useEffect(() => {
@@ -9005,7 +9177,7 @@ var __publicField = (obj, key, value) => {
9005
9177
  isLocalMode: (_b = (_a = cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isLocalMode,
9006
9178
  showCollections: isTinaAdminEnabled,
9007
9179
  collectionsInfo,
9008
- screens: allScreens,
9180
+ screens: activeScreens,
9009
9181
  cloudConfigs: allConfigs,
9010
9182
  contentCreators,
9011
9183
  sidebarWidth,
@@ -9028,6 +9200,16 @@ var __publicField = (obj, key, value) => {
9028
9200
  },
9029
9201
  collection
9030
9202
  }
9203
+ ),
9204
+ AuthRenderNavCollection: ({ collection }) => /* @__PURE__ */ React__namespace.createElement(
9205
+ SidebarCollectionLink,
9206
+ {
9207
+ onClick: () => {
9208
+ setMenuIsOpen(false);
9209
+ },
9210
+ collection,
9211
+ Icon: ImUsers
9212
+ }
9031
9213
  )
9032
9214
  }
9033
9215
  ), /* @__PURE__ */ React__namespace.createElement(SidebarBody, null, /* @__PURE__ */ React__namespace.createElement(
@@ -9062,7 +9244,7 @@ var __publicField = (obj, key, value) => {
9062
9244
  className: "rounded-r-md",
9063
9245
  showCollections: isTinaAdminEnabled,
9064
9246
  collectionsInfo,
9065
- screens: allScreens,
9247
+ screens: activeScreens,
9066
9248
  cloudConfigs: allConfigs,
9067
9249
  contentCreators,
9068
9250
  sidebarWidth,
@@ -9085,6 +9267,16 @@ var __publicField = (obj, key, value) => {
9085
9267
  },
9086
9268
  collection
9087
9269
  }
9270
+ ),
9271
+ AuthRenderNavCollection: ({ collection }) => /* @__PURE__ */ React__namespace.createElement(
9272
+ SidebarCollectionLink,
9273
+ {
9274
+ onClick: () => {
9275
+ setMenuIsOpen(false);
9276
+ },
9277
+ collection,
9278
+ Icon: ImUsers
9279
+ }
9088
9280
  )
9089
9281
  },
9090
9282
  /* @__PURE__ */ React__namespace.createElement("div", { className: "absolute top-8 right-0 transform translate-x-full overflow-hidden" }, /* @__PURE__ */ React__namespace.createElement(
@@ -9246,6 +9438,7 @@ var __publicField = (obj, key, value) => {
9246
9438
  return /* @__PURE__ */ React__namespace.createElement("span", { className: "text-base tracking-wide text-gray-500 hover:text-blue-600 flex items-center opacity-90 hover:opacity-100" }, /* @__PURE__ */ React__namespace.createElement(config.Icon, { className: "mr-2 h-6 opacity-80 w-auto" }), /* @__PURE__ */ React__namespace.createElement("a", { target: "_blank", href: config.link.href }, config.link.text));
9247
9439
  };
9248
9440
  const SidebarCollectionLink = ({
9441
+ Icon = ImFilesEmpty,
9249
9442
  collection,
9250
9443
  onClick
9251
9444
  }) => {
@@ -9258,7 +9451,7 @@ var __publicField = (obj, key, value) => {
9258
9451
  href: `${tinaPreview ? `/${tinaPreview}/index.html#` : "/admin#"}/collections/${collection.name}/~`,
9259
9452
  className: "text-base tracking-wide text-gray-500 hover:text-blue-600 flex items-center opacity-90 hover:opacity-100"
9260
9453
  },
9261
- /* @__PURE__ */ React__namespace.createElement(ImFilesEmpty, { className: "mr-2 h-6 opacity-80 w-auto" }),
9454
+ /* @__PURE__ */ React__namespace.createElement(Icon, { className: "mr-2 h-6 opacity-80 w-auto" }),
9262
9455
  " ",
9263
9456
  collection.label ? collection.label : collection.name
9264
9457
  );
@@ -9974,7 +10167,9 @@ var __publicField = (obj, key, value) => {
9974
10167
  setSyncStatus(project.mediaBranch ? "synced" : "needs-sync");
9975
10168
  }
9976
10169
  };
9977
- checkSyncStatus();
10170
+ if (!cms.media.store.isStatic) {
10171
+ checkSyncStatus();
10172
+ }
9978
10173
  }, []);
9979
10174
  return syncStatus == "needs-sync" ? /* @__PURE__ */ React.createElement("div", { className: "h-full flex items-center justify-center p-6 bg-gradient-to-t from-gray-200 to-transparent" }, /* @__PURE__ */ React.createElement("div", { className: "rounded-lg border shadow-sm px-4 lg:px-6 py-3 lg:py-4 bg-gradient-to-r from-yellow-50 to-yellow-100 border-yellow-200 mx-auto mb-12" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-start sm:items-center gap-2" }, /* @__PURE__ */ React.createElement(
9980
10175
  BiError,
@@ -10064,6 +10259,108 @@ var __publicField = (obj, key, value) => {
10064
10259
  allowDelete: true
10065
10260
  }
10066
10261
  });
10262
+ function UpdatePassword(props) {
10263
+ const cms = useCMS$1();
10264
+ const client = cms.api.tina;
10265
+ const [password, setPassword] = React.useState("");
10266
+ const [confirmPassword, setConfirmPassword] = React.useState("");
10267
+ const [dirty, setDirty] = React.useState(false);
10268
+ const [result, setResult] = React.useState(null);
10269
+ const [formState, setFormState] = React.useState("idle");
10270
+ const [passwordChangeRequired, setPasswordChangeRequired] = React.useState(false);
10271
+ React.useEffect(() => {
10272
+ var _a;
10273
+ (_a = client == null ? void 0 : client.authProvider) == null ? void 0 : _a.getUser().then(
10274
+ (user) => setPasswordChangeRequired((user == null ? void 0 : user.passwordChangeRequired) ?? false)
10275
+ );
10276
+ }, []);
10277
+ let err = null;
10278
+ if (dirty && password !== confirmPassword) {
10279
+ err = "Passwords do not match";
10280
+ }
10281
+ if (dirty && !password) {
10282
+ err = "Please enter a password";
10283
+ }
10284
+ const updatePassword = async () => {
10285
+ var _a;
10286
+ setResult(null);
10287
+ setFormState("busy");
10288
+ const res = await cms.api.tina.request(
10289
+ `mutation($password: String!) { updatePassword(password: $password) }`,
10290
+ {
10291
+ variables: {
10292
+ password
10293
+ }
10294
+ }
10295
+ );
10296
+ if (!(res == null ? void 0 : res.updatePassword)) {
10297
+ setResult("Error updating password");
10298
+ } else {
10299
+ setDirty(false);
10300
+ setPassword("");
10301
+ setConfirmPassword("");
10302
+ setResult("Password updated");
10303
+ setPasswordChangeRequired(false);
10304
+ await new Promise((resolve) => setTimeout(resolve, 1e3));
10305
+ (_a = client == null ? void 0 : client.authProvider) == null ? void 0 : _a.logout().then(async () => {
10306
+ if (typeof (client == null ? void 0 : client.onLogout) === "function") {
10307
+ await client.onLogout();
10308
+ }
10309
+ window.location.href = new URL(window.location.href).pathname;
10310
+ }).catch((e) => console.error(e));
10311
+ }
10312
+ setFormState("idle");
10313
+ };
10314
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { className: "flex justify-center items-center h-full" }, /* @__PURE__ */ React.createElement("div", { className: "flex flex-col space-y-8 p-6" }, passwordChangeRequired && /* @__PURE__ */ React.createElement("div", { className: "text-center text-red-500" }, "Your password has expired. Please update your password."), /* @__PURE__ */ React.createElement("label", { className: "block" }, /* @__PURE__ */ React.createElement("span", { className: "text-gray-700" }, "New Password"), /* @__PURE__ */ React.createElement(
10315
+ BaseTextField,
10316
+ {
10317
+ type: "password",
10318
+ name: "password",
10319
+ id: "password",
10320
+ placeholder: "Enter password",
10321
+ className: err ? "border-red-500" : "border-gray-300 focus:ring-indigo-500 focus:border-indigo-500",
10322
+ value: password,
10323
+ onKeyDown: () => {
10324
+ setDirty(true);
10325
+ setResult(null);
10326
+ },
10327
+ onChange: (e) => setPassword(e.target.value),
10328
+ required: true
10329
+ }
10330
+ )), /* @__PURE__ */ React.createElement("label", { className: "block" }, /* @__PURE__ */ React.createElement("span", { className: "text-gray-700" }, "Confirm New Password"), /* @__PURE__ */ React.createElement(
10331
+ BaseTextField,
10332
+ {
10333
+ type: "password",
10334
+ name: "confirmPassword",
10335
+ id: "confirmPassword",
10336
+ placeholder: "Confirm password",
10337
+ className: err ? "border-red-500" : "border-gray-300 focus:ring-indigo-500 focus:border-indigo-500",
10338
+ value: confirmPassword,
10339
+ onKeyDown: () => {
10340
+ setDirty(true);
10341
+ setResult(null);
10342
+ },
10343
+ onChange: (e) => setConfirmPassword(e.target.value),
10344
+ required: true
10345
+ }
10346
+ )), result && /* @__PURE__ */ React.createElement("div", { className: "text-center text-sm text-gray-500" }, result), err && /* @__PURE__ */ React.createElement("div", { className: "text-center text-sm text-red-500" }, err), /* @__PURE__ */ React.createElement(
10347
+ Button,
10348
+ {
10349
+ onClick: updatePassword,
10350
+ disabled: err,
10351
+ variant: "primary",
10352
+ busy: formState === "busy"
10353
+ },
10354
+ "Update"
10355
+ ))));
10356
+ }
10357
+ const PasswordScreenPlugin = createScreen({
10358
+ name: "Change Password",
10359
+ Component: UpdatePassword,
10360
+ Icon: MdVpnKey,
10361
+ layout: "fullscreen",
10362
+ navCategory: "Account"
10363
+ });
10067
10364
  function createCloudConfig({
10068
10365
  ...options
10069
10366
  }) {
@@ -10093,7 +10390,8 @@ var __publicField = (obj, key, value) => {
10093
10390
  CheckboxGroupFieldPlugin,
10094
10391
  ReferenceFieldPlugin,
10095
10392
  ButtonToggleFieldPlugin,
10096
- HiddenFieldPlugin
10393
+ HiddenFieldPlugin,
10394
+ PasswordFieldPlugin
10097
10395
  ];
10098
10396
  class TinaCMS extends CMS {
10099
10397
  constructor({
@@ -10111,7 +10409,7 @@ var __publicField = (obj, key, value) => {
10111
10409
  return {
10112
10410
  error: event.error,
10113
10411
  level: "error",
10114
- message: `Failed to upload file(s) ${event == null ? void 0 : event.uploaded.map((x) => x.file.name).join(", ")}. See error message:
10412
+ message: `Failed to upload file(s) ${event == null ? void 0 : event.uploaded.map((x) => x.file.name).join(", ")}.
10115
10413
 
10116
10414
  ${event == null ? void 0 : event.error.toString()}`
10117
10415
  };
@@ -10132,6 +10430,7 @@ var __publicField = (obj, key, value) => {
10132
10430
  }
10133
10431
  });
10134
10432
  this.plugins.add(MediaManagerScreenPlugin);
10433
+ this.plugins.add(PasswordScreenPlugin);
10135
10434
  if (isLocalClient !== true) {
10136
10435
  if (clientId) {
10137
10436
  this.plugins.add(
@@ -10822,6 +11121,16 @@ var __publicField = (obj, key, value) => {
10822
11121
  const [createBranchModalOpen, setCreateBranchModalOpen] = React__namespace.useState(false);
10823
11122
  const tinaForm = form.tinaForm;
10824
11123
  const finalForm2 = form.tinaForm.finalForm;
11124
+ const schema = cms.api.tina.schema;
11125
+ React__namespace.useEffect(() => {
11126
+ var _a;
11127
+ const collection = schema.getCollectionByFullPath(tinaForm.relativePath);
11128
+ if ((_a = collection == null ? void 0 : collection.ui) == null ? void 0 : _a.beforeSubmit) {
11129
+ tinaForm.beforeSubmit = (values) => collection.ui.beforeSubmit({ cms, form: tinaForm, values });
11130
+ } else {
11131
+ tinaForm.beforeSubmit = void 0;
11132
+ }
11133
+ }, [tinaForm.relativePath]);
10825
11134
  const moveArrayItem = React__namespace.useCallback(
10826
11135
  (result) => {
10827
11136
  if (!result.destination || !finalForm2)
@@ -10854,18 +11163,7 @@ var __publicField = (obj, key, value) => {
10854
11163
  {
10855
11164
  key: tinaForm.id,
10856
11165
  form: tinaForm.finalForm,
10857
- onSubmit: async (values, form2, cb) => {
10858
- var _a, _b;
10859
- const schema = cms.api.tina.schema;
10860
- const collection = schema.getCollectionByFullPath(tinaForm.relativePath);
10861
- const valOverride = ((_a = collection == null ? void 0 : collection.ui) == null ? void 0 : _a.beforeSubmit) ? await ((_b = collection == null ? void 0 : collection.ui) == null ? void 0 : _b.beforeSubmit({ cms, values, form: tinaForm })) : false;
10862
- if (valOverride) {
10863
- for (const [key, value] of Object.entries(valOverride)) {
10864
- form2.change(key, value);
10865
- }
10866
- }
10867
- return tinaForm.onSubmit(valOverride || values, form2, cb);
10868
- }
11166
+ onSubmit: tinaForm.onSubmit
10869
11167
  },
10870
11168
  ({
10871
11169
  handleSubmit,
@@ -26362,25 +26660,6 @@ var __publicField = (obj, key, value) => {
26362
26660
  };
26363
26661
  }
26364
26662
  };
26365
- const captureBranchName = /^refs\/heads\/(.*)/;
26366
- const parseRefForBranchName = (ref) => {
26367
- const matches = ref.match(captureBranchName);
26368
- return matches[1];
26369
- };
26370
- const ListBranchResponse = zod.z.object({
26371
- name: zod.z.string(),
26372
- protected: zod.z.boolean().optional().default(false),
26373
- githubPullRequestUrl: zod.z.string().optional()
26374
- }).array().nonempty();
26375
- const IndexStatusResponse = zod.z.object({
26376
- status: zod.z.union([
26377
- zod.z.literal("complete"),
26378
- zod.z.literal("unknown"),
26379
- zod.z.literal("failed"),
26380
- zod.z.literal("inprogress")
26381
- ]).optional(),
26382
- timestamp: zod.z.number().optional()
26383
- });
26384
26663
  function asyncPoll(fn, pollInterval = 5 * 1e3, pollTimeout = 30 * 1e3) {
26385
26664
  const endTime = (/* @__PURE__ */ new Date()).getTime() + pollTimeout;
26386
26665
  let stop = false;
@@ -26405,9 +26684,251 @@ var __publicField = (obj, key, value) => {
26405
26684
  };
26406
26685
  return [new Promise(checkCondition), cancel];
26407
26686
  }
26687
+ function popupWindow(url, title, window2, w, h) {
26688
+ const y = window2.top.outerHeight / 2 + window2.top.screenY - h / 2;
26689
+ const x = window2.top.outerWidth / 2 + window2.top.screenX - w / 2;
26690
+ return window2.open(
26691
+ url,
26692
+ title,
26693
+ "toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=yes, resizable=yes, copyhistory=no, width=" + w + ", height=" + h + ", top=" + y + ", left=" + x
26694
+ );
26695
+ }
26696
+ const TINA_LOGIN_EVENT = "tinaCloudLogin";
26697
+ const AUTH_TOKEN_KEY = "tinacms-auth";
26698
+ const authenticate = (clientId, frontendUrl) => {
26699
+ return new Promise((resolve) => {
26700
+ let authTab;
26701
+ window.addEventListener("message", function(e) {
26702
+ if (e.data.source === TINA_LOGIN_EVENT) {
26703
+ if (authTab) {
26704
+ authTab.close();
26705
+ }
26706
+ resolve({
26707
+ id_token: e.data.id_token,
26708
+ access_token: e.data.access_token,
26709
+ refresh_token: e.data.refresh_token
26710
+ });
26711
+ }
26712
+ });
26713
+ const origin = `${window.location.protocol}//${window.location.host}`;
26714
+ authTab = popupWindow(
26715
+ `${frontendUrl}/signin?clientId=${clientId}&origin=${origin}`,
26716
+ "_blank",
26717
+ window,
26718
+ 1e3,
26719
+ 700
26720
+ );
26721
+ });
26722
+ };
26723
+ const DefaultSessionProvider = ({
26724
+ children
26725
+ }) => /* @__PURE__ */ React.createElement(React.Fragment, null, children);
26726
+ class AbstractAuthProvider {
26727
+ /**
26728
+ * Wraps the normal fetch function with same API but adds the authorization header token.
26729
+ *
26730
+ * @example
26731
+ * const test = await tinaCloudClient.fetchWithToken(`/mycustomAPI/thing/one`) // the token will be passed in the authorization header
26732
+ *
26733
+ * @param input fetch function input
26734
+ * @param init fetch function init
26735
+ */
26736
+ async fetchWithToken(input, init) {
26737
+ const headers2 = (init == null ? void 0 : init.headers) || {};
26738
+ const token = await this.getToken();
26739
+ if (token == null ? void 0 : token.id_token) {
26740
+ headers2["Authorization"] = "Bearer " + (token == null ? void 0 : token.id_token);
26741
+ }
26742
+ return await fetch(input, {
26743
+ ...init || {},
26744
+ headers: new Headers(headers2)
26745
+ });
26746
+ }
26747
+ async authorize(context) {
26748
+ return this.getToken();
26749
+ }
26750
+ async isAuthorized(context) {
26751
+ return !!await this.authorize(context);
26752
+ }
26753
+ async isAuthenticated() {
26754
+ return !!await this.getUser();
26755
+ }
26756
+ getLoginStrategy() {
26757
+ return "Redirect";
26758
+ }
26759
+ getSessionProvider() {
26760
+ return DefaultSessionProvider;
26761
+ }
26762
+ }
26763
+ class TinaCloudAuthProvider extends AbstractAuthProvider {
26764
+ constructor({
26765
+ clientId,
26766
+ identityApiUrl,
26767
+ tokenStorage = "MEMORY",
26768
+ frontendUrl,
26769
+ ...options
26770
+ }) {
26771
+ super();
26772
+ this.frontendUrl = frontendUrl;
26773
+ this.clientId = clientId;
26774
+ this.identityApiUrl = identityApiUrl;
26775
+ switch (tokenStorage) {
26776
+ case "LOCAL_STORAGE":
26777
+ this.getToken = async function() {
26778
+ const tokens = localStorage.getItem(AUTH_TOKEN_KEY) || null;
26779
+ if (tokens) {
26780
+ return await this.getRefreshedToken(tokens);
26781
+ } else {
26782
+ return {
26783
+ access_token: null,
26784
+ id_token: null,
26785
+ refresh_token: null
26786
+ };
26787
+ }
26788
+ };
26789
+ this.setToken = function(token) {
26790
+ localStorage.setItem(AUTH_TOKEN_KEY, JSON.stringify(token, null, 2));
26791
+ };
26792
+ break;
26793
+ case "MEMORY":
26794
+ this.getToken = async () => {
26795
+ if (this.token) {
26796
+ return await this.getRefreshedToken(this.token);
26797
+ } else {
26798
+ return {
26799
+ access_token: null,
26800
+ id_token: null,
26801
+ refresh_token: null
26802
+ };
26803
+ }
26804
+ };
26805
+ this.setToken = (token) => {
26806
+ this.token = JSON.stringify(token, null, 2);
26807
+ };
26808
+ break;
26809
+ case "CUSTOM":
26810
+ if (!options.getTokenFn) {
26811
+ throw new Error(
26812
+ "When CUSTOM token storage is selected, a getTokenFn must be provided"
26813
+ );
26814
+ }
26815
+ this.getToken = options.getTokenFn;
26816
+ break;
26817
+ }
26818
+ }
26819
+ async authenticate() {
26820
+ const token = await authenticate(this.clientId, this.frontendUrl);
26821
+ this.setToken(token);
26822
+ return token;
26823
+ }
26824
+ async getUser() {
26825
+ if (!this.clientId) {
26826
+ return null;
26827
+ }
26828
+ const url = `${this.identityApiUrl}/v2/apps/${this.clientId}/currentUser`;
26829
+ try {
26830
+ const res = await this.fetchWithToken(url, {
26831
+ method: "GET"
26832
+ });
26833
+ const val = await res.json();
26834
+ if (!res.status.toString().startsWith("2")) {
26835
+ console.error(val.error);
26836
+ return null;
26837
+ }
26838
+ return val;
26839
+ } catch (e) {
26840
+ console.error(e);
26841
+ return null;
26842
+ }
26843
+ }
26844
+ async logout() {
26845
+ this.setToken(null);
26846
+ }
26847
+ async getRefreshedToken(tokens) {
26848
+ const { access_token, id_token, refresh_token } = JSON.parse(tokens);
26849
+ const { exp, iss, client_id } = this.parseJwt(access_token);
26850
+ if (Date.now() / 1e3 >= exp - 120) {
26851
+ const refreshResponse = await fetch(iss, {
26852
+ method: "POST",
26853
+ headers: {
26854
+ "Content-Type": "application/x-amz-json-1.1",
26855
+ "x-amz-target": "AWSCognitoIdentityProviderService.InitiateAuth"
26856
+ },
26857
+ body: JSON.stringify({
26858
+ ClientId: client_id,
26859
+ AuthFlow: "REFRESH_TOKEN_AUTH",
26860
+ AuthParameters: {
26861
+ REFRESH_TOKEN: refresh_token,
26862
+ DEVICE_KEY: null
26863
+ }
26864
+ })
26865
+ });
26866
+ if (refreshResponse.status !== 200) {
26867
+ throw new Error("Unable to refresh auth tokens");
26868
+ }
26869
+ const responseJson = await refreshResponse.json();
26870
+ const newToken = {
26871
+ access_token: responseJson.AuthenticationResult.AccessToken,
26872
+ id_token: responseJson.AuthenticationResult.IdToken,
26873
+ refresh_token
26874
+ };
26875
+ this.setToken(newToken);
26876
+ return Promise.resolve(newToken);
26877
+ }
26878
+ return Promise.resolve({ access_token, id_token, refresh_token });
26879
+ }
26880
+ parseJwt(token) {
26881
+ const base64Url = token.split(".")[1];
26882
+ const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
26883
+ const jsonPayload = decodeURIComponent(
26884
+ atob(base64).split("").map(function(c) {
26885
+ return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
26886
+ }).join("")
26887
+ );
26888
+ return JSON.parse(jsonPayload);
26889
+ }
26890
+ }
26891
+ const LOCAL_CLIENT_KEY = "tina.local.isLogedIn";
26892
+ class LocalAuthProvider extends AbstractAuthProvider {
26893
+ constructor() {
26894
+ super();
26895
+ }
26896
+ async authenticate() {
26897
+ localStorage.setItem(LOCAL_CLIENT_KEY, "true");
26898
+ return { access_token: "LOCAL", id_token: "LOCAL", refresh_token: "LOCAL" };
26899
+ }
26900
+ async getUser() {
26901
+ return localStorage.getItem(LOCAL_CLIENT_KEY) === "true";
26902
+ }
26903
+ async getToken() {
26904
+ return Promise.resolve({ id_token: "" });
26905
+ }
26906
+ async logout() {
26907
+ localStorage.removeItem(LOCAL_CLIENT_KEY);
26908
+ }
26909
+ }
26910
+ const captureBranchName = /^refs\/heads\/(.*)/;
26911
+ const parseRefForBranchName = (ref) => {
26912
+ const matches = ref.match(captureBranchName);
26913
+ return matches[1];
26914
+ };
26915
+ const ListBranchResponse = zod.z.object({
26916
+ name: zod.z.string(),
26917
+ protected: zod.z.boolean().optional().default(false),
26918
+ githubPullRequestUrl: zod.z.string().optional()
26919
+ }).array().nonempty();
26920
+ const IndexStatusResponse = zod.z.object({
26921
+ status: zod.z.union([
26922
+ zod.z.literal("complete"),
26923
+ zod.z.literal("unknown"),
26924
+ zod.z.literal("failed"),
26925
+ zod.z.literal("inprogress")
26926
+ ]).optional(),
26927
+ timestamp: zod.z.number().optional()
26928
+ });
26408
26929
  class Client {
26409
26930
  constructor({ tokenStorage = "MEMORY", ...options }) {
26410
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X;
26931
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
26411
26932
  this.events = new EventBus();
26412
26933
  this.protectedBranches = [];
26413
26934
  this.usingEditorialWorkflow = false;
@@ -26461,20 +26982,8 @@ mutation addPendingDocumentMutation(
26461
26982
  return graphql.parse(data.getOptimizedQuery);
26462
26983
  };
26463
26984
  this.tinaGraphQLVersion = options.tinaGraphQLVersion;
26464
- this.onLogin = (_d = (_c = (_b = (_a = options.schema) == null ? void 0 : _a.config) == null ? void 0 : _b.admin) == null ? void 0 : _c.auth) == null ? void 0 : _d.onLogin;
26465
- this.onLogout = (_h = (_g = (_f = (_e = options.schema) == null ? void 0 : _e.config) == null ? void 0 : _f.admin) == null ? void 0 : _g.auth) == null ? void 0 : _h.onLogout;
26466
- if ((_l = (_k = (_j = (_i = options.schema) == null ? void 0 : _i.config) == null ? void 0 : _j.admin) == null ? void 0 : _k.auth) == null ? void 0 : _l.logout) {
26467
- this.onLogout = (_p = (_o = (_n = (_m = options.schema) == null ? void 0 : _m.config) == null ? void 0 : _n.admin) == null ? void 0 : _o.auth) == null ? void 0 : _p.logout;
26468
- }
26469
- if ((_t = (_s = (_r = (_q = options.schema) == null ? void 0 : _q.config) == null ? void 0 : _r.admin) == null ? void 0 : _s.auth) == null ? void 0 : _t.getUser) {
26470
- this.getUser = (_x = (_w = (_v = (_u = options.schema) == null ? void 0 : _u.config) == null ? void 0 : _v.admin) == null ? void 0 : _w.auth) == null ? void 0 : _x.getUser;
26471
- }
26472
- if ((_B = (_A = (_z = (_y = options.schema) == null ? void 0 : _y.config) == null ? void 0 : _z.admin) == null ? void 0 : _A.auth) == null ? void 0 : _B.authenticate) {
26473
- this.authenticate = (_F = (_E = (_D = (_C = options.schema) == null ? void 0 : _C.config) == null ? void 0 : _D.admin) == null ? void 0 : _E.auth) == null ? void 0 : _F.authenticate;
26474
- }
26475
- if ((_J = (_I = (_H = (_G = options.schema) == null ? void 0 : _G.config) == null ? void 0 : _H.admin) == null ? void 0 : _I.auth) == null ? void 0 : _J.authorize) {
26476
- this.authorize = (_N = (_M = (_L = (_K = options.schema) == null ? void 0 : _K.config) == null ? void 0 : _L.admin) == null ? void 0 : _M.auth) == null ? void 0 : _N.authorize;
26477
- }
26985
+ this.onLogin = ((_d = (_c = (_b = (_a = options.schema) == null ? void 0 : _a.config) == null ? void 0 : _b.admin) == null ? void 0 : _c.authHooks) == null ? void 0 : _d.onLogin) || ((_h = (_g = (_f = (_e = options.schema) == null ? void 0 : _e.config) == null ? void 0 : _f.admin) == null ? void 0 : _g.auth) == null ? void 0 : _h.onLogin);
26986
+ this.onLogout = ((_l = (_k = (_j = (_i = options.schema) == null ? void 0 : _i.config) == null ? void 0 : _j.admin) == null ? void 0 : _k.authHooks) == null ? void 0 : _l.onLogout) || ((_p = (_o = (_n = (_m = options.schema) == null ? void 0 : _m.config) == null ? void 0 : _n.admin) == null ? void 0 : _o.auth) == null ? void 0 : _p.onLogout);
26478
26987
  if (options.schema) {
26479
26988
  const enrichedSchema = new schemaTools.TinaSchema({
26480
26989
  version: { fullVersion: "", major: "", minor: "", patch: "" },
@@ -26484,7 +26993,7 @@ mutation addPendingDocumentMutation(
26484
26993
  this.schema = enrichedSchema;
26485
26994
  }
26486
26995
  this.options = options;
26487
- if ((_P = (_O = options.schema) == null ? void 0 : _O.config) == null ? void 0 : _P.contentApiUrlOverride) {
26996
+ if ((_r = (_q = options.schema) == null ? void 0 : _q.config) == null ? void 0 : _r.contentApiUrlOverride) {
26488
26997
  this.options.customContentApiUrl = options.schema.config.contentApiUrlOverride;
26489
26998
  }
26490
26999
  this.setBranch(options.branch);
@@ -26495,52 +27004,13 @@ mutation addPendingDocumentMutation(
26495
27004
  }
26496
27005
  );
26497
27006
  this.clientId = options.clientId;
26498
- switch (tokenStorage) {
26499
- case "LOCAL_STORAGE":
26500
- this.getToken = async function() {
26501
- const tokens = localStorage.getItem(AUTH_TOKEN_KEY) || null;
26502
- if (tokens) {
26503
- return await this.getRefreshedToken(tokens);
26504
- } else {
26505
- return {
26506
- access_token: null,
26507
- id_token: null,
26508
- refresh_token: null
26509
- };
26510
- }
26511
- };
26512
- this.setToken = function(token) {
26513
- localStorage.setItem(AUTH_TOKEN_KEY, JSON.stringify(token, null, 2));
26514
- };
26515
- break;
26516
- case "MEMORY":
26517
- this.getToken = async () => {
26518
- if (this.token) {
26519
- return await this.getRefreshedToken(this.token);
26520
- } else {
26521
- return {
26522
- access_token: null,
26523
- id_token: null,
26524
- refresh_token: null
26525
- };
26526
- }
26527
- };
26528
- this.setToken = (token) => {
26529
- this.token = JSON.stringify(token, null, 2);
26530
- };
26531
- break;
26532
- case "CUSTOM":
26533
- if (!options.getTokenFn) {
26534
- throw new Error(
26535
- "When CUSTOM token storage is selected, a getTokenFn must be provided"
26536
- );
26537
- }
26538
- this.getToken = options.getTokenFn;
26539
- break;
26540
- }
26541
- if ((_T = (_S = (_R = (_Q = options.schema) == null ? void 0 : _Q.config) == null ? void 0 : _R.admin) == null ? void 0 : _S.auth) == null ? void 0 : _T.getToken) {
26542
- this.getToken = (_X = (_W = (_V = (_U = options.schema) == null ? void 0 : _U.config) == null ? void 0 : _V.admin) == null ? void 0 : _W.auth) == null ? void 0 : _X.getToken;
26543
- }
27007
+ this.authProvider = ((_u = (_t = (_s = this.schema) == null ? void 0 : _s.config) == null ? void 0 : _t.config) == null ? void 0 : _u.authProvider) || new TinaCloudAuthProvider({
27008
+ clientId: options.clientId,
27009
+ identityApiUrl: this.identityApiUrl,
27010
+ getTokenFn: options.getTokenFn,
27011
+ tokenStorage,
27012
+ frontendUrl: this.frontendUrl
27013
+ });
26544
27014
  }
26545
27015
  get isLocalMode() {
26546
27016
  return false;
@@ -26557,12 +27027,16 @@ mutation addPendingDocumentMutation(
26557
27027
  this.identityApiUrl = ((_c = this.options.tinaioConfig) == null ? void 0 : _c.identityApiUrlOverride) || "https://identity.tinajs.io";
26558
27028
  this.contentApiBase = ((_d = this.options.tinaioConfig) == null ? void 0 : _d.contentApiUrlOverride) || `https://content.tinajs.io`;
26559
27029
  this.contentApiUrl = this.options.customContentApiUrl || `${this.contentApiBase}/${this.tinaGraphQLVersion}/content/${this.options.clientId}/github/${encodedBranch}`;
27030
+ if (this.authProvider instanceof TinaCloudAuthProvider) {
27031
+ this.authProvider.identityApiUrl = this.identityApiUrl;
27032
+ this.authProvider.frontendUrl = this.frontendUrl;
27033
+ }
26560
27034
  }
26561
27035
  getBranch() {
26562
27036
  return this.branch;
26563
27037
  }
26564
27038
  async request(query, { variables }) {
26565
- const token = await this.getToken();
27039
+ const token = await this.authProvider.getToken();
26566
27040
  const headers2 = {
26567
27041
  "Content-Type": "application/json"
26568
27042
  };
@@ -26609,7 +27083,7 @@ mutation addPendingDocumentMutation(
26609
27083
  async checkSyncStatus({
26610
27084
  assetsSyncing
26611
27085
  }) {
26612
- const res = await this.fetchWithToken(
27086
+ const res = await this.authProvider.fetchWithToken(
26613
27087
  `${this.assetsApiUrl}/v1/${this.clientId}/syncStatus`,
26614
27088
  {
26615
27089
  method: "POST",
@@ -26623,7 +27097,7 @@ mutation addPendingDocumentMutation(
26623
27097
  return jsonRes;
26624
27098
  }
26625
27099
  async getProject() {
26626
- const res = await this.fetchWithToken(
27100
+ const res = await this.authProvider.fetchWithToken(
26627
27101
  `${this.identityApiUrl}/v2/apps/${this.clientId}`,
26628
27102
  {
26629
27103
  method: "GET"
@@ -26639,7 +27113,7 @@ mutation addPendingDocumentMutation(
26639
27113
  }) {
26640
27114
  const url = `${this.contentApiBase}/github/${this.clientId}/create_pull_request`;
26641
27115
  try {
26642
- const res = await this.fetchWithToken(url, {
27116
+ const res = await this.authProvider.fetchWithToken(url, {
26643
27117
  method: "POST",
26644
27118
  body: JSON.stringify({
26645
27119
  baseBranch,
@@ -26668,119 +27142,19 @@ mutation addPendingDocumentMutation(
26668
27142
  events: []
26669
27143
  };
26670
27144
  } else {
26671
- return (await this.fetchWithToken(
27145
+ return (await this.authProvider.fetchWithToken(
26672
27146
  `${this.contentApiBase}/events/${this.clientId}/${this.branch}?limit=${limit || 1}${cursor ? `&cursor=${cursor}` : ""}`,
26673
27147
  { method: "GET" }
26674
27148
  )).json();
26675
27149
  }
26676
27150
  }
26677
- parseJwt(token) {
26678
- const base64Url = token.split(".")[1];
26679
- const base64 = base64Url.replace(/-/g, "+").replace(/_/g, "/");
26680
- const jsonPayload = decodeURIComponent(
26681
- atob(base64).split("").map(function(c) {
26682
- return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
26683
- }).join("")
26684
- );
26685
- return JSON.parse(jsonPayload);
26686
- }
26687
- async getRefreshedToken(tokens) {
26688
- const { access_token, id_token, refresh_token } = JSON.parse(tokens);
26689
- const { exp, iss, client_id } = this.parseJwt(access_token);
26690
- if (Date.now() / 1e3 >= exp - 120) {
26691
- const refreshResponse = await fetch(iss, {
26692
- method: "POST",
26693
- headers: {
26694
- "Content-Type": "application/x-amz-json-1.1",
26695
- "x-amz-target": "AWSCognitoIdentityProviderService.InitiateAuth"
26696
- },
26697
- body: JSON.stringify({
26698
- ClientId: client_id,
26699
- AuthFlow: "REFRESH_TOKEN_AUTH",
26700
- AuthParameters: {
26701
- REFRESH_TOKEN: refresh_token,
26702
- DEVICE_KEY: null
26703
- }
26704
- })
26705
- });
26706
- if (refreshResponse.status !== 200) {
26707
- throw new Error("Unable to refresh auth tokens");
26708
- }
26709
- const responseJson = await refreshResponse.json();
26710
- const newToken = {
26711
- access_token: responseJson.AuthenticationResult.AccessToken,
26712
- id_token: responseJson.AuthenticationResult.IdToken,
26713
- refresh_token
26714
- };
26715
- this.setToken(newToken);
26716
- return Promise.resolve(newToken);
26717
- }
26718
- return Promise.resolve({ access_token, id_token, refresh_token });
26719
- }
26720
- async isAuthorized(context) {
26721
- return !!await this.authorize(context);
26722
- }
26723
- async isAuthenticated() {
26724
- return !!await this.getUser();
26725
- }
26726
- async logout() {
26727
- this.setToken(null);
26728
- }
26729
- async authenticate() {
26730
- const token = await authenticate(this.clientId, this.frontendUrl);
26731
- this.setToken(token);
26732
- return token;
26733
- }
26734
- async authorize(context) {
26735
- return this.getToken();
26736
- }
26737
- /**
26738
- * Wraps the normal fetch function with same API but adds the authorization header token.
26739
- *
26740
- * @example
26741
- * const test = await tinaCloudClient.fetchWithToken(`/mycustomAPI/thing/one`) // the token will be passed in the authorization header
26742
- *
26743
- * @param input fetch function input
26744
- * @param init fetch function init
26745
- */
26746
- async fetchWithToken(input, init) {
26747
- const headers2 = (init == null ? void 0 : init.headers) || {};
26748
- const token = await this.getToken();
26749
- if (token == null ? void 0 : token.id_token) {
26750
- headers2["Authorization"] = "Bearer " + (token == null ? void 0 : token.id_token);
26751
- }
26752
- return await fetch(input, {
26753
- ...init,
26754
- headers: new Headers(headers2)
26755
- });
26756
- }
26757
- async getUser() {
26758
- if (!this.clientId) {
26759
- return null;
26760
- }
26761
- const url = `${this.identityApiUrl}/v2/apps/${this.clientId}/currentUser`;
26762
- try {
26763
- const res = await this.fetchWithToken(url, {
26764
- method: "GET"
26765
- });
26766
- const val = await res.json();
26767
- if (!res.status.toString().startsWith("2")) {
26768
- console.error(val.error);
26769
- return null;
26770
- }
26771
- return val;
26772
- } catch (e) {
26773
- console.error(e);
26774
- return null;
26775
- }
26776
- }
26777
27151
  async getBillingState() {
26778
27152
  if (!this.clientId) {
26779
27153
  return null;
26780
27154
  }
26781
27155
  const url = `${this.identityApiUrl}/v2/apps/${this.clientId}/billing/state`;
26782
27156
  try {
26783
- const res = await this.fetchWithToken(url, {
27157
+ const res = await this.authProvider.fetchWithToken(url, {
26784
27158
  method: "GET"
26785
27159
  });
26786
27160
  const val = await res.json();
@@ -26846,7 +27220,7 @@ mutation addPendingDocumentMutation(
26846
27220
  }
26847
27221
  async getIndexStatus({ ref }) {
26848
27222
  const url = `${this.contentApiBase}/db/${this.clientId}/status/${ref}`;
26849
- const res = await this.fetchWithToken(url);
27223
+ const res = await this.authProvider.fetchWithToken(url);
26850
27224
  const result = await res.json();
26851
27225
  const parsedResult = IndexStatusResponse.parse(result);
26852
27226
  return parsedResult;
@@ -26854,7 +27228,7 @@ mutation addPendingDocumentMutation(
26854
27228
  async listBranches(args) {
26855
27229
  try {
26856
27230
  const url = `${this.contentApiBase}/github/${this.clientId}/list_branches`;
26857
- const res = await this.fetchWithToken(url, {
27231
+ const res = await this.authProvider.fetchWithToken(url, {
26858
27232
  method: "GET"
26859
27233
  });
26860
27234
  const branches = await res.json();
@@ -26884,7 +27258,7 @@ mutation addPendingDocumentMutation(
26884
27258
  async createBranch({ baseBranch, branchName }) {
26885
27259
  const url = `${this.contentApiBase}/github/${this.clientId}/create_branch`;
26886
27260
  try {
26887
- const res = await this.fetchWithToken(url, {
27261
+ const res = await this.authProvider.fetchWithToken(url, {
26888
27262
  method: "POST",
26889
27263
  body: JSON.stringify({
26890
27264
  baseBranch,
@@ -26908,9 +27282,9 @@ mutation addPendingDocumentMutation(
26908
27282
  }
26909
27283
  }
26910
27284
  const DEFAULT_LOCAL_TINA_GQL_SERVER_URL = "http://localhost:4001/graphql";
26911
- const LOCAL_CLIENT_KEY = "tina.local.isLogedIn";
26912
27285
  class LocalClient extends Client {
26913
27286
  constructor(props) {
27287
+ var _a, _b, _c;
26914
27288
  const clientProps = {
26915
27289
  ...props,
26916
27290
  clientId: "",
@@ -26919,21 +27293,11 @@ mutation addPendingDocumentMutation(
26919
27293
  customContentApiUrl: props && props.customContentApiUrl ? props.customContentApiUrl : DEFAULT_LOCAL_TINA_GQL_SERVER_URL
26920
27294
  };
26921
27295
  super(clientProps);
27296
+ this.authProvider = ((_c = (_b = (_a = this.schema) == null ? void 0 : _a.config) == null ? void 0 : _b.config) == null ? void 0 : _c.authProvider) || new LocalAuthProvider();
26922
27297
  }
26923
27298
  get isLocalMode() {
26924
27299
  return true;
26925
27300
  }
26926
- // These functions allow the local client to have a login state so that we can correctly call the "OnLogin" callback. This is important for things like preview mode
26927
- async logout() {
26928
- localStorage.removeItem(LOCAL_CLIENT_KEY);
26929
- }
26930
- async authenticate() {
26931
- localStorage.setItem(LOCAL_CLIENT_KEY, "true");
26932
- return { access_token: "LOCAL", id_token: "LOCAL", refresh_token: "LOCAL" };
26933
- }
26934
- async getUser() {
26935
- return localStorage.getItem(LOCAL_CLIENT_KEY) === "true";
26936
- }
26937
27301
  }
26938
27302
  class TinaCMSSearchClient {
26939
27303
  constructor(client, tinaSearchConfig) {
@@ -26948,13 +27312,13 @@ mutation addPendingDocumentMutation(
26948
27312
  );
26949
27313
  const opt = optionsToSearchIndexOptions(options);
26950
27314
  const optionsParam = opt["PAGE"] ? `&options=${JSON.stringify(opt)}` : "";
26951
- const res = await this.client.fetchWithToken(
27315
+ const res = await this.client.authProvider.fetchWithToken(
26952
27316
  `${this.client.contentApiBase}/searchIndex/${this.client.clientId}/${this.client.getBranch()}?q=${JSON.stringify(q)}${optionsParam}`
26953
27317
  );
26954
27318
  return parseSearchIndexResponse(await res.json(), options);
26955
27319
  }
26956
27320
  async del(ids) {
26957
- const res = await this.client.fetchWithToken(
27321
+ const res = await this.client.authProvider.fetchWithToken(
26958
27322
  `${this.client.contentApiBase}/searchIndex/${this.client.clientId}/${this.client.getBranch()}?ids=${ids.join(",")}`,
26959
27323
  {
26960
27324
  method: "DELETE"
@@ -26965,7 +27329,7 @@ mutation addPendingDocumentMutation(
26965
27329
  }
26966
27330
  }
26967
27331
  async put(docs) {
26968
- const res = await this.client.fetchWithToken(
27332
+ const res = await this.client.authProvider.fetchWithToken(
26969
27333
  `${this.client.contentApiBase}/searchIndex/${this.client.clientId}/${this.client.getBranch()}`,
26970
27334
  {
26971
27335
  method: "POST",
@@ -26991,7 +27355,7 @@ mutation addPendingDocumentMutation(
26991
27355
  const q = queryToSearchIndexQuery(query);
26992
27356
  const opt = optionsToSearchIndexOptions(options);
26993
27357
  const optionsParam = opt["PAGE"] ? `&options=${JSON.stringify(opt)}` : "";
26994
- const res = await this.client.fetchWithToken(
27358
+ const res = await this.client.authProvider.fetchWithToken(
26995
27359
  `http://localhost:4001/searchIndex?q=${JSON.stringify(q)}${optionsParam}`
26996
27360
  );
26997
27361
  return parseSearchIndexResponse(await res.json(), options);
@@ -27007,12 +27371,19 @@ mutation addPendingDocumentMutation(
27007
27371
  }
27008
27372
  }
27009
27373
  function ModalBuilder(modalProps) {
27010
- return /* @__PURE__ */ React.createElement(Modal, null, /* @__PURE__ */ React.createElement(ModalPopup, null, /* @__PURE__ */ React.createElement(ModalHeader, null, modalProps.title), /* @__PURE__ */ React.createElement(ModalBody, { padded: true }, /* @__PURE__ */ React.createElement("p", null, modalProps.message), modalProps.error && /* @__PURE__ */ React.createElement(ErrorLabel, null, modalProps.error)), /* @__PURE__ */ React.createElement(ModalActions, null, modalProps.actions.map((action) => /* @__PURE__ */ React.createElement(AsyncButton, { key: action.name, ...action })))));
27374
+ return /* @__PURE__ */ React.createElement(Modal, null, /* @__PURE__ */ React.createElement(ModalPopup, null, /* @__PURE__ */ React.createElement(ModalHeader, null, modalProps.title), /* @__PURE__ */ React.createElement(ModalBody, { padded: true }, modalProps.message && /* @__PURE__ */ React.createElement("p", null, modalProps.message), modalProps.error && /* @__PURE__ */ React.createElement(ErrorLabel, null, modalProps.error), modalProps.children), /* @__PURE__ */ React.createElement(ModalActions, null, modalProps.actions.map((action) => /* @__PURE__ */ React.createElement(AsyncButton, { key: action.name, ...action })))));
27011
27375
  }
27012
27376
  const ErrorLabel = ({ style = {}, ...props }) => /* @__PURE__ */ React.createElement("p", { style: { ...style, color: "var(--tina-color-error)" }, ...props });
27013
27377
  const AsyncButton = ({ name, primary, action }) => {
27014
27378
  const [submitting, setSubmitting] = React.useState(false);
27379
+ const [mounted, setMounted] = React.useState(false);
27380
+ React.useEffect(() => {
27381
+ setMounted(true);
27382
+ return () => setMounted(false);
27383
+ }, []);
27015
27384
  const onClick = React.useCallback(async () => {
27385
+ if (!mounted)
27386
+ return;
27016
27387
  setSubmitting(true);
27017
27388
  try {
27018
27389
  await action();
@@ -27021,7 +27392,7 @@ mutation addPendingDocumentMutation(
27021
27392
  setSubmitting(false);
27022
27393
  throw e;
27023
27394
  }
27024
- }, [action, setSubmitting]);
27395
+ }, [action, setSubmitting, mounted]);
27025
27396
  return /* @__PURE__ */ React.createElement(
27026
27397
  Button,
27027
27398
  {
@@ -27097,7 +27468,7 @@ mutation addPendingDocumentMutation(
27097
27468
  }
27098
27469
  }
27099
27470
  async isAuthenticated() {
27100
- return await this.api.isAuthenticated();
27471
+ return await this.api.authProvider.isAuthenticated();
27101
27472
  }
27102
27473
  async checkGraphqlSchema({ localSchema }) {
27103
27474
  const schemaFromCloud = await this.api.getSchema();
@@ -27419,17 +27790,29 @@ mutation addPendingDocumentMutation(
27419
27790
  loginScreen,
27420
27791
  getModalActions
27421
27792
  }) => {
27422
- var _a, _b, _c, _d, _e;
27793
+ var _a, _b, _c;
27423
27794
  const client = cms.api.tina;
27424
- const isTinaCloud = !client.isLocalMode && !((_e = (_d = (_c = (_b = (_a = client.schema) == null ? void 0 : _a.config) == null ? void 0 : _b.config) == null ? void 0 : _c.admin) == null ? void 0 : _d.auth) == null ? void 0 : _e.customAuth);
27795
+ const isTinaCloud = !client.isLocalMode && !((_c = (_b = (_a = client.schema) == null ? void 0 : _a.config) == null ? void 0 : _b.config) == null ? void 0 : _c.contentApiUrlOverride);
27796
+ const loginStrategy = client.authProvider.getLoginStrategy();
27425
27797
  const [activeModal, setActiveModal] = React.useState(null);
27426
27798
  const [errorMessage, setErrorMessage] = React.useState();
27427
27799
  const [showChildren, setShowChildren] = React.useState(false);
27800
+ const [authProps, setAuthProps] = React.useState({ username: "", password: "" });
27801
+ const [authenticated, setAuthenticated] = React.useState(false);
27428
27802
  React.useEffect(() => {
27429
- client.isAuthenticated().then((isAuthenticated) => {
27803
+ let mounted = true;
27804
+ client.authProvider.isAuthenticated().then((isAuthenticated) => {
27805
+ if (!mounted)
27806
+ return;
27430
27807
  if (isAuthenticated) {
27431
- client.isAuthorized().then((isAuthorized) => {
27808
+ client.authProvider.isAuthorized().then(async (isAuthorized) => {
27809
+ if (!mounted)
27810
+ return;
27432
27811
  if (isAuthorized) {
27812
+ const user = await client.authProvider.getUser();
27813
+ if (user.passwordChangeRequired) {
27814
+ window.location.hash = "#/screens/change_password";
27815
+ }
27433
27816
  setShowChildren(true);
27434
27817
  cms.enable();
27435
27818
  } else {
@@ -27440,6 +27823,8 @@ mutation addPendingDocumentMutation(
27440
27823
  setActiveModal("error");
27441
27824
  }
27442
27825
  }).catch((e) => {
27826
+ if (!mounted)
27827
+ return;
27443
27828
  console.error(e);
27444
27829
  setErrorMessage({ title: "Unexpected Error:", message: `${e}` });
27445
27830
  setActiveModal("error");
@@ -27450,33 +27835,59 @@ mutation addPendingDocumentMutation(
27450
27835
  });
27451
27836
  }
27452
27837
  }).catch((e) => {
27838
+ if (!mounted)
27839
+ return;
27453
27840
  console.error(e);
27454
27841
  setErrorMessage({ title: "Unexpected Error:", message: `${e}` });
27455
27842
  setActiveModal("error");
27456
27843
  });
27457
- }, []);
27844
+ return () => {
27845
+ mounted = false;
27846
+ };
27847
+ }, [authenticated]);
27458
27848
  const onAuthenticated = async () => {
27459
- if (await client.isAuthorized()) {
27460
- setShowChildren(true);
27461
- setActiveModal(null);
27462
- cms.events.dispatch({ type: "cms:login" });
27463
- } else {
27464
- setErrorMessage({
27465
- title: "Access Denied:",
27466
- message: "Not Authorized To Edit"
27467
- });
27468
- setActiveModal("error");
27469
- }
27849
+ setAuthenticated(true);
27850
+ setActiveModal(null);
27851
+ cms.events.dispatch({ type: "cms:login" });
27470
27852
  };
27471
27853
  const otherModalActions = getModalActions ? getModalActions({
27472
27854
  closeModal: () => {
27473
27855
  setActiveModal(null);
27474
27856
  }
27475
27857
  }) : [];
27476
- return /* @__PURE__ */ React.createElement(React.Fragment, null, activeModal === "authenticate" && /* @__PURE__ */ React.createElement(
27858
+ const handleAuthenticate = async () => {
27859
+ try {
27860
+ setAuthenticated(false);
27861
+ const token = await client.authProvider.authenticate(authProps);
27862
+ if (typeof (client == null ? void 0 : client.onLogin) === "function") {
27863
+ await (client == null ? void 0 : client.onLogin({ token }));
27864
+ }
27865
+ return onAuthenticated();
27866
+ } catch (e) {
27867
+ console.error(e);
27868
+ setActiveModal("error");
27869
+ setErrorMessage({
27870
+ title: "Authentication Error",
27871
+ message: `${e}`
27872
+ });
27873
+ }
27874
+ };
27875
+ let modalTitle = "Tina Cloud Authorization";
27876
+ if (activeModal === "authenticate" && loginStrategy === "Redirect" && !isTinaCloud) {
27877
+ modalTitle = "Enter into edit mode";
27878
+ } else if (activeModal === "authenticate" && loginStrategy === "UsernamePassword") {
27879
+ modalTitle = "Sign in to Tina";
27880
+ } else if (activeModal === "error") {
27881
+ if (loginStrategy === "Redirect" && !isTinaCloud) {
27882
+ modalTitle = "Enter into edit mode";
27883
+ } else if (loginStrategy === "UsernamePassword") {
27884
+ modalTitle = "Sign in to Tina";
27885
+ }
27886
+ }
27887
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, activeModal === "authenticate" && loginStrategy === "Redirect" && /* @__PURE__ */ React.createElement(
27477
27888
  ModalBuilder,
27478
27889
  {
27479
- title: isTinaCloud ? "Tina Cloud Authorization" : "Enter into edit mode",
27890
+ title: modalTitle,
27480
27891
  message: isTinaCloud ? "To save edits, Tina Cloud authorization is required. On save, changes will get committed using your account." : "To save edits, enter into edit mode. On save, changes will saved to the local filesystem.",
27481
27892
  close,
27482
27893
  actions: [
@@ -27491,30 +27902,61 @@ mutation addPendingDocumentMutation(
27491
27902
  },
27492
27903
  {
27493
27904
  name: isTinaCloud ? "Continue to Tina Cloud" : "Enter Edit Mode",
27494
- action: async () => {
27495
- try {
27496
- const token = await client.authenticate();
27497
- if (typeof (client == null ? void 0 : client.onLogin) === "function") {
27498
- await (client == null ? void 0 : client.onLogin({ token }));
27499
- }
27500
- return onAuthenticated();
27501
- } catch (e) {
27502
- console.error(e);
27503
- setActiveModal("error");
27504
- setErrorMessage({
27505
- title: "Unexpected Error:",
27506
- message: `${e}`
27507
- });
27508
- }
27509
- },
27905
+ action: handleAuthenticate,
27510
27906
  primary: true
27511
27907
  }
27512
27908
  ]
27513
27909
  }
27910
+ ), activeModal === "authenticate" && loginStrategy === "UsernamePassword" && /* @__PURE__ */ React.createElement(
27911
+ ModalBuilder,
27912
+ {
27913
+ title: modalTitle,
27914
+ message: "",
27915
+ close,
27916
+ actions: [
27917
+ ...otherModalActions,
27918
+ {
27919
+ name: "Login",
27920
+ action: handleAuthenticate,
27921
+ primary: true
27922
+ }
27923
+ ]
27924
+ },
27925
+ /* @__PURE__ */ React.createElement("div", { className: "flex items-center justify-center bg-gray-50 px-4 sm:px-6 lg:px-8" }, /* @__PURE__ */ React.createElement("div", { className: "max-w-md w-full space-y-6" }, /* @__PURE__ */ React.createElement("label", { className: "block" }, /* @__PURE__ */ React.createElement("span", { className: "text-gray-700" }, "Username"), /* @__PURE__ */ React.createElement(
27926
+ BaseTextField,
27927
+ {
27928
+ id: "username",
27929
+ name: "username",
27930
+ type: "text",
27931
+ autoComplete: "username",
27932
+ required: true,
27933
+ placeholder: "Username",
27934
+ value: authProps.username,
27935
+ onChange: (e) => setAuthProps((prevState) => ({
27936
+ ...prevState,
27937
+ username: e.target.value
27938
+ }))
27939
+ }
27940
+ )), /* @__PURE__ */ React.createElement("label", { className: "block" }, /* @__PURE__ */ React.createElement("span", { className: "text-gray-700" }, "Password"), /* @__PURE__ */ React.createElement(
27941
+ BaseTextField,
27942
+ {
27943
+ id: "password",
27944
+ name: "password",
27945
+ type: "password",
27946
+ autoComplete: "current-password",
27947
+ required: true,
27948
+ placeholder: "Password",
27949
+ value: authProps.password,
27950
+ onChange: (e) => setAuthProps((prevState) => ({
27951
+ ...prevState,
27952
+ password: e.target.value
27953
+ }))
27954
+ }
27955
+ ))))
27514
27956
  ), activeModal === "error" && errorMessage && /* @__PURE__ */ React.createElement(
27515
27957
  ModalBuilder,
27516
27958
  {
27517
- title: isTinaCloud ? "Tina Cloud Authorization" : "Enter into edit mode",
27959
+ title: modalTitle,
27518
27960
  message: errorMessage.title,
27519
27961
  error: errorMessage.message,
27520
27962
  close,
@@ -27526,13 +27968,12 @@ mutation addPendingDocumentMutation(
27526
27968
  try {
27527
27969
  setActiveModal(null);
27528
27970
  setErrorMessage(void 0);
27529
- await client.logout();
27530
- await client.onLogout();
27531
- const token = await client.authenticate();
27532
- if (typeof (client == null ? void 0 : client.onLogin) === "function") {
27533
- await (client == null ? void 0 : client.onLogin({ token }));
27971
+ const { authProvider } = client;
27972
+ await authProvider.logout();
27973
+ if (typeof (client == null ? void 0 : client.onLogout) === "function") {
27974
+ await client.onLogout();
27534
27975
  }
27535
- return onAuthenticated();
27976
+ window.location.href = new URL(window.location.href).pathname;
27536
27977
  } catch (e) {
27537
27978
  console.error(e);
27538
27979
  setActiveModal("error");
@@ -27549,7 +27990,7 @@ mutation addPendingDocumentMutation(
27549
27990
  ), showChildren ? children : loginScreen ? loginScreen : null);
27550
27991
  };
27551
27992
  const TinaCloudProvider = (props) => {
27552
- var _a, _b, _c, _d, _e;
27993
+ var _a, _b, _c;
27553
27994
  const baseBranch = props.branch || "main";
27554
27995
  const [currentBranch, setCurrentBranch] = useLocalStorage(
27555
27996
  "tinacms-current-branch",
@@ -27572,7 +28013,7 @@ mutation addPendingDocumentMutation(
27572
28013
  cms.api.tina.setBranch(currentBranch);
27573
28014
  }
27574
28015
  React.useEffect(() => {
27575
- var _a2, _b2, _c2, _d2, _e2, _f;
28016
+ var _a2, _b2, _c2, _d, _e, _f;
27576
28017
  let searchClient;
27577
28018
  if (props.isLocalClient) {
27578
28019
  searchClient = new LocalSearchClient(cms.api.tina);
@@ -27581,10 +28022,10 @@ mutation addPendingDocumentMutation(
27581
28022
  if (hasTinaSearch) {
27582
28023
  searchClient = new TinaCMSSearchClient(
27583
28024
  cms.api.tina,
27584
- (_d2 = (_c2 = props.schema.config) == null ? void 0 : _c2.search) == null ? void 0 : _d2.tina
28025
+ (_d = (_c2 = props.schema.config) == null ? void 0 : _c2.search) == null ? void 0 : _d.tina
27585
28026
  );
27586
28027
  } else {
27587
- searchClient = (_f = (_e2 = props.schema.config) == null ? void 0 : _e2.search) == null ? void 0 : _f.searchClient;
28028
+ searchClient = (_f = (_e = props.schema.config) == null ? void 0 : _e.search) == null ? void 0 : _f.searchClient;
27588
28029
  }
27589
28030
  }
27590
28031
  if (searchClient) {
@@ -27595,7 +28036,7 @@ mutation addPendingDocumentMutation(
27595
28036
  cms.registerApi("admin", new TinaAdminApi(cms));
27596
28037
  }
27597
28038
  const setupMedia = async (staticMedia) => {
27598
- var _a2, _b2, _c2, _d2, _e2, _f, _g;
28039
+ var _a2, _b2, _c2, _d, _e, _f, _g;
27599
28040
  const hasTinaMedia = Boolean((_b2 = (_a2 = props.schema.config) == null ? void 0 : _a2.media) == null ? void 0 : _b2.tina);
27600
28041
  if (hasTinaMedia) {
27601
28042
  cms.media.store = new TinaMediaStore(cms, staticMedia);
@@ -27603,9 +28044,9 @@ mutation addPendingDocumentMutation(
27603
28044
  /*
27604
28045
  Has tina custom media (set up in the schema or define schema)
27605
28046
  */
27606
- ((_d2 = (_c2 = props.schema.config) == null ? void 0 : _c2.media) == null ? void 0 : _d2.loadCustomStore) || props.mediaStore
28047
+ ((_d = (_c2 = props.schema.config) == null ? void 0 : _c2.media) == null ? void 0 : _d.loadCustomStore) || props.mediaStore
27607
28048
  ) {
27608
- const mediaStoreFromProps = ((_f = (_e2 = props.schema.config) == null ? void 0 : _e2.media) == null ? void 0 : _f.loadCustomStore) || props.mediaStore;
28049
+ const mediaStoreFromProps = ((_f = (_e = props.schema.config) == null ? void 0 : _e.media) == null ? void 0 : _f.loadCustomStore) || props.mediaStore;
27609
28050
  if ((_g = mediaStoreFromProps.prototype) == null ? void 0 : _g.persist) {
27610
28051
  cms.media.store = new mediaStoreFromProps(cms.api.tina);
27611
28052
  } else {
@@ -27617,7 +28058,8 @@ mutation addPendingDocumentMutation(
27617
28058
  }
27618
28059
  };
27619
28060
  const client = cms.api.tina;
27620
- const isTinaCloud = !client.isLocalMode && !((_e = (_d = (_c = (_b = (_a = client.schema) == null ? void 0 : _a.config) == null ? void 0 : _b.config) == null ? void 0 : _c.admin) == null ? void 0 : _d.auth) == null ? void 0 : _e.customAuth);
28061
+ const isTinaCloud = !client.isLocalMode && !((_c = (_b = (_a = client.schema) == null ? void 0 : _a.config) == null ? void 0 : _b.config) == null ? void 0 : _c.contentApiUrlOverride);
28062
+ const SessionProvider = client.authProvider.getSessionProvider();
27621
28063
  const handleListBranches = async () => {
27622
28064
  const branches = await cms.api.tina.listBranches({
27623
28065
  includeIndexStatus: true
@@ -27631,7 +28073,9 @@ mutation addPendingDocumentMutation(
27631
28073
  const newBranch = await cms.api.tina.createBranch(data);
27632
28074
  return newBranch;
27633
28075
  };
27634
- setupMedia(props.staticMedia);
28076
+ setupMedia(props.staticMedia).catch((e) => {
28077
+ console.error(e);
28078
+ });
27635
28079
  const [branchingEnabled, setBranchingEnabled] = React.useState(
27636
28080
  () => cms.flags.get("branch-switcher")
27637
28081
  );
@@ -27684,7 +28128,7 @@ mutation addPendingDocumentMutation(
27684
28128
  });
27685
28129
  return unsubscribe;
27686
28130
  }, [isTinaCloud, cms]);
27687
- return /* @__PURE__ */ React.createElement(
28131
+ return /* @__PURE__ */ React.createElement(SessionProvider, { basePath: "/api/tina/auth" }, /* @__PURE__ */ React.createElement(
27688
28132
  BranchDataProvider,
27689
28133
  {
27690
28134
  currentBranch,
@@ -27693,7 +28137,7 @@ mutation addPendingDocumentMutation(
27693
28137
  }
27694
28138
  },
27695
28139
  /* @__PURE__ */ React.createElement(TinaProvider, { cms }, /* @__PURE__ */ React.createElement(AuthWallInner, { ...props, cms }))
27696
- );
28140
+ ));
27697
28141
  };
27698
28142
  const TinaCloudAuthWall = TinaCloudProvider;
27699
28143
  class ContentCreatorPlugin {
@@ -27972,14 +28416,13 @@ mutation addPendingDocumentMutation(
27972
28416
  schema,
27973
28417
  ...props
27974
28418
  }) => {
27975
- var _a, _b, _c, _d, _e, _f;
28419
+ var _a, _b, _c;
27976
28420
  if (props == null ? void 0 : props.apiURL) {
27977
28421
  console.warn(
27978
28422
  "The apiURL prop is deprecated. Please see https://tina.io/blog/tina-v-0.68.14 for information on how to upgrade to the new API"
27979
28423
  );
27980
28424
  }
27981
28425
  const apiURL = ((_a = props == null ? void 0 : props.client) == null ? void 0 : _a.apiUrl) || (props == null ? void 0 : props.apiURL);
27982
- const isLocalOverride = (_d = (_c = (_b = schema == null ? void 0 : schema.config) == null ? void 0 : _b.admin) == null ? void 0 : _c.auth) == null ? void 0 : _d.useLocalAuth;
27983
28426
  const { branch, clientId, isLocalClient } = apiURL ? schemaTools.parseURL(apiURL) : {
27984
28427
  branch: props.branch,
27985
28428
  clientId: props.clientId,
@@ -28005,10 +28448,10 @@ mutation addPendingDocumentMutation(
28005
28448
  TinaCloudProvider,
28006
28449
  {
28007
28450
  branch,
28008
- clientId: clientId || ((_e = schema == null ? void 0 : schema.config) == null ? void 0 : _e.clientId),
28451
+ clientId: clientId || ((_b = schema == null ? void 0 : schema.config) == null ? void 0 : _b.clientId),
28009
28452
  tinaioConfig: props.tinaioConfig,
28010
- isLocalClient: isLocalOverride || isLocalClient,
28011
- isSelfHosted: !!((_f = schema == null ? void 0 : schema.config) == null ? void 0 : _f.contentApiUrlOverride),
28453
+ isLocalClient,
28454
+ isSelfHosted: !!((_c = schema == null ? void 0 : schema.config) == null ? void 0 : _c.contentApiUrlOverride),
28012
28455
  cmsCallback: props.cmsCallback,
28013
28456
  mediaStore: props.mediaStore,
28014
28457
  apiUrl: apiURL,
@@ -28212,6 +28655,12 @@ This will work when developing locally but NOT when deployed to production.
28212
28655
  const navBreakpoint2 = 1e3;
28213
28656
  const windowWidth = windowSize.useWindowWidth();
28214
28657
  const renderDesktopNav = windowWidth > navBreakpoint2;
28658
+ const activeScreens = screens.filter(
28659
+ (screen) => {
28660
+ var _a2;
28661
+ return screen.navCategory !== "Account" || ((_a2 = cms.api.tina.authProvider) == null ? void 0 : _a2.getLoginStrategy()) === "UsernamePassword";
28662
+ }
28663
+ );
28215
28664
  return /* @__PURE__ */ React.createElement(React.Fragment, null, renderDesktopNav && /* @__PURE__ */ React.createElement(
28216
28665
  Nav,
28217
28666
  {
@@ -28219,7 +28668,7 @@ This will work when developing locally but NOT when deployed to production.
28219
28668
  sidebarWidth: 360,
28220
28669
  showCollections: true,
28221
28670
  collectionsInfo,
28222
- screens,
28671
+ screens: activeScreens,
28223
28672
  cloudConfigs,
28224
28673
  contentCreators: [],
28225
28674
  RenderNavSite: ({ view }) => /* @__PURE__ */ React.createElement(
@@ -28238,6 +28687,14 @@ This will work when developing locally but NOT when deployed to production.
28238
28687
  to: `/collections/${collection.name}/~`,
28239
28688
  Icon: ImFilesEmpty
28240
28689
  }
28690
+ ),
28691
+ AuthRenderNavCollection: ({ collection }) => /* @__PURE__ */ React.createElement(
28692
+ SidebarLink,
28693
+ {
28694
+ label: collection.label ? collection.label : collection.name,
28695
+ to: `/collections/${collection.name}/~`,
28696
+ Icon: ImUsers
28697
+ }
28241
28698
  )
28242
28699
  }
28243
28700
  ), !renderDesktopNav && /* @__PURE__ */ React.createElement(react.Transition, { show: menuIsOpen }, /* @__PURE__ */ React.createElement(
@@ -28259,7 +28716,7 @@ This will work when developing locally but NOT when deployed to production.
28259
28716
  sidebarWidth: 360,
28260
28717
  showCollections: true,
28261
28718
  collectionsInfo,
28262
- screens,
28719
+ screens: activeScreens,
28263
28720
  cloudConfigs,
28264
28721
  contentCreators: [],
28265
28722
  RenderNavSite: ({ view }) => /* @__PURE__ */ React.createElement(
@@ -28284,6 +28741,17 @@ This will work when developing locally but NOT when deployed to production.
28284
28741
  setMenuIsOpen(false);
28285
28742
  }
28286
28743
  }
28744
+ ),
28745
+ AuthRenderNavCollection: ({ collection }) => /* @__PURE__ */ React.createElement(
28746
+ SidebarLink,
28747
+ {
28748
+ label: collection.label ? collection.label : collection.name,
28749
+ to: `/collections/${collection.name}/~`,
28750
+ Icon: ImUsers,
28751
+ onClick: () => {
28752
+ setMenuIsOpen(false);
28753
+ }
28754
+ }
28287
28755
  )
28288
28756
  },
28289
28757
  /* @__PURE__ */ React.createElement("div", { className: "absolute top-8 right-0 transform translate-x-full overflow-hidden" }, /* @__PURE__ */ React.createElement(
@@ -28422,11 +28890,11 @@ This will work when developing locally but NOT when deployed to production.
28422
28890
  const [searchParams] = reactRouterDom.useSearchParams();
28423
28891
  const slug = searchParams.get("slug") || "/";
28424
28892
  const logout2 = async () => {
28425
- var _a, _b, _c, _d, _e, _f;
28426
- if ((_b = (_a = cms == null ? void 0 : cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.logout) {
28427
- await cms.api.tina.logout();
28428
- if ((_d = (_c = cms == null ? void 0 : cms.api) == null ? void 0 : _c.tina) == null ? void 0 : _d.onLogout) {
28429
- await ((_f = (_e = cms == null ? void 0 : cms.api) == null ? void 0 : _e.tina) == null ? void 0 : _f.onLogout());
28893
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
28894
+ if ((_c = (_b = (_a = cms == null ? void 0 : cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.authProvider) == null ? void 0 : _c.logout) {
28895
+ await ((_f = (_e = (_d = cms == null ? void 0 : cms.api) == null ? void 0 : _d.tina) == null ? void 0 : _e.authProvider) == null ? void 0 : _f.logout());
28896
+ if ((_h = (_g = cms == null ? void 0 : cms.api) == null ? void 0 : _g.tina) == null ? void 0 : _h.onLogout) {
28897
+ await ((_j = (_i = cms == null ? void 0 : cms.api) == null ? void 0 : _i.tina) == null ? void 0 : _j.onLogout());
28430
28898
  }
28431
28899
  }
28432
28900
  setEdit(false);
@@ -29430,8 +29898,7 @@ This will work when developing locally but NOT when deployed to production.
29430
29898
  setSearch(searchInput);
29431
29899
  setSearchLoaded(false);
29432
29900
  },
29433
- variant: "primary",
29434
- type: "submit"
29901
+ variant: "primary"
29435
29902
  },
29436
29903
  "Search ",
29437
29904
  /* @__PURE__ */ React.createElement(BiSearch, { className: "w-5 h-full ml-1.5 opacity-70" })
@@ -29715,13 +30182,13 @@ This will work when developing locally but NOT when deployed to production.
29715
30182
  }
29716
30183
  const defaultItem = customDefaults || // @ts-ignore internal types aren't up to date
29717
30184
  ((_d = template.ui) == null ? void 0 : _d.defaultItem) || // @ts-ignore
29718
- (template == null ? void 0 : template.defaultItem);
30185
+ (template == null ? void 0 : template.defaultItem) || {};
29719
30186
  const form = React.useMemo(() => {
29720
30187
  var _a2, _b2;
29721
30188
  const folderName = folder.fullyQualifiedName ? folder.name : "";
29722
30189
  return new Form({
29723
30190
  crudType: "create",
29724
- initialValues: typeof defaultItem === "function" ? defaultItem() : defaultItem,
30191
+ initialValues: typeof defaultItem === "function" ? { ...defaultItem(), _template: templateName } : { ...defaultItem, _template: templateName },
29725
30192
  extraSubscribeValues: { active: true, submitting: true, touched: true },
29726
30193
  onChange: (values) => {
29727
30194
  var _a3, _b3;
@@ -30253,10 +30720,12 @@ This will work when developing locally but NOT when deployed to production.
30253
30720
  redirect,
30254
30721
  children
30255
30722
  }) => {
30723
+ const cms = useCMS$1();
30256
30724
  const navigate = reactRouterDom.useNavigate();
30257
30725
  React.useEffect(() => {
30726
+ const basePath = cms.flags.get("tina-basepath");
30258
30727
  if (redirect) {
30259
- navigate("/~");
30728
+ navigate(`/~${basePath ? `/${basePath}` : ""}`);
30260
30729
  }
30261
30730
  }, [redirect]);
30262
30731
  return children;
@@ -30500,22 +30969,6 @@ This will work when developing locally but NOT when deployed to production.
30500
30969
  this.mapper = mapper;
30501
30970
  }
30502
30971
  }
30503
- const defineSchema = (config) => {
30504
- schemaTools.validateSchema({ schema: config });
30505
- return config;
30506
- };
30507
- const defineLegacyConfig = (config) => {
30508
- schemaTools.validateSchema({ schema: config.schema });
30509
- return config;
30510
- };
30511
- const defineStaticConfig = (config) => {
30512
- if (!config.schema) {
30513
- throw new Error("Static config must have a schema");
30514
- }
30515
- schemaTools.validateSchema({ schema: config.schema });
30516
- return config;
30517
- };
30518
- const defineConfig = defineStaticConfig;
30519
30972
  const tinaTableTemplate = {
30520
30973
  name: "table",
30521
30974
  label: "Table",
@@ -30525,6 +30978,13 @@ This will work when developing locally but NOT when deployed to production.
30525
30978
  label: "First row is a header",
30526
30979
  type: "boolean"
30527
30980
  },
30981
+ {
30982
+ name: "align",
30983
+ label: "Align",
30984
+ type: "string",
30985
+ list: true,
30986
+ description: 'Possible values: "left", "right", or "center".'
30987
+ },
30528
30988
  {
30529
30989
  name: "tableRows",
30530
30990
  label: "Rows",
@@ -30537,7 +30997,7 @@ This will work when developing locally but NOT when deployed to production.
30537
30997
  return {
30538
30998
  label: value.tableCells.map((cellItem) => {
30539
30999
  var _a;
30540
- return (_a = stringifyCell(cellItem.tableCell)) == null ? void 0 : _a.trim();
31000
+ return (_a = stringifyCell(cellItem.value)) == null ? void 0 : _a.trim();
30541
31001
  }).join(" | ")
30542
31002
  };
30543
31003
  }
@@ -30552,24 +31012,36 @@ This will work when developing locally but NOT when deployed to production.
30552
31012
  list: true,
30553
31013
  type: "object",
30554
31014
  ui: {
30555
- itemProps: (value) => {
31015
+ itemProps: (cell) => {
30556
31016
  var _a;
30557
- if (value) {
30558
- if (value.tableCell) {
31017
+ if (cell) {
31018
+ if (cell.value) {
30559
31019
  return {
30560
- label: (_a = stringifyCell(value.tableCell)) == null ? void 0 : _a.trim()
31020
+ label: (_a = stringifyCell(cell.value)) == null ? void 0 : _a.trim()
30561
31021
  };
30562
31022
  }
30563
31023
  }
30564
- return { label: "Table Cell" };
31024
+ return { label: "Value" };
30565
31025
  }
30566
31026
  },
30567
31027
  fields: [
30568
31028
  {
30569
- label: "Table Cell",
30570
- description: "Note: table cells do not support block-level elements like headers, code blocks, or lists. Any block-level items other than the first paragraph will be ignored.",
30571
- name: "tableCell",
30572
- type: "rich-text"
31029
+ label: "Value",
31030
+ description: "Note: table cells do not support block-level elements like headers, code blocks, or lists. Any block-level items other than the first paragraph will be considered invalid.",
31031
+ name: "value",
31032
+ type: "rich-text",
31033
+ ui: {
31034
+ validate(value) {
31035
+ try {
31036
+ tableCellSchema.parse(value);
31037
+ } catch (e) {
31038
+ if (e instanceof zod.z.ZodError) {
31039
+ return e.errors[0].message;
31040
+ }
31041
+ return e.message;
31042
+ }
31043
+ }
31044
+ }
30573
31045
  }
30574
31046
  ]
30575
31047
  }
@@ -30577,9 +31049,54 @@ This will work when developing locally but NOT when deployed to production.
30577
31049
  }
30578
31050
  ]
30579
31051
  };
31052
+ const tableCellSchema = zod.z.object({
31053
+ type: zod.z.literal("root"),
31054
+ children: zod.z.array(
31055
+ zod.z.object({
31056
+ type: zod.z.string(),
31057
+ children: zod.z.any().array()
31058
+ })
31059
+ ).refine(
31060
+ (value) => {
31061
+ const firstValue = value[0];
31062
+ return firstValue && firstValue.type === "p";
31063
+ },
31064
+ {
31065
+ message: `Table cell content cannot contain block elements like headers, blockquotes, or lists.`
31066
+ }
31067
+ ).refine(
31068
+ (value) => {
31069
+ var _a;
31070
+ if (value.length > 1) {
31071
+ const secondBlock = value[1];
31072
+ return secondBlock && secondBlock.children.length === 1 && !((_a = secondBlock.children[0]) == null ? void 0 : _a.text);
31073
+ }
31074
+ return true;
31075
+ },
31076
+ {
31077
+ message: `Table cells can only have 1 block level element.`
31078
+ }
31079
+ )
31080
+ });
30580
31081
  const stringifyCell = (cell) => {
30581
31082
  return mdx.stringifyMDX(cell, { name: "body", type: "rich-text" }, () => "");
30582
31083
  };
31084
+ const defineSchema = (config) => {
31085
+ schemaTools.validateSchema({ schema: config });
31086
+ return config;
31087
+ };
31088
+ const defineLegacyConfig = (config) => {
31089
+ schemaTools.validateSchema({ schema: config.schema });
31090
+ return config;
31091
+ };
31092
+ const defineStaticConfig = (config) => {
31093
+ if (!config.schema) {
31094
+ throw new Error("Static config must have a schema");
31095
+ }
31096
+ schemaTools.validateSchema({ schema: config.schema });
31097
+ return config;
31098
+ };
31099
+ const defineConfig = defineStaticConfig;
30583
31100
  Object.defineProperty(exports2, "NAMER", {
30584
31101
  enumerable: true,
30585
31102
  get: () => schemaTools.NAMER
@@ -30588,6 +31105,7 @@ This will work when developing locally but NOT when deployed to production.
30588
31105
  enumerable: true,
30589
31106
  get: () => schemaTools.resolveField
30590
31107
  });
31108
+ exports2.AbstractAuthProvider = AbstractAuthProvider;
30591
31109
  exports2.ActionButton = ActionButton;
30592
31110
  exports2.AddIcon = AddIcon;
30593
31111
  exports2.AlertIcon = AlertIcon;
@@ -30596,6 +31114,7 @@ This will work when developing locally but NOT when deployed to production.
30596
31114
  exports2.AlignLeft = AlignLeft;
30597
31115
  exports2.AlignRight = AlignRight;
30598
31116
  exports2.AuthWallInner = AuthWallInner;
31117
+ exports2.BasePasswordField = BasePasswordField;
30599
31118
  exports2.BaseTextField = BaseTextField;
30600
31119
  exports2.BillingWarning = BillingWarning;
30601
31120
  exports2.BlocksField = BlocksField;
@@ -30690,6 +31209,7 @@ This will work when developing locally but NOT when deployed to production.
30690
31209
  exports2.ListField = ListField;
30691
31210
  exports2.ListFieldPlugin = ListFieldPlugin;
30692
31211
  exports2.LoadingDots = LoadingDots;
31212
+ exports2.LocalAuthProvider = LocalAuthProvider;
30693
31213
  exports2.LocalClient = LocalClient;
30694
31214
  exports2.LocalSearchClient = LocalSearchClient;
30695
31215
  exports2.LocalWarning = LocalWarning;
@@ -30717,6 +31237,8 @@ This will work when developing locally but NOT when deployed to production.
30717
31237
  exports2.OverflowMenu = OverflowMenu$1;
30718
31238
  exports2.PanelBody = PanelBody;
30719
31239
  exports2.PanelHeader = PanelHeader$1;
31240
+ exports2.PasswordFieldComponent = PasswordFieldComponent;
31241
+ exports2.PasswordFieldPlugin = PasswordFieldPlugin;
30720
31242
  exports2.PopupModal = PopupModal;
30721
31243
  exports2.PrefixedTextField = PrefixedTextField;
30722
31244
  exports2.PullRequestIcon = PullRequestIcon;
@@ -30758,6 +31280,7 @@ This will work when developing locally but NOT when deployed to production.
30758
31280
  exports2.TinaCMSProvider = TinaCMSProvider;
30759
31281
  exports2.TinaCMSProvider2 = TinaCMSProvider2;
30760
31282
  exports2.TinaCMSSearchClient = TinaCMSSearchClient;
31283
+ exports2.TinaCloudAuthProvider = TinaCloudAuthProvider;
30761
31284
  exports2.TinaCloudAuthWall = TinaCloudAuthWall;
30762
31285
  exports2.TinaCloudProvider = TinaCloudProvider;
30763
31286
  exports2.TinaField = TinaField;
@@ -30776,7 +31299,6 @@ This will work when developing locally but NOT when deployed to production.
30776
31299
  exports2.UploadIcon = UploadIcon;
30777
31300
  exports2.WarningIcon = WarningIcon;
30778
31301
  exports2.assertShape = assertShape;
30779
- exports2.asyncPoll = asyncPoll;
30780
31302
  exports2.classNames = classNames;
30781
31303
  exports2.createClient = createClient;
30782
31304
  exports2.default = TinaCMSProvider2;
@@ -30788,6 +31310,7 @@ This will work when developing locally but NOT when deployed to production.
30788
31310
  exports2.getFilteredBranchList = getFilteredBranchList;
30789
31311
  exports2.getStaticPropsForTina = getStaticPropsForTina;
30790
31312
  exports2.gql = gql;
31313
+ exports2.passwordFieldClasses = passwordFieldClasses;
30791
31314
  exports2.safeAssertShape = safeAssertShape;
30792
31315
  exports2.selectFieldClasses = selectFieldClasses;
30793
31316
  exports2.staticRequest = staticRequest;