tinacms 0.0.0-d240606-20250315175410 → 0.0.0-d28d795-20250427004334

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/cn"), require("@udecode/plate"), require("@udecode/plate-common"), require("@udecode/plate-slash-command"), require("slate-react"), require("@udecode/plate-code-block"), require("@monaco-editor/react"), require("@headlessui/react"), require("class-variance-authority"), require("lucide-react"), require("mermaid"), require("@udecode/plate-heading"), require("@ariakit/react"), require("@udecode/plate-combobox"), require("@udecode/plate-table"), require("@udecode/plate-resizable"), require("@radix-ui/react-popover"), require("@radix-ui/react-slot"), require("@radix-ui/react-dropdown-menu"), require("@radix-ui/react-separator"), 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("react-color"), require("color-string"), require("react-dropzone"), require("clsx"), require("tailwind-merge"), require("cmdk"), require("is-hotkey"), require("slate"), require("lodash.get"), require("moment"), require("date-fns"), require("@udecode/plate-link"), require("@radix-ui/react-toolbar"), require("@radix-ui/react-tooltip"), require("@udecode/plate-paragraph"), require("@udecode/plate-block-quote"), require("@udecode/plate-floating"), require("@react-hook/window-size"), require("graphql"), require("graphql-tag"), require("@tinacms/schema-tools"), require("@graphql-inspector/core"), require("yup"), require("react-router-dom"), require("@tinacms/mdx")) : typeof define === "function" && define.amd ? define(["exports", "zod", "react", "react-dom", "@udecode/cn", "@udecode/plate", "@udecode/plate-common", "@udecode/plate-slash-command", "slate-react", "@udecode/plate-code-block", "@monaco-editor/react", "@headlessui/react", "class-variance-authority", "lucide-react", "mermaid", "@udecode/plate-heading", "@ariakit/react", "@udecode/plate-combobox", "@udecode/plate-table", "@udecode/plate-resizable", "@radix-ui/react-popover", "@radix-ui/react-slot", "@radix-ui/react-dropdown-menu", "@radix-ui/react-separator", "final-form-arrays", "final-form-set-field-data", "final-form", "react-final-form", "prop-types", "react-beautiful-dnd", "react-color", "color-string", "react-dropzone", "clsx", "tailwind-merge", "cmdk", "is-hotkey", "slate", "lodash.get", "moment", "date-fns", "@udecode/plate-link", "@radix-ui/react-toolbar", "@radix-ui/react-tooltip", "@udecode/plate-paragraph", "@udecode/plate-block-quote", "@udecode/plate-floating", "@react-hook/window-size", "graphql", "graphql-tag", "@tinacms/schema-tools", "@graphql-inspector/core", "yup", "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, 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, cn$1, plate, plateCommon, plateSlashCommand, slateReact, plateCodeBlock, MonacoEditor, react, classVarianceAuthority, lucideReact, mermaid, plateHeading, react$1, plateCombobox, plateTable, plateResizable, PopoverPrimitive, reactSlot, DropdownMenuPrimitive, SeparatorPrimitive, arrayMutators, setFieldData, finalForm, reactFinalForm, PropTypes, reactBeautifulDnd, pkg$1, pkg, dropzone, clsx, tailwindMerge, cmdk, isHotkey, slate, get, moment, dateFns, plateLink, ToolbarPrimitive, TooltipPrimitive, plateParagraph, plateBlockQuote, plateFloating, windowSize, graphql, gql, schemaTools, core, yup, reactRouterDom, mdx) {
2
+ typeof exports === "object" && typeof module !== "undefined" ? factory(exports, require("zod"), require("react"), require("react-dom"), require("@udecode/cn"), require("@udecode/plate"), require("@udecode/plate-common"), require("@udecode/plate-slash-command"), require("slate-react"), require("@udecode/plate-code-block"), require("@monaco-editor/react"), require("@headlessui/react"), require("class-variance-authority"), require("lucide-react"), require("mermaid"), require("@udecode/plate-heading"), require("@ariakit/react"), require("@udecode/plate-combobox"), require("@udecode/plate-table"), require("@udecode/plate-resizable"), require("@radix-ui/react-popover"), require("@radix-ui/react-slot"), require("@radix-ui/react-dropdown-menu"), require("@radix-ui/react-separator"), 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("react-color"), require("color-string"), require("react-dropzone"), require("clsx"), require("tailwind-merge"), require("cmdk"), require("is-hotkey"), require("slate"), require("@react-hook/window-size"), require("lodash.get"), require("moment"), require("date-fns"), require("@udecode/plate-link"), require("@radix-ui/react-toolbar"), require("@radix-ui/react-tooltip"), require("@udecode/plate-paragraph"), require("@udecode/plate-block-quote"), require("@udecode/plate-floating"), require("graphql"), require("@tinacms/schema-tools"), require("graphql-tag"), require("@graphql-inspector/core"), require("yup"), require("react-router-dom"), require("@tinacms/mdx")) : typeof define === "function" && define.amd ? define(["exports", "zod", "react", "react-dom", "@udecode/cn", "@udecode/plate", "@udecode/plate-common", "@udecode/plate-slash-command", "slate-react", "@udecode/plate-code-block", "@monaco-editor/react", "@headlessui/react", "class-variance-authority", "lucide-react", "mermaid", "@udecode/plate-heading", "@ariakit/react", "@udecode/plate-combobox", "@udecode/plate-table", "@udecode/plate-resizable", "@radix-ui/react-popover", "@radix-ui/react-slot", "@radix-ui/react-dropdown-menu", "@radix-ui/react-separator", "final-form-arrays", "final-form-set-field-data", "final-form", "react-final-form", "prop-types", "react-beautiful-dnd", "react-color", "color-string", "react-dropzone", "clsx", "tailwind-merge", "cmdk", "is-hotkey", "slate", "@react-hook/window-size", "lodash.get", "moment", "date-fns", "@udecode/plate-link", "@radix-ui/react-toolbar", "@radix-ui/react-tooltip", "@udecode/plate-paragraph", "@udecode/plate-block-quote", "@udecode/plate-floating", "graphql", "@tinacms/schema-tools", "graphql-tag", "@graphql-inspector/core", "yup", "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, 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, cn$1, plate, plateCommon, plateSlashCommand, slateReact, plateCodeBlock, MonacoEditor, react, classVarianceAuthority, lucideReact, mermaid, plateHeading, react$1, plateCombobox, plateTable, plateResizable, PopoverPrimitive, reactSlot, DropdownMenuPrimitive, SeparatorPrimitive, arrayMutators, setFieldData, finalForm, reactFinalForm, PropTypes, reactBeautifulDnd, pkg$1, pkg, dropzone, clsx, tailwindMerge, cmdk, isHotkey, slate, windowSize, get, moment, dateFns, plateLink, ToolbarPrimitive, TooltipPrimitive, plateParagraph, plateBlockQuote, plateFloating, graphql, schemaTools, gql, core, yup, 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) => {
@@ -4403,36 +4403,6 @@ flowchart TD
4403
4403
  function MdOutlinePerson(props) {
4404
4404
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "fill": "none", "d": "M0 0h24v24H0V0z" }, "child": [] }, { "tag": "path", "attr": { "d": "M12 6c1.1 0 2 .9 2 2s-.9 2-2 2-2-.9-2-2 .9-2 2-2m0 10c2.7 0 5.8 1.29 6 2H6c.23-.72 3.31-2 6-2m0-12C9.79 4 8 5.79 8 8s1.79 4 4 4 4-1.79 4-4-1.79-4-4-4zm0 10c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z" }, "child": [] }] })(props);
4405
4405
  }
4406
- const BranchContext = React__namespace.createContext({
4407
- currentBranch: null,
4408
- setCurrentBranch: (branch) => {
4409
- console.warn("BranchContext not initialized");
4410
- }
4411
- });
4412
- const BranchDataProvider = ({
4413
- currentBranch,
4414
- setCurrentBranch,
4415
- children
4416
- }) => {
4417
- return /* @__PURE__ */ React__namespace.createElement(
4418
- BranchContext.Provider,
4419
- {
4420
- value: {
4421
- currentBranch,
4422
- setCurrentBranch
4423
- }
4424
- },
4425
- children
4426
- );
4427
- };
4428
- const useBranchData = () => {
4429
- const branchData = React__namespace.useContext(BranchContext);
4430
- const { dispatch } = useEvent("branch:change");
4431
- React__namespace.useEffect(() => {
4432
- dispatch({ branchName: branchData.currentBranch });
4433
- }, [branchData.currentBranch]);
4434
- return branchData;
4435
- };
4436
4406
  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";
4437
4407
  const disabledClasses$1 = "opacity-50 pointer-events-none cursor-not-allowed";
4438
4408
  const BaseTextField = React__namespace.forwardRef(({ className, disabled, ...rest }, ref) => {
@@ -8036,9 +8006,6 @@ flowchart TD
8036
8006
  },
8037
8007
  parse: parse$2
8038
8008
  };
8039
- function GrCircleQuestion(props) {
8040
- return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "fill": "none", "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" }, "child": [] }] })(props);
8041
- }
8042
8009
  function AiFillWarning(props) {
8043
8010
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 1024 1024" }, "child": [{ "tag": "path", "attr": { "d": "M955.7 856l-416-720c-6.2-10.7-16.9-16-27.7-16s-21.6 5.3-27.7 16l-416 720C56 877.4 71.4 904 96 904h832c24.6 0 40-26.6 27.7-48zM480 416c0-4.4 3.6-8 8-8h48c4.4 0 8 3.6 8 8v184c0 4.4-3.6 8-8 8h-48c-4.4 0-8-3.6-8-8V416zm32 352a48.01 48.01 0 0 1 0-96 48.01 48.01 0 0 1 0 96z" }, "child": [] }] })(props);
8044
8011
  }
@@ -8057,6 +8024,39 @@ flowchart TD
8057
8024
  function FaUnlock(props) {
8058
8025
  return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 448 512" }, "child": [{ "tag": "path", "attr": { "d": "M400 256H152V152.9c0-39.6 31.7-72.5 71.3-72.9 40-.4 72.7 32.1 72.7 72v16c0 13.3 10.7 24 24 24h32c13.3 0 24-10.7 24-24v-16C376 68 307.5-.3 223.5 0 139.5.3 72 69.5 72 153.5V256H48c-26.5 0-48 21.5-48 48v160c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V304c0-26.5-21.5-48-48-48z" }, "child": [] }] })(props);
8059
8026
  }
8027
+ function GrCircleQuestion(props) {
8028
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24" }, "child": [{ "tag": "path", "attr": { "fill": "none", "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" }, "child": [] }] })(props);
8029
+ }
8030
+ const BranchContext = React__namespace.createContext({
8031
+ currentBranch: null,
8032
+ setCurrentBranch: (branch) => {
8033
+ console.warn("BranchContext not initialized");
8034
+ }
8035
+ });
8036
+ const BranchDataProvider = ({
8037
+ currentBranch,
8038
+ setCurrentBranch,
8039
+ children
8040
+ }) => {
8041
+ return /* @__PURE__ */ React__namespace.createElement(
8042
+ BranchContext.Provider,
8043
+ {
8044
+ value: {
8045
+ currentBranch,
8046
+ setCurrentBranch
8047
+ }
8048
+ },
8049
+ children
8050
+ );
8051
+ };
8052
+ const useBranchData = () => {
8053
+ const branchData = React__namespace.useContext(BranchContext);
8054
+ const { dispatch } = useEvent("branch:change");
8055
+ React__namespace.useEffect(() => {
8056
+ dispatch({ branchName: branchData.currentBranch });
8057
+ }, [branchData.currentBranch]);
8058
+ return branchData;
8059
+ };
8060
8060
  function formatBranchName$1(str) {
8061
8061
  const pattern = /[^/\w-]+/g;
8062
8062
  const formattedStr = str.replace(pattern, "");
@@ -8155,7 +8155,7 @@ flowchart TD
8155
8155
  className: "transition-all duration-150 ease-out text-blue-600 hover:text-blue-400 hover:underline no-underline",
8156
8156
  href: "https://tina.io/docs/tina-cloud/"
8157
8157
  },
8158
- "Learn more about moving to production with Tina Cloud."
8158
+ "Learn more about moving to production with TinaCloud."
8159
8159
  )), /* @__PURE__ */ React__namespace.createElement("p", null, /* @__PURE__ */ React__namespace.createElement(
8160
8160
  Button$1,
8161
8161
  {
@@ -8391,7 +8391,7 @@ flowchart TD
8391
8391
  className: "transition-all duration-150 ease-out text-blue-600 hover:text-blue-400 hover:underline no-underline",
8392
8392
  href: "https://tina.io/docs/tina-cloud/"
8393
8393
  },
8394
- "Learn more about moving to production with Tina Cloud."
8394
+ "Learn more about moving to production with TinaCloud."
8395
8395
  )), /* @__PURE__ */ React__namespace.createElement("p", null, /* @__PURE__ */ React__namespace.createElement(
8396
8396
  Button$1,
8397
8397
  {
@@ -9423,7 +9423,7 @@ flowchart TD
9423
9423
  });
9424
9424
  new MediaListError({
9425
9425
  title: "An Error Occurred",
9426
- message: "Something went wrong accessing your media from Tina Cloud.",
9426
+ message: "Something went wrong accessing your media from TinaCloud.",
9427
9427
  docsLink: ""
9428
9428
  // TODO
9429
9429
  });
@@ -9608,7 +9608,7 @@ flowchart TD
9608
9608
  return this.add("error", message, timeout);
9609
9609
  }
9610
9610
  };
9611
- const NoFormsPlaceholder = () => /* @__PURE__ */ React__namespace.createElement(
9611
+ const SidebarLoadingPlaceholder = () => /* @__PURE__ */ React__namespace.createElement(
9612
9612
  "div",
9613
9613
  {
9614
9614
  className: "relative flex flex-col items-center justify-center text-center p-5 pb-16 w-full h-full overflow-y-auto",
@@ -9621,25 +9621,8 @@ flowchart TD
9621
9621
  animationDuration: "150ms"
9622
9622
  }
9623
9623
  },
9624
- /* @__PURE__ */ React__namespace.createElement(Emoji$1, { className: "pb-5" }, "🔎"),
9625
- /* @__PURE__ */ React__namespace.createElement("p", { className: "block pb-5" }, "Looks like there's ", /* @__PURE__ */ React__namespace.createElement("br", null), "nothing to edit on ", /* @__PURE__ */ React__namespace.createElement("br", null), "this page."),
9626
- /* @__PURE__ */ React__namespace.createElement("p", { className: "block" }, /* @__PURE__ */ React__namespace.createElement(
9627
- Button$1,
9628
- {
9629
- href: "https://tina.io/docs/tinacms-context/",
9630
- target: "_blank",
9631
- as: "a"
9632
- },
9633
- /* @__PURE__ */ React__namespace.createElement(Emoji$1, { className: "mr-1.5" }, "📖"),
9634
- " Contextual Editing"
9635
- ))
9636
- );
9637
- const Emoji$1 = ({ className = "", ...props }) => /* @__PURE__ */ React__namespace.createElement(
9638
- "span",
9639
- {
9640
- className: `text-[24px] leading-none inline-block ${className}`,
9641
- ...props
9642
- }
9624
+ /* @__PURE__ */ React__namespace.createElement("p", { className: "block pb-5" }, "Please wait while TinaCMS", /* @__PURE__ */ React__namespace.createElement("br", null), "loads your content"),
9625
+ /* @__PURE__ */ React__namespace.createElement(LoadingDots, { color: "var(--tina-color-primary)" })
9643
9626
  );
9644
9627
  class SidebarState {
9645
9628
  constructor(events, options = {}) {
@@ -9654,7 +9637,7 @@ flowchart TD
9654
9637
  };
9655
9638
  this.position = options.position || "displace";
9656
9639
  this.renderNav = options.renderNav || true;
9657
- this.placeholder = options.placeholder || NoFormsPlaceholder;
9640
+ this.loadingPlaceholder = options.placeholder || SidebarLoadingPlaceholder;
9658
9641
  if ((_a = options.buttons) == null ? void 0 : _a.save) {
9659
9642
  this.buttons.save = options.buttons.save;
9660
9643
  }
@@ -9728,238 +9711,6 @@ flowchart TD
9728
9711
  children
9729
9712
  )));
9730
9713
  };
9731
- const Item = ({
9732
- item,
9733
- depth,
9734
- setActiveFormId
9735
- }) => {
9736
- const cms = useCMS();
9737
- const depths = ["pl-6", "pl-10", "pl-14"];
9738
- const form = React__namespace.useMemo(
9739
- () => cms.state.forms.find(({ tinaForm }) => item.formId === tinaForm.id),
9740
- [item.formId]
9741
- );
9742
- return /* @__PURE__ */ React__namespace.createElement(
9743
- "button",
9744
- {
9745
- type: "button",
9746
- key: item.path,
9747
- onClick: () => setActiveFormId(item.formId),
9748
- className: `${depths[depth] || "pl-12"} pr-6 py-3 w-full h-full bg-transparent border-none text-lg text-gray-700 group hover:bg-gray-50 transition-all ease-out duration-150 flex items-center justify-between gap-2`
9749
- },
9750
- /* @__PURE__ */ React__namespace.createElement(BiEdit, { className: "opacity-70 w-5 h-auto text-blue-500 flex-none" }),
9751
- /* @__PURE__ */ React__namespace.createElement("div", { className: "flex-1 flex flex-col gap-0.5 items-start" }, /* @__PURE__ */ React__namespace.createElement("div", { className: "group-hover:text-blue-500 font-sans text-xs font-semibold text-gray-700 whitespace-normal" }, form.tinaForm.label), /* @__PURE__ */ React__namespace.createElement("div", { className: "group-hover:text-blue-500 text-base truncate leading-tight text-gray-600" }, form.tinaForm.id))
9752
- );
9753
- };
9754
- const FormListItem = ({
9755
- item,
9756
- depth,
9757
- setActiveFormId
9758
- }) => {
9759
- var _a;
9760
- return /* @__PURE__ */ React__namespace.createElement("div", { className: "divide-y divide-gray-200" }, /* @__PURE__ */ React__namespace.createElement(Item, { setActiveFormId, item, depth }), item.subItems && /* @__PURE__ */ React__namespace.createElement("ul", { className: "divide-y divide-gray-200" }, (_a = item.subItems) == null ? void 0 : _a.map((subItem) => {
9761
- if (subItem.type === "document") {
9762
- return /* @__PURE__ */ React__namespace.createElement("li", { key: subItem.formId }, /* @__PURE__ */ React__namespace.createElement(
9763
- Item,
9764
- {
9765
- setActiveFormId,
9766
- depth: depth + 1,
9767
- item: subItem
9768
- }
9769
- ));
9770
- }
9771
- })));
9772
- };
9773
- const FormLists = (props) => {
9774
- const cms = useCMS();
9775
- return /* @__PURE__ */ React__namespace.createElement(
9776
- react.Transition,
9777
- {
9778
- appear: true,
9779
- show: true,
9780
- as: "div",
9781
- enter: "transition-all ease-out duration-150",
9782
- enterFrom: "opacity-0 -translate-x-1/2",
9783
- enterTo: "opacity-100",
9784
- leave: "transition-all ease-out duration-150",
9785
- leaveFrom: "opacity-100",
9786
- leaveTo: "opacity-0 -translate-x-1/2"
9787
- },
9788
- cms.state.formLists.map((formList, index) => /* @__PURE__ */ React__namespace.createElement("div", { key: `${formList.id}-${index}`, className: "pt-16" }, /* @__PURE__ */ React__namespace.createElement(
9789
- FormList,
9790
- {
9791
- isEditing: props.isEditing,
9792
- setActiveFormId: (id) => {
9793
- cms.dispatch({ type: "forms:set-active-form-id", value: id });
9794
- },
9795
- formList
9796
- }
9797
- )))
9798
- );
9799
- };
9800
- const FormList = (props) => {
9801
- const cms = useCMS();
9802
- const listItems = React__namespace.useMemo(() => {
9803
- var _a;
9804
- const orderedListItems = [];
9805
- const globalItems = [];
9806
- const topItems = [];
9807
- props.formList.items.forEach((item) => {
9808
- if (item.type === "document") {
9809
- const form = cms.state.forms.find(
9810
- ({ tinaForm }) => tinaForm.id === item.formId
9811
- );
9812
- if (form.tinaForm.global) {
9813
- globalItems.push(item);
9814
- } else {
9815
- orderedListItems.push(item);
9816
- }
9817
- } else {
9818
- orderedListItems.push(item);
9819
- }
9820
- });
9821
- if (((_a = orderedListItems[0]) == null ? void 0 : _a.type) === "document") {
9822
- topItems.push({ type: "list", label: "Documents" });
9823
- }
9824
- let extra = [];
9825
- if (globalItems.length) {
9826
- extra = [{ type: "list", label: "Global Documents" }, ...globalItems];
9827
- }
9828
- return [...topItems, ...orderedListItems, ...extra];
9829
- }, [JSON.stringify(props.formList.items)]);
9830
- return /* @__PURE__ */ React__namespace.createElement("ul", null, /* @__PURE__ */ React__namespace.createElement("li", { className: "divide-y divide-gray-200" }, listItems.map((item, index) => {
9831
- if (item.type === "list") {
9832
- return /* @__PURE__ */ React__namespace.createElement(
9833
- "div",
9834
- {
9835
- key: item.label,
9836
- className: `relative group text-left w-full bg-white shadow-sm
9837
- border-gray-100 px-6 -mt-px pb-3 ${index > 0 ? "pt-6 bg-gradient-to-b from-gray-50 via-white to-white" : "pt-3"}`
9838
- },
9839
- /* @__PURE__ */ React__namespace.createElement(
9840
- "span",
9841
- {
9842
- className: "text-sm tracking-wide font-bold text-gray-700 uppercase"
9843
- },
9844
- item.label
9845
- )
9846
- );
9847
- }
9848
- return /* @__PURE__ */ React__namespace.createElement(
9849
- FormListItem,
9850
- {
9851
- setActiveFormId: (id) => props.setActiveFormId(id),
9852
- key: item.formId,
9853
- item,
9854
- depth: 0
9855
- }
9856
- );
9857
- })));
9858
- };
9859
- const FormsView = ({
9860
- children
9861
- }) => {
9862
- const cms = useCMS$1();
9863
- const { setFormIsPristine } = React__namespace.useContext(SidebarContext);
9864
- const isMultiform = cms.state.forms.length > 1;
9865
- const activeForm = cms.state.forms.find(
9866
- ({ tinaForm }) => tinaForm.id === cms.state.activeFormId
9867
- );
9868
- const isEditing = !!activeForm;
9869
- if (!cms.state.formLists.length) {
9870
- return /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, " ", children, " ");
9871
- }
9872
- if (isMultiform && !activeForm) {
9873
- return /* @__PURE__ */ React__namespace.createElement(FormLists, { isEditing });
9874
- }
9875
- const formMetas = cms.plugins.all("form:meta");
9876
- return /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, activeForm && /* @__PURE__ */ React__namespace.createElement(FormWrapper$1, { isEditing, isMultiform }, isMultiform && /* @__PURE__ */ React__namespace.createElement(MultiformFormHeader, { activeForm }), !isMultiform && /* @__PURE__ */ React__namespace.createElement(FormHeader, { activeForm }), formMetas == null ? void 0 : formMetas.map((meta) => /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, { key: meta.name }, /* @__PURE__ */ React__namespace.createElement(meta.Component, null))), /* @__PURE__ */ React__namespace.createElement(FormBuilder, { form: activeForm, onPristineChange: setFormIsPristine })));
9877
- };
9878
- const FormWrapper$1 = ({ isEditing, children }) => {
9879
- return /* @__PURE__ */ React__namespace.createElement(
9880
- "div",
9881
- {
9882
- className: "flex-1 flex flex-col flex-nowrap overflow-hidden h-full w-full relative bg-white",
9883
- style: isEditing ? {
9884
- transform: "none",
9885
- animationName: "fly-in-left",
9886
- animationDuration: "150ms",
9887
- animationDelay: "0",
9888
- animationIterationCount: 1,
9889
- animationTimingFunction: "ease-out"
9890
- } : {
9891
- transform: "translate3d(100%, 0, 0)"
9892
- }
9893
- },
9894
- children
9895
- );
9896
- };
9897
- const MultiformFormHeader = ({
9898
- activeForm
9899
- }) => {
9900
- const cms = useCMS$1();
9901
- const { formIsPristine } = React__namespace.useContext(SidebarContext);
9902
- return /* @__PURE__ */ React__namespace.createElement(
9903
- "div",
9904
- {
9905
- className: "pt-18 pb-4 px-6 border-b border-gray-200 bg-gradient-to-t from-white to-gray-50"
9906
- },
9907
- /* @__PURE__ */ React__namespace.createElement("div", { className: "max-w-form mx-auto flex gap-2 justify-between items-center" }, /* @__PURE__ */ React__namespace.createElement(
9908
- "button",
9909
- {
9910
- type: "button",
9911
- className: "pointer-events-auto text-xs text-blue-400 hover:text-blue-500 hover:underline transition-all ease-out duration-150",
9912
- onClick: () => {
9913
- const state = activeForm.tinaForm.finalForm.getState();
9914
- if (state.invalid === true) {
9915
- cms.alerts.error("Cannot navigate away from an invalid form.");
9916
- } else {
9917
- cms.dispatch({ type: "forms:set-active-form-id", value: null });
9918
- }
9919
- }
9920
- },
9921
- /* @__PURE__ */ React__namespace.createElement(BiDotsVertical, { className: "h-auto w-5 inline-block opacity-70" })
9922
- ), /* @__PURE__ */ React__namespace.createElement(
9923
- "button",
9924
- {
9925
- type: "button",
9926
- className: "pointer-events-auto text-xs text-blue-400 hover:text-blue-500 hover:underline transition-all ease-out duration-150",
9927
- onClick: () => {
9928
- const collectionName = cms.api.tina.schema.getCollectionByFullPath(
9929
- cms.state.activeFormId
9930
- ).name;
9931
- window.location.href = `${new URL(window.location.href).pathname}#/collections/${collectionName}/~`;
9932
- }
9933
- },
9934
- /* @__PURE__ */ React__namespace.createElement(BiHomeAlt, { className: "h-auto w-5 inline-block opacity-70" })
9935
- ), /* @__PURE__ */ React__namespace.createElement("span", { className: "opacity-30 text-sm leading-tight whitespace-nowrap flex-0" }, "/"), /* @__PURE__ */ React__namespace.createElement("span", { className: "block w-full text-sm leading-tight whitespace-nowrap truncate" }, activeForm.tinaForm.label || activeForm.tinaForm.id), /* @__PURE__ */ React__namespace.createElement(FormStatus, { pristine: formIsPristine }))
9936
- );
9937
- };
9938
- const FormHeader = ({ activeForm }) => {
9939
- const { formIsPristine } = React__namespace.useContext(SidebarContext);
9940
- const cms = useCMS$1();
9941
- const shortFormLabel = activeForm.tinaForm.label ? activeForm.tinaForm.label.replace(/^.*[\\\/]/, "") : false;
9942
- return /* @__PURE__ */ React__namespace.createElement(
9943
- "div",
9944
- {
9945
- className: "pt-18 pb-4 px-6 border-b border-gray-200 bg-gradient-to-t from-white to-gray-50"
9946
- },
9947
- /* @__PURE__ */ React__namespace.createElement("div", { className: "max-w-form mx-auto flex gap-2 justify-between items-center" }, /* @__PURE__ */ React__namespace.createElement(
9948
- "button",
9949
- {
9950
- type: "button",
9951
- className: "pointer-events-auto text-xs text-blue-400 hover:text-blue-500 hover:underline transition-all ease-out duration-150",
9952
- onClick: () => {
9953
- const collectionName = cms.api.tina.schema.getCollectionByFullPath(
9954
- cms.state.activeFormId
9955
- ).name;
9956
- window.location.href = `${new URL(window.location.href).pathname}#/collections/${collectionName}/~`;
9957
- }
9958
- },
9959
- /* @__PURE__ */ React__namespace.createElement(BiHomeAlt, { className: "h-auto w-5 inline-block opacity-70" })
9960
- ), shortFormLabel && /* @__PURE__ */ React__namespace.createElement("span", { className: "block w-full text-sm leading-tight whitespace-nowrap truncate" }, shortFormLabel), /* @__PURE__ */ React__namespace.createElement(FormStatus, { pristine: formIsPristine }))
9961
- );
9962
- };
9963
9714
  function ImFilesEmpty(props) {
9964
9715
  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" }, "child": [] }, { "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" }, "child": [] }] })(props);
9965
9716
  }
@@ -10202,7 +9953,7 @@ flowchart TD
10202
9953
  "Event Log"
10203
9954
  ));
10204
9955
  };
10205
- const version = "2.7.2";
9956
+ const version = "2.7.5";
10206
9957
  const Nav = ({
10207
9958
  isLocalMode,
10208
9959
  className = "",
@@ -10444,6 +10195,293 @@ flowchart TD
10444
10195
  /* @__PURE__ */ React__namespace.createElement("span", { className: "absolute top-1/2 left-1/2 h-4/6 w-px bg-gray-200 transform -translate-y-1/2 -translate-x-1/2 opacity-30 transition-opacity duration-150 ease-out group-hover:opacity-100" })
10445
10196
  );
10446
10197
  };
10198
+ const Item = ({
10199
+ item,
10200
+ depth,
10201
+ setActiveFormId
10202
+ }) => {
10203
+ const cms = useCMS();
10204
+ const depths = ["pl-6", "pl-10", "pl-14"];
10205
+ const form = React__namespace.useMemo(
10206
+ () => cms.state.forms.find(({ tinaForm }) => item.formId === tinaForm.id),
10207
+ [item.formId]
10208
+ );
10209
+ return /* @__PURE__ */ React__namespace.createElement(
10210
+ "button",
10211
+ {
10212
+ type: "button",
10213
+ key: item.path,
10214
+ onClick: () => setActiveFormId(item.formId),
10215
+ className: `${depths[depth] || "pl-12"} pr-6 py-3 w-full h-full bg-transparent border-none text-lg text-gray-700 group hover:bg-gray-50 transition-all ease-out duration-150 flex items-center justify-between gap-2`
10216
+ },
10217
+ /* @__PURE__ */ React__namespace.createElement(BiEdit, { className: "opacity-70 w-5 h-auto text-blue-500 flex-none" }),
10218
+ /* @__PURE__ */ React__namespace.createElement("div", { className: "flex-1 flex flex-col gap-0.5 items-start" }, /* @__PURE__ */ React__namespace.createElement("div", { className: "group-hover:text-blue-500 font-sans text-xs font-semibold text-gray-700 whitespace-normal" }, form.tinaForm.label), /* @__PURE__ */ React__namespace.createElement("div", { className: "group-hover:text-blue-500 text-base truncate leading-tight text-gray-600" }, form.tinaForm.id))
10219
+ );
10220
+ };
10221
+ const FormListItem = ({
10222
+ item,
10223
+ depth,
10224
+ setActiveFormId
10225
+ }) => {
10226
+ var _a;
10227
+ return /* @__PURE__ */ React__namespace.createElement("div", { className: "divide-y divide-gray-200" }, /* @__PURE__ */ React__namespace.createElement(Item, { setActiveFormId, item, depth }), item.subItems && /* @__PURE__ */ React__namespace.createElement("ul", { className: "divide-y divide-gray-200" }, (_a = item.subItems) == null ? void 0 : _a.map((subItem) => {
10228
+ if (subItem.type === "document") {
10229
+ return /* @__PURE__ */ React__namespace.createElement("li", { key: subItem.formId }, /* @__PURE__ */ React__namespace.createElement(
10230
+ Item,
10231
+ {
10232
+ setActiveFormId,
10233
+ depth: depth + 1,
10234
+ item: subItem
10235
+ }
10236
+ ));
10237
+ }
10238
+ })));
10239
+ };
10240
+ const FormLists = (props) => {
10241
+ const cms = useCMS();
10242
+ return /* @__PURE__ */ React__namespace.createElement(
10243
+ react.Transition,
10244
+ {
10245
+ appear: true,
10246
+ show: true,
10247
+ as: "div",
10248
+ enter: "transition-all ease-out duration-150",
10249
+ enterFrom: "opacity-0 -translate-x-1/2",
10250
+ enterTo: "opacity-100",
10251
+ leave: "transition-all ease-out duration-150",
10252
+ leaveFrom: "opacity-100",
10253
+ leaveTo: "opacity-0 -translate-x-1/2"
10254
+ },
10255
+ cms.state.formLists.map((formList, index) => /* @__PURE__ */ React__namespace.createElement("div", { key: `${formList.id}-${index}`, className: "pt-16" }, /* @__PURE__ */ React__namespace.createElement(
10256
+ FormList,
10257
+ {
10258
+ isEditing: props.isEditing,
10259
+ setActiveFormId: (id) => {
10260
+ cms.dispatch({ type: "forms:set-active-form-id", value: id });
10261
+ },
10262
+ formList
10263
+ }
10264
+ )))
10265
+ );
10266
+ };
10267
+ const FormList = (props) => {
10268
+ const cms = useCMS();
10269
+ const listItems = React__namespace.useMemo(() => {
10270
+ var _a;
10271
+ const orderedListItems = [];
10272
+ const globalItems = [];
10273
+ const topItems = [];
10274
+ props.formList.items.forEach((item) => {
10275
+ if (item.type === "document") {
10276
+ const form = cms.state.forms.find(
10277
+ ({ tinaForm }) => tinaForm.id === item.formId
10278
+ );
10279
+ if (form.tinaForm.global) {
10280
+ globalItems.push(item);
10281
+ } else {
10282
+ orderedListItems.push(item);
10283
+ }
10284
+ } else {
10285
+ orderedListItems.push(item);
10286
+ }
10287
+ });
10288
+ if (((_a = orderedListItems[0]) == null ? void 0 : _a.type) === "document") {
10289
+ topItems.push({ type: "list", label: "Documents" });
10290
+ }
10291
+ let extra = [];
10292
+ if (globalItems.length) {
10293
+ extra = [{ type: "list", label: "Global Documents" }, ...globalItems];
10294
+ }
10295
+ return [...topItems, ...orderedListItems, ...extra];
10296
+ }, [JSON.stringify(props.formList.items)]);
10297
+ return /* @__PURE__ */ React__namespace.createElement("ul", null, /* @__PURE__ */ React__namespace.createElement("li", { className: "divide-y divide-gray-200" }, listItems.map((item, index) => {
10298
+ if (item.type === "list") {
10299
+ return /* @__PURE__ */ React__namespace.createElement(
10300
+ "div",
10301
+ {
10302
+ key: item.label,
10303
+ className: `relative group text-left w-full bg-white shadow-sm
10304
+ border-gray-100 px-6 -mt-px pb-3 ${index > 0 ? "pt-6 bg-gradient-to-b from-gray-50 via-white to-white" : "pt-3"}`
10305
+ },
10306
+ /* @__PURE__ */ React__namespace.createElement(
10307
+ "span",
10308
+ {
10309
+ className: "text-sm tracking-wide font-bold text-gray-700 uppercase"
10310
+ },
10311
+ item.label
10312
+ )
10313
+ );
10314
+ }
10315
+ return /* @__PURE__ */ React__namespace.createElement(
10316
+ FormListItem,
10317
+ {
10318
+ setActiveFormId: (id) => props.setActiveFormId(id),
10319
+ key: item.formId,
10320
+ item,
10321
+ depth: 0
10322
+ }
10323
+ );
10324
+ })));
10325
+ };
10326
+ const SidebarNoFormsPlaceholder = () => /* @__PURE__ */ React__namespace.createElement(
10327
+ "div",
10328
+ {
10329
+ className: "relative flex flex-col items-center justify-center text-center p-5 pb-16 w-full h-full overflow-y-auto",
10330
+ style: {
10331
+ animationName: "fade-in",
10332
+ animationDelay: "300ms",
10333
+ animationTimingFunction: "ease-out",
10334
+ animationIterationCount: 1,
10335
+ animationFillMode: "both",
10336
+ animationDuration: "150ms"
10337
+ }
10338
+ },
10339
+ /* @__PURE__ */ React__namespace.createElement("p", { className: "block pb-5" }, "Looks like there's ", /* @__PURE__ */ React__namespace.createElement("br", null), "nothing to edit on ", /* @__PURE__ */ React__namespace.createElement("br", null), "this page."),
10340
+ /* @__PURE__ */ React__namespace.createElement("p", { className: "block pt-5" }, /* @__PURE__ */ React__namespace.createElement(
10341
+ Button$1,
10342
+ {
10343
+ href: "https://tina.io/docs/contextual-editing/overview",
10344
+ target: "_blank",
10345
+ as: "a"
10346
+ },
10347
+ /* @__PURE__ */ React__namespace.createElement(Emoji$1, { className: "mr-1.5" }, "📖"),
10348
+ " Contextual Editing Docs"
10349
+ ))
10350
+ );
10351
+ const Emoji$1 = ({ className = "", ...props }) => /* @__PURE__ */ React__namespace.createElement(
10352
+ "span",
10353
+ {
10354
+ className: `text-[24px] leading-none inline-block ${className}`,
10355
+ ...props
10356
+ }
10357
+ );
10358
+ const minimumTimeToShowLoadingIndicator = 1e3;
10359
+ const FormsView = ({ loadingPlaceholder } = {}) => {
10360
+ const cms = useCMS$1();
10361
+ const { setFormIsPristine } = React__namespace.useContext(SidebarContext);
10362
+ const [isShowingLoading, setIsShowingLoading] = React__namespace.useState(true);
10363
+ const [initialLoadComplete, setInitialLoadComplete] = React__namespace.useState(false);
10364
+ React__namespace.useEffect(() => {
10365
+ if (cms.state.isLoadingContent) {
10366
+ setIsShowingLoading(true);
10367
+ const timer = setTimeout(() => {
10368
+ if (!cms.state.isLoadingContent) {
10369
+ setIsShowingLoading(false);
10370
+ setInitialLoadComplete(true);
10371
+ }
10372
+ }, minimumTimeToShowLoadingIndicator);
10373
+ return () => clearTimeout(timer);
10374
+ } else {
10375
+ const timer = setTimeout(() => {
10376
+ setIsShowingLoading(false);
10377
+ setInitialLoadComplete(true);
10378
+ }, minimumTimeToShowLoadingIndicator);
10379
+ return () => clearTimeout(timer);
10380
+ }
10381
+ }, [cms.state.isLoadingContent]);
10382
+ if (isShowingLoading || !initialLoadComplete) {
10383
+ const LoadingPlaceholder = loadingPlaceholder || SidebarLoadingPlaceholder;
10384
+ return /* @__PURE__ */ React__namespace.createElement(LoadingPlaceholder, null);
10385
+ }
10386
+ if (!cms.state.formLists.length) {
10387
+ return /* @__PURE__ */ React__namespace.createElement(SidebarNoFormsPlaceholder, null);
10388
+ }
10389
+ const isMultiform = cms.state.forms.length > 1;
10390
+ const activeForm = cms.state.forms.find(
10391
+ ({ tinaForm }) => tinaForm.id === cms.state.activeFormId
10392
+ );
10393
+ const isEditing = !!activeForm;
10394
+ if (isMultiform && !activeForm) {
10395
+ return /* @__PURE__ */ React__namespace.createElement(FormLists, { isEditing });
10396
+ }
10397
+ const formMetas = cms.plugins.all("form:meta");
10398
+ return /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, null, activeForm && /* @__PURE__ */ React__namespace.createElement(FormWrapper$1, { isEditing, isMultiform }, isMultiform && /* @__PURE__ */ React__namespace.createElement(MultiformFormHeader, { activeForm }), !isMultiform && /* @__PURE__ */ React__namespace.createElement(FormHeader, { activeForm }), formMetas == null ? void 0 : formMetas.map((meta) => /* @__PURE__ */ React__namespace.createElement(React__namespace.Fragment, { key: meta.name }, /* @__PURE__ */ React__namespace.createElement(meta.Component, null))), /* @__PURE__ */ React__namespace.createElement(FormBuilder, { form: activeForm, onPristineChange: setFormIsPristine })));
10399
+ };
10400
+ const FormWrapper$1 = ({ isEditing, children }) => {
10401
+ return /* @__PURE__ */ React__namespace.createElement(
10402
+ "div",
10403
+ {
10404
+ className: "flex-1 flex flex-col flex-nowrap overflow-hidden h-full w-full relative bg-white",
10405
+ style: isEditing ? {
10406
+ transform: "none",
10407
+ animationName: "fly-in-left",
10408
+ animationDuration: "150ms",
10409
+ animationDelay: "0",
10410
+ animationIterationCount: 1,
10411
+ animationTimingFunction: "ease-out"
10412
+ } : {
10413
+ transform: "translate3d(100%, 0, 0)"
10414
+ }
10415
+ },
10416
+ children
10417
+ );
10418
+ };
10419
+ const MultiformFormHeader = ({
10420
+ activeForm
10421
+ }) => {
10422
+ const cms = useCMS$1();
10423
+ const { formIsPristine } = React__namespace.useContext(SidebarContext);
10424
+ return /* @__PURE__ */ React__namespace.createElement(
10425
+ "div",
10426
+ {
10427
+ className: "pt-18 pb-4 px-6 border-b border-gray-200 bg-gradient-to-t from-white to-gray-50"
10428
+ },
10429
+ /* @__PURE__ */ React__namespace.createElement("div", { className: "max-w-form mx-auto flex gap-2 justify-between items-center" }, /* @__PURE__ */ React__namespace.createElement(
10430
+ "button",
10431
+ {
10432
+ type: "button",
10433
+ className: "pointer-events-auto text-xs text-blue-400 hover:text-blue-500 hover:underline transition-all ease-out duration-150",
10434
+ onClick: () => {
10435
+ const state = activeForm.tinaForm.finalForm.getState();
10436
+ if (state.invalid === true) {
10437
+ cms.alerts.error("Cannot navigate away from an invalid form.");
10438
+ } else {
10439
+ cms.dispatch({ type: "forms:set-active-form-id", value: null });
10440
+ }
10441
+ }
10442
+ },
10443
+ /* @__PURE__ */ React__namespace.createElement(BiDotsVertical, { className: "h-auto w-5 inline-block opacity-70" })
10444
+ ), /* @__PURE__ */ React__namespace.createElement(
10445
+ "button",
10446
+ {
10447
+ type: "button",
10448
+ className: "pointer-events-auto text-xs text-blue-400 hover:text-blue-500 hover:underline transition-all ease-out duration-150",
10449
+ onClick: () => {
10450
+ const collectionName = cms.api.tina.schema.getCollectionByFullPath(
10451
+ cms.state.activeFormId
10452
+ ).name;
10453
+ window.location.href = `${new URL(window.location.href).pathname}#/collections/${collectionName}/~`;
10454
+ }
10455
+ },
10456
+ /* @__PURE__ */ React__namespace.createElement(BiHomeAlt, { className: "h-auto w-5 inline-block opacity-70" })
10457
+ ), /* @__PURE__ */ React__namespace.createElement("span", { className: "opacity-30 text-sm leading-tight whitespace-nowrap flex-0" }, "/"), /* @__PURE__ */ React__namespace.createElement("span", { className: "block w-full text-sm leading-tight whitespace-nowrap truncate" }, activeForm.tinaForm.label || activeForm.tinaForm.id), /* @__PURE__ */ React__namespace.createElement(FormStatus, { pristine: formIsPristine }))
10458
+ );
10459
+ };
10460
+ const FormHeader = ({ activeForm }) => {
10461
+ const { formIsPristine } = React__namespace.useContext(SidebarContext);
10462
+ const cms = useCMS$1();
10463
+ const shortFormLabel = activeForm.tinaForm.label ? activeForm.tinaForm.label.replace(/^.*[\\\/]/, "") : false;
10464
+ return /* @__PURE__ */ React__namespace.createElement(
10465
+ "div",
10466
+ {
10467
+ className: "pt-18 pb-4 px-6 border-b border-gray-200 bg-gradient-to-t from-white to-gray-50"
10468
+ },
10469
+ /* @__PURE__ */ React__namespace.createElement("div", { className: "max-w-form mx-auto flex gap-2 justify-between items-center" }, /* @__PURE__ */ React__namespace.createElement(
10470
+ "button",
10471
+ {
10472
+ type: "button",
10473
+ className: "pointer-events-auto text-xs text-blue-400 hover:text-blue-500 hover:underline transition-all ease-out duration-150",
10474
+ onClick: () => {
10475
+ const collectionName = cms.api.tina.schema.getCollectionByFullPath(
10476
+ cms.state.activeFormId
10477
+ ).name;
10478
+ window.location.href = `${new URL(window.location.href).pathname}#/collections/${collectionName}/~`;
10479
+ }
10480
+ },
10481
+ /* @__PURE__ */ React__namespace.createElement(BiHomeAlt, { className: "h-auto w-5 inline-block opacity-70" })
10482
+ ), shortFormLabel && /* @__PURE__ */ React__namespace.createElement("span", { className: "block w-full text-sm leading-tight whitespace-nowrap truncate" }, shortFormLabel), /* @__PURE__ */ React__namespace.createElement(FormStatus, { pristine: formIsPristine }))
10483
+ );
10484
+ };
10447
10485
  const SidebarContext = React__namespace.createContext(null);
10448
10486
  const minPreviewWidth = 440;
10449
10487
  const minSidebarWidth = 360;
@@ -10662,7 +10700,7 @@ flowchart TD
10662
10700
  isLocalMode: (_d = (_c = cms.api) == null ? void 0 : _c.tina) == null ? void 0 : _d.isLocalMode,
10663
10701
  branchingEnabled
10664
10702
  }
10665
- ), /* @__PURE__ */ React__namespace.createElement(FormsView, null, /* @__PURE__ */ React__namespace.createElement(sidebar.placeholder, null)), activeScreen && /* @__PURE__ */ React__namespace.createElement(
10703
+ ), /* @__PURE__ */ React__namespace.createElement(FormsView, { loadingPlaceholder: sidebar.loadingPlaceholder }), activeScreen && /* @__PURE__ */ React__namespace.createElement(
10666
10704
  ScreenPluginModal,
10667
10705
  {
10668
10706
  screen: activeScreen,
@@ -10978,6 +11016,93 @@ flowchart TD
10978
11016
  );
10979
11017
  };
10980
11018
  }
11019
+ function dirname(path) {
11020
+ var _a, _b;
11021
+ const pattern = new RegExp("(?<prevDir>.*)/");
11022
+ return (_b = (_a = path.match(pattern)) == null ? void 0 : _a.groups) == null ? void 0 : _b.prevDir;
11023
+ }
11024
+ const BreadcrumbButton = ({ className = "", ...props }) => /* @__PURE__ */ React.createElement(
11025
+ "button",
11026
+ {
11027
+ className: "capitalize transition-colors duration-150 border-0 bg-transparent hover:text-blue-500 " + className,
11028
+ ...props
11029
+ }
11030
+ );
11031
+ function Breadcrumb$1({ directory = "", setDirectory }) {
11032
+ directory = directory.replace(/^\/|\/$/g, "");
11033
+ let prevDir = dirname(directory) || "";
11034
+ if (prevDir === ".") {
11035
+ prevDir = "";
11036
+ }
11037
+ return /* @__PURE__ */ React.createElement("div", { className: "w-full flex items-center text-[16px] text-gray-300" }, directory !== "" && /* @__PURE__ */ React.createElement(
11038
+ IconButton,
11039
+ {
11040
+ variant: "ghost",
11041
+ className: "mr-2",
11042
+ onClick: () => setDirectory(prevDir)
11043
+ },
11044
+ /* @__PURE__ */ React.createElement(
11045
+ LeftArrowIcon,
11046
+ {
11047
+ className: `w-7 h-auto fill-gray-300 hover:fill-gray-900 transition duration-150 ease-out`
11048
+ }
11049
+ )
11050
+ ), /* @__PURE__ */ React.createElement(
11051
+ BreadcrumbButton,
11052
+ {
11053
+ onClick: () => setDirectory(""),
11054
+ className: directory === "" ? "text-gray-500 font-bold" : "text-gray-300 font-medium after:pl-1.5 after:content-['/']"
11055
+ },
11056
+ "Media"
11057
+ ), directory && directory.split("/").map((part, index, parts) => {
11058
+ const currentDir = parts.slice(0, index + 1).join("/");
11059
+ return /* @__PURE__ */ React.createElement(
11060
+ BreadcrumbButton,
11061
+ {
11062
+ className: "pl-1.5 " + (index + 1 === parts.length ? "text-gray-500 font-bold" : "text-gray-300 font-medium after:pl-1.5 after:content-['/']"),
11063
+ key: currentDir,
11064
+ onClick: () => {
11065
+ setDirectory(currentDir);
11066
+ }
11067
+ },
11068
+ part
11069
+ );
11070
+ }));
11071
+ }
11072
+ const CopyField = ({ label, description, value }) => {
11073
+ const [copied, setCopied] = React.useState(false);
11074
+ const [fadeOut, setFadeOut] = React.useState(false);
11075
+ return /* @__PURE__ */ React.createElement("div", { className: "w-full" }, label && /* @__PURE__ */ React.createElement("label", { className: "w-full mb-1 block flex-1 text-sm font-bold leading-5 text-gray-700" }, label), /* @__PURE__ */ React.createElement(
11076
+ "span",
11077
+ {
11078
+ onClick: () => {
11079
+ if (copied === true)
11080
+ return;
11081
+ setCopied(true);
11082
+ setTimeout(() => {
11083
+ setFadeOut(true);
11084
+ }, 2500);
11085
+ setTimeout(() => {
11086
+ setCopied(false);
11087
+ setFadeOut(false);
11088
+ }, 3e3);
11089
+ navigator.clipboard.writeText(value);
11090
+ },
11091
+ className: `shadow-inner text-base leading-5 whitespace-normal break-all px-3 py-2 text-gray-600 w-full bg-gray-50 border border-gray-200 transition-all ease-out duration-150 rounded-md relative overflow-hidden appearance-none flex items-center w-full cursor-pointer hover:bg-white hover:text-blue-500 ${copied ? `pointer-events-none` : ``}`
11092
+ },
11093
+ /* @__PURE__ */ React.createElement(BiCopyAlt, { className: "relative text-blue-500 shrink-0 w-5 h-auto mr-1.5 -ml-0.5 z-20" }),
11094
+ " ",
11095
+ value,
11096
+ " ",
11097
+ copied && /* @__PURE__ */ React.createElement(
11098
+ "span",
11099
+ {
11100
+ className: `${fadeOut ? `opacity-0` : `opacity-100`} text-blue-500 transition-opacity duration-500 absolute right-0 w-full h-full px-3 py-2 bg-white bg-opacity-90 flex items-center justify-center text-center tracking-wide font-medium z-10`
11101
+ },
11102
+ /* @__PURE__ */ React.createElement("span", null, "Copied to clipboard!")
11103
+ )
11104
+ ), description && /* @__PURE__ */ React.createElement("p", { className: "mt-2 text-sm text-gray-500" }, description));
11105
+ };
10981
11106
  function ListMediaItem({ item, onClick, active }) {
10982
11107
  let FileIcon = BiFile;
10983
11108
  if (item.type === "dir") {
@@ -11053,59 +11178,6 @@ flowchart TD
11053
11178
  )
11054
11179
  );
11055
11180
  }
11056
- function dirname(path) {
11057
- var _a, _b;
11058
- const pattern = new RegExp("(?<prevDir>.*)/");
11059
- return (_b = (_a = path.match(pattern)) == null ? void 0 : _a.groups) == null ? void 0 : _b.prevDir;
11060
- }
11061
- const BreadcrumbButton = ({ className = "", ...props }) => /* @__PURE__ */ React.createElement(
11062
- "button",
11063
- {
11064
- className: "capitalize transition-colors duration-150 border-0 bg-transparent hover:text-blue-500 " + className,
11065
- ...props
11066
- }
11067
- );
11068
- function Breadcrumb$1({ directory = "", setDirectory }) {
11069
- directory = directory.replace(/^\/|\/$/g, "");
11070
- let prevDir = dirname(directory) || "";
11071
- if (prevDir === ".") {
11072
- prevDir = "";
11073
- }
11074
- return /* @__PURE__ */ React.createElement("div", { className: "w-full flex items-center text-[16px] text-gray-300" }, directory !== "" && /* @__PURE__ */ React.createElement(
11075
- IconButton,
11076
- {
11077
- variant: "ghost",
11078
- className: "mr-2",
11079
- onClick: () => setDirectory(prevDir)
11080
- },
11081
- /* @__PURE__ */ React.createElement(
11082
- LeftArrowIcon,
11083
- {
11084
- className: `w-7 h-auto fill-gray-300 hover:fill-gray-900 transition duration-150 ease-out`
11085
- }
11086
- )
11087
- ), /* @__PURE__ */ React.createElement(
11088
- BreadcrumbButton,
11089
- {
11090
- onClick: () => setDirectory(""),
11091
- className: directory === "" ? "text-gray-500 font-bold" : "text-gray-300 font-medium after:pl-1.5 after:content-['/']"
11092
- },
11093
- "Media"
11094
- ), directory && directory.split("/").map((part, index, parts) => {
11095
- const currentDir = parts.slice(0, index + 1).join("/");
11096
- return /* @__PURE__ */ React.createElement(
11097
- BreadcrumbButton,
11098
- {
11099
- className: "pl-1.5 " + (index + 1 === parts.length ? "text-gray-500 font-bold" : "text-gray-300 font-medium after:pl-1.5 after:content-['/']"),
11100
- key: currentDir,
11101
- onClick: () => {
11102
- setDirectory(currentDir);
11103
- }
11104
- },
11105
- part
11106
- );
11107
- }));
11108
- }
11109
11181
  const DeleteModal$1 = ({
11110
11182
  close: close2,
11111
11183
  deleteFunc,
@@ -11159,40 +11231,6 @@ flowchart TD
11159
11231
  "Create New Folder"
11160
11232
  ))));
11161
11233
  };
11162
- const CopyField = ({ label, description, value }) => {
11163
- const [copied, setCopied] = React.useState(false);
11164
- const [fadeOut, setFadeOut] = React.useState(false);
11165
- return /* @__PURE__ */ React.createElement("div", { className: "w-full" }, label && /* @__PURE__ */ React.createElement("label", { className: "w-full mb-1 block flex-1 text-sm font-bold leading-5 text-gray-700" }, label), /* @__PURE__ */ React.createElement(
11166
- "span",
11167
- {
11168
- onClick: () => {
11169
- if (copied === true)
11170
- return;
11171
- setCopied(true);
11172
- setTimeout(() => {
11173
- setFadeOut(true);
11174
- }, 2500);
11175
- setTimeout(() => {
11176
- setCopied(false);
11177
- setFadeOut(false);
11178
- }, 3e3);
11179
- navigator.clipboard.writeText(value);
11180
- },
11181
- className: `shadow-inner text-base leading-5 whitespace-normal break-all px-3 py-2 text-gray-600 w-full bg-gray-50 border border-gray-200 transition-all ease-out duration-150 rounded-md relative overflow-hidden appearance-none flex items-center w-full cursor-pointer hover:bg-white hover:text-blue-500 ${copied ? `pointer-events-none` : ``}`
11182
- },
11183
- /* @__PURE__ */ React.createElement(BiCopyAlt, { className: "relative text-blue-500 shrink-0 w-5 h-auto mr-1.5 -ml-0.5 z-20" }),
11184
- " ",
11185
- value,
11186
- " ",
11187
- copied && /* @__PURE__ */ React.createElement(
11188
- "span",
11189
- {
11190
- className: `${fadeOut ? `opacity-0` : `opacity-100`} text-blue-500 transition-opacity duration-500 absolute right-0 w-full h-full px-3 py-2 bg-white bg-opacity-90 flex items-center justify-center text-center tracking-wide font-medium z-10`
11191
- },
11192
- /* @__PURE__ */ React.createElement("span", null, "Copied to clipboard!")
11193
- )
11194
- ), description && /* @__PURE__ */ React.createElement("p", { className: "mt-2 text-sm text-gray-500" }, description));
11195
- };
11196
11234
  const { useDropzone } = dropzone__namespace;
11197
11235
  const join = function(...parts) {
11198
11236
  const [first, last, slash] = [0, parts.length - 1, "/"];
@@ -11694,7 +11732,7 @@ flowchart TD
11694
11732
  target: "_blank",
11695
11733
  href: `${cms.api.tina.appDashboardLink}/media`
11696
11734
  },
11697
- "Sync Your Media In Tina Cloud.",
11735
+ "Sync Your Media In TinaCloud.",
11698
11736
  /* @__PURE__ */ React.createElement(BiLinkExternal, { className: `w-5 h-auto flex-shrink-0` })
11699
11737
  )
11700
11738
  )))) : /* @__PURE__ */ React.createElement(SyncStatusContext.Provider, { value: { syncStatus } }, children);
@@ -12026,6 +12064,7 @@ flowchart TD
12026
12064
  forms: [],
12027
12065
  formLists: [],
12028
12066
  editingMode: "basic",
12067
+ isLoadingContent: false,
12029
12068
  quickEditSupported: false,
12030
12069
  sidebarDisplayState: ((_a = cms == null ? void 0 : cms.sidebar) == null ? void 0 : _a.defaultState) || "open"
12031
12070
  };
@@ -12085,7 +12124,12 @@ flowchart TD
12085
12124
  }
12086
12125
  });
12087
12126
  }
12088
- return { ...state, activeFormId, formLists: nextFormLists };
12127
+ return {
12128
+ ...state,
12129
+ activeFormId,
12130
+ formLists: nextFormLists,
12131
+ isLoadingContent: false
12132
+ };
12089
12133
  }
12090
12134
  case "form-lists:remove": {
12091
12135
  const nextFormLists = state.formLists.filter(
@@ -12154,6 +12198,9 @@ flowchart TD
12154
12198
  }
12155
12199
  return { ...state, sidebarDisplayState: action.value };
12156
12200
  }
12201
+ case "sidebar:set-loading-state": {
12202
+ return { ...state, isLoadingContent: action.value };
12203
+ }
12157
12204
  default:
12158
12205
  throw new Error(`Unhandled action ${action.type}`);
12159
12206
  }
@@ -12839,7 +12886,6 @@ flowchart TD
12839
12886
  }) => {
12840
12887
  const cms = useCMS$1();
12841
12888
  const tinaApi = cms.api.tina;
12842
- tinaApi.branch;
12843
12889
  const [disabled, setDisabled] = React__namespace.useState(false);
12844
12890
  const [newBranchName, setNewBranchName] = React__namespace.useState("");
12845
12891
  const [error, setError] = React__namespace.useState("");
@@ -12865,10 +12911,10 @@ flowchart TD
12865
12911
  const newUrl = window.location.href.replace(hash, newHash);
12866
12912
  window.location.href = newUrl;
12867
12913
  };
12868
- return /* @__PURE__ */ React__namespace.createElement(Modal, null, /* @__PURE__ */ React__namespace.createElement(PopupModal, null, /* @__PURE__ */ React__namespace.createElement(ModalHeader, { close: close2 }, /* @__PURE__ */ React__namespace.createElement(BiGitBranch, { className: "w-6 h-auto mr-1 text-blue-500 opacity-70" }), " ", "Create Branch"), /* @__PURE__ */ React__namespace.createElement(ModalBody, { padded: true }, /* @__PURE__ */ React__namespace.createElement("p", { className: "text-base text-gray-700 mb-2" }, "This branch is ", /* @__PURE__ */ React__namespace.createElement("strong", null, "protected"), ". Create a new branch to save your changes."), /* @__PURE__ */ React__namespace.createElement(
12914
+ return /* @__PURE__ */ React__namespace.createElement(Modal, null, /* @__PURE__ */ React__namespace.createElement(PopupModal, null, /* @__PURE__ */ React__namespace.createElement(ModalHeader, { close: close2 }, /* @__PURE__ */ React__namespace.createElement(BiGitBranch, { className: "w-6 h-auto mr-1 text-blue-500 opacity-70" }), " ", "Create Branch"), /* @__PURE__ */ React__namespace.createElement(ModalBody, { padded: true }, /* @__PURE__ */ React__namespace.createElement("p", { className: "text-lg text-gray-700 font-bold mb-2" }, "This content is protected 🚧"), /* @__PURE__ */ React__namespace.createElement("p", { className: "text-sm text-gray-700 mb-4" }, "To make changes, you need to create a copy then get it approved and merged for it to go live."), /* @__PURE__ */ React__namespace.createElement(
12869
12915
  PrefixedTextField,
12870
12916
  {
12871
- placeholder: "Branch Name",
12917
+ placeholder: "e.g. {{PAGE-NAME}}-updates",
12872
12918
  value: newBranchName,
12873
12919
  onChange: (e) => {
12874
12920
  setError("");
@@ -30291,9 +30337,31 @@ flowchart TD
30291
30337
  }
30292
30338
  const TINA_LOGIN_EVENT = "tinaCloudLogin";
30293
30339
  const AUTH_TOKEN_KEY = "tinacms-auth";
30294
- const authenticate = (clientId, frontendUrl) => {
30295
- return new Promise((resolve) => {
30340
+ const generateRandomString = (length) => {
30341
+ const array = new Uint32Array(length);
30342
+ window.crypto.getRandomValues(array);
30343
+ return Array.from(array, (dec) => ("0" + dec.toString(16)).slice(-2)).join(
30344
+ ""
30345
+ );
30346
+ };
30347
+ const generateCodeChallenge = async (codeVerifier) => {
30348
+ const encoder = new TextEncoder();
30349
+ const data = encoder.encode(codeVerifier);
30350
+ const digest = await window.crypto.subtle.digest("SHA-256", data);
30351
+ return btoa(String.fromCharCode(...new Uint8Array(digest))).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
30352
+ };
30353
+ const authenticate = (clientId, frontendUrl, oauth2) => {
30354
+ return new Promise(async (resolve) => {
30296
30355
  const origin = `${window.location.protocol}//${window.location.host}`;
30356
+ if (oauth2) {
30357
+ const codeVerifier = generateRandomString(32);
30358
+ const codeChallenge = await generateCodeChallenge(codeVerifier);
30359
+ localStorage.setItem("code_verifier", codeVerifier);
30360
+ const redirectUri = encodeURIComponent(`${origin}/admin`);
30361
+ window.location.href = `${frontendUrl}/oauth-signin?redirect_uri=${redirectUri}&code_challenge=${codeChallenge}&client_id=${clientId}`;
30362
+ resolve(void 0);
30363
+ return;
30364
+ }
30297
30365
  const authTab = popupWindow(
30298
30366
  `${frontendUrl}/signin?clientId=${clientId}&origin=${origin}`,
30299
30367
  "_blank",
@@ -30374,6 +30442,7 @@ flowchart TD
30374
30442
  this.frontendUrl = frontendUrl;
30375
30443
  this.clientId = clientId;
30376
30444
  this.identityApiUrl = identityApiUrl;
30445
+ this.oauth2 = options.oauth2 || false;
30377
30446
  switch (tokenStorage) {
30378
30447
  case "LOCAL_STORAGE":
30379
30448
  this.getToken = async function() {
@@ -30419,9 +30488,52 @@ flowchart TD
30419
30488
  }
30420
30489
  }
30421
30490
  async authenticate() {
30422
- const token = await authenticate(this.clientId, this.frontendUrl);
30423
- this.setToken(token);
30424
- return token;
30491
+ const params = new URLSearchParams(window.location.search);
30492
+ console.log({ params });
30493
+ const code = params.get("code");
30494
+ const state = params.get("state");
30495
+ const codeVerifier = localStorage.getItem("code_verifier");
30496
+ console.log({
30497
+ code,
30498
+ state,
30499
+ codeVerifier
30500
+ });
30501
+ if (code && state && codeVerifier) {
30502
+ const origin = `${window.location.protocol}//${window.location.host}`;
30503
+ const redirectUri = encodeURIComponent(`${origin}/admin`);
30504
+ const tokenUrl = `${this.identityApiUrl}/oauth2/${this.clientId}/token`;
30505
+ console.log("Token URL:", tokenUrl);
30506
+ await fetch(tokenUrl, {
30507
+ method: "POST",
30508
+ headers: {
30509
+ "Content-Type": "application/x-www-form-urlencoded"
30510
+ },
30511
+ body: new URLSearchParams({
30512
+ grant_type: "authorization_code",
30513
+ code,
30514
+ redirect_uri: redirectUri,
30515
+ client_id: this.clientId,
30516
+ code_verifier: localStorage.getItem("code_verifier")
30517
+ })
30518
+ }).then((response) => response.json()).then((data) => {
30519
+ console.log("Token exchange response:", data);
30520
+ this.setToken(data);
30521
+ }).catch((error) => {
30522
+ console.error("Error during token exchange:", error);
30523
+ });
30524
+ } else {
30525
+ console.log("calling authenticate");
30526
+ const token = await authenticate(
30527
+ this.clientId,
30528
+ this.frontendUrl,
30529
+ this.oauth2
30530
+ );
30531
+ console.log("Token:", token);
30532
+ if (token) {
30533
+ this.setToken(token);
30534
+ }
30535
+ }
30536
+ return this.getToken();
30425
30537
  }
30426
30538
  async getUser() {
30427
30539
  if (!this.clientId) {
@@ -30530,7 +30642,7 @@ flowchart TD
30530
30642
  });
30531
30643
  class Client {
30532
30644
  constructor({ tokenStorage = "MEMORY", ...options }) {
30533
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u;
30645
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w;
30534
30646
  this.events = new EventBus();
30535
30647
  this.protectedBranches = [];
30536
30648
  this.usingEditorialWorkflow = false;
@@ -30611,7 +30723,8 @@ mutation addPendingDocumentMutation(
30611
30723
  identityApiUrl: this.identityApiUrl,
30612
30724
  getTokenFn: options.getTokenFn,
30613
30725
  tokenStorage,
30614
- frontendUrl: this.frontendUrl
30726
+ frontendUrl: this.frontendUrl,
30727
+ oauth2: (_w = (_v = options.schema) == null ? void 0 : _v.config) == null ? void 0 : _w.oauth2
30615
30728
  });
30616
30729
  }
30617
30730
  get isLocalMode() {
@@ -30623,6 +30736,7 @@ mutation addPendingDocumentMutation(
30623
30736
  setBranch(branchName) {
30624
30737
  var _a, _b, _c, _d;
30625
30738
  const encodedBranch = encodeURIComponent(branchName);
30739
+ document.cookie = `x-branch=${encodedBranch}; path=/; max-age=3600`;
30626
30740
  this.branch = encodedBranch;
30627
30741
  this.assetsApiUrl = ((_a = this.options.tinaioConfig) == null ? void 0 : _a.assetsApiUrlOverride) || "https://assets.tinajs.io";
30628
30742
  this.frontendUrl = ((_b = this.options.tinaioConfig) == null ? void 0 : _b.frontendUrlOverride) || "https://app.tina.io";
@@ -30665,7 +30779,7 @@ mutation addPendingDocumentMutation(
30665
30779
  branch: ${this.branch}.`;
30666
30780
  if (this.branch !== "main") {
30667
30781
  errorMessage = `${errorMessage}
30668
- Note: This error can occur if the branch does not exist on GitHub or on Tina Cloud`;
30782
+ Note: This error can occur if the branch does not exist on GitHub or on TinaCloud`;
30669
30783
  }
30670
30784
  }
30671
30785
  throw new Error(errorMessage);
@@ -30801,7 +30915,7 @@ mutation addPendingDocumentMutation(
30801
30915
  unknownCount++;
30802
30916
  if (unknownCount > 5) {
30803
30917
  throw new Error(
30804
- "AsyncPoller: status unknown for too long, please check indexing progress the Tina Cloud dashboard"
30918
+ "AsyncPoller: status unknown for too long, please check indexing progress the TinaCloud dashboard"
30805
30919
  );
30806
30920
  }
30807
30921
  }
@@ -31437,7 +31551,52 @@ mutation addPendingDocumentMutation(
31437
31551
  const [showChildren, setShowChildren] = React.useState(false);
31438
31552
  const [authProps, setAuthProps] = React.useState({ username: "", password: "" });
31439
31553
  const [authenticated, setAuthenticated] = React.useState(false);
31554
+ const [code, setCode] = React.useState(null);
31555
+ const [state, setState] = React.useState(null);
31556
+ const [retrievingToken, setRetrievingToken] = React.useState(false);
31557
+ React.useEffect(() => {
31558
+ if (typeof window !== "undefined") {
31559
+ const queryParams = new URLSearchParams(window.location.search);
31560
+ setCode(queryParams.get("code"));
31561
+ setState(queryParams.get("state"));
31562
+ }
31563
+ }, []);
31564
+ React.useEffect(() => {
31565
+ const codeVerifier = localStorage.getItem("code_verifier");
31566
+ if (codeVerifier && code && state) {
31567
+ setRetrievingToken(true);
31568
+ const origin = `${window.location.protocol}//${window.location.host}`;
31569
+ const redirectUri = encodeURIComponent(`${origin}/admin`);
31570
+ const tokenUrl = `${client.identityApiUrl}/oauth2/${client.clientId}/token`;
31571
+ console.log("Token URL:", tokenUrl);
31572
+ fetch(tokenUrl, {
31573
+ method: "POST",
31574
+ headers: {
31575
+ "Content-Type": "application/x-www-form-urlencoded"
31576
+ },
31577
+ body: new URLSearchParams({
31578
+ grant_type: "authorization_code",
31579
+ code,
31580
+ redirect_uri: redirectUri,
31581
+ client_id: client.clientId,
31582
+ code_verifier: localStorage.getItem("code_verifier")
31583
+ })
31584
+ }).then((response) => response.json()).then((data) => {
31585
+ console.log("Token exchange response:", data);
31586
+ setRetrievingToken(false);
31587
+ localStorage.setItem(AUTH_TOKEN_KEY, JSON.stringify(data));
31588
+ setAuthenticated(true);
31589
+ }).catch((error) => {
31590
+ console.error("Error during token exchange:", error);
31591
+ setRetrievingToken(false);
31592
+ });
31593
+ }
31594
+ }, [code, state]);
31440
31595
  React.useEffect(() => {
31596
+ if (retrievingToken) {
31597
+ console.log("Retrieving token...");
31598
+ return;
31599
+ }
31441
31600
  let mounted = true;
31442
31601
  client.authProvider.isAuthenticated().then((isAuthenticated) => {
31443
31602
  if (!mounted)
@@ -31482,7 +31641,7 @@ mutation addPendingDocumentMutation(
31482
31641
  return () => {
31483
31642
  mounted = false;
31484
31643
  };
31485
- }, [authenticated]);
31644
+ }, [authenticated, retrievingToken]);
31486
31645
  const onAuthenticated = async () => {
31487
31646
  setAuthenticated(true);
31488
31647
  setActiveModal(null);
@@ -31512,7 +31671,7 @@ mutation addPendingDocumentMutation(
31512
31671
  });
31513
31672
  }
31514
31673
  };
31515
- let modalTitle = "Tina Cloud";
31674
+ let modalTitle = "TinaCloud";
31516
31675
  if (activeModal === "authenticate" && loginStrategy === "Redirect" && !isTinaCloud) {
31517
31676
  modalTitle = "Enter into edit mode";
31518
31677
  } else if (activeModal === "authenticate" && loginStrategy === "UsernamePassword") {
@@ -31528,7 +31687,7 @@ mutation addPendingDocumentMutation(
31528
31687
  ModalBuilder,
31529
31688
  {
31530
31689
  title: modalTitle,
31531
- message: isTinaCloud ? "Your site uses Tina Cloud to track changes. To make edits, you must log in." : "To save edits, enter into edit mode. On save, changes will saved to the local filesystem.",
31690
+ message: isTinaCloud ? "Your site uses TinaCloud to track changes. To make edits, you must log in." : "To save edits, enter into edit mode. On save, changes will saved to the local filesystem.",
31532
31691
  close,
31533
31692
  actions: [
31534
31693
  ...otherModalActions,
@@ -31631,7 +31790,6 @@ mutation addPendingDocumentMutation(
31631
31790
  "tinacms-current-branch",
31632
31791
  baseBranch
31633
31792
  );
31634
- console.log({ currentBranch });
31635
31793
  useTinaAuthRedirect();
31636
31794
  const cms = React.useMemo(
31637
31795
  () => props.cms || new TinaCMS({
@@ -31751,10 +31909,7 @@ mutation addPendingDocumentMutation(
31751
31909
  cms.flags.set("branch-switcher", true);
31752
31910
  client.usingEditorialWorkflow = true;
31753
31911
  client.protectedBranches = project.protectedBranches;
31754
- console.log("currentBranch", currentBranch);
31755
- console.log(project.metadata[currentBranch]);
31756
31912
  if (!project.metadata[currentBranch]) {
31757
- console.log("resetting to default branch", project.defaultBranch);
31758
31913
  setCurrentBranch(project.defaultBranch || "main");
31759
31914
  }
31760
31915
  }
@@ -32255,6 +32410,14 @@ This will work when developing locally but NOT when deployed to production.
32255
32410
  }
32256
32411
  return client.request(query, { variables });
32257
32412
  };
32413
+ const GetCMS = ({ children }) => {
32414
+ try {
32415
+ const cms = useCMS$1();
32416
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, children(cms));
32417
+ } catch (e) {
32418
+ return null;
32419
+ }
32420
+ };
32258
32421
  const Layout = ({ children }) => {
32259
32422
  return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
32260
32423
  "div",
@@ -32466,47 +32629,6 @@ This will work when developing locally but NOT when deployed to production.
32466
32629
  }
32467
32630
  return /* @__PURE__ */ React.createElement("span", { className: "text-base tracking-wide text-gray-500 hover:text-blue-600 flex items-center opacity-90 hover:opacity-100" }, /* @__PURE__ */ React.createElement(config.Icon, { className: "mr-2 h-6 opacity-80 w-auto" }), /* @__PURE__ */ React.createElement("a", { target: "_blank", href: config.link.href }, config.link.text));
32468
32631
  };
32469
- const GetCMS = ({ children }) => {
32470
- try {
32471
- const cms = useCMS$1();
32472
- return /* @__PURE__ */ React.createElement(React.Fragment, null, children(cms));
32473
- } catch (e) {
32474
- return null;
32475
- }
32476
- };
32477
- const PageWrapper = ({ children }) => {
32478
- var _a, _b;
32479
- const cms = useCMS$1();
32480
- const isLocalMode = (_b = (_a = cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isLocalMode;
32481
- const [branchingEnabled, setBranchingEnabled] = React.useState(
32482
- () => cms.flags.get("branch-switcher")
32483
- );
32484
- React.useEffect(() => {
32485
- cms.events.subscribe("flag:set", ({ key, value }) => {
32486
- if (key === "branch-switcher") {
32487
- setBranchingEnabled(value);
32488
- }
32489
- });
32490
- }, [cms.events]);
32491
- return /* @__PURE__ */ React.createElement("div", { className: "relative left-0 w-full h-full bg-gradient-to-b from-gray-50/50 to-gray-50 shadow-2xl overflow-y-auto transition-opacity duration-300 ease-out flex flex-col opacity-100" }, branchingEnabled && !isLocalMode && /* @__PURE__ */ React.createElement(BranchBanner, null), children);
32492
- };
32493
- const PageHeader = ({
32494
- isLocalMode,
32495
- children
32496
- }) => {
32497
- return /* @__PURE__ */ React.createElement(React.Fragment, null, isLocalMode && /* @__PURE__ */ React.createElement(LocalWarning, null), !isLocalMode && /* @__PURE__ */ React.createElement(BillingWarning, null), /* @__PURE__ */ React.createElement("div", { className: "pt-16 xl:pt-12 px-6 xl:px-12" }, /* @__PURE__ */ React.createElement("div", { className: "w-full mx-auto max-w-screen-xl" }, /* @__PURE__ */ React.createElement("div", { className: "w-full flex justify-between items-end" }, children))));
32498
- };
32499
- const PageBody = ({ children }) => /* @__PURE__ */ React.createElement("div", { className: "py-8 px-6 xl:px-12" }, children);
32500
- const PageBodyNarrow = ({ children }) => /* @__PURE__ */ React.createElement("div", { className: "py-10 px-6 xl:px-12" }, /* @__PURE__ */ React.createElement("div", { className: "w-full mx-auto max-w-screen-xl" }, children));
32501
- const DashboardPage = () => {
32502
- return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => {
32503
- var _a, _b;
32504
- return /* @__PURE__ */ React.createElement(PageWrapper, null, /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(PageHeader, { isLocalMode: (_b = (_a = cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isLocalMode }, /* @__PURE__ */ React.createElement("h3", { className: "text-2xl font-sans text-gray-700" }, "Welcome to Tina!")), /* @__PURE__ */ React.createElement(PageBodyNarrow, null, "This is your dashboard for editing or creating content. Select a collection on the left to begin.")));
32505
- });
32506
- };
32507
- function RiHome2Line(props) {
32508
- return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24", "fill": "currentColor" }, "child": [{ "tag": "path", "attr": { "d": "M19 21H5C4.44772 21 4 20.5523 4 20V11L1 11L11.3273 1.6115C11.7087 1.26475 12.2913 1.26475 12.6727 1.6115L23 11L20 11V20C20 20.5523 19.5523 21 19 21ZM6 19H18V9.15745L12 3.7029L6 9.15745V19Z" }, "child": [] }] })(props);
32509
- }
32510
32632
  const LoadingPage = () => /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
32511
32633
  "div",
32512
32634
  {
@@ -32616,203 +32738,33 @@ This will work when developing locally but NOT when deployed to production.
32616
32738
  )
32617
32739
  )
32618
32740
  ));
32619
- const FullscreenError = ({
32620
- title = "Error",
32621
- errorMessage = "It looks like something went wrong."
32622
- }) => {
32623
- return /* @__PURE__ */ React.createElement("div", { className: "flex flex-col justify-center items-center h-screen bg-gray-100" }, /* @__PURE__ */ React.createElement("div", { className: "text-red-500 text-4xl mb-6 flex items-center" }, /* @__PURE__ */ React.createElement(BiError, { className: "w-12 h-auto fill-current text-red-400 opacity-70 mr-1" }), " ", title), /* @__PURE__ */ React.createElement("p", { className: "text-gray-700 text-xl mb-8" }, errorMessage), /* @__PURE__ */ React.createElement(Button$1, { variant: "danger", onClick: () => window.location.reload() }, /* @__PURE__ */ React.createElement(BiSync, { className: "w-7 h-auto fill-current opacity-70 mr-1" }), " Reload"));
32624
- };
32625
- const useGetCollection = (cms, collectionName, includeDocuments = true, folder, after = "", sortKey, filterArgs) => {
32626
- const api = new TinaAdminApi(cms);
32627
- const schema = cms.api.tina.schema;
32628
- const collectionExtra = schema.getCollection(collectionName);
32629
- const [collection, setCollection] = React.useState(void 0);
32630
- const [loading, setLoading] = React.useState(true);
32631
- const [error, setError] = React.useState(void 0);
32632
- const [resetState, setResetSate] = React.useState(0);
32633
- React.useEffect(() => {
32634
- let cancelled = false;
32635
- const fetchCollection = async () => {
32636
- var _a;
32637
- if (await api.isAuthenticated() && !folder.loading && !cancelled) {
32638
- const { name, order } = JSON.parse(sortKey || "{}");
32639
- const validSortKey = ((_a = collectionExtra.fields) == null ? void 0 : _a.map((x) => x.name).includes(name)) ? name : void 0;
32640
- try {
32641
- const collection2 = await api.fetchCollection(
32642
- collectionName,
32643
- includeDocuments,
32644
- (filterArgs == null ? void 0 : filterArgs.filterField) ? "" : folder.fullyQualifiedName,
32645
- after,
32646
- validSortKey,
32647
- order,
32648
- filterArgs
32649
- );
32650
- setCollection(collection2);
32651
- } catch (error2) {
32652
- cms.alerts.error(
32653
- `[${error2.name}] GetCollection failed: ${error2.message}`
32654
- );
32655
- console.error(error2);
32656
- setCollection(void 0);
32657
- setError(error2);
32658
- }
32659
- setLoading(false);
32660
- }
32661
- };
32662
- if (cancelled)
32663
- return;
32664
- setLoading(true);
32665
- fetchCollection();
32666
- return () => {
32667
- cancelled = true;
32668
- };
32669
- }, [
32670
- cms,
32671
- collectionName,
32672
- folder.loading,
32673
- folder.fullyQualifiedName,
32674
- resetState,
32675
- after,
32676
- sortKey
32677
- ]);
32678
- const reFetchCollection = () => setResetSate((x) => x + 1);
32679
- return { collection, loading, error, reFetchCollection, collectionExtra };
32680
- };
32681
- const useSearchCollection = (cms, collectionName, includeDocuments = true, folder, after = "", search) => {
32682
- const api = new TinaAdminApi(cms);
32683
- const schema = cms.api.tina.schema;
32684
- const collectionExtra = schema.getCollection(collectionName);
32685
- const [collection, setCollection] = React.useState(void 0);
32686
- const [loading, setLoading] = React.useState(true);
32687
- const [error, setError] = React.useState(void 0);
32688
- const [resetState, setResetSate] = React.useState(0);
32741
+ function RiHome2Line(props) {
32742
+ return GenIcon({ "tag": "svg", "attr": { "viewBox": "0 0 24 24", "fill": "currentColor" }, "child": [{ "tag": "path", "attr": { "d": "M19 21H5C4.44772 21 4 20.5523 4 20V11L1 11L11.3273 1.6115C11.7087 1.26475 12.2913 1.26475 12.6727 1.6115L23 11L20 11V20C20 20.5523 19.5523 21 19 21ZM6 19H18V9.15745L12 3.7029L6 9.15745V19Z" }, "child": [] }] })(props);
32743
+ }
32744
+ const PageWrapper = ({ children }) => {
32745
+ var _a, _b;
32746
+ const cms = useCMS$1();
32747
+ const isLocalMode = (_b = (_a = cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isLocalMode;
32748
+ const [branchingEnabled, setBranchingEnabled] = React.useState(
32749
+ () => cms.flags.get("branch-switcher")
32750
+ );
32689
32751
  React.useEffect(() => {
32690
- let cancelled = false;
32691
- const searchCollection = async () => {
32692
- if (await api.isAuthenticated() && !folder.loading && !cancelled) {
32693
- try {
32694
- const response = await cms.api.search.query(
32695
- `${search} AND _collection:${collectionName}`,
32696
- {
32697
- limit: 15,
32698
- cursor: after
32699
- }
32700
- );
32701
- const docs = await Promise.allSettled(
32702
- response.results.map((result) => {
32703
- const [collection2, relativePath2] = result._id.split(":");
32704
- return api.fetchDocument(collection2, relativePath2, false);
32705
- })
32706
- );
32707
- const edges = docs.filter((p) => {
32708
- var _a;
32709
- return p.status === "fulfilled" && !!((_a = p.value) == null ? void 0 : _a.document);
32710
- }).map((result) => ({ node: result.value.document }));
32711
- const c = await api.fetchCollection(collectionName, false, "");
32712
- setCollection({
32713
- format: collection.format,
32714
- label: collection.label,
32715
- name: collectionName,
32716
- templates: collection.templates,
32717
- documents: {
32718
- pageInfo: {
32719
- hasNextPage: !!response.nextCursor,
32720
- hasPreviousPage: !!response.prevCursor,
32721
- startCursor: "",
32722
- endCursor: response.nextCursor || ""
32723
- },
32724
- edges
32725
- }
32726
- });
32727
- } catch (error2) {
32728
- cms.alerts.error(
32729
- `[${error2.name}] GetCollection failed: ${error2.message}`
32730
- );
32731
- console.error(error2);
32732
- setCollection(void 0);
32733
- setError(error2);
32734
- }
32735
- setLoading(false);
32752
+ cms.events.subscribe("flag:set", ({ key, value }) => {
32753
+ if (key === "branch-switcher") {
32754
+ setBranchingEnabled(value);
32736
32755
  }
32737
- };
32738
- if (cancelled)
32739
- return;
32740
- setLoading(true);
32741
- searchCollection();
32742
- return () => {
32743
- cancelled = true;
32744
- };
32745
- }, [
32746
- cms,
32747
- collectionName,
32748
- folder.loading,
32749
- folder.fullyQualifiedName,
32750
- resetState,
32751
- after,
32752
- search
32753
- ]);
32754
- const reFetchCollection = () => setResetSate((x) => x + 1);
32755
- return { collection, loading, error, reFetchCollection, collectionExtra };
32756
+ });
32757
+ }, [cms.events]);
32758
+ return /* @__PURE__ */ React.createElement("div", { className: "relative left-0 w-full h-full bg-gradient-to-b from-gray-50/50 to-gray-50 shadow-2xl overflow-y-auto transition-opacity duration-300 ease-out flex flex-col opacity-100" }, branchingEnabled && !isLocalMode && /* @__PURE__ */ React.createElement(BranchBanner, null), children);
32756
32759
  };
32757
- const GetCollection = ({
32758
- cms,
32759
- collectionName,
32760
- folder,
32761
- includeDocuments = true,
32762
- startCursor,
32763
- sortKey,
32764
- children,
32765
- filterArgs,
32766
- search
32760
+ const PageHeader = ({
32761
+ isLocalMode,
32762
+ children
32767
32763
  }) => {
32768
- const navigate = reactRouterDom.useNavigate();
32769
- const { collection, loading, error, reFetchCollection, collectionExtra } = search ? useSearchCollection(
32770
- cms,
32771
- collectionName,
32772
- includeDocuments,
32773
- folder,
32774
- startCursor || "",
32775
- search
32776
- ) : useGetCollection(
32777
- cms,
32778
- collectionName,
32779
- includeDocuments,
32780
- folder,
32781
- startCursor || "",
32782
- sortKey,
32783
- filterArgs
32784
- ) || {};
32785
- React.useEffect(() => {
32786
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
32787
- if (loading)
32788
- return;
32789
- const collectionDefinition = cms.api.tina.schema.getCollection(
32790
- collection.name
32791
- );
32792
- const allowCreate = ((_b = (_a = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _a.allowedActions) == null ? void 0 : _b.create) ?? true;
32793
- const allowDelete = ((_d = (_c = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _c.allowedActions) == null ? void 0 : _d.delete) ?? true;
32794
- const collectionResponse = collection;
32795
- if (!allowCreate && !allowDelete && // Check there is only one document
32796
- ((_f = (_e = collectionResponse.documents) == null ? void 0 : _e.edges) == null ? void 0 : _f.length) === 1 && // Check to make sure the file is not a folder
32797
- ((_i = (_h = (_g = collectionResponse.documents) == null ? void 0 : _g.edges[0]) == null ? void 0 : _h.node) == null ? void 0 : _i.__typename) !== "Folder") {
32798
- const doc = collectionResponse.documents.edges[0].node;
32799
- handleNavigate(
32800
- navigate,
32801
- cms,
32802
- collectionResponse,
32803
- collectionDefinition,
32804
- doc
32805
- );
32806
- }
32807
- }, [(collection == null ? void 0 : collection.name) || "", loading]);
32808
- if (error) {
32809
- return /* @__PURE__ */ React.createElement(FullscreenError, null);
32810
- }
32811
- if (loading) {
32812
- return /* @__PURE__ */ React.createElement(LoadingPage, null);
32813
- }
32814
- return /* @__PURE__ */ React.createElement(React.Fragment, null, children(collection, loading, reFetchCollection, collectionExtra));
32764
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, isLocalMode && /* @__PURE__ */ React.createElement(LocalWarning, null), !isLocalMode && /* @__PURE__ */ React.createElement(BillingWarning, null), /* @__PURE__ */ React.createElement("div", { className: "pt-16 xl:pt-12 px-6 xl:px-12" }, /* @__PURE__ */ React.createElement("div", { className: "w-full mx-auto max-w-screen-xl" }, /* @__PURE__ */ React.createElement("div", { className: "w-full flex justify-between items-end" }, children))));
32815
32765
  };
32766
+ const PageBody = ({ children }) => /* @__PURE__ */ React.createElement("div", { className: "py-8 px-6 xl:px-12" }, children);
32767
+ const PageBodyNarrow = ({ children }) => /* @__PURE__ */ React.createElement("div", { className: "py-10 px-6 xl:px-12" }, /* @__PURE__ */ React.createElement("div", { className: "w-full mx-auto max-w-screen-xl" }, children));
32816
32768
  const folderRegex = /^.*\/~\/*(.*)$/;
32817
32769
  const parentFolder = (folder) => {
32818
32770
  return {
@@ -33690,6 +33642,231 @@ This will work when developing locally but NOT when deployed to production.
33690
33642
  "Rename"
33691
33643
  ))));
33692
33644
  };
33645
+ const FullscreenError = ({
33646
+ title = "Error",
33647
+ errorMessage = "It looks like something went wrong."
33648
+ }) => {
33649
+ return /* @__PURE__ */ React.createElement("div", { className: "flex flex-col justify-center items-center h-screen bg-gray-100" }, /* @__PURE__ */ React.createElement("div", { className: "text-red-500 text-4xl mb-6 flex items-center" }, /* @__PURE__ */ React.createElement(BiError, { className: "w-12 h-auto fill-current text-red-400 opacity-70 mr-1" }), " ", title), /* @__PURE__ */ React.createElement("p", { className: "text-gray-700 text-xl mb-8" }, errorMessage), /* @__PURE__ */ React.createElement(Button$1, { variant: "danger", onClick: () => window.location.reload() }, /* @__PURE__ */ React.createElement(BiSync, { className: "w-7 h-auto fill-current opacity-70 mr-1" }), " Reload"));
33650
+ };
33651
+ const isValidSortKey = (sortKey, collection) => {
33652
+ if (collection.fields) {
33653
+ const sortKeys = collection.fields.map((x) => x.name);
33654
+ return sortKeys.includes(sortKey);
33655
+ } else if (collection.templates) {
33656
+ const collectionMap = {};
33657
+ const conflictedFields = /* @__PURE__ */ new Set();
33658
+ for (const template of collection.templates) {
33659
+ for (const field of template.fields) {
33660
+ if (collectionMap[field.name]) {
33661
+ if (collectionMap[field.name].type !== field.type) {
33662
+ conflictedFields.add(field.name);
33663
+ }
33664
+ } else {
33665
+ collectionMap[field.name] = field;
33666
+ }
33667
+ }
33668
+ }
33669
+ for (const key in conflictedFields) {
33670
+ delete collectionMap[key];
33671
+ }
33672
+ for (const key in collectionMap) {
33673
+ if (key === sortKey) {
33674
+ return true;
33675
+ }
33676
+ }
33677
+ return false;
33678
+ }
33679
+ };
33680
+ const useGetCollection = (cms, collectionName, includeDocuments = true, folder, after = "", sortKey, filterArgs) => {
33681
+ const api = new TinaAdminApi(cms);
33682
+ const schema = cms.api.tina.schema;
33683
+ const collectionExtra = schema.getCollection(collectionName);
33684
+ const [collection, setCollection] = React.useState(void 0);
33685
+ const [loading, setLoading] = React.useState(true);
33686
+ const [error, setError] = React.useState(void 0);
33687
+ const [resetState, setResetSate] = React.useState(0);
33688
+ React.useEffect(() => {
33689
+ let cancelled = false;
33690
+ const fetchCollection = async () => {
33691
+ if (await api.isAuthenticated() && !folder.loading && !cancelled) {
33692
+ const { name, order } = JSON.parse(sortKey || "{}");
33693
+ const validSortKey = isValidSortKey(name, collectionExtra) ? name : void 0;
33694
+ try {
33695
+ const collection2 = await api.fetchCollection(
33696
+ collectionName,
33697
+ includeDocuments,
33698
+ (filterArgs == null ? void 0 : filterArgs.filterField) ? "" : folder.fullyQualifiedName,
33699
+ after,
33700
+ validSortKey,
33701
+ order,
33702
+ filterArgs
33703
+ );
33704
+ setCollection(collection2);
33705
+ } catch (error2) {
33706
+ cms.alerts.error(
33707
+ `[${error2.name}] GetCollection failed: ${error2.message}`
33708
+ );
33709
+ console.error(error2);
33710
+ setCollection(void 0);
33711
+ setError(error2);
33712
+ }
33713
+ setLoading(false);
33714
+ }
33715
+ };
33716
+ if (cancelled)
33717
+ return;
33718
+ setLoading(true);
33719
+ fetchCollection();
33720
+ return () => {
33721
+ cancelled = true;
33722
+ };
33723
+ }, [
33724
+ cms,
33725
+ collectionName,
33726
+ folder.loading,
33727
+ folder.fullyQualifiedName,
33728
+ resetState,
33729
+ after,
33730
+ sortKey
33731
+ ]);
33732
+ const reFetchCollection = () => setResetSate((x) => x + 1);
33733
+ return { collection, loading, error, reFetchCollection, collectionExtra };
33734
+ };
33735
+ const useSearchCollection = (cms, collectionName, includeDocuments = true, folder, after = "", search) => {
33736
+ const api = new TinaAdminApi(cms);
33737
+ const schema = cms.api.tina.schema;
33738
+ const collectionExtra = schema.getCollection(collectionName);
33739
+ const [collection, setCollection] = React.useState(void 0);
33740
+ const [loading, setLoading] = React.useState(true);
33741
+ const [error, setError] = React.useState(void 0);
33742
+ const [resetState, setResetSate] = React.useState(0);
33743
+ React.useEffect(() => {
33744
+ let cancelled = false;
33745
+ const searchCollection = async () => {
33746
+ if (await api.isAuthenticated() && !folder.loading && !cancelled) {
33747
+ try {
33748
+ const response = await cms.api.search.query(
33749
+ `${search} AND _collection:${collectionName}`,
33750
+ {
33751
+ limit: 15,
33752
+ cursor: after
33753
+ }
33754
+ );
33755
+ const docs = await Promise.allSettled(
33756
+ response.results.map((result) => {
33757
+ const [collection2, relativePath2] = result._id.split(":");
33758
+ return api.fetchDocument(collection2, relativePath2, false);
33759
+ })
33760
+ );
33761
+ const edges = docs.filter((p) => {
33762
+ var _a;
33763
+ return p.status === "fulfilled" && !!((_a = p.value) == null ? void 0 : _a.document);
33764
+ }).map((result) => ({ node: result.value.document }));
33765
+ const c = await api.fetchCollection(collectionName, false, "");
33766
+ setCollection({
33767
+ format: collection.format,
33768
+ label: collection.label,
33769
+ name: collectionName,
33770
+ templates: collection.templates,
33771
+ documents: {
33772
+ pageInfo: {
33773
+ hasNextPage: !!response.nextCursor,
33774
+ hasPreviousPage: !!response.prevCursor,
33775
+ startCursor: "",
33776
+ endCursor: response.nextCursor || ""
33777
+ },
33778
+ edges
33779
+ }
33780
+ });
33781
+ } catch (error2) {
33782
+ cms.alerts.error(
33783
+ `[${error2.name}] GetCollection failed: ${error2.message}`
33784
+ );
33785
+ console.error(error2);
33786
+ setCollection(void 0);
33787
+ setError(error2);
33788
+ }
33789
+ setLoading(false);
33790
+ }
33791
+ };
33792
+ if (cancelled)
33793
+ return;
33794
+ setLoading(true);
33795
+ searchCollection();
33796
+ return () => {
33797
+ cancelled = true;
33798
+ };
33799
+ }, [
33800
+ cms,
33801
+ collectionName,
33802
+ folder.loading,
33803
+ folder.fullyQualifiedName,
33804
+ resetState,
33805
+ after,
33806
+ search
33807
+ ]);
33808
+ const reFetchCollection = () => setResetSate((x) => x + 1);
33809
+ return { collection, loading, error, reFetchCollection, collectionExtra };
33810
+ };
33811
+ const GetCollection = ({
33812
+ cms,
33813
+ collectionName,
33814
+ folder,
33815
+ includeDocuments = true,
33816
+ startCursor,
33817
+ sortKey,
33818
+ children,
33819
+ filterArgs,
33820
+ search
33821
+ }) => {
33822
+ const navigate = reactRouterDom.useNavigate();
33823
+ const { collection, loading, error, reFetchCollection, collectionExtra } = search ? useSearchCollection(
33824
+ cms,
33825
+ collectionName,
33826
+ includeDocuments,
33827
+ folder,
33828
+ startCursor || "",
33829
+ search
33830
+ ) : useGetCollection(
33831
+ cms,
33832
+ collectionName,
33833
+ includeDocuments,
33834
+ folder,
33835
+ startCursor || "",
33836
+ sortKey,
33837
+ filterArgs
33838
+ ) || {};
33839
+ React.useEffect(() => {
33840
+ var _a, _b, _c, _d, _e, _f, _g, _h, _i;
33841
+ if (loading)
33842
+ return;
33843
+ const collectionDefinition = cms.api.tina.schema.getCollection(
33844
+ collection.name
33845
+ );
33846
+ const allowCreate = ((_b = (_a = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _a.allowedActions) == null ? void 0 : _b.create) ?? true;
33847
+ const allowDelete = ((_d = (_c = collectionDefinition == null ? void 0 : collectionDefinition.ui) == null ? void 0 : _c.allowedActions) == null ? void 0 : _d.delete) ?? true;
33848
+ const collectionResponse = collection;
33849
+ if (!allowCreate && !allowDelete && // Check there is only one document
33850
+ ((_f = (_e = collectionResponse.documents) == null ? void 0 : _e.edges) == null ? void 0 : _f.length) === 1 && // Check to make sure the file is not a folder
33851
+ ((_i = (_h = (_g = collectionResponse.documents) == null ? void 0 : _g.edges[0]) == null ? void 0 : _h.node) == null ? void 0 : _i.__typename) !== "Folder") {
33852
+ const doc = collectionResponse.documents.edges[0].node;
33853
+ handleNavigate(
33854
+ navigate,
33855
+ cms,
33856
+ collectionResponse,
33857
+ collectionDefinition,
33858
+ doc
33859
+ );
33860
+ }
33861
+ }, [(collection == null ? void 0 : collection.name) || "", loading]);
33862
+ if (error) {
33863
+ return /* @__PURE__ */ React.createElement(FullscreenError, null);
33864
+ }
33865
+ if (loading) {
33866
+ return /* @__PURE__ */ React.createElement(LoadingPage, null);
33867
+ }
33868
+ return /* @__PURE__ */ React.createElement(React.Fragment, null, children(collection, loading, reFetchCollection, collectionExtra));
33869
+ };
33693
33870
  const ErrorDialog = (props) => {
33694
33871
  return /* @__PURE__ */ React.createElement(
33695
33872
  "div",
@@ -34233,6 +34410,12 @@ This will work when developing locally but NOT when deployed to production.
34233
34410
  ), /* @__PURE__ */ React.createElement("span", { className: "opacity-30 text-sm leading-tight whitespace-nowrap flex-0" }, "/"), /* @__PURE__ */ React.createElement("span", { className: "flex-1 w-full text-sm leading-tight whitespace-nowrap truncate" }, `${filename}.${collection.format}`), /* @__PURE__ */ React.createElement(FormStatus, { pristine: formIsPristine }))
34234
34411
  ), activeForm && /* @__PURE__ */ React.createElement(FormBuilder, { form: activeForm, onPristineChange: setFormIsPristine }));
34235
34412
  };
34413
+ const DashboardPage = () => {
34414
+ return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => {
34415
+ var _a, _b;
34416
+ return /* @__PURE__ */ React.createElement(PageWrapper, null, /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(PageHeader, { isLocalMode: (_b = (_a = cms.api) == null ? void 0 : _a.tina) == null ? void 0 : _b.isLocalMode }, /* @__PURE__ */ React.createElement("h3", { className: "text-2xl font-sans text-gray-700" }, "Welcome to Tina!")), /* @__PURE__ */ React.createElement(PageBodyNarrow, null, "This is your dashboard for editing or creating content. Select a collection on the left to begin.")));
34417
+ });
34418
+ };
34236
34419
  const ScreenPage = () => {
34237
34420
  const { screenName } = reactRouterDom.useParams();
34238
34421
  return /* @__PURE__ */ React.createElement(GetCMS, null, (cms) => {
@@ -34251,6 +34434,71 @@ This will work when developing locally but NOT when deployed to production.
34251
34434
  } })));
34252
34435
  });
34253
34436
  };
34437
+ function AuthCallback({
34438
+ clientId,
34439
+ identityApiUrl
34440
+ }) {
34441
+ console.log("AuthCallback", clientId, identityApiUrl);
34442
+ const [code, setCode] = React__namespace.useState(null);
34443
+ const [state, setState] = React__namespace.useState(null);
34444
+ const [tokenResponse, setTokenResponse] = React__namespace.useState(null);
34445
+ const [app, setApp] = React__namespace.useState(null);
34446
+ React__namespace.useEffect(() => {
34447
+ if (typeof window !== "undefined") {
34448
+ const queryParams = new URLSearchParams(window.location.search);
34449
+ setCode(queryParams.get("code"));
34450
+ setState(queryParams.get("state"));
34451
+ }
34452
+ }, []);
34453
+ React__namespace.useEffect(() => {
34454
+ if (code && state) {
34455
+ if (localStorage.getItem("code_verifier")) {
34456
+ const origin = `${window.location.protocol}//${window.location.host}`;
34457
+ const redirectUri = encodeURIComponent(
34458
+ `${origin}/admin#/auth/callback`
34459
+ );
34460
+ fetch(`${identityApiUrl}/oauth2/${clientId}/token`, {
34461
+ method: "POST",
34462
+ headers: {
34463
+ "Content-Type": "application/x-www-form-urlencoded"
34464
+ },
34465
+ body: new URLSearchParams({
34466
+ grant_type: "authorization_code",
34467
+ code,
34468
+ redirect_uri: redirectUri,
34469
+ client_id: clientId || "",
34470
+ code_verifier: localStorage.getItem("code_verifier")
34471
+ })
34472
+ }).then((response) => response.json()).then((data) => {
34473
+ console.log("Token exchange response:", data);
34474
+ setTokenResponse(data);
34475
+ }).catch((error) => {
34476
+ console.error("Error during token exchange:", error);
34477
+ });
34478
+ }
34479
+ }
34480
+ }, [code, state]);
34481
+ React__namespace.useEffect(() => {
34482
+ localStorage.setItem(
34483
+ AUTH_TOKEN_KEY,
34484
+ JSON.stringify(tokenResponse, null, 2)
34485
+ );
34486
+ }, [tokenResponse]);
34487
+ React__namespace.useEffect(() => {
34488
+ fetch(`${identityApiUrl}/v2/apps/${clientId}`, {
34489
+ method: "GET",
34490
+ headers: {
34491
+ "Content-Type": "application/x-www-form-urlencoded",
34492
+ Authorization: "Bearer " + (tokenResponse == null ? void 0 : tokenResponse.access_token)
34493
+ }
34494
+ }).then((response) => response.json()).then((data) => {
34495
+ setApp(data);
34496
+ }).catch((error) => {
34497
+ console.error("Error fetching apps:", error);
34498
+ });
34499
+ }, [tokenResponse]);
34500
+ return /* @__PURE__ */ React__namespace.createElement("div", null, code && /* @__PURE__ */ React__namespace.createElement("div", null, "Code: ", /* @__PURE__ */ React__namespace.createElement("pre", null, code), /* @__PURE__ */ React__namespace.createElement("br", null)), state && /* @__PURE__ */ React__namespace.createElement("div", null, "State: ", /* @__PURE__ */ React__namespace.createElement("pre", null, state), /* @__PURE__ */ React__namespace.createElement("br", null)), tokenResponse && /* @__PURE__ */ React__namespace.createElement("div", null, /* @__PURE__ */ React__namespace.createElement("h2", null, "Token Response:"), /* @__PURE__ */ React__namespace.createElement("pre", null, tokenResponse.access_token), /* @__PURE__ */ React__namespace.createElement("br", null)), /* @__PURE__ */ React__namespace.createElement("div", null, app && /* @__PURE__ */ React__namespace.createElement("div", null, /* @__PURE__ */ React__namespace.createElement("h2", null, "Project Name: ", app.name), /* @__PURE__ */ React__namespace.createElement("p", null, "Project ID: ", /* @__PURE__ */ React__namespace.createElement("pre", null, app.id)))));
34501
+ }
34254
34502
  const IndexingPage = () => {
34255
34503
  const cms = useCMS$1();
34256
34504
  const tinaApi = cms.api.tina;
@@ -34315,7 +34563,7 @@ This will work when developing locally but NOT when deployed to production.
34315
34563
  } catch {
34316
34564
  cms.alerts.error("Branch indexing failed.");
34317
34565
  setErrorMessage(
34318
- 'Branch indexing failed, please check the Tina Cloud dashboard for more information. To try again chick "re-index" on the branch in the dashboard.'
34566
+ 'Branch indexing failed, please check the TinaCloud dashboard for more information. To try again chick "re-index" on the branch in the dashboard.'
34319
34567
  );
34320
34568
  setState("error");
34321
34569
  }
@@ -34483,7 +34731,7 @@ This will work when developing locally but NOT when deployed to production.
34483
34731
  );
34484
34732
  }
34485
34733
  }).catch((e) => {
34486
- if (e.message.includes("has not been indexed by Tina Cloud")) {
34734
+ if (e.message.includes("has not been indexed by TinaCloud")) {
34487
34735
  setSchemaMissingError(true);
34488
34736
  } else {
34489
34737
  cms.alerts.error(`Unexpected error checking schema: ${e}`);
@@ -34598,6 +34846,18 @@ This will work when developing locally but NOT when deployed to production.
34598
34846
  path: "screens/:screenName",
34599
34847
  element: /* @__PURE__ */ React.createElement(DefaultWrapper, { cms }, /* @__PURE__ */ React.createElement(ScreenPage, null))
34600
34848
  }
34849
+ ), /* @__PURE__ */ React.createElement(
34850
+ reactRouterDom.Route,
34851
+ {
34852
+ path: "auth/callback",
34853
+ element: /* @__PURE__ */ React.createElement(DefaultWrapper, { cms }, /* @__PURE__ */ React.createElement(
34854
+ AuthCallback,
34855
+ {
34856
+ clientId: tinaClient.clientId,
34857
+ identityApiUrl: tinaClient.identityApiUrl
34858
+ }
34859
+ ))
34860
+ }
34601
34861
  ), /* @__PURE__ */ React.createElement(
34602
34862
  reactRouterDom.Route,
34603
34863
  {