@ynput/ayon-frontend-shared 0.2.1 → 0.2.2

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.
Files changed (53) hide show
  1. package/dist/_virtual/index.cjs4.js +4 -4
  2. package/dist/_virtual/index.cjs5.js +3 -5
  3. package/dist/_virtual/index.cjs5.js.map +1 -1
  4. package/dist/_virtual/index.cjs6.js +5 -3
  5. package/dist/_virtual/index.cjs6.js.map +1 -1
  6. package/dist/_virtual/index.cjs7.js +2 -2
  7. package/dist/_virtual/index.es4.js +4 -4
  8. package/dist/_virtual/index.es5.js +2 -5
  9. package/dist/_virtual/index.es5.js.map +1 -1
  10. package/dist/_virtual/index.es6.js +5 -2
  11. package/dist/_virtual/index.es6.js.map +1 -1
  12. package/dist/_virtual/index.es7.js +2 -2
  13. package/dist/hooks.cjs.js +2 -0
  14. package/dist/hooks.cjs.js.map +1 -1
  15. package/dist/hooks.es.js +2 -0
  16. package/dist/hooks.es.js.map +1 -1
  17. package/dist/node_modules/match-sorter/dist/match-sorter.esm.cjs.js +1 -1
  18. package/dist/node_modules/match-sorter/dist/match-sorter.esm.es.js +1 -1
  19. package/dist/node_modules/parse-numeric-range/index.cjs.js +1 -1
  20. package/dist/node_modules/parse-numeric-range/index.es.js +1 -1
  21. package/dist/node_modules/rehype-prism-plus/dist/index.es.cjs.js +1 -1
  22. package/dist/node_modules/rehype-prism-plus/dist/index.es.es.js +1 -1
  23. package/dist/node_modules/remove-accents/index.cjs.js +1 -1
  24. package/dist/node_modules/remove-accents/index.es.js +1 -1
  25. package/dist/shared/src/components/EntityPath/EntityPath.cjs.js +11 -1
  26. package/dist/shared/src/components/EntityPath/EntityPath.cjs.js.map +1 -1
  27. package/dist/shared/src/components/EntityPath/EntityPath.es.js +12 -2
  28. package/dist/shared/src/components/EntityPath/EntityPath.es.js.map +1 -1
  29. package/dist/shared/src/components/EntityPath/EntityPath.styled.cjs.js +10 -1
  30. package/dist/shared/src/components/EntityPath/EntityPath.styled.cjs.js.map +1 -1
  31. package/dist/shared/src/components/EntityPath/EntityPath.styled.es.js +10 -1
  32. package/dist/shared/src/components/EntityPath/EntityPath.styled.es.js.map +1 -1
  33. package/dist/shared/src/containers/RepresentationsList/RepresentationsList.cjs.js +1 -2
  34. package/dist/shared/src/containers/RepresentationsList/RepresentationsList.cjs.js.map +1 -1
  35. package/dist/shared/src/containers/RepresentationsList/RepresentationsList.es.js +1 -2
  36. package/dist/shared/src/containers/RepresentationsList/RepresentationsList.es.js.map +1 -1
  37. package/dist/shared/src/context/RemoteModulesContext.cjs.js +1 -1
  38. package/dist/shared/src/context/RemoteModulesContext.cjs.js.map +1 -1
  39. package/dist/shared/src/context/RemoteModulesContext.es.js +1 -1
  40. package/dist/shared/src/context/RemoteModulesContext.es.js.map +1 -1
  41. package/dist/shared/src/hooks/useLoadModules.cjs.js +136 -0
  42. package/dist/shared/src/hooks/useLoadModules.cjs.js.map +1 -0
  43. package/dist/shared/src/hooks/useLoadModules.es.js +136 -0
  44. package/dist/shared/src/hooks/useLoadModules.es.js.map +1 -0
  45. package/dist/shared/src/hooks/useScopedStatuses.cjs.js +4 -1
  46. package/dist/shared/src/hooks/useScopedStatuses.cjs.js.map +1 -1
  47. package/dist/shared/src/hooks/useScopedStatuses.es.js +4 -1
  48. package/dist/shared/src/hooks/useScopedStatuses.es.js.map +1 -1
  49. package/dist/types/components/EntityPath/EntityPath.styled.d.ts +1 -0
  50. package/dist/types/containers/RepresentationsList/RepresentationsList.d.ts +1 -1
  51. package/dist/types/hooks/index.d.ts +1 -0
  52. package/dist/types/hooks/useLoadModules.d.ts +28 -0
  53. package/package.json +1 -1
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  const _commonjsHelpers = require("./_commonjsHelpers.cjs.js");
3
- const index = require("../node_modules/parse-numeric-range/index.cjs.js");
4
- var parseNumericRangeExports = index.__require();
5
- const n = /* @__PURE__ */ _commonjsHelpers.getDefaultExportFromCjs(parseNumericRangeExports);
6
- module.exports = n;
3
+ const index = require("../node_modules/remove-accents/index.cjs.js");
4
+ var removeAccentsExports = index.__require();
5
+ const removeAccents = /* @__PURE__ */ _commonjsHelpers.getDefaultExportFromCjs(removeAccentsExports);
6
+ module.exports = removeAccents;
7
7
  //# sourceMappingURL=index.cjs4.js.map
@@ -1,7 +1,5 @@
1
1
  "use strict";
2
- const _commonjsHelpers = require("./_commonjsHelpers.cjs.js");
3
- const index = require("../node_modules/remove-accents/index.cjs.js");
4
- var removeAccentsExports = index.__require();
5
- const removeAccents = /* @__PURE__ */ _commonjsHelpers.getDefaultExportFromCjs(removeAccentsExports);
6
- module.exports = removeAccents;
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ var removeAccents = { exports: {} };
4
+ exports.__module = removeAccents;
7
5
  //# sourceMappingURL=index.cjs5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs5.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
1
+ {"version":3,"file":"index.cjs5.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,5 +1,7 @@
1
1
  "use strict";
2
- Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- var parseNumericRange = { exports: {} };
4
- exports.__module = parseNumericRange;
2
+ const _commonjsHelpers = require("./_commonjsHelpers.cjs.js");
3
+ const index = require("../node_modules/parse-numeric-range/index.cjs.js");
4
+ var parseNumericRangeExports = index.__require();
5
+ const n = /* @__PURE__ */ _commonjsHelpers.getDefaultExportFromCjs(parseNumericRangeExports);
6
+ module.exports = n;
5
7
  //# sourceMappingURL=index.cjs6.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.cjs6.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
1
+ {"version":3,"file":"index.cjs6.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -1,5 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- var removeAccents = { exports: {} };
4
- exports.__module = removeAccents;
3
+ var parseNumericRange = { exports: {} };
4
+ exports.__module = parseNumericRange;
5
5
  //# sourceMappingURL=index.cjs7.js.map
@@ -1,8 +1,8 @@
1
1
  import { getDefaultExportFromCjs } from "./_commonjsHelpers.es.js";
2
- import { __require as requireParseNumericRange } from "../node_modules/parse-numeric-range/index.es.js";
3
- var parseNumericRangeExports = requireParseNumericRange();
4
- const n = /* @__PURE__ */ getDefaultExportFromCjs(parseNumericRangeExports);
2
+ import { __require as requireRemoveAccents } from "../node_modules/remove-accents/index.es.js";
3
+ var removeAccentsExports = requireRemoveAccents();
4
+ const removeAccents = /* @__PURE__ */ getDefaultExportFromCjs(removeAccentsExports);
5
5
  export {
6
- n as default
6
+ removeAccents as default
7
7
  };
8
8
  //# sourceMappingURL=index.es4.js.map
@@ -1,8 +1,5 @@
1
- import { getDefaultExportFromCjs } from "./_commonjsHelpers.es.js";
2
- import { __require as requireRemoveAccents } from "../node_modules/remove-accents/index.es.js";
3
- var removeAccentsExports = requireRemoveAccents();
4
- const removeAccents = /* @__PURE__ */ getDefaultExportFromCjs(removeAccentsExports);
1
+ var removeAccents = { exports: {} };
5
2
  export {
6
- removeAccents as default
3
+ removeAccents as __module
7
4
  };
8
5
  //# sourceMappingURL=index.es5.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.es5.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
1
+ {"version":3,"file":"index.es5.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -1,5 +1,8 @@
1
- var parseNumericRange = { exports: {} };
1
+ import { getDefaultExportFromCjs } from "./_commonjsHelpers.es.js";
2
+ import { __require as requireParseNumericRange } from "../node_modules/parse-numeric-range/index.es.js";
3
+ var parseNumericRangeExports = requireParseNumericRange();
4
+ const n = /* @__PURE__ */ getDefaultExportFromCjs(parseNumericRangeExports);
2
5
  export {
3
- parseNumericRange as __module
6
+ n as default
4
7
  };
5
8
  //# sourceMappingURL=index.es6.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.es6.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
1
+ {"version":3,"file":"index.es6.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
@@ -1,5 +1,5 @@
1
- var removeAccents = { exports: {} };
1
+ var parseNumericRange = { exports: {} };
2
2
  export {
3
- removeAccents as __module
3
+ parseNumericRange as __module
4
4
  };
5
5
  //# sourceMappingURL=index.es7.js.map
package/dist/hooks.cjs.js CHANGED
@@ -2,11 +2,13 @@
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
3
  const useLocalStorage = require("./shared/src/hooks/useLocalStorage.cjs.js");
4
4
  const useLoadModule = require("./shared/src/hooks/useLoadModule.cjs.js");
5
+ const useLoadModules = require("./shared/src/hooks/useLoadModules.cjs.js");
5
6
  const useScopedStatuses = require("./shared/src/hooks/useScopedStatuses.cjs.js");
6
7
  const useEntityUpdate = require("./shared/src/hooks/useEntityUpdate.cjs.js");
7
8
  const useActionTriggers = require("./shared/src/hooks/useActionTriggers.cjs.js");
8
9
  exports.useLocalStorage = useLocalStorage.useLocalStorage;
9
10
  exports.useLoadModule = useLoadModule.useLoadModule;
11
+ exports.useLoadModules = useLoadModules.useLoadModules;
10
12
  exports.filterProjectStatuses = useScopedStatuses.filterProjectStatuses;
11
13
  exports.useScopedStatuses = useScopedStatuses.useScopedStatuses;
12
14
  exports.useEntityUpdate = useEntityUpdate.useEntityUpdate;
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;"}
1
+ {"version":3,"file":"hooks.cjs.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;"}
package/dist/hooks.es.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import { useLocalStorage } from "./shared/src/hooks/useLocalStorage.es.js";
2
2
  import { useLoadModule } from "./shared/src/hooks/useLoadModule.es.js";
3
+ import { useLoadModules } from "./shared/src/hooks/useLoadModules.es.js";
3
4
  import { filterProjectStatuses, useScopedStatuses } from "./shared/src/hooks/useScopedStatuses.es.js";
4
5
  import { useEntityUpdate } from "./shared/src/hooks/useEntityUpdate.es.js";
5
6
  import { useActionTriggers } from "./shared/src/hooks/useActionTriggers.es.js";
@@ -8,6 +9,7 @@ export {
8
9
  useActionTriggers,
9
10
  useEntityUpdate,
10
11
  useLoadModule,
12
+ useLoadModules,
11
13
  useLocalStorage,
12
14
  useScopedStatuses
13
15
  };
@@ -1 +1 @@
1
- {"version":3,"file":"hooks.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;"}
1
+ {"version":3,"file":"hooks.es.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const index = require("../../../_virtual/index.cjs5.js");
3
+ const index = require("../../../_virtual/index.cjs4.js");
4
4
  /**
5
5
  * @name match-sorter
6
6
  * @license MIT license.
@@ -1,4 +1,4 @@
1
- import removeAccents from "../../../_virtual/index.es5.js";
1
+ import removeAccents from "../../../_virtual/index.es4.js";
2
2
  /**
3
3
  * @name match-sorter
4
4
  * @license MIT license.
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const index = require("../../_virtual/index.cjs6.js");
3
+ const index = require("../../_virtual/index.cjs7.js");
4
4
  var hasRequiredParseNumericRange;
5
5
  function requireParseNumericRange() {
6
6
  if (hasRequiredParseNumericRange) return index.__module.exports;
@@ -1,4 +1,4 @@
1
- import { __module as parseNumericRange } from "../../_virtual/index.es6.js";
1
+ import { __module as parseNumericRange } from "../../_virtual/index.es7.js";
2
2
  var hasRequiredParseNumericRange;
3
3
  function requireParseNumericRange() {
4
4
  if (hasRequiredParseNumericRange) return parseNumericRange.exports;
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: "Module" } });
3
3
  const index$1 = require("../../hast-util-to-string/index.cjs.js");
4
- const index$2 = require("../../../_virtual/index.cjs4.js");
4
+ const index$2 = require("../../../_virtual/index.cjs6.js");
5
5
  require("../../refractor/lib/common.cjs.js");
6
6
  require("../../refractor/lib/all.cjs.js");
7
7
  const index = require("../node_modules/unist-util-visit/lib/index.cjs.js");
@@ -1,5 +1,5 @@
1
1
  import { toString } from "../../hast-util-to-string/index.es.js";
2
- import n from "../../../_virtual/index.es4.js";
2
+ import n from "../../../_virtual/index.es6.js";
3
3
  import "../../refractor/lib/common.es.js";
4
4
  import "../../refractor/lib/all.es.js";
5
5
  import { visit } from "../node_modules/unist-util-visit/lib/index.es.js";
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
- const index = require("../../_virtual/index.cjs7.js");
3
+ const index = require("../../_virtual/index.cjs5.js");
4
4
  var hasRequiredRemoveAccents;
5
5
  function requireRemoveAccents() {
6
6
  if (hasRequiredRemoveAccents) return index.__module.exports;
@@ -1,4 +1,4 @@
1
- import { __module as removeAccents } from "../../_virtual/index.es7.js";
1
+ import { __module as removeAccents } from "../../_virtual/index.es5.js";
2
2
  var hasRequiredRemoveAccents;
3
3
  function requireRemoveAccents() {
4
4
  if (hasRequiredRemoveAccents) return removeAccents.exports;
@@ -27,6 +27,7 @@ const EntityPath = ({
27
27
  const [dropdownOpen, setDropdownOpen] = React.useState(null);
28
28
  const [maxSegments, setMaxSegments] = React.useState(null);
29
29
  const [calcMaxWidth, setCalcMaxWidth] = React.useState(false);
30
+ const finalSegmentRef = React.useRef(null);
30
31
  React.useLayoutEffect(() => {
31
32
  setMaxSegments(null);
32
33
  setCalcMaxWidth(true);
@@ -56,6 +57,15 @@ const EntityPath = ({
56
57
  setMaxSegments(newMaxSegments);
57
58
  setCalcMaxWidth(false);
58
59
  }, [containerRef.current, calcMaxWidth]);
60
+ React.useLayoutEffect(() => {
61
+ if (!containerRef.current || !finalSegmentRef.current || !maxSegments) return;
62
+ const container = containerRef.current;
63
+ const maxWidth = getPathMaxWidth(container) ?? Infinity;
64
+ const diff = container.clientWidth - maxWidth;
65
+ if (diff <= 0) return;
66
+ const newWidth = `${finalSegmentRef.current.clientWidth - diff}px`;
67
+ finalSegmentRef.current.style.width = newWidth;
68
+ }, [maxSegments]);
59
69
  const segmentsToShow = maxSegments && segments.length > maxSegments ? segments.slice(-maxSegments) : segments;
60
70
  const hiddenSegments = maxSegments && segments.length > maxSegments ? segments.slice(0, -maxSegments) : [];
61
71
  if (hideProjectName)
@@ -120,7 +130,7 @@ const EntityPath = ({
120
130
  segment: versionSegment,
121
131
  isOpen: dropdownOpen === "versions",
122
132
  children: /* @__PURE__ */ jsxRuntime.jsxRuntimeExports.jsxs(EntityPath_styled.Segment, { children: [
123
- /* @__PURE__ */ jsxRuntime.jsxRuntimeExports.jsx("span", { className: "label", children: versionSegment.label }),
133
+ /* @__PURE__ */ jsxRuntime.jsxRuntimeExports.jsx(EntityPath_styled.FinalSegmentLabel, { ref: finalSegmentRef, className: "label", children: versionSegment.label }),
124
134
  /* @__PURE__ */ jsxRuntime.jsxRuntimeExports.jsx(ayonReactComponents.Icon, { icon: "expand_more" })
125
135
  ] })
126
136
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EntityPath.cjs.js","sources":["../../../../../src/components/EntityPath/EntityPath.tsx"],"sourcesContent":["import { FC, Fragment, MouseEvent, useLayoutEffect, useRef, useState } from 'react'\nimport * as Styled from './EntityPath.styled'\nimport clsx from 'clsx'\nimport SegmentProvider from './SegmentProvider'\nimport { Icon } from '@ynput/ayon-react-components'\nimport { DetailsPanelEntityType } from '@shared/api'\n\nconst Slash = () => <span className=\"slash\">/</span>\n\nexport type PathSegment = {\n type: DetailsPanelEntityType | 'product' | 'project'\n label: string\n id: string\n}\n\nconst dropdownStates = ['more', 'versions']\ntype DropdownState = (typeof dropdownStates)[number]\n\ntype DropdownMouseEvent = MouseEvent<HTMLSpanElement>\nconst getDropdownElements = (e: DropdownMouseEvent): [HTMLElement, string] => {\n const target = e.target as HTMLElement\n const dropdownId = target.closest('.dropdown')?.id || ''\n return [target, dropdownId]\n}\n\nexport interface EntityPathProps {\n projectName: string\n hideProjectName: boolean\n segments: PathSegment[]\n isLoading: boolean\n entityType: string\n versions: PathSegment[]\n scope: string\n}\n\nexport const EntityPath: FC<EntityPathProps> = ({\n projectName,\n hideProjectName,\n segments,\n versions = [],\n isLoading,\n entityType,\n scope,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [dropdownOpen, setDropdownOpen] = useState<null | DropdownState>(null)\n // defaults to whole path\n const [maxSegments, setMaxSegments] = useState<null | number>(null)\n const [calcMaxWidth, setCalcMaxWidth] = useState(false)\n\n useLayoutEffect(() => {\n setMaxSegments(null)\n setCalcMaxWidth(true)\n }, [segments])\n\n useLayoutEffect(() => {\n if (!containerRef.current) {\n setCalcMaxWidth(false)\n return\n }\n // find max width the path can be\n const container = containerRef.current\n const pathWidth = container.clientWidth\n const maxWidth = getPathMaxWidth(container)\n\n if (!maxWidth) return\n\n // we need to reduce the number of segments shown\n // but maybe even then it is still longer than the max width\n // so we need to reduce the number of segments until the total width is less than the max width\n const children = container.children\n let totalWidth = pathWidth\n // number of segments to keep\n const fullCount = container.childElementCount\n let segmentsCount = fullCount\n // while loop that removes segments until the total width is less than the max width\n while (totalWidth > maxWidth && segmentsCount > 0) {\n // remove 2 segments at a time (because of slashes)\n segmentsCount -= 2\n totalWidth = totalUpSegmentsWidth(children, segmentsCount, fullCount)\n }\n\n // count number of \"full\" segments left\n // if something goes wrong, removing 1 (2) is probably enough\n let newMaxSegments =\n Array.from(children)\n .slice(0, segmentsCount)\n .filter(\n (segment) => segment.nodeType === Node.ELEMENT_NODE && segment.className.includes('full'),\n )?.length || 2\n\n // cap at 1\n newMaxSegments = Math.max(newMaxSegments, 1)\n\n setMaxSegments(newMaxSegments)\n setCalcMaxWidth(false)\n }, [containerRef.current, calcMaxWidth])\n\n // Check if there are fewer than or equal to maxSegments segments\n const segmentsToShow =\n maxSegments && segments.length > maxSegments ? segments.slice(-maxSegments) : segments\n const hiddenSegments =\n maxSegments && segments.length > maxSegments ? segments.slice(0, -maxSegments) : []\n\n // if there is no project name, add to hidden segments\n if (hideProjectName)\n hiddenSegments.unshift({ type: 'project', label: projectName, id: projectName })\n\n // if the entityType is a version, separate the version\n let versionSegment\n let finalSegmentsToShow = segmentsToShow\n\n if (entityType === 'version' && segments.length > 0) {\n versionSegment = segments[segments.length - 1]\n finalSegmentsToShow = segmentsToShow.slice(0, -1)\n }\n\n const handleMouseEnter = (e: DropdownMouseEvent) => {\n const [, id] = getDropdownElements(e)\n if (id && !dropdownOpen) setDropdownOpen(id)\n }\n const handleMouseLeave = () => setDropdownOpen(null)\n\n const handleDropdownClick = (e: DropdownMouseEvent) => {\n const [target, id] = getDropdownElements(e)\n\n if (!dropdownStates.includes(id)) return\n const isListItem = !!target.closest('li')\n\n if (isListItem) setDropdownOpen(null)\n else if (dropdownOpen !== id) setDropdownOpen(id)\n }\n\n const segmentProps = { scope, projectName }\n\n return (\n <Styled.Path className={clsx({ loading: isLoading })} id=\"entity-path\" ref={containerRef}>\n {!hideProjectName && <Styled.Segment>{projectName}</Styled.Segment>}\n\n {!!hiddenSegments.length && (\n <>\n {!hideProjectName && <Slash />}\n <Styled.Segment\n className=\"dropdown more\"\n id=\"more\"\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={handleDropdownClick}\n >\n ...\n {dropdownOpen === 'more' && (\n <Styled.MoreModal>\n <Styled.MoreList>\n {hiddenSegments.map((segment) => (\n <SegmentProvider {...segmentProps} segment={segment} key={segment.id}>\n <Styled.MoreItem>{segment.label}</Styled.MoreItem>\n </SegmentProvider>\n ))}\n </Styled.MoreList>\n </Styled.MoreModal>\n )}\n </Styled.Segment>\n </>\n )}\n\n {finalSegmentsToShow.map((segment) => (\n <Fragment key={segment.id}>\n <Slash />\n\n <SegmentProvider {...segmentProps} segment={segment} className=\"full\">\n <Styled.Segment>\n <span className=\"label\">{segment.label}</span>\n </Styled.Segment>\n </SegmentProvider>\n </Fragment>\n ))}\n\n {versionSegment && (\n <>\n <Slash />\n <Styled.SegmentWrapper\n className=\"full dropdown\"\n id=\"versions\"\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={handleDropdownClick}\n >\n <SegmentProvider\n {...segmentProps}\n segment={versionSegment}\n isOpen={dropdownOpen === 'versions'}\n >\n <Styled.Segment>\n <span className=\"label\">{versionSegment.label}</span>\n <Icon icon=\"expand_more\" />\n </Styled.Segment>\n </SegmentProvider>\n {dropdownOpen === 'versions' && (\n <Styled.MoreModal>\n <Styled.MoreList>\n {versions.map((version) => (\n <SegmentProvider {...segmentProps} segment={version} key={version.id}>\n <Styled.MoreItem>{version.label}</Styled.MoreItem>\n </SegmentProvider>\n ))}\n </Styled.MoreList>\n </Styled.MoreModal>\n )}\n </Styled.SegmentWrapper>\n </>\n )}\n </Styled.Path>\n )\n}\n\nconst getPathMaxWidth = (pathEl: HTMLDivElement) => {\n const toolbar = pathEl.parentElement\n if (!toolbar) return\n // get width of toolbar without padding\n const toolbarStyle = getComputedStyle(toolbar)\n const paddingLeft = parseInt(toolbarStyle.paddingLeft) || 0\n const paddingRight = parseInt(toolbarStyle.paddingRight) || 0\n const gap = parseInt(toolbarStyle.gap) || 0\n const toolbarWidth = toolbar.clientWidth - paddingLeft - paddingRight\n\n // get child elements that are not path\n const children = Array.from(toolbar.children).filter((child) => child.id !== 'entity-path')\n // find total width of children including the gap between them\n const childrenWidth = Array.from(children).reduce(\n (acc, child) => acc + (child as HTMLElement).clientWidth,\n 0,\n )\n\n return toolbarWidth - childrenWidth - gap * (children.length - 1)\n}\n\nconst totalUpSegmentsWidth = (children: HTMLCollection, count: number, full: number) => {\n const skip = full - count\n let total = 0\n for (let i = 0; i < full - skip; i++) {\n const index = i > 1 ? i + skip : i\n const width = (children[index] as Element)?.clientWidth\n if (isNaN(width)) continue\n total += width\n }\n const gap = 4\n const moreWidth = 40\n return total + (gap * count - 1) + moreWidth\n}\n"],"names":["jsx","useRef","useState","useLayoutEffect","jsxs","Styled.Path","Styled.Segment","Fragment","Styled.MoreModal","Styled.MoreList","createElement","Styled.MoreItem","Styled.SegmentWrapper","Icon"],"mappings":"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"}
1
+ {"version":3,"file":"EntityPath.cjs.js","sources":["../../../../../src/components/EntityPath/EntityPath.tsx"],"sourcesContent":["import { FC, Fragment, MouseEvent, useLayoutEffect, useRef, useState } from 'react'\nimport * as Styled from './EntityPath.styled'\nimport clsx from 'clsx'\nimport SegmentProvider from './SegmentProvider'\nimport { Icon } from '@ynput/ayon-react-components'\nimport { DetailsPanelEntityType } from '@shared/api'\n\nconst Slash = () => <span className=\"slash\">/</span>\n\nexport type PathSegment = {\n type: DetailsPanelEntityType | 'product' | 'project'\n label: string\n id: string\n}\n\nconst dropdownStates = ['more', 'versions']\ntype DropdownState = (typeof dropdownStates)[number]\n\ntype DropdownMouseEvent = MouseEvent<HTMLSpanElement>\nconst getDropdownElements = (e: DropdownMouseEvent): [HTMLElement, string] => {\n const target = e.target as HTMLElement\n const dropdownId = target.closest('.dropdown')?.id || ''\n return [target, dropdownId]\n}\n\nexport interface EntityPathProps {\n projectName: string\n hideProjectName: boolean\n segments: PathSegment[]\n isLoading: boolean\n entityType: string\n versions: PathSegment[]\n scope: string\n}\n\nexport const EntityPath: FC<EntityPathProps> = ({\n projectName,\n hideProjectName,\n segments,\n versions = [],\n isLoading,\n entityType,\n scope,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [dropdownOpen, setDropdownOpen] = useState<null | DropdownState>(null)\n // defaults to whole path\n const [maxSegments, setMaxSegments] = useState<null | number>(null)\n const [calcMaxWidth, setCalcMaxWidth] = useState(false)\n const finalSegmentRef = useRef<HTMLSpanElement>(null)\n\n useLayoutEffect(() => {\n setMaxSegments(null)\n setCalcMaxWidth(true)\n }, [segments])\n\n useLayoutEffect(() => {\n if (!containerRef.current) {\n setCalcMaxWidth(false)\n return\n }\n // find max width the path can be\n const container = containerRef.current\n const pathWidth = container.clientWidth\n const maxWidth = getPathMaxWidth(container)\n\n if (!maxWidth) return\n\n // we need to reduce the number of segments shown\n // but maybe even then it is still longer than the max width\n // so we need to reduce the number of segments until the total width is less than the max width\n const children = container.children\n let totalWidth = pathWidth\n // number of segments to keep\n const fullCount = container.childElementCount\n let segmentsCount = fullCount\n // while loop that removes segments until the total width is less than the max width\n while (totalWidth > maxWidth && segmentsCount > 0) {\n // remove 2 segments at a time (because of slashes)\n segmentsCount -= 2\n totalWidth = totalUpSegmentsWidth(children, segmentsCount, fullCount)\n }\n\n // count number of \"full\" segments left\n // if something goes wrong, removing 1 (2) is probably enough\n let newMaxSegments =\n Array.from(children)\n .slice(0, segmentsCount)\n .filter(\n (segment) => segment.nodeType === Node.ELEMENT_NODE && segment.className.includes('full'),\n )?.length || 2\n\n // cap at 1\n newMaxSegments = Math.max(newMaxSegments, 1)\n\n setMaxSegments(newMaxSegments)\n setCalcMaxWidth(false)\n }, [containerRef.current, calcMaxWidth])\n\n // Ensure that, even if the collapsed segments still aren't\n // enough to fit the path within the available space,\n // we fit everything in by truncating the last segment's label.\n // This segment is typically the product + version name,\n // which is typically also shown in much larger font below,\n // so there's no reason to always show it in full.\n useLayoutEffect(() => {\n if (!containerRef.current || !finalSegmentRef.current || !maxSegments) return\n const container = containerRef.current\n\n // The amount of truncation is exactly the difference between the container's width\n // and the maximum available width.\n const maxWidth = getPathMaxWidth(container) ?? Infinity\n const diff = container.clientWidth - maxWidth\n if (diff <= 0) return\n\n // Reduce the segment's width by the difference\n const newWidth = `${finalSegmentRef.current.clientWidth - diff}px`\n finalSegmentRef.current.style.width = newWidth\n }, [maxSegments])\n\n // Check if there are fewer than or equal to maxSegments segments\n const segmentsToShow =\n maxSegments && segments.length > maxSegments ? segments.slice(-maxSegments) : segments\n const hiddenSegments =\n maxSegments && segments.length > maxSegments ? segments.slice(0, -maxSegments) : []\n\n // if there is no project name, add to hidden segments\n if (hideProjectName)\n hiddenSegments.unshift({ type: 'project', label: projectName, id: projectName })\n\n // if the entityType is a version, separate the version\n let versionSegment\n let finalSegmentsToShow = segmentsToShow\n\n if (entityType === 'version' && segments.length > 0) {\n versionSegment = segments[segments.length - 1]\n finalSegmentsToShow = segmentsToShow.slice(0, -1)\n }\n\n const handleMouseEnter = (e: DropdownMouseEvent) => {\n const [, id] = getDropdownElements(e)\n if (id && !dropdownOpen) setDropdownOpen(id)\n }\n const handleMouseLeave = () => setDropdownOpen(null)\n\n const handleDropdownClick = (e: DropdownMouseEvent) => {\n const [target, id] = getDropdownElements(e)\n\n if (!dropdownStates.includes(id)) return\n const isListItem = !!target.closest('li')\n\n if (isListItem) setDropdownOpen(null)\n else if (dropdownOpen !== id) setDropdownOpen(id)\n }\n\n const segmentProps = { scope, projectName }\n\n return (\n <Styled.Path className={clsx({ loading: isLoading })} id=\"entity-path\" ref={containerRef}>\n {!hideProjectName && <Styled.Segment>{projectName}</Styled.Segment>}\n\n {!!hiddenSegments.length && (\n <>\n {!hideProjectName && <Slash />}\n <Styled.Segment\n className=\"dropdown more\"\n id=\"more\"\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={handleDropdownClick}\n >\n ...\n {dropdownOpen === 'more' && (\n <Styled.MoreModal>\n <Styled.MoreList>\n {hiddenSegments.map((segment) => (\n <SegmentProvider {...segmentProps} segment={segment} key={segment.id}>\n <Styled.MoreItem>{segment.label}</Styled.MoreItem>\n </SegmentProvider>\n ))}\n </Styled.MoreList>\n </Styled.MoreModal>\n )}\n </Styled.Segment>\n </>\n )}\n\n {finalSegmentsToShow.map((segment) => (\n <Fragment key={segment.id}>\n <Slash />\n\n <SegmentProvider {...segmentProps} segment={segment} className=\"full\">\n <Styled.Segment>\n <span className=\"label\">{segment.label}</span>\n </Styled.Segment>\n </SegmentProvider>\n </Fragment>\n ))}\n\n {versionSegment && (\n <>\n <Slash />\n <Styled.SegmentWrapper\n className=\"full dropdown\"\n id=\"versions\"\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={handleDropdownClick}\n >\n <SegmentProvider\n {...segmentProps}\n segment={versionSegment}\n isOpen={dropdownOpen === 'versions'}\n >\n <Styled.Segment>\n <Styled.FinalSegmentLabel ref={finalSegmentRef} className=\"label\">\n {versionSegment.label}\n </Styled.FinalSegmentLabel>\n <Icon icon=\"expand_more\" />\n </Styled.Segment>\n </SegmentProvider>\n {dropdownOpen === 'versions' && (\n <Styled.MoreModal>\n <Styled.MoreList>\n {versions.map((version) => (\n <SegmentProvider {...segmentProps} segment={version} key={version.id}>\n <Styled.MoreItem>{version.label}</Styled.MoreItem>\n </SegmentProvider>\n ))}\n </Styled.MoreList>\n </Styled.MoreModal>\n )}\n </Styled.SegmentWrapper>\n </>\n )}\n </Styled.Path>\n )\n}\n\nconst getPathMaxWidth = (pathEl: HTMLDivElement) => {\n const toolbar = pathEl.parentElement\n if (!toolbar) return\n // get width of toolbar without padding\n const toolbarStyle = getComputedStyle(toolbar)\n const paddingLeft = parseInt(toolbarStyle.paddingLeft) || 0\n const paddingRight = parseInt(toolbarStyle.paddingRight) || 0\n const gap = parseInt(toolbarStyle.gap) || 0\n const toolbarWidth = toolbar.clientWidth - paddingLeft - paddingRight\n\n // get child elements that are not path\n const children = Array.from(toolbar.children).filter((child) => child.id !== 'entity-path')\n // find total width of children including the gap between them\n const childrenWidth = Array.from(children).reduce(\n (acc, child) => acc + (child as HTMLElement).clientWidth,\n 0,\n )\n\n return toolbarWidth - childrenWidth - gap * (children.length - 1)\n}\n\nconst totalUpSegmentsWidth = (children: HTMLCollection, count: number, full: number) => {\n const skip = full - count\n let total = 0\n for (let i = 0; i < full - skip; i++) {\n const index = i > 1 ? i + skip : i\n const width = (children[index] as Element)?.clientWidth\n if (isNaN(width)) continue\n total += width\n }\n const gap = 4\n const moreWidth = 40\n return total + (gap * count - 1) + moreWidth\n}\n"],"names":["jsx","useRef","useState","useLayoutEffect","jsxs","Styled.Path","Styled.Segment","Fragment","Styled.MoreModal","Styled.MoreList","createElement","Styled.MoreItem","Styled.SegmentWrapper","Styled.FinalSegmentLabel","Icon"],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import { j as jsxRuntimeExports } from "../../../../_virtual/jsx-runtime.es.js";
2
2
  import { useRef, useState, useLayoutEffect, createElement, Fragment } from "react";
3
- import { Path, Segment, MoreModal, MoreList, MoreItem, SegmentWrapper } from "./EntityPath.styled.es.js";
3
+ import { Path, Segment, MoreModal, MoreList, MoreItem, SegmentWrapper, FinalSegmentLabel } from "./EntityPath.styled.es.js";
4
4
  import clsx from "clsx";
5
5
  import SegmentProvider from "./SegmentProvider.es.js";
6
6
  import { Icon } from "@ynput/ayon-react-components";
@@ -25,6 +25,7 @@ const EntityPath = ({
25
25
  const [dropdownOpen, setDropdownOpen] = useState(null);
26
26
  const [maxSegments, setMaxSegments] = useState(null);
27
27
  const [calcMaxWidth, setCalcMaxWidth] = useState(false);
28
+ const finalSegmentRef = useRef(null);
28
29
  useLayoutEffect(() => {
29
30
  setMaxSegments(null);
30
31
  setCalcMaxWidth(true);
@@ -54,6 +55,15 @@ const EntityPath = ({
54
55
  setMaxSegments(newMaxSegments);
55
56
  setCalcMaxWidth(false);
56
57
  }, [containerRef.current, calcMaxWidth]);
58
+ useLayoutEffect(() => {
59
+ if (!containerRef.current || !finalSegmentRef.current || !maxSegments) return;
60
+ const container = containerRef.current;
61
+ const maxWidth = getPathMaxWidth(container) ?? Infinity;
62
+ const diff = container.clientWidth - maxWidth;
63
+ if (diff <= 0) return;
64
+ const newWidth = `${finalSegmentRef.current.clientWidth - diff}px`;
65
+ finalSegmentRef.current.style.width = newWidth;
66
+ }, [maxSegments]);
57
67
  const segmentsToShow = maxSegments && segments.length > maxSegments ? segments.slice(-maxSegments) : segments;
58
68
  const hiddenSegments = maxSegments && segments.length > maxSegments ? segments.slice(0, -maxSegments) : [];
59
69
  if (hideProjectName)
@@ -118,7 +128,7 @@ const EntityPath = ({
118
128
  segment: versionSegment,
119
129
  isOpen: dropdownOpen === "versions",
120
130
  children: /* @__PURE__ */ jsxRuntimeExports.jsxs(Segment, { children: [
121
- /* @__PURE__ */ jsxRuntimeExports.jsx("span", { className: "label", children: versionSegment.label }),
131
+ /* @__PURE__ */ jsxRuntimeExports.jsx(FinalSegmentLabel, { ref: finalSegmentRef, className: "label", children: versionSegment.label }),
122
132
  /* @__PURE__ */ jsxRuntimeExports.jsx(Icon, { icon: "expand_more" })
123
133
  ] })
124
134
  }
@@ -1 +1 @@
1
- {"version":3,"file":"EntityPath.es.js","sources":["../../../../../src/components/EntityPath/EntityPath.tsx"],"sourcesContent":["import { FC, Fragment, MouseEvent, useLayoutEffect, useRef, useState } from 'react'\nimport * as Styled from './EntityPath.styled'\nimport clsx from 'clsx'\nimport SegmentProvider from './SegmentProvider'\nimport { Icon } from '@ynput/ayon-react-components'\nimport { DetailsPanelEntityType } from '@shared/api'\n\nconst Slash = () => <span className=\"slash\">/</span>\n\nexport type PathSegment = {\n type: DetailsPanelEntityType | 'product' | 'project'\n label: string\n id: string\n}\n\nconst dropdownStates = ['more', 'versions']\ntype DropdownState = (typeof dropdownStates)[number]\n\ntype DropdownMouseEvent = MouseEvent<HTMLSpanElement>\nconst getDropdownElements = (e: DropdownMouseEvent): [HTMLElement, string] => {\n const target = e.target as HTMLElement\n const dropdownId = target.closest('.dropdown')?.id || ''\n return [target, dropdownId]\n}\n\nexport interface EntityPathProps {\n projectName: string\n hideProjectName: boolean\n segments: PathSegment[]\n isLoading: boolean\n entityType: string\n versions: PathSegment[]\n scope: string\n}\n\nexport const EntityPath: FC<EntityPathProps> = ({\n projectName,\n hideProjectName,\n segments,\n versions = [],\n isLoading,\n entityType,\n scope,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [dropdownOpen, setDropdownOpen] = useState<null | DropdownState>(null)\n // defaults to whole path\n const [maxSegments, setMaxSegments] = useState<null | number>(null)\n const [calcMaxWidth, setCalcMaxWidth] = useState(false)\n\n useLayoutEffect(() => {\n setMaxSegments(null)\n setCalcMaxWidth(true)\n }, [segments])\n\n useLayoutEffect(() => {\n if (!containerRef.current) {\n setCalcMaxWidth(false)\n return\n }\n // find max width the path can be\n const container = containerRef.current\n const pathWidth = container.clientWidth\n const maxWidth = getPathMaxWidth(container)\n\n if (!maxWidth) return\n\n // we need to reduce the number of segments shown\n // but maybe even then it is still longer than the max width\n // so we need to reduce the number of segments until the total width is less than the max width\n const children = container.children\n let totalWidth = pathWidth\n // number of segments to keep\n const fullCount = container.childElementCount\n let segmentsCount = fullCount\n // while loop that removes segments until the total width is less than the max width\n while (totalWidth > maxWidth && segmentsCount > 0) {\n // remove 2 segments at a time (because of slashes)\n segmentsCount -= 2\n totalWidth = totalUpSegmentsWidth(children, segmentsCount, fullCount)\n }\n\n // count number of \"full\" segments left\n // if something goes wrong, removing 1 (2) is probably enough\n let newMaxSegments =\n Array.from(children)\n .slice(0, segmentsCount)\n .filter(\n (segment) => segment.nodeType === Node.ELEMENT_NODE && segment.className.includes('full'),\n )?.length || 2\n\n // cap at 1\n newMaxSegments = Math.max(newMaxSegments, 1)\n\n setMaxSegments(newMaxSegments)\n setCalcMaxWidth(false)\n }, [containerRef.current, calcMaxWidth])\n\n // Check if there are fewer than or equal to maxSegments segments\n const segmentsToShow =\n maxSegments && segments.length > maxSegments ? segments.slice(-maxSegments) : segments\n const hiddenSegments =\n maxSegments && segments.length > maxSegments ? segments.slice(0, -maxSegments) : []\n\n // if there is no project name, add to hidden segments\n if (hideProjectName)\n hiddenSegments.unshift({ type: 'project', label: projectName, id: projectName })\n\n // if the entityType is a version, separate the version\n let versionSegment\n let finalSegmentsToShow = segmentsToShow\n\n if (entityType === 'version' && segments.length > 0) {\n versionSegment = segments[segments.length - 1]\n finalSegmentsToShow = segmentsToShow.slice(0, -1)\n }\n\n const handleMouseEnter = (e: DropdownMouseEvent) => {\n const [, id] = getDropdownElements(e)\n if (id && !dropdownOpen) setDropdownOpen(id)\n }\n const handleMouseLeave = () => setDropdownOpen(null)\n\n const handleDropdownClick = (e: DropdownMouseEvent) => {\n const [target, id] = getDropdownElements(e)\n\n if (!dropdownStates.includes(id)) return\n const isListItem = !!target.closest('li')\n\n if (isListItem) setDropdownOpen(null)\n else if (dropdownOpen !== id) setDropdownOpen(id)\n }\n\n const segmentProps = { scope, projectName }\n\n return (\n <Styled.Path className={clsx({ loading: isLoading })} id=\"entity-path\" ref={containerRef}>\n {!hideProjectName && <Styled.Segment>{projectName}</Styled.Segment>}\n\n {!!hiddenSegments.length && (\n <>\n {!hideProjectName && <Slash />}\n <Styled.Segment\n className=\"dropdown more\"\n id=\"more\"\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={handleDropdownClick}\n >\n ...\n {dropdownOpen === 'more' && (\n <Styled.MoreModal>\n <Styled.MoreList>\n {hiddenSegments.map((segment) => (\n <SegmentProvider {...segmentProps} segment={segment} key={segment.id}>\n <Styled.MoreItem>{segment.label}</Styled.MoreItem>\n </SegmentProvider>\n ))}\n </Styled.MoreList>\n </Styled.MoreModal>\n )}\n </Styled.Segment>\n </>\n )}\n\n {finalSegmentsToShow.map((segment) => (\n <Fragment key={segment.id}>\n <Slash />\n\n <SegmentProvider {...segmentProps} segment={segment} className=\"full\">\n <Styled.Segment>\n <span className=\"label\">{segment.label}</span>\n </Styled.Segment>\n </SegmentProvider>\n </Fragment>\n ))}\n\n {versionSegment && (\n <>\n <Slash />\n <Styled.SegmentWrapper\n className=\"full dropdown\"\n id=\"versions\"\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={handleDropdownClick}\n >\n <SegmentProvider\n {...segmentProps}\n segment={versionSegment}\n isOpen={dropdownOpen === 'versions'}\n >\n <Styled.Segment>\n <span className=\"label\">{versionSegment.label}</span>\n <Icon icon=\"expand_more\" />\n </Styled.Segment>\n </SegmentProvider>\n {dropdownOpen === 'versions' && (\n <Styled.MoreModal>\n <Styled.MoreList>\n {versions.map((version) => (\n <SegmentProvider {...segmentProps} segment={version} key={version.id}>\n <Styled.MoreItem>{version.label}</Styled.MoreItem>\n </SegmentProvider>\n ))}\n </Styled.MoreList>\n </Styled.MoreModal>\n )}\n </Styled.SegmentWrapper>\n </>\n )}\n </Styled.Path>\n )\n}\n\nconst getPathMaxWidth = (pathEl: HTMLDivElement) => {\n const toolbar = pathEl.parentElement\n if (!toolbar) return\n // get width of toolbar without padding\n const toolbarStyle = getComputedStyle(toolbar)\n const paddingLeft = parseInt(toolbarStyle.paddingLeft) || 0\n const paddingRight = parseInt(toolbarStyle.paddingRight) || 0\n const gap = parseInt(toolbarStyle.gap) || 0\n const toolbarWidth = toolbar.clientWidth - paddingLeft - paddingRight\n\n // get child elements that are not path\n const children = Array.from(toolbar.children).filter((child) => child.id !== 'entity-path')\n // find total width of children including the gap between them\n const childrenWidth = Array.from(children).reduce(\n (acc, child) => acc + (child as HTMLElement).clientWidth,\n 0,\n )\n\n return toolbarWidth - childrenWidth - gap * (children.length - 1)\n}\n\nconst totalUpSegmentsWidth = (children: HTMLCollection, count: number, full: number) => {\n const skip = full - count\n let total = 0\n for (let i = 0; i < full - skip; i++) {\n const index = i > 1 ? i + skip : i\n const width = (children[index] as Element)?.clientWidth\n if (isNaN(width)) continue\n total += width\n }\n const gap = 4\n const moreWidth = 40\n return total + (gap * count - 1) + moreWidth\n}\n"],"names":["jsx","jsxs","Styled.Path","Styled.Segment","Fragment","Styled.MoreModal","Styled.MoreList","Styled.MoreItem","Styled.SegmentWrapper"],"mappings":"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"}
1
+ {"version":3,"file":"EntityPath.es.js","sources":["../../../../../src/components/EntityPath/EntityPath.tsx"],"sourcesContent":["import { FC, Fragment, MouseEvent, useLayoutEffect, useRef, useState } from 'react'\nimport * as Styled from './EntityPath.styled'\nimport clsx from 'clsx'\nimport SegmentProvider from './SegmentProvider'\nimport { Icon } from '@ynput/ayon-react-components'\nimport { DetailsPanelEntityType } from '@shared/api'\n\nconst Slash = () => <span className=\"slash\">/</span>\n\nexport type PathSegment = {\n type: DetailsPanelEntityType | 'product' | 'project'\n label: string\n id: string\n}\n\nconst dropdownStates = ['more', 'versions']\ntype DropdownState = (typeof dropdownStates)[number]\n\ntype DropdownMouseEvent = MouseEvent<HTMLSpanElement>\nconst getDropdownElements = (e: DropdownMouseEvent): [HTMLElement, string] => {\n const target = e.target as HTMLElement\n const dropdownId = target.closest('.dropdown')?.id || ''\n return [target, dropdownId]\n}\n\nexport interface EntityPathProps {\n projectName: string\n hideProjectName: boolean\n segments: PathSegment[]\n isLoading: boolean\n entityType: string\n versions: PathSegment[]\n scope: string\n}\n\nexport const EntityPath: FC<EntityPathProps> = ({\n projectName,\n hideProjectName,\n segments,\n versions = [],\n isLoading,\n entityType,\n scope,\n}) => {\n const containerRef = useRef<HTMLDivElement>(null)\n const [dropdownOpen, setDropdownOpen] = useState<null | DropdownState>(null)\n // defaults to whole path\n const [maxSegments, setMaxSegments] = useState<null | number>(null)\n const [calcMaxWidth, setCalcMaxWidth] = useState(false)\n const finalSegmentRef = useRef<HTMLSpanElement>(null)\n\n useLayoutEffect(() => {\n setMaxSegments(null)\n setCalcMaxWidth(true)\n }, [segments])\n\n useLayoutEffect(() => {\n if (!containerRef.current) {\n setCalcMaxWidth(false)\n return\n }\n // find max width the path can be\n const container = containerRef.current\n const pathWidth = container.clientWidth\n const maxWidth = getPathMaxWidth(container)\n\n if (!maxWidth) return\n\n // we need to reduce the number of segments shown\n // but maybe even then it is still longer than the max width\n // so we need to reduce the number of segments until the total width is less than the max width\n const children = container.children\n let totalWidth = pathWidth\n // number of segments to keep\n const fullCount = container.childElementCount\n let segmentsCount = fullCount\n // while loop that removes segments until the total width is less than the max width\n while (totalWidth > maxWidth && segmentsCount > 0) {\n // remove 2 segments at a time (because of slashes)\n segmentsCount -= 2\n totalWidth = totalUpSegmentsWidth(children, segmentsCount, fullCount)\n }\n\n // count number of \"full\" segments left\n // if something goes wrong, removing 1 (2) is probably enough\n let newMaxSegments =\n Array.from(children)\n .slice(0, segmentsCount)\n .filter(\n (segment) => segment.nodeType === Node.ELEMENT_NODE && segment.className.includes('full'),\n )?.length || 2\n\n // cap at 1\n newMaxSegments = Math.max(newMaxSegments, 1)\n\n setMaxSegments(newMaxSegments)\n setCalcMaxWidth(false)\n }, [containerRef.current, calcMaxWidth])\n\n // Ensure that, even if the collapsed segments still aren't\n // enough to fit the path within the available space,\n // we fit everything in by truncating the last segment's label.\n // This segment is typically the product + version name,\n // which is typically also shown in much larger font below,\n // so there's no reason to always show it in full.\n useLayoutEffect(() => {\n if (!containerRef.current || !finalSegmentRef.current || !maxSegments) return\n const container = containerRef.current\n\n // The amount of truncation is exactly the difference between the container's width\n // and the maximum available width.\n const maxWidth = getPathMaxWidth(container) ?? Infinity\n const diff = container.clientWidth - maxWidth\n if (diff <= 0) return\n\n // Reduce the segment's width by the difference\n const newWidth = `${finalSegmentRef.current.clientWidth - diff}px`\n finalSegmentRef.current.style.width = newWidth\n }, [maxSegments])\n\n // Check if there are fewer than or equal to maxSegments segments\n const segmentsToShow =\n maxSegments && segments.length > maxSegments ? segments.slice(-maxSegments) : segments\n const hiddenSegments =\n maxSegments && segments.length > maxSegments ? segments.slice(0, -maxSegments) : []\n\n // if there is no project name, add to hidden segments\n if (hideProjectName)\n hiddenSegments.unshift({ type: 'project', label: projectName, id: projectName })\n\n // if the entityType is a version, separate the version\n let versionSegment\n let finalSegmentsToShow = segmentsToShow\n\n if (entityType === 'version' && segments.length > 0) {\n versionSegment = segments[segments.length - 1]\n finalSegmentsToShow = segmentsToShow.slice(0, -1)\n }\n\n const handleMouseEnter = (e: DropdownMouseEvent) => {\n const [, id] = getDropdownElements(e)\n if (id && !dropdownOpen) setDropdownOpen(id)\n }\n const handleMouseLeave = () => setDropdownOpen(null)\n\n const handleDropdownClick = (e: DropdownMouseEvent) => {\n const [target, id] = getDropdownElements(e)\n\n if (!dropdownStates.includes(id)) return\n const isListItem = !!target.closest('li')\n\n if (isListItem) setDropdownOpen(null)\n else if (dropdownOpen !== id) setDropdownOpen(id)\n }\n\n const segmentProps = { scope, projectName }\n\n return (\n <Styled.Path className={clsx({ loading: isLoading })} id=\"entity-path\" ref={containerRef}>\n {!hideProjectName && <Styled.Segment>{projectName}</Styled.Segment>}\n\n {!!hiddenSegments.length && (\n <>\n {!hideProjectName && <Slash />}\n <Styled.Segment\n className=\"dropdown more\"\n id=\"more\"\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={handleDropdownClick}\n >\n ...\n {dropdownOpen === 'more' && (\n <Styled.MoreModal>\n <Styled.MoreList>\n {hiddenSegments.map((segment) => (\n <SegmentProvider {...segmentProps} segment={segment} key={segment.id}>\n <Styled.MoreItem>{segment.label}</Styled.MoreItem>\n </SegmentProvider>\n ))}\n </Styled.MoreList>\n </Styled.MoreModal>\n )}\n </Styled.Segment>\n </>\n )}\n\n {finalSegmentsToShow.map((segment) => (\n <Fragment key={segment.id}>\n <Slash />\n\n <SegmentProvider {...segmentProps} segment={segment} className=\"full\">\n <Styled.Segment>\n <span className=\"label\">{segment.label}</span>\n </Styled.Segment>\n </SegmentProvider>\n </Fragment>\n ))}\n\n {versionSegment && (\n <>\n <Slash />\n <Styled.SegmentWrapper\n className=\"full dropdown\"\n id=\"versions\"\n onMouseEnter={handleMouseEnter}\n onMouseLeave={handleMouseLeave}\n onClick={handleDropdownClick}\n >\n <SegmentProvider\n {...segmentProps}\n segment={versionSegment}\n isOpen={dropdownOpen === 'versions'}\n >\n <Styled.Segment>\n <Styled.FinalSegmentLabel ref={finalSegmentRef} className=\"label\">\n {versionSegment.label}\n </Styled.FinalSegmentLabel>\n <Icon icon=\"expand_more\" />\n </Styled.Segment>\n </SegmentProvider>\n {dropdownOpen === 'versions' && (\n <Styled.MoreModal>\n <Styled.MoreList>\n {versions.map((version) => (\n <SegmentProvider {...segmentProps} segment={version} key={version.id}>\n <Styled.MoreItem>{version.label}</Styled.MoreItem>\n </SegmentProvider>\n ))}\n </Styled.MoreList>\n </Styled.MoreModal>\n )}\n </Styled.SegmentWrapper>\n </>\n )}\n </Styled.Path>\n )\n}\n\nconst getPathMaxWidth = (pathEl: HTMLDivElement) => {\n const toolbar = pathEl.parentElement\n if (!toolbar) return\n // get width of toolbar without padding\n const toolbarStyle = getComputedStyle(toolbar)\n const paddingLeft = parseInt(toolbarStyle.paddingLeft) || 0\n const paddingRight = parseInt(toolbarStyle.paddingRight) || 0\n const gap = parseInt(toolbarStyle.gap) || 0\n const toolbarWidth = toolbar.clientWidth - paddingLeft - paddingRight\n\n // get child elements that are not path\n const children = Array.from(toolbar.children).filter((child) => child.id !== 'entity-path')\n // find total width of children including the gap between them\n const childrenWidth = Array.from(children).reduce(\n (acc, child) => acc + (child as HTMLElement).clientWidth,\n 0,\n )\n\n return toolbarWidth - childrenWidth - gap * (children.length - 1)\n}\n\nconst totalUpSegmentsWidth = (children: HTMLCollection, count: number, full: number) => {\n const skip = full - count\n let total = 0\n for (let i = 0; i < full - skip; i++) {\n const index = i > 1 ? i + skip : i\n const width = (children[index] as Element)?.clientWidth\n if (isNaN(width)) continue\n total += width\n }\n const gap = 4\n const moreWidth = 40\n return total + (gap * count - 1) + moreWidth\n}\n"],"names":["jsx","jsxs","Styled.Path","Styled.Segment","Fragment","Styled.MoreModal","Styled.MoreList","Styled.MoreItem","Styled.SegmentWrapper","Styled.FinalSegmentLabel"],"mappings":"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"}
@@ -24,7 +24,9 @@ const Segment = styled.span`
24
24
  position: relative;
25
25
  padding: 0px 2px;
26
26
  border-radius: var(--border-radius-m);
27
- transition: color 0.2s, background-color 0.2s;
27
+ transition:
28
+ color 0.2s,
29
+ background-color 0.2s;
28
30
  min-width: max-content;
29
31
 
30
32
  display: flex;
@@ -41,6 +43,12 @@ const Segment = styled.span`
41
43
  }
42
44
  }
43
45
  `;
46
+ const FinalSegmentLabel = styled.span`
47
+ text-overflow: ellipsis;
48
+ overflow: hidden;
49
+ display: inline-block;
50
+ white-space: nowrap;
51
+ `;
44
52
  const NotClickableHover = styled.css`
45
53
  background-color: var(--md-sys-color-surface-container);
46
54
  &,
@@ -106,6 +114,7 @@ const MoreItem = styled.li`
106
114
  width: 100%;
107
115
  `;
108
116
  exports.ActiveSegment = ActiveSegment;
117
+ exports.FinalSegmentLabel = FinalSegmentLabel;
109
118
  exports.MoreItem = MoreItem;
110
119
  exports.MoreList = MoreList;
111
120
  exports.MoreModal = MoreModal;
@@ -1 +1 @@
1
- {"version":3,"file":"EntityPath.styled.cjs.js","sources":["../../../../../src/components/EntityPath/EntityPath.styled.ts"],"sourcesContent":["import styled, { css } from 'styled-components'\n\nexport const Path = styled.div`\n position: relative;\n border-radius: var(--border-radius-m);\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--base-gap-small);\n user-select: none;\n height: 100%;\n &,\n .icon {\n color: var(--md-sys-color-outline);\n }\n\n flex: 1;\n`\n\nexport const SegmentWrapper = styled.div`\n position: relative;\n`\n\nexport const Segment = styled.span`\n position: relative;\n padding: 0px 2px;\n border-radius: var(--border-radius-m);\n transition: color 0.2s, background-color 0.2s;\n min-width: max-content;\n\n display: flex;\n align-items: center;\n\n /* ... styles */\n &.more {\n cursor: pointer;\n\n padding: 0px 6px;\n &:hover {\n background-color: var(--md-sys-color-surface-container);\n color: var(--md-sys-color-on-surface);\n }\n }\n`\n\nconst NotClickableHover = css`\n background-color: var(--md-sys-color-surface-container);\n &,\n .icon {\n color: var(--md-sys-color-on-surface);\n }\n`\n\nexport const ActiveSegment = styled.div`\n & > span,\n & > li {\n cursor: pointer;\n &:hover {\n ${NotClickableHover}\n }\n }\n\n &.open {\n & > span {\n ${NotClickableHover}\n }\n }\n\n &.link {\n & > span,\n & > li {\n &:hover {\n background-color: var(--md-sys-color-surface-container-highest-hover);\n }\n }\n }\n`\n\nexport const MoreModal = styled.div`\n position: absolute;\n top: 100%;\n left: 0px;\n width: 100%;\n min-width: fit-content;\n\n z-index: 200;\n padding-top: 4px;\n`\n\nexport const MoreList = styled.ul`\n display: flex;\n flex-direction: column;\n gap: var(--base-gap-small);\n\n background-color: var(--md-sys-color-surface-container-high);\n border-radius: var(--border-radius-m);\n box-shadow: var(--md-sys-shadow-elevation-4);\n padding: var(--padding-s);\n\n margin: 0;\n list-style: none;\n\n max-height: 500px;\n overflow: auto;\n`\n\nexport const MoreItem = styled.li`\n padding: var(--base-gap-small);\n border-radius: var(--border-radius-m);\n color: var(--md-sys-color-on-surface);\n min-width: max-content;\n width: 100%;\n`\n"],"names":["css"],"mappings":";;;AAEO,MAAM,OAAO,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBpB,MAAM,iBAAiB,OAAO;AAAA;AAAA;AAI9B,MAAM,UAAU,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsB9B,MAAM,oBAAoBA,OAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQnB,MAAM,gBAAgB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,QAK5B,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAclB,MAAM,YAAY,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWzB,MAAM,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBxB,MAAM,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;;;"}
1
+ {"version":3,"file":"EntityPath.styled.cjs.js","sources":["../../../../../src/components/EntityPath/EntityPath.styled.ts"],"sourcesContent":["import styled, { css } from 'styled-components'\n\nexport const Path = styled.div`\n position: relative;\n border-radius: var(--border-radius-m);\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--base-gap-small);\n user-select: none;\n height: 100%;\n &,\n .icon {\n color: var(--md-sys-color-outline);\n }\n\n flex: 1;\n`\n\nexport const SegmentWrapper = styled.div`\n position: relative;\n`\n\nexport const Segment = styled.span`\n position: relative;\n padding: 0px 2px;\n border-radius: var(--border-radius-m);\n transition:\n color 0.2s,\n background-color 0.2s;\n min-width: max-content;\n\n display: flex;\n align-items: center;\n\n /* ... styles */\n &.more {\n cursor: pointer;\n\n padding: 0px 6px;\n &:hover {\n background-color: var(--md-sys-color-surface-container);\n color: var(--md-sys-color-on-surface);\n }\n }\n`\n\nexport const FinalSegmentLabel = styled.span`\n text-overflow: ellipsis;\n overflow: hidden;\n display: inline-block;\n white-space: nowrap;\n`\n\nconst NotClickableHover = css`\n background-color: var(--md-sys-color-surface-container);\n &,\n .icon {\n color: var(--md-sys-color-on-surface);\n }\n`\n\nexport const ActiveSegment = styled.div`\n & > span,\n & > li {\n cursor: pointer;\n &:hover {\n ${NotClickableHover}\n }\n }\n\n &.open {\n & > span {\n ${NotClickableHover}\n }\n }\n\n &.link {\n & > span,\n & > li {\n &:hover {\n background-color: var(--md-sys-color-surface-container-highest-hover);\n }\n }\n }\n`\n\nexport const MoreModal = styled.div`\n position: absolute;\n top: 100%;\n left: 0px;\n width: 100%;\n min-width: fit-content;\n\n z-index: 200;\n padding-top: 4px;\n`\n\nexport const MoreList = styled.ul`\n display: flex;\n flex-direction: column;\n gap: var(--base-gap-small);\n\n background-color: var(--md-sys-color-surface-container-high);\n border-radius: var(--border-radius-m);\n box-shadow: var(--md-sys-shadow-elevation-4);\n padding: var(--padding-s);\n\n margin: 0;\n list-style: none;\n\n max-height: 500px;\n overflow: auto;\n`\n\nexport const MoreItem = styled.li`\n padding: var(--base-gap-small);\n border-radius: var(--border-radius-m);\n color: var(--md-sys-color-on-surface);\n min-width: max-content;\n width: 100%;\n`\n"],"names":["css"],"mappings":";;;AAEO,MAAM,OAAO,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBpB,MAAM,iBAAiB,OAAO;AAAA;AAAA;AAI9B,MAAM,UAAU,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBvB,MAAM,oBAAoB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAOxC,MAAM,oBAAoBA,OAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQnB,MAAM,gBAAgB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,QAK5B,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAclB,MAAM,YAAY,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWzB,MAAM,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBxB,MAAM,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;;;;;;;"}
@@ -22,7 +22,9 @@ const Segment = styled.span`
22
22
  position: relative;
23
23
  padding: 0px 2px;
24
24
  border-radius: var(--border-radius-m);
25
- transition: color 0.2s, background-color 0.2s;
25
+ transition:
26
+ color 0.2s,
27
+ background-color 0.2s;
26
28
  min-width: max-content;
27
29
 
28
30
  display: flex;
@@ -39,6 +41,12 @@ const Segment = styled.span`
39
41
  }
40
42
  }
41
43
  `;
44
+ const FinalSegmentLabel = styled.span`
45
+ text-overflow: ellipsis;
46
+ overflow: hidden;
47
+ display: inline-block;
48
+ white-space: nowrap;
49
+ `;
42
50
  const NotClickableHover = css`
43
51
  background-color: var(--md-sys-color-surface-container);
44
52
  &,
@@ -105,6 +113,7 @@ const MoreItem = styled.li`
105
113
  `;
106
114
  export {
107
115
  ActiveSegment,
116
+ FinalSegmentLabel,
108
117
  MoreItem,
109
118
  MoreList,
110
119
  MoreModal,
@@ -1 +1 @@
1
- {"version":3,"file":"EntityPath.styled.es.js","sources":["../../../../../src/components/EntityPath/EntityPath.styled.ts"],"sourcesContent":["import styled, { css } from 'styled-components'\n\nexport const Path = styled.div`\n position: relative;\n border-radius: var(--border-radius-m);\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--base-gap-small);\n user-select: none;\n height: 100%;\n &,\n .icon {\n color: var(--md-sys-color-outline);\n }\n\n flex: 1;\n`\n\nexport const SegmentWrapper = styled.div`\n position: relative;\n`\n\nexport const Segment = styled.span`\n position: relative;\n padding: 0px 2px;\n border-radius: var(--border-radius-m);\n transition: color 0.2s, background-color 0.2s;\n min-width: max-content;\n\n display: flex;\n align-items: center;\n\n /* ... styles */\n &.more {\n cursor: pointer;\n\n padding: 0px 6px;\n &:hover {\n background-color: var(--md-sys-color-surface-container);\n color: var(--md-sys-color-on-surface);\n }\n }\n`\n\nconst NotClickableHover = css`\n background-color: var(--md-sys-color-surface-container);\n &,\n .icon {\n color: var(--md-sys-color-on-surface);\n }\n`\n\nexport const ActiveSegment = styled.div`\n & > span,\n & > li {\n cursor: pointer;\n &:hover {\n ${NotClickableHover}\n }\n }\n\n &.open {\n & > span {\n ${NotClickableHover}\n }\n }\n\n &.link {\n & > span,\n & > li {\n &:hover {\n background-color: var(--md-sys-color-surface-container-highest-hover);\n }\n }\n }\n`\n\nexport const MoreModal = styled.div`\n position: absolute;\n top: 100%;\n left: 0px;\n width: 100%;\n min-width: fit-content;\n\n z-index: 200;\n padding-top: 4px;\n`\n\nexport const MoreList = styled.ul`\n display: flex;\n flex-direction: column;\n gap: var(--base-gap-small);\n\n background-color: var(--md-sys-color-surface-container-high);\n border-radius: var(--border-radius-m);\n box-shadow: var(--md-sys-shadow-elevation-4);\n padding: var(--padding-s);\n\n margin: 0;\n list-style: none;\n\n max-height: 500px;\n overflow: auto;\n`\n\nexport const MoreItem = styled.li`\n padding: var(--base-gap-small);\n border-radius: var(--border-radius-m);\n color: var(--md-sys-color-on-surface);\n min-width: max-content;\n width: 100%;\n`\n"],"names":[],"mappings":";AAEO,MAAM,OAAO,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBpB,MAAM,iBAAiB,OAAO;AAAA;AAAA;AAI9B,MAAM,UAAU,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAsB9B,MAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQnB,MAAM,gBAAgB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,QAK5B,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAclB,MAAM,YAAY,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWzB,MAAM,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBxB,MAAM,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;"}
1
+ {"version":3,"file":"EntityPath.styled.es.js","sources":["../../../../../src/components/EntityPath/EntityPath.styled.ts"],"sourcesContent":["import styled, { css } from 'styled-components'\n\nexport const Path = styled.div`\n position: relative;\n border-radius: var(--border-radius-m);\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: var(--base-gap-small);\n user-select: none;\n height: 100%;\n &,\n .icon {\n color: var(--md-sys-color-outline);\n }\n\n flex: 1;\n`\n\nexport const SegmentWrapper = styled.div`\n position: relative;\n`\n\nexport const Segment = styled.span`\n position: relative;\n padding: 0px 2px;\n border-radius: var(--border-radius-m);\n transition:\n color 0.2s,\n background-color 0.2s;\n min-width: max-content;\n\n display: flex;\n align-items: center;\n\n /* ... styles */\n &.more {\n cursor: pointer;\n\n padding: 0px 6px;\n &:hover {\n background-color: var(--md-sys-color-surface-container);\n color: var(--md-sys-color-on-surface);\n }\n }\n`\n\nexport const FinalSegmentLabel = styled.span`\n text-overflow: ellipsis;\n overflow: hidden;\n display: inline-block;\n white-space: nowrap;\n`\n\nconst NotClickableHover = css`\n background-color: var(--md-sys-color-surface-container);\n &,\n .icon {\n color: var(--md-sys-color-on-surface);\n }\n`\n\nexport const ActiveSegment = styled.div`\n & > span,\n & > li {\n cursor: pointer;\n &:hover {\n ${NotClickableHover}\n }\n }\n\n &.open {\n & > span {\n ${NotClickableHover}\n }\n }\n\n &.link {\n & > span,\n & > li {\n &:hover {\n background-color: var(--md-sys-color-surface-container-highest-hover);\n }\n }\n }\n`\n\nexport const MoreModal = styled.div`\n position: absolute;\n top: 100%;\n left: 0px;\n width: 100%;\n min-width: fit-content;\n\n z-index: 200;\n padding-top: 4px;\n`\n\nexport const MoreList = styled.ul`\n display: flex;\n flex-direction: column;\n gap: var(--base-gap-small);\n\n background-color: var(--md-sys-color-surface-container-high);\n border-radius: var(--border-radius-m);\n box-shadow: var(--md-sys-shadow-elevation-4);\n padding: var(--padding-s);\n\n margin: 0;\n list-style: none;\n\n max-height: 500px;\n overflow: auto;\n`\n\nexport const MoreItem = styled.li`\n padding: var(--base-gap-small);\n border-radius: var(--border-radius-m);\n color: var(--md-sys-color-on-surface);\n min-width: max-content;\n width: 100%;\n`\n"],"names":[],"mappings":";AAEO,MAAM,OAAO,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBpB,MAAM,iBAAiB,OAAO;AAAA;AAAA;AAI9B,MAAM,UAAU,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwBvB,MAAM,oBAAoB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAOxC,MAAM,oBAAoB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQnB,MAAM,gBAAgB,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA,QAK5B,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,QAMjB,iBAAiB;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAclB,MAAM,YAAY,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAWzB,MAAM,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAiBxB,MAAM,WAAW,OAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;"}
@@ -203,7 +203,6 @@ const RepresentationsList = ({ entities = [] }) => {
203
203
  ctxMenuShow(e.originalEvent, ctxMenuItems(id));
204
204
  }
205
205
  };
206
- if (!showDetail) return;
207
206
  return /* @__PURE__ */ jsxRuntime.jsxRuntimeExports.jsxs(jsxRuntime.jsxRuntimeExports.Fragment, { children: [
208
207
  /* @__PURE__ */ jsxRuntime.jsxRuntimeExports.jsx(ayonReactComponents.TablePanel, { children: /* @__PURE__ */ jsxRuntime.jsxRuntimeExports.jsx(
209
208
  treetable_esm.TreeTable,
@@ -230,7 +229,7 @@ const RepresentationsList = ({ entities = [] }) => {
230
229
  })
231
230
  }
232
231
  ) }),
233
- /* @__PURE__ */ jsxRuntime.jsxRuntimeExports.jsx(
232
+ showDetail && /* @__PURE__ */ jsxRuntime.jsxRuntimeExports.jsx(
234
233
  DetailsDialog.DetailsDialog,
235
234
  {
236
235
  projectName: showDetailProjectName,
@@ -1 +1 @@
1
- {"version":3,"file":"RepresentationsList.cjs.js","sources":["../../../../../src/containers/RepresentationsList/RepresentationsList.tsx"],"sourcesContent":["import { useMemo, useState } from 'react'\nimport { TablePanel } from '@ynput/ayon-react-components'\n\nimport { TreeTable } from 'primereact/treetable'\nimport { Column } from 'primereact/column'\n\nimport { groupResult } from '@shared/util'\nimport { useCreateContextMenu } from '@shared/containers/ContextMenu'\nimport { DetailsDialog } from '@shared/components'\nimport versionsToRepresentations from './versionsToRepresentations'\nimport { DetailsPanelEntityData } from '@shared/api'\n\nconst columns = [\n {\n field: 'name',\n header: 'Name',\n width: 90,\n expander: true,\n },\n {\n field: 'folderName',\n header: 'Folder',\n width: 130,\n },\n {\n field: 'productName',\n header: 'Product',\n width: 130,\n },\n {\n field: 'Product type',\n header: 'productType',\n width: 110,\n },\n]\n\ntype Props = {\n entities: DetailsPanelEntityData[]\n}\n\nexport const RepresentationsList = ({ entities = [] }: Props) => {\n // merge all entities data into one array of entities\n const representations = useMemo(() => versionsToRepresentations(entities) || [], [entities])\n\n const [showDetail, setShowDetail] = useState<false | string>(false)\n const showDetailProjectName = representations.find((rep) => rep.id === showDetail)?.projectName\n\n const [selected, setSelected] = useState<string[]>([])\n\n const data = useMemo(() => {\n // @ts-expect-error - groupResult is not typed\n return groupResult(representations, 'name')\n }, [representations])\n\n const onRepSelectionChange = (entityId: string) => {\n // set focused state\n setSelected([entityId])\n }\n\n const onRowClick = (e: any) => {\n onRepSelectionChange(e.node.data.id)\n }\n\n const ctxMenuItems = (id: string) => [\n {\n label: 'Representation detail',\n command: () => setShowDetail(id),\n icon: 'database',\n },\n ]\n\n const [ctxMenuShow] = useCreateContextMenu([])\n\n const handleContextMenu = (e: any) => {\n const id = e.node.data.id\n\n if (id) {\n // update focused representations\n onRepSelectionChange(id)\n // open context menu\n ctxMenuShow(e.originalEvent, ctxMenuItems(id))\n }\n }\n\n if (!showDetail) return\n\n return (\n <>\n <TablePanel>\n <TreeTable\n scrollable\n scrollHeight=\"100%\"\n value={data}\n emptyMessage=\"No representation found\"\n selectionMode=\"single\"\n selectionKeys={selected[0]}\n onRowClick={onRowClick}\n onContextMenu={handleContextMenu}\n >\n {columns.map((col) => {\n return (\n <Column\n key={col.field}\n field={col.field}\n header={col.header}\n expander={col.expander}\n style={{ width: col.width }}\n />\n )\n })}\n </TreeTable>\n </TablePanel>\n <DetailsDialog\n projectName={showDetailProjectName}\n entityType={'representation'}\n entityIds={[showDetail]}\n visible={!!showDetail}\n onHide={() => setShowDetail(false)}\n />\n </>\n )\n}\n"],"names":["useMemo","useState","groupResult","useCreateContextMenu","jsxs","Fragment","jsx","TablePanel","TreeTable","Column","DetailsDialog"],"mappings":"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"}
1
+ {"version":3,"file":"RepresentationsList.cjs.js","sources":["../../../../../src/containers/RepresentationsList/RepresentationsList.tsx"],"sourcesContent":["import { useMemo, useState } from 'react'\nimport { TablePanel } from '@ynput/ayon-react-components'\n\nimport { TreeTable } from 'primereact/treetable'\nimport { Column } from 'primereact/column'\n\nimport { groupResult } from '@shared/util'\nimport { useCreateContextMenu } from '@shared/containers/ContextMenu'\nimport { DetailsDialog } from '@shared/components'\nimport versionsToRepresentations from './versionsToRepresentations'\nimport { DetailsPanelEntityData } from '@shared/api'\n\nconst columns = [\n {\n field: 'name',\n header: 'Name',\n width: 90,\n expander: true,\n },\n {\n field: 'folderName',\n header: 'Folder',\n width: 130,\n },\n {\n field: 'productName',\n header: 'Product',\n width: 130,\n },\n {\n field: 'Product type',\n header: 'productType',\n width: 110,\n },\n]\n\ntype Props = {\n entities: DetailsPanelEntityData[]\n}\n\nexport const RepresentationsList = ({ entities = [] }: Props) => {\n // merge all entities data into one array of entities\n const representations = useMemo(() => versionsToRepresentations(entities) || [], [entities])\n\n const [showDetail, setShowDetail] = useState<false | string>(false)\n const showDetailProjectName = representations.find((rep) => rep.id === showDetail)?.projectName\n\n const [selected, setSelected] = useState<string[]>([])\n\n const data = useMemo(() => {\n // @ts-expect-error - groupResult is not typed\n return groupResult(representations, 'name')\n }, [representations])\n\n const onRepSelectionChange = (entityId: string) => {\n // set focused state\n setSelected([entityId])\n }\n\n const onRowClick = (e: any) => {\n onRepSelectionChange(e.node.data.id)\n }\n\n const ctxMenuItems = (id: string) => [\n {\n label: 'Representation detail',\n command: () => setShowDetail(id),\n icon: 'database',\n },\n ]\n\n const [ctxMenuShow] = useCreateContextMenu([])\n\n const handleContextMenu = (e: any) => {\n const id = e.node.data.id\n\n if (id) {\n // update focused representations\n onRepSelectionChange(id)\n // open context menu\n ctxMenuShow(e.originalEvent, ctxMenuItems(id))\n }\n }\n\n return (\n <>\n <TablePanel>\n <TreeTable\n scrollable\n scrollHeight=\"100%\"\n value={data}\n emptyMessage=\"No representation found\"\n selectionMode=\"single\"\n selectionKeys={selected[0]}\n onRowClick={onRowClick}\n onContextMenu={handleContextMenu}\n >\n {columns.map((col) => {\n return (\n <Column\n key={col.field}\n field={col.field}\n header={col.header}\n expander={col.expander}\n style={{ width: col.width }}\n />\n )\n })}\n </TreeTable>\n </TablePanel>\n\n {showDetail && (\n <DetailsDialog\n projectName={showDetailProjectName}\n entityType={'representation'}\n entityIds={[showDetail]}\n visible={!!showDetail}\n onHide={() => setShowDetail(false)}\n />\n )}\n </>\n )\n}\n"],"names":["useMemo","useState","groupResult","useCreateContextMenu","jsxs","Fragment","jsx","TablePanel","TreeTable","Column","DetailsDialog"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,MAAM,UAAU;AAAA,EACd;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,EAAA;AAEX;AAMO,MAAM,sBAAsB,CAAC,EAAE,WAAW,CAAA,QAAgB;;AAEzD,QAAA,kBAAkBA,MAAQ,QAAA,MAAM,0BAA0B,QAAQ,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;AAE3F,QAAM,CAAC,YAAY,aAAa,IAAIC,MAAAA,SAAyB,KAAK;AAC5D,QAAA,yBAAwB,qBAAgB,KAAK,CAAC,QAAQ,IAAI,OAAO,UAAU,MAAnD,mBAAsD;AAEpF,QAAM,CAAC,UAAU,WAAW,IAAIA,MAAAA,SAAmB,CAAA,CAAE;AAE/C,QAAA,OAAOD,MAAAA,QAAQ,MAAM;AAElB,WAAAE,YAAA,YAAY,iBAAiB,MAAM;AAAA,EAAA,GACzC,CAAC,eAAe,CAAC;AAEd,QAAA,uBAAuB,CAAC,aAAqB;AAErC,gBAAA,CAAC,QAAQ,CAAC;AAAA,EACxB;AAEM,QAAA,aAAa,CAAC,MAAW;AACR,yBAAA,EAAE,KAAK,KAAK,EAAE;AAAA,EACrC;AAEM,QAAA,eAAe,CAAC,OAAe;AAAA,IACnC;AAAA,MACE,OAAO;AAAA,MACP,SAAS,MAAM,cAAc,EAAE;AAAA,MAC/B,MAAM;AAAA,IAAA;AAAA,EAEV;AAEA,QAAM,CAAC,WAAW,IAAIC,qBAAA,qBAAqB,EAAE;AAEvC,QAAA,oBAAoB,CAAC,MAAW;AAC9B,UAAA,KAAK,EAAE,KAAK,KAAK;AAEvB,QAAI,IAAI;AAEN,2BAAqB,EAAE;AAEvB,kBAAY,EAAE,eAAe,aAAa,EAAE,CAAC;AAAA,IAAA;AAAA,EAEjD;AAEA,SAEIC,2BAAA,kBAAA,KAAAC,uCAAA,EAAA,UAAA;AAAA,IAAAC,iDAACC,oBAAAA,YACC,EAAA,UAAAD,2BAAA,kBAAA;AAAA,MAACE,cAAA;AAAA,MAAA;AAAA,QACC,YAAU;AAAA,QACV,cAAa;AAAA,QACb,OAAO;AAAA,QACP,cAAa;AAAA,QACb,eAAc;AAAA,QACd,eAAe,SAAS,CAAC;AAAA,QACzB;AAAA,QACA,eAAe;AAAA,QAEd,UAAA,QAAQ,IAAI,CAAC,QAAQ;AAElB,iBAAAF,2BAAA,kBAAA;AAAA,YAACG,WAAA;AAAA,YAAA;AAAA,cAEC,OAAO,IAAI;AAAA,cACX,QAAQ,IAAI;AAAA,cACZ,UAAU,IAAI;AAAA,cACd,OAAO,EAAE,OAAO,IAAI,MAAM;AAAA,YAAA;AAAA,YAJrB,IAAI;AAAA,UAKX;AAAA,QAEH,CAAA;AAAA,MAAA;AAAA,IAAA,GAEL;AAAA,IAEC,cACCH,2BAAA,kBAAA;AAAA,MAACI,cAAA;AAAA,MAAA;AAAA,QACC,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW,CAAC,UAAU;AAAA,QACtB,SAAS,CAAC,CAAC;AAAA,QACX,QAAQ,MAAM,cAAc,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EACnC,GAEJ;AAEJ;;"}
@@ -201,7 +201,6 @@ const RepresentationsList = ({ entities = [] }) => {
201
201
  ctxMenuShow(e.originalEvent, ctxMenuItems(id));
202
202
  }
203
203
  };
204
- if (!showDetail) return;
205
204
  return /* @__PURE__ */ jsxRuntimeExports.jsxs(jsxRuntimeExports.Fragment, { children: [
206
205
  /* @__PURE__ */ jsxRuntimeExports.jsx(TablePanel, { children: /* @__PURE__ */ jsxRuntimeExports.jsx(
207
206
  TreeTable,
@@ -228,7 +227,7 @@ const RepresentationsList = ({ entities = [] }) => {
228
227
  })
229
228
  }
230
229
  ) }),
231
- /* @__PURE__ */ jsxRuntimeExports.jsx(
230
+ showDetail && /* @__PURE__ */ jsxRuntimeExports.jsx(
232
231
  DetailsDialog,
233
232
  {
234
233
  projectName: showDetailProjectName,
@@ -1 +1 @@
1
- {"version":3,"file":"RepresentationsList.es.js","sources":["../../../../../src/containers/RepresentationsList/RepresentationsList.tsx"],"sourcesContent":["import { useMemo, useState } from 'react'\nimport { TablePanel } from '@ynput/ayon-react-components'\n\nimport { TreeTable } from 'primereact/treetable'\nimport { Column } from 'primereact/column'\n\nimport { groupResult } from '@shared/util'\nimport { useCreateContextMenu } from '@shared/containers/ContextMenu'\nimport { DetailsDialog } from '@shared/components'\nimport versionsToRepresentations from './versionsToRepresentations'\nimport { DetailsPanelEntityData } from '@shared/api'\n\nconst columns = [\n {\n field: 'name',\n header: 'Name',\n width: 90,\n expander: true,\n },\n {\n field: 'folderName',\n header: 'Folder',\n width: 130,\n },\n {\n field: 'productName',\n header: 'Product',\n width: 130,\n },\n {\n field: 'Product type',\n header: 'productType',\n width: 110,\n },\n]\n\ntype Props = {\n entities: DetailsPanelEntityData[]\n}\n\nexport const RepresentationsList = ({ entities = [] }: Props) => {\n // merge all entities data into one array of entities\n const representations = useMemo(() => versionsToRepresentations(entities) || [], [entities])\n\n const [showDetail, setShowDetail] = useState<false | string>(false)\n const showDetailProjectName = representations.find((rep) => rep.id === showDetail)?.projectName\n\n const [selected, setSelected] = useState<string[]>([])\n\n const data = useMemo(() => {\n // @ts-expect-error - groupResult is not typed\n return groupResult(representations, 'name')\n }, [representations])\n\n const onRepSelectionChange = (entityId: string) => {\n // set focused state\n setSelected([entityId])\n }\n\n const onRowClick = (e: any) => {\n onRepSelectionChange(e.node.data.id)\n }\n\n const ctxMenuItems = (id: string) => [\n {\n label: 'Representation detail',\n command: () => setShowDetail(id),\n icon: 'database',\n },\n ]\n\n const [ctxMenuShow] = useCreateContextMenu([])\n\n const handleContextMenu = (e: any) => {\n const id = e.node.data.id\n\n if (id) {\n // update focused representations\n onRepSelectionChange(id)\n // open context menu\n ctxMenuShow(e.originalEvent, ctxMenuItems(id))\n }\n }\n\n if (!showDetail) return\n\n return (\n <>\n <TablePanel>\n <TreeTable\n scrollable\n scrollHeight=\"100%\"\n value={data}\n emptyMessage=\"No representation found\"\n selectionMode=\"single\"\n selectionKeys={selected[0]}\n onRowClick={onRowClick}\n onContextMenu={handleContextMenu}\n >\n {columns.map((col) => {\n return (\n <Column\n key={col.field}\n field={col.field}\n header={col.header}\n expander={col.expander}\n style={{ width: col.width }}\n />\n )\n })}\n </TreeTable>\n </TablePanel>\n <DetailsDialog\n projectName={showDetailProjectName}\n entityType={'representation'}\n entityIds={[showDetail]}\n visible={!!showDetail}\n onHide={() => setShowDetail(false)}\n />\n </>\n )\n}\n"],"names":["jsxs","Fragment","jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,MAAM,UAAU;AAAA,EACd;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,EAAA;AAEX;AAMO,MAAM,sBAAsB,CAAC,EAAE,WAAW,CAAA,QAAgB;;AAEzD,QAAA,kBAAkB,QAAQ,MAAM,0BAA0B,QAAQ,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;AAE3F,QAAM,CAAC,YAAY,aAAa,IAAI,SAAyB,KAAK;AAC5D,QAAA,yBAAwB,qBAAgB,KAAK,CAAC,QAAQ,IAAI,OAAO,UAAU,MAAnD,mBAAsD;AAEpF,QAAM,CAAC,UAAU,WAAW,IAAI,SAAmB,CAAA,CAAE;AAE/C,QAAA,OAAO,QAAQ,MAAM;AAElB,WAAA,YAAY,iBAAiB,MAAM;AAAA,EAAA,GACzC,CAAC,eAAe,CAAC;AAEd,QAAA,uBAAuB,CAAC,aAAqB;AAErC,gBAAA,CAAC,QAAQ,CAAC;AAAA,EACxB;AAEM,QAAA,aAAa,CAAC,MAAW;AACR,yBAAA,EAAE,KAAK,KAAK,EAAE;AAAA,EACrC;AAEM,QAAA,eAAe,CAAC,OAAe;AAAA,IACnC;AAAA,MACE,OAAO;AAAA,MACP,SAAS,MAAM,cAAc,EAAE;AAAA,MAC/B,MAAM;AAAA,IAAA;AAAA,EAEV;AAEA,QAAM,CAAC,WAAW,IAAI,qBAAqB,EAAE;AAEvC,QAAA,oBAAoB,CAAC,MAAW;AAC9B,UAAA,KAAK,EAAE,KAAK,KAAK;AAEvB,QAAI,IAAI;AAEN,2BAAqB,EAAE;AAEvB,kBAAY,EAAE,eAAe,aAAa,EAAE,CAAC;AAAA,IAAA;AAAA,EAEjD;AAEA,MAAI,CAAC,WAAY;AAEjB,SAEIA,kCAAA,KAAAC,4BAAA,EAAA,UAAA;AAAA,IAAAC,sCAAC,YACC,EAAA,UAAAA,kCAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,YAAU;AAAA,QACV,cAAa;AAAA,QACb,OAAO;AAAA,QACP,cAAa;AAAA,QACb,eAAc;AAAA,QACd,eAAe,SAAS,CAAC;AAAA,QACzB;AAAA,QACA,eAAe;AAAA,QAEd,UAAA,QAAQ,IAAI,CAAC,QAAQ;AAElB,iBAAAA,kCAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,OAAO,IAAI;AAAA,cACX,QAAQ,IAAI;AAAA,cACZ,UAAU,IAAI;AAAA,cACd,OAAO,EAAE,OAAO,IAAI,MAAM;AAAA,YAAA;AAAA,YAJrB,IAAI;AAAA,UAKX;AAAA,QAEH,CAAA;AAAA,MAAA;AAAA,IAAA,GAEL;AAAA,IACAA,kCAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW,CAAC,UAAU;AAAA,QACtB,SAAS,CAAC,CAAC;AAAA,QACX,QAAQ,MAAM,cAAc,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EACnC,GACF;AAEJ;"}
1
+ {"version":3,"file":"RepresentationsList.es.js","sources":["../../../../../src/containers/RepresentationsList/RepresentationsList.tsx"],"sourcesContent":["import { useMemo, useState } from 'react'\nimport { TablePanel } from '@ynput/ayon-react-components'\n\nimport { TreeTable } from 'primereact/treetable'\nimport { Column } from 'primereact/column'\n\nimport { groupResult } from '@shared/util'\nimport { useCreateContextMenu } from '@shared/containers/ContextMenu'\nimport { DetailsDialog } from '@shared/components'\nimport versionsToRepresentations from './versionsToRepresentations'\nimport { DetailsPanelEntityData } from '@shared/api'\n\nconst columns = [\n {\n field: 'name',\n header: 'Name',\n width: 90,\n expander: true,\n },\n {\n field: 'folderName',\n header: 'Folder',\n width: 130,\n },\n {\n field: 'productName',\n header: 'Product',\n width: 130,\n },\n {\n field: 'Product type',\n header: 'productType',\n width: 110,\n },\n]\n\ntype Props = {\n entities: DetailsPanelEntityData[]\n}\n\nexport const RepresentationsList = ({ entities = [] }: Props) => {\n // merge all entities data into one array of entities\n const representations = useMemo(() => versionsToRepresentations(entities) || [], [entities])\n\n const [showDetail, setShowDetail] = useState<false | string>(false)\n const showDetailProjectName = representations.find((rep) => rep.id === showDetail)?.projectName\n\n const [selected, setSelected] = useState<string[]>([])\n\n const data = useMemo(() => {\n // @ts-expect-error - groupResult is not typed\n return groupResult(representations, 'name')\n }, [representations])\n\n const onRepSelectionChange = (entityId: string) => {\n // set focused state\n setSelected([entityId])\n }\n\n const onRowClick = (e: any) => {\n onRepSelectionChange(e.node.data.id)\n }\n\n const ctxMenuItems = (id: string) => [\n {\n label: 'Representation detail',\n command: () => setShowDetail(id),\n icon: 'database',\n },\n ]\n\n const [ctxMenuShow] = useCreateContextMenu([])\n\n const handleContextMenu = (e: any) => {\n const id = e.node.data.id\n\n if (id) {\n // update focused representations\n onRepSelectionChange(id)\n // open context menu\n ctxMenuShow(e.originalEvent, ctxMenuItems(id))\n }\n }\n\n return (\n <>\n <TablePanel>\n <TreeTable\n scrollable\n scrollHeight=\"100%\"\n value={data}\n emptyMessage=\"No representation found\"\n selectionMode=\"single\"\n selectionKeys={selected[0]}\n onRowClick={onRowClick}\n onContextMenu={handleContextMenu}\n >\n {columns.map((col) => {\n return (\n <Column\n key={col.field}\n field={col.field}\n header={col.header}\n expander={col.expander}\n style={{ width: col.width }}\n />\n )\n })}\n </TreeTable>\n </TablePanel>\n\n {showDetail && (\n <DetailsDialog\n projectName={showDetailProjectName}\n entityType={'representation'}\n entityIds={[showDetail]}\n visible={!!showDetail}\n onHide={() => setShowDetail(false)}\n />\n )}\n </>\n )\n}\n"],"names":["jsxs","Fragment","jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,MAAM,UAAU;AAAA,EACd;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,UAAU;AAAA,EACZ;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,EACT;AAAA,EACA;AAAA,IACE,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,EAAA;AAEX;AAMO,MAAM,sBAAsB,CAAC,EAAE,WAAW,CAAA,QAAgB;;AAEzD,QAAA,kBAAkB,QAAQ,MAAM,0BAA0B,QAAQ,KAAK,CAAC,GAAG,CAAC,QAAQ,CAAC;AAE3F,QAAM,CAAC,YAAY,aAAa,IAAI,SAAyB,KAAK;AAC5D,QAAA,yBAAwB,qBAAgB,KAAK,CAAC,QAAQ,IAAI,OAAO,UAAU,MAAnD,mBAAsD;AAEpF,QAAM,CAAC,UAAU,WAAW,IAAI,SAAmB,CAAA,CAAE;AAE/C,QAAA,OAAO,QAAQ,MAAM;AAElB,WAAA,YAAY,iBAAiB,MAAM;AAAA,EAAA,GACzC,CAAC,eAAe,CAAC;AAEd,QAAA,uBAAuB,CAAC,aAAqB;AAErC,gBAAA,CAAC,QAAQ,CAAC;AAAA,EACxB;AAEM,QAAA,aAAa,CAAC,MAAW;AACR,yBAAA,EAAE,KAAK,KAAK,EAAE;AAAA,EACrC;AAEM,QAAA,eAAe,CAAC,OAAe;AAAA,IACnC;AAAA,MACE,OAAO;AAAA,MACP,SAAS,MAAM,cAAc,EAAE;AAAA,MAC/B,MAAM;AAAA,IAAA;AAAA,EAEV;AAEA,QAAM,CAAC,WAAW,IAAI,qBAAqB,EAAE;AAEvC,QAAA,oBAAoB,CAAC,MAAW;AAC9B,UAAA,KAAK,EAAE,KAAK,KAAK;AAEvB,QAAI,IAAI;AAEN,2BAAqB,EAAE;AAEvB,kBAAY,EAAE,eAAe,aAAa,EAAE,CAAC;AAAA,IAAA;AAAA,EAEjD;AAEA,SAEIA,kCAAA,KAAAC,4BAAA,EAAA,UAAA;AAAA,IAAAC,sCAAC,YACC,EAAA,UAAAA,kCAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,YAAU;AAAA,QACV,cAAa;AAAA,QACb,OAAO;AAAA,QACP,cAAa;AAAA,QACb,eAAc;AAAA,QACd,eAAe,SAAS,CAAC;AAAA,QACzB;AAAA,QACA,eAAe;AAAA,QAEd,UAAA,QAAQ,IAAI,CAAC,QAAQ;AAElB,iBAAAA,kCAAA;AAAA,YAAC;AAAA,YAAA;AAAA,cAEC,OAAO,IAAI;AAAA,cACX,QAAQ,IAAI;AAAA,cACZ,UAAU,IAAI;AAAA,cACd,OAAO,EAAE,OAAO,IAAI,MAAM;AAAA,YAAA;AAAA,YAJrB,IAAI;AAAA,UAKX;AAAA,QAEH,CAAA;AAAA,MAAA;AAAA,IAAA,GAEL;AAAA,IAEC,cACCA,kCAAA;AAAA,MAAC;AAAA,MAAA;AAAA,QACC,aAAa;AAAA,QACb,YAAY;AAAA,QACZ,WAAW,CAAC,UAAU;AAAA,QACtB,SAAS,CAAC,CAAC;AAAA,QACX,QAAQ,MAAM,cAAc,KAAK;AAAA,MAAA;AAAA,IAAA;AAAA,EACnC,GAEJ;AAEJ;"}
@@ -98,7 +98,7 @@ const RemoteModulesProvider = ({ children, skip }) => {
98
98
  return {
99
99
  name: r.remote,
100
100
  alias: r.remote,
101
- entry: `/addons/${r.addon || r.remote}/${r.version}/frontend/modules/${r.remote}/remoteEntry.js?server=${(_a = info == null ? void 0 : info.releaseInfo) == null ? void 0 : _a.version}-${(_b = info == null ? void 0 : info.releaseInfo) == null ? void 0 : _b.buildDate}`,
101
+ entry: `/addons/${r.addon || r.remote}/${r.version}/frontend/modules/${r.remote}/remoteEntry.js?server=${((_a = info == null ? void 0 : info.releaseInfo) == null ? void 0 : _a.version) || (info == null ? void 0 : info.releaseInfo)}-${(_b = info == null ? void 0 : info.releaseInfo) == null ? void 0 : _b.buildDate}-${(/* @__PURE__ */ new Date()).getTime()}`,
102
102
  type: "module"
103
103
  };
104
104
  })
@@ -1 +1 @@
1
- {"version":3,"file":"RemoteModulesContext.cjs.js","sources":["../../../../src/context/RemoteModulesContext.tsx"],"sourcesContent":["import { createContext, useContext, ReactNode, useEffect, useState } from 'react'\nimport { registerRemotes } from '@module-federation/enhanced/runtime'\nimport {\n FrontendModuleListItem,\n useListFrontendModulesQuery,\n useGetSiteInfoQuery,\n} from '@shared/api'\n\ntype Module = {\n remote: string\n addon: string\n version: string\n modules: string[]\n}\n\ntype RemoteModulesContextType = {\n isLoading: boolean\n modules: FrontendModuleListItem[]\n remotesInitialized: boolean\n}\n\nconst RemoteModulesContext = createContext<RemoteModulesContextType>({\n isLoading: true,\n modules: [],\n remotesInitialized: false,\n})\n\ntype Props = {\n children: ReactNode\n skip?: boolean\n}\n\nexport const RemoteModulesProvider = ({ children, skip }: Props) => {\n // only load if logged in\n const { data: addonRemoteModules = [], isLoading } = useListFrontendModulesQuery(undefined, {\n skip,\n })\n\n const { data: info = {}, isLoading: isLoadingInfo } = useGetSiteInfoQuery(\n { full: true },\n { skip },\n )\n\n const [remotesInitialized, setRemotesInitialized] = useState(false)\n\n useEffect(() => {\n if (isLoading || !addonRemoteModules.length || isLoadingInfo || remotesInitialized) return\n\n // create a flat map of modules to load\n const allRemotes: Module[] = []\n\n addonRemoteModules.forEach((addon) => {\n const { addonName, addonVersion, modules = {} } = addon\n\n Object.entries(modules).forEach(([remote, modules]) => {\n allRemotes.push({\n remote,\n addon: addonName,\n version: addonVersion,\n modules,\n })\n })\n })\n\n console.log('registerAddonRemotes', allRemotes)\n registerRemotes(\n allRemotes.map((r) => ({\n name: r.remote,\n alias: r.remote,\n entry: `/addons/${r.addon || r.remote}/${r.version}/frontend/modules/${\n r.remote\n }/remoteEntry.js?server=${info?.releaseInfo?.version}-${info?.releaseInfo?.buildDate}`,\n type: 'module',\n })),\n )\n\n setRemotesInitialized(true)\n }, [addonRemoteModules, isLoading, isLoadingInfo, remotesInitialized])\n\n return (\n <RemoteModulesContext.Provider\n value={{\n isLoading,\n modules: addonRemoteModules,\n remotesInitialized,\n }}\n >\n {children}\n </RemoteModulesContext.Provider>\n )\n}\n\nexport const useRemoteModules = () => {\n const context = useContext(RemoteModulesContext)\n\n if (context === undefined) {\n throw new Error('useRemoteModules must be used within a RemoteModulesProvider')\n }\n\n return context\n}\n"],"names":["createContext","useListFrontendModulesQuery","useGetSiteInfoQuery","useState","useEffect","modules","registerRemotes","jsx","useContext"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,MAAM,uBAAuBA,MAAAA,cAAwC;AAAA,EACnE,WAAW;AAAA,EACX,SAAS,CAAC;AAAA,EACV,oBAAoB;AACtB,CAAC;AAOM,MAAM,wBAAwB,CAAC,EAAE,UAAU,WAAkB;AAE5D,QAAA,EAAE,MAAM,qBAAqB,CAAA,GAAI,UAAU,IAAIC,sCAA4B,QAAW;AAAA,IAC1F;AAAA,EAAA,CACD;AAED,QAAM,EAAE,MAAM,OAAO,CAAI,GAAA,WAAW,kBAAkBC,UAAA;AAAA,IACpD,EAAE,MAAM,KAAK;AAAA,IACb,EAAE,KAAK;AAAA,EACT;AAEA,QAAM,CAAC,oBAAoB,qBAAqB,IAAIC,MAAAA,SAAS,KAAK;AAElEC,QAAAA,UAAU,MAAM;AACd,QAAI,aAAa,CAAC,mBAAmB,UAAU,iBAAiB,mBAAoB;AAGpF,UAAM,aAAuB,CAAC;AAEX,uBAAA,QAAQ,CAAC,UAAU;AACpC,YAAM,EAAE,WAAW,cAAc,UAAU,CAAA,EAAO,IAAA;AAE3C,aAAA,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQC,QAAO,MAAM;AACrD,mBAAW,KAAK;AAAA,UACd;AAAA,UACA,OAAO;AAAA,UACP,SAAS;AAAA,UACT,SAAAA;AAAAA,QAAA,CACD;AAAA,MAAA,CACF;AAAA,IAAA,CACF;AAEO,YAAA,IAAI,wBAAwB,UAAU;AAC9CC,YAAA,eAAA;AAAA,MACE,WAAW,IAAI,CAAC,MAAO;;AAAA;AAAA,UACrB,MAAM,EAAE;AAAA,UACR,OAAO,EAAE;AAAA,UACT,OAAO,WAAW,EAAE,SAAS,EAAE,MAAM,IAAI,EAAE,OAAO,qBAChD,EAAE,MACJ,2BAA0B,kCAAM,gBAAN,mBAAmB,OAAO,KAAI,kCAAM,gBAAN,mBAAmB,SAAS;AAAA,UACpF,MAAM;AAAA,QAAA;AAAA,OACN;AAAA,IACJ;AAEA,0BAAsB,IAAI;AAAA,KACzB,CAAC,oBAAoB,WAAW,eAAe,kBAAkB,CAAC;AAGnE,SAAAC,2BAAA,kBAAA;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC,OAAO;AAAA,QACL;AAAA,QACA,SAAS;AAAA,QACT;AAAA,MACF;AAAA,MAEC;AAAA,IAAA;AAAA,EACH;AAEJ;AAEO,MAAM,mBAAmB,MAAM;AAC9B,QAAA,UAAUC,iBAAW,oBAAoB;AAE/C,MAAI,YAAY,QAAW;AACnB,UAAA,IAAI,MAAM,8DAA8D;AAAA,EAAA;AAGzE,SAAA;AACT;;;"}
1
+ {"version":3,"file":"RemoteModulesContext.cjs.js","sources":["../../../../src/context/RemoteModulesContext.tsx"],"sourcesContent":["import { createContext, useContext, ReactNode, useEffect, useState } from 'react'\nimport { registerRemotes } from '@module-federation/enhanced/runtime'\nimport {\n FrontendModuleListItem,\n useListFrontendModulesQuery,\n useGetSiteInfoQuery,\n} from '@shared/api'\n\ntype Module = {\n remote: string\n addon: string\n version: string\n modules: string[]\n}\n\ntype RemoteModulesContextType = {\n isLoading: boolean\n modules: FrontendModuleListItem[]\n remotesInitialized: boolean\n}\n\nconst RemoteModulesContext = createContext<RemoteModulesContextType>({\n isLoading: true,\n modules: [],\n remotesInitialized: false,\n})\n\ntype Props = {\n children: ReactNode\n skip?: boolean\n}\n\nexport const RemoteModulesProvider = ({ children, skip }: Props) => {\n // only load if logged in\n const { data: addonRemoteModules = [], isLoading } = useListFrontendModulesQuery(undefined, {\n skip,\n })\n\n const { data: info = {}, isLoading: isLoadingInfo } = useGetSiteInfoQuery(\n { full: true },\n { skip },\n )\n\n const [remotesInitialized, setRemotesInitialized] = useState(false)\n\n useEffect(() => {\n if (isLoading || !addonRemoteModules.length || isLoadingInfo || remotesInitialized) return\n\n // create a flat map of modules to load\n const allRemotes: Module[] = []\n\n addonRemoteModules.forEach((addon) => {\n const { addonName, addonVersion, modules = {} } = addon\n\n Object.entries(modules).forEach(([remote, modules]) => {\n allRemotes.push({\n remote,\n addon: addonName,\n version: addonVersion,\n modules,\n })\n })\n })\n\n console.log('registerAddonRemotes', allRemotes)\n registerRemotes(\n allRemotes.map((r) => ({\n name: r.remote,\n alias: r.remote,\n entry: `/addons/${r.addon || r.remote}/${r.version}/frontend/modules/${\n r.remote\n }/remoteEntry.js?server=${info?.releaseInfo?.version || info?.releaseInfo}-${\n info?.releaseInfo?.buildDate\n }-${new Date().getTime()}`,\n type: 'module',\n })),\n )\n\n setRemotesInitialized(true)\n }, [addonRemoteModules, isLoading, isLoadingInfo, remotesInitialized])\n\n return (\n <RemoteModulesContext.Provider\n value={{\n isLoading,\n modules: addonRemoteModules,\n remotesInitialized,\n }}\n >\n {children}\n </RemoteModulesContext.Provider>\n )\n}\n\nexport const useRemoteModules = () => {\n const context = useContext(RemoteModulesContext)\n\n if (context === undefined) {\n throw new Error('useRemoteModules must be used within a RemoteModulesProvider')\n }\n\n return context\n}\n"],"names":["createContext","useListFrontendModulesQuery","useGetSiteInfoQuery","useState","useEffect","modules","registerRemotes","jsx","useContext"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,MAAM,uBAAuBA,MAAAA,cAAwC;AAAA,EACnE,WAAW;AAAA,EACX,SAAS,CAAC;AAAA,EACV,oBAAoB;AACtB,CAAC;AAOM,MAAM,wBAAwB,CAAC,EAAE,UAAU,WAAkB;AAE5D,QAAA,EAAE,MAAM,qBAAqB,CAAA,GAAI,UAAU,IAAIC,sCAA4B,QAAW;AAAA,IAC1F;AAAA,EAAA,CACD;AAED,QAAM,EAAE,MAAM,OAAO,CAAI,GAAA,WAAW,kBAAkBC,UAAA;AAAA,IACpD,EAAE,MAAM,KAAK;AAAA,IACb,EAAE,KAAK;AAAA,EACT;AAEA,QAAM,CAAC,oBAAoB,qBAAqB,IAAIC,MAAAA,SAAS,KAAK;AAElEC,QAAAA,UAAU,MAAM;AACd,QAAI,aAAa,CAAC,mBAAmB,UAAU,iBAAiB,mBAAoB;AAGpF,UAAM,aAAuB,CAAC;AAEX,uBAAA,QAAQ,CAAC,UAAU;AACpC,YAAM,EAAE,WAAW,cAAc,UAAU,CAAA,EAAO,IAAA;AAE3C,aAAA,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQC,QAAO,MAAM;AACrD,mBAAW,KAAK;AAAA,UACd;AAAA,UACA,OAAO;AAAA,UACP,SAAS;AAAA,UACT,SAAAA;AAAAA,QAAA,CACD;AAAA,MAAA,CACF;AAAA,IAAA,CACF;AAEO,YAAA,IAAI,wBAAwB,UAAU;AAC9CC,YAAA,eAAA;AAAA,MACE,WAAW,IAAI,CAAC,MAAO;;AAAA;AAAA,UACrB,MAAM,EAAE;AAAA,UACR,OAAO,EAAE;AAAA,UACT,OAAO,WAAW,EAAE,SAAS,EAAE,MAAM,IAAI,EAAE,OAAO,qBAChD,EAAE,MACJ,4BAA0B,kCAAM,gBAAN,mBAAmB,aAAW,6BAAM,YAAW,KACvE,kCAAM,gBAAN,mBAAmB,SACrB,KAAQ,oBAAA,KAAA,GAAO,QAAS,CAAA;AAAA,UACxB,MAAM;AAAA,QAAA;AAAA,OACN;AAAA,IACJ;AAEA,0BAAsB,IAAI;AAAA,KACzB,CAAC,oBAAoB,WAAW,eAAe,kBAAkB,CAAC;AAGnE,SAAAC,2BAAA,kBAAA;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC,OAAO;AAAA,QACL;AAAA,QACA,SAAS;AAAA,QACT;AAAA,MACF;AAAA,MAEC;AAAA,IAAA;AAAA,EACH;AAEJ;AAEO,MAAM,mBAAmB,MAAM;AAC9B,QAAA,UAAUC,iBAAW,oBAAoB;AAE/C,MAAI,YAAY,QAAW;AACnB,UAAA,IAAI,MAAM,8DAA8D;AAAA,EAAA;AAGzE,SAAA;AACT;;;"}
@@ -96,7 +96,7 @@ const RemoteModulesProvider = ({ children, skip }) => {
96
96
  return {
97
97
  name: r.remote,
98
98
  alias: r.remote,
99
- entry: `/addons/${r.addon || r.remote}/${r.version}/frontend/modules/${r.remote}/remoteEntry.js?server=${(_a = info == null ? void 0 : info.releaseInfo) == null ? void 0 : _a.version}-${(_b = info == null ? void 0 : info.releaseInfo) == null ? void 0 : _b.buildDate}`,
99
+ entry: `/addons/${r.addon || r.remote}/${r.version}/frontend/modules/${r.remote}/remoteEntry.js?server=${((_a = info == null ? void 0 : info.releaseInfo) == null ? void 0 : _a.version) || (info == null ? void 0 : info.releaseInfo)}-${(_b = info == null ? void 0 : info.releaseInfo) == null ? void 0 : _b.buildDate}-${(/* @__PURE__ */ new Date()).getTime()}`,
100
100
  type: "module"
101
101
  };
102
102
  })
@@ -1 +1 @@
1
- {"version":3,"file":"RemoteModulesContext.es.js","sources":["../../../../src/context/RemoteModulesContext.tsx"],"sourcesContent":["import { createContext, useContext, ReactNode, useEffect, useState } from 'react'\nimport { registerRemotes } from '@module-federation/enhanced/runtime'\nimport {\n FrontendModuleListItem,\n useListFrontendModulesQuery,\n useGetSiteInfoQuery,\n} from '@shared/api'\n\ntype Module = {\n remote: string\n addon: string\n version: string\n modules: string[]\n}\n\ntype RemoteModulesContextType = {\n isLoading: boolean\n modules: FrontendModuleListItem[]\n remotesInitialized: boolean\n}\n\nconst RemoteModulesContext = createContext<RemoteModulesContextType>({\n isLoading: true,\n modules: [],\n remotesInitialized: false,\n})\n\ntype Props = {\n children: ReactNode\n skip?: boolean\n}\n\nexport const RemoteModulesProvider = ({ children, skip }: Props) => {\n // only load if logged in\n const { data: addonRemoteModules = [], isLoading } = useListFrontendModulesQuery(undefined, {\n skip,\n })\n\n const { data: info = {}, isLoading: isLoadingInfo } = useGetSiteInfoQuery(\n { full: true },\n { skip },\n )\n\n const [remotesInitialized, setRemotesInitialized] = useState(false)\n\n useEffect(() => {\n if (isLoading || !addonRemoteModules.length || isLoadingInfo || remotesInitialized) return\n\n // create a flat map of modules to load\n const allRemotes: Module[] = []\n\n addonRemoteModules.forEach((addon) => {\n const { addonName, addonVersion, modules = {} } = addon\n\n Object.entries(modules).forEach(([remote, modules]) => {\n allRemotes.push({\n remote,\n addon: addonName,\n version: addonVersion,\n modules,\n })\n })\n })\n\n console.log('registerAddonRemotes', allRemotes)\n registerRemotes(\n allRemotes.map((r) => ({\n name: r.remote,\n alias: r.remote,\n entry: `/addons/${r.addon || r.remote}/${r.version}/frontend/modules/${\n r.remote\n }/remoteEntry.js?server=${info?.releaseInfo?.version}-${info?.releaseInfo?.buildDate}`,\n type: 'module',\n })),\n )\n\n setRemotesInitialized(true)\n }, [addonRemoteModules, isLoading, isLoadingInfo, remotesInitialized])\n\n return (\n <RemoteModulesContext.Provider\n value={{\n isLoading,\n modules: addonRemoteModules,\n remotesInitialized,\n }}\n >\n {children}\n </RemoteModulesContext.Provider>\n )\n}\n\nexport const useRemoteModules = () => {\n const context = useContext(RemoteModulesContext)\n\n if (context === undefined) {\n throw new Error('useRemoteModules must be used within a RemoteModulesProvider')\n }\n\n return context\n}\n"],"names":["modules","registerRemotes","jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,MAAM,uBAAuB,cAAwC;AAAA,EACnE,WAAW;AAAA,EACX,SAAS,CAAC;AAAA,EACV,oBAAoB;AACtB,CAAC;AAOM,MAAM,wBAAwB,CAAC,EAAE,UAAU,WAAkB;AAE5D,QAAA,EAAE,MAAM,qBAAqB,CAAA,GAAI,UAAU,IAAI,4BAA4B,QAAW;AAAA,IAC1F;AAAA,EAAA,CACD;AAED,QAAM,EAAE,MAAM,OAAO,CAAI,GAAA,WAAW,kBAAkB;AAAA,IACpD,EAAE,MAAM,KAAK;AAAA,IACb,EAAE,KAAK;AAAA,EACT;AAEA,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAS,KAAK;AAElE,YAAU,MAAM;AACd,QAAI,aAAa,CAAC,mBAAmB,UAAU,iBAAiB,mBAAoB;AAGpF,UAAM,aAAuB,CAAC;AAEX,uBAAA,QAAQ,CAAC,UAAU;AACpC,YAAM,EAAE,WAAW,cAAc,UAAU,CAAA,EAAO,IAAA;AAE3C,aAAA,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQA,QAAO,MAAM;AACrD,mBAAW,KAAK;AAAA,UACd;AAAA,UACA,OAAO;AAAA,UACP,SAAS;AAAA,UACT,SAAAA;AAAAA,QAAA,CACD;AAAA,MAAA,CACF;AAAA,IAAA,CACF;AAEO,YAAA,IAAI,wBAAwB,UAAU;AAC9CC,mBAAA;AAAA,MACE,WAAW,IAAI,CAAC,MAAO;;AAAA;AAAA,UACrB,MAAM,EAAE;AAAA,UACR,OAAO,EAAE;AAAA,UACT,OAAO,WAAW,EAAE,SAAS,EAAE,MAAM,IAAI,EAAE,OAAO,qBAChD,EAAE,MACJ,2BAA0B,kCAAM,gBAAN,mBAAmB,OAAO,KAAI,kCAAM,gBAAN,mBAAmB,SAAS;AAAA,UACpF,MAAM;AAAA,QAAA;AAAA,OACN;AAAA,IACJ;AAEA,0BAAsB,IAAI;AAAA,KACzB,CAAC,oBAAoB,WAAW,eAAe,kBAAkB,CAAC;AAGnE,SAAAC,kCAAA;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC,OAAO;AAAA,QACL;AAAA,QACA,SAAS;AAAA,QACT;AAAA,MACF;AAAA,MAEC;AAAA,IAAA;AAAA,EACH;AAEJ;AAEO,MAAM,mBAAmB,MAAM;AAC9B,QAAA,UAAU,WAAW,oBAAoB;AAE/C,MAAI,YAAY,QAAW;AACnB,UAAA,IAAI,MAAM,8DAA8D;AAAA,EAAA;AAGzE,SAAA;AACT;"}
1
+ {"version":3,"file":"RemoteModulesContext.es.js","sources":["../../../../src/context/RemoteModulesContext.tsx"],"sourcesContent":["import { createContext, useContext, ReactNode, useEffect, useState } from 'react'\nimport { registerRemotes } from '@module-federation/enhanced/runtime'\nimport {\n FrontendModuleListItem,\n useListFrontendModulesQuery,\n useGetSiteInfoQuery,\n} from '@shared/api'\n\ntype Module = {\n remote: string\n addon: string\n version: string\n modules: string[]\n}\n\ntype RemoteModulesContextType = {\n isLoading: boolean\n modules: FrontendModuleListItem[]\n remotesInitialized: boolean\n}\n\nconst RemoteModulesContext = createContext<RemoteModulesContextType>({\n isLoading: true,\n modules: [],\n remotesInitialized: false,\n})\n\ntype Props = {\n children: ReactNode\n skip?: boolean\n}\n\nexport const RemoteModulesProvider = ({ children, skip }: Props) => {\n // only load if logged in\n const { data: addonRemoteModules = [], isLoading } = useListFrontendModulesQuery(undefined, {\n skip,\n })\n\n const { data: info = {}, isLoading: isLoadingInfo } = useGetSiteInfoQuery(\n { full: true },\n { skip },\n )\n\n const [remotesInitialized, setRemotesInitialized] = useState(false)\n\n useEffect(() => {\n if (isLoading || !addonRemoteModules.length || isLoadingInfo || remotesInitialized) return\n\n // create a flat map of modules to load\n const allRemotes: Module[] = []\n\n addonRemoteModules.forEach((addon) => {\n const { addonName, addonVersion, modules = {} } = addon\n\n Object.entries(modules).forEach(([remote, modules]) => {\n allRemotes.push({\n remote,\n addon: addonName,\n version: addonVersion,\n modules,\n })\n })\n })\n\n console.log('registerAddonRemotes', allRemotes)\n registerRemotes(\n allRemotes.map((r) => ({\n name: r.remote,\n alias: r.remote,\n entry: `/addons/${r.addon || r.remote}/${r.version}/frontend/modules/${\n r.remote\n }/remoteEntry.js?server=${info?.releaseInfo?.version || info?.releaseInfo}-${\n info?.releaseInfo?.buildDate\n }-${new Date().getTime()}`,\n type: 'module',\n })),\n )\n\n setRemotesInitialized(true)\n }, [addonRemoteModules, isLoading, isLoadingInfo, remotesInitialized])\n\n return (\n <RemoteModulesContext.Provider\n value={{\n isLoading,\n modules: addonRemoteModules,\n remotesInitialized,\n }}\n >\n {children}\n </RemoteModulesContext.Provider>\n )\n}\n\nexport const useRemoteModules = () => {\n const context = useContext(RemoteModulesContext)\n\n if (context === undefined) {\n throw new Error('useRemoteModules must be used within a RemoteModulesProvider')\n }\n\n return context\n}\n"],"names":["modules","registerRemotes","jsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAqBA,MAAM,uBAAuB,cAAwC;AAAA,EACnE,WAAW;AAAA,EACX,SAAS,CAAC;AAAA,EACV,oBAAoB;AACtB,CAAC;AAOM,MAAM,wBAAwB,CAAC,EAAE,UAAU,WAAkB;AAE5D,QAAA,EAAE,MAAM,qBAAqB,CAAA,GAAI,UAAU,IAAI,4BAA4B,QAAW;AAAA,IAC1F;AAAA,EAAA,CACD;AAED,QAAM,EAAE,MAAM,OAAO,CAAI,GAAA,WAAW,kBAAkB;AAAA,IACpD,EAAE,MAAM,KAAK;AAAA,IACb,EAAE,KAAK;AAAA,EACT;AAEA,QAAM,CAAC,oBAAoB,qBAAqB,IAAI,SAAS,KAAK;AAElE,YAAU,MAAM;AACd,QAAI,aAAa,CAAC,mBAAmB,UAAU,iBAAiB,mBAAoB;AAGpF,UAAM,aAAuB,CAAC;AAEX,uBAAA,QAAQ,CAAC,UAAU;AACpC,YAAM,EAAE,WAAW,cAAc,UAAU,CAAA,EAAO,IAAA;AAE3C,aAAA,QAAQ,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQA,QAAO,MAAM;AACrD,mBAAW,KAAK;AAAA,UACd;AAAA,UACA,OAAO;AAAA,UACP,SAAS;AAAA,UACT,SAAAA;AAAAA,QAAA,CACD;AAAA,MAAA,CACF;AAAA,IAAA,CACF;AAEO,YAAA,IAAI,wBAAwB,UAAU;AAC9CC,mBAAA;AAAA,MACE,WAAW,IAAI,CAAC,MAAO;;AAAA;AAAA,UACrB,MAAM,EAAE;AAAA,UACR,OAAO,EAAE;AAAA,UACT,OAAO,WAAW,EAAE,SAAS,EAAE,MAAM,IAAI,EAAE,OAAO,qBAChD,EAAE,MACJ,4BAA0B,kCAAM,gBAAN,mBAAmB,aAAW,6BAAM,YAAW,KACvE,kCAAM,gBAAN,mBAAmB,SACrB,KAAQ,oBAAA,KAAA,GAAO,QAAS,CAAA;AAAA,UACxB,MAAM;AAAA,QAAA;AAAA,OACN;AAAA,IACJ;AAEA,0BAAsB,IAAI;AAAA,KACzB,CAAC,oBAAoB,WAAW,eAAe,kBAAkB,CAAC;AAGnE,SAAAC,kCAAA;AAAA,IAAC,qBAAqB;AAAA,IAArB;AAAA,MACC,OAAO;AAAA,QACL;AAAA,QACA,SAAS;AAAA,QACT;AAAA,MACF;AAAA,MAEC;AAAA,IAAA;AAAA,EACH;AAEJ;AAEO,MAAM,mBAAmB,MAAM;AAC9B,QAAA,UAAU,WAAW,oBAAoB;AAE/C,MAAI,YAAY,QAAW;AACnB,UAAA,IAAI,MAAM,8DAA8D;AAAA,EAAA;AAGzE,SAAA;AACT;"}
@@ -0,0 +1,136 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
3
+ const runtime = require("../../../_virtual/runtime.cjs.js");
4
+ const React = require("react");
5
+ const semver = require("../../../_virtual/semver.cjs.js");
6
+ const useLoadModules = (moduleSpecs, modules, skip) => {
7
+ const processedModules = React.useRef(/* @__PURE__ */ new Set());
8
+ const [results, setResults] = React.useState(
9
+ () => initializeResults(moduleSpecs)
10
+ );
11
+ const [isLoading, setIsLoading] = React.useState(true);
12
+ React.useEffect(() => {
13
+ if (skip) return;
14
+ processedModules.current = /* @__PURE__ */ new Set();
15
+ setResults(initializeResults(moduleSpecs));
16
+ }, [JSON.stringify(moduleSpecs), skip]);
17
+ const loadModule = async (remote, module2, addon, fallback, minVersion) => {
18
+ try {
19
+ const result = await runtime.runtimeExports.loadRemote(`${remote}/${module2}`, {
20
+ from: "runtime"
21
+ });
22
+ updateResultWithLoaded(addon, remote, module2, (result == null ? void 0 : result.default) || fallback, minVersion);
23
+ } catch (error) {
24
+ console.error("Error loading remote module", remote, module2, error);
25
+ throw error;
26
+ }
27
+ };
28
+ React.useEffect(() => {
29
+ if (skip) return;
30
+ console.log("loading modules");
31
+ const promises = [];
32
+ moduleSpecs.forEach((spec, index) => {
33
+ var _a, _b;
34
+ const { addon, remote, module: module2, fallback, minVersion } = spec;
35
+ if (!addon || !remote || !module2) return;
36
+ const moduleKey = `${addon}/${remote}/${module2}`;
37
+ if (processedModules.current.has(moduleKey)) return;
38
+ if ((_b = (_a = results[index]) == null ? void 0 : _a[1]) == null ? void 0 : _b.isLoaded) {
39
+ processedModules.current.add(moduleKey);
40
+ return;
41
+ }
42
+ processedModules.current.add(moduleKey);
43
+ const addonInfo = modules.find((m) => m.addonName === addon);
44
+ if (!addonInfo) {
45
+ console.log("Addon not found", { addon, remote, module: module2 });
46
+ return;
47
+ }
48
+ if (minVersion && !semver.gte(addonInfo.addonVersion, minVersion)) {
49
+ updateResultWithOutdated(
50
+ index,
51
+ addon,
52
+ remote,
53
+ module2,
54
+ fallback,
55
+ minVersion,
56
+ addonInfo.addonVersion
57
+ );
58
+ return;
59
+ }
60
+ if (!addonInfo.modules[remote]) {
61
+ console.log("Module not found", { addon, remote, module: module2 });
62
+ return;
63
+ }
64
+ promises.push(loadModule(remote, module2, addon, fallback, minVersion));
65
+ });
66
+ setIsLoading(true);
67
+ Promise.all(promises).then(() => {
68
+ setIsLoading(false);
69
+ }).catch((error) => {
70
+ console.error("Error loading modules", error);
71
+ setIsLoading(false);
72
+ });
73
+ }, [skip, modules, JSON.stringify(moduleSpecs)]);
74
+ function initializeResults(specs) {
75
+ return specs.map(
76
+ ({ addon = "", remote = "", module: module2 = "", fallback, minVersion }) => [
77
+ fallback,
78
+ {
79
+ isLoaded: false,
80
+ addon,
81
+ remote,
82
+ module: module2,
83
+ minVersion,
84
+ outdated: void 0
85
+ }
86
+ ]
87
+ );
88
+ }
89
+ function updateResultWithOutdated(index, addon, remote, module2, fallback, requiredVersion, currentVersion) {
90
+ setResults((prev) => {
91
+ const updated = [...prev];
92
+ if (index >= 0 && index < updated.length) {
93
+ updated[index] = [
94
+ fallback,
95
+ {
96
+ isLoaded: false,
97
+ addon,
98
+ remote,
99
+ module: module2,
100
+ minVersion: requiredVersion,
101
+ outdated: {
102
+ current: currentVersion,
103
+ required: requiredVersion
104
+ }
105
+ }
106
+ ];
107
+ }
108
+ return updated;
109
+ });
110
+ }
111
+ function updateResultWithLoaded(addon, remote, module2, loadedModule, minVersion) {
112
+ setResults((prev) => {
113
+ const updated = [...prev];
114
+ const index = moduleSpecs.findIndex(
115
+ (spec) => spec.addon === addon && spec.remote === remote && spec.module === module2
116
+ );
117
+ if (index >= 0 && index < updated.length) {
118
+ updated[index] = [
119
+ loadedModule,
120
+ {
121
+ isLoaded: true,
122
+ addon,
123
+ remote,
124
+ module: module2,
125
+ minVersion,
126
+ outdated: void 0
127
+ }
128
+ ];
129
+ }
130
+ return updated;
131
+ });
132
+ }
133
+ return { modules: results, isLoading };
134
+ };
135
+ exports.useLoadModules = useLoadModules;
136
+ //# sourceMappingURL=useLoadModules.cjs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLoadModules.cjs.js","sources":["../../../../src/hooks/useLoadModules.ts"],"sourcesContent":["import { useRemoteModules } from '@shared/context/RemoteModulesContext'\nimport { loadRemote } from '@module-federation/enhanced/runtime'\nimport { useEffect, useRef, useState } from 'react'\nimport semver from 'semver'\nimport { FrontendModuleListItem } from '@shared/api'\n\nexport interface ModuleSpec<T> {\n addon: string\n remote: string\n module: string\n fallback?: T\n debug?: boolean\n minVersion?: string\n}\n\ntype ModuleResult<T> = [\n T,\n {\n isLoaded: boolean\n addon: string\n remote: string\n module: string\n minVersion?: string\n outdated?: {\n current: string\n required: string\n }\n },\n]\n\nexport const useLoadModules = <T extends any[]>(\n moduleSpecs: ModuleSpec<T[number]>[],\n modules: FrontendModuleListItem[],\n skip: boolean,\n): { modules: ModuleResult<T[number]>[]; isLoading: boolean } => {\n // Use a ref to track which modules have been processed\n const processedModules = useRef<Set<string>>(new Set())\n\n // Initialize results state\n const [results, setResults] = useState<ModuleResult<T[number]>[]>(() =>\n initializeResults(moduleSpecs),\n )\n const [isLoading, setIsLoading] = useState(true)\n\n // Reset and reinitialize when moduleSpecs change\n useEffect(() => {\n if (skip) return\n // Reset the processed modules tracker\n processedModules.current = new Set()\n\n // Initialize results with proper structure\n setResults(initializeResults(moduleSpecs))\n }, [JSON.stringify(moduleSpecs), skip])\n\n const loadModule = async (\n remote: string,\n module: string,\n addon: string,\n fallback: T[number] | undefined,\n minVersion?: string,\n ) => {\n try {\n const result = await loadRemote<{ default: T[number] }>(`${remote}/${module}`, {\n from: 'runtime',\n })\n updateResultWithLoaded(addon, remote, module, result?.default || fallback, minVersion)\n } catch (error) {\n console.error('Error loading remote module', remote, module, error)\n throw error\n }\n }\n\n // Load modules when remotes are initialized\n useEffect(() => {\n if (skip) return\n\n console.log('loading modules')\n\n const promises: Promise<void>[] = []\n moduleSpecs.forEach((spec, index) => {\n const { addon, remote, module, fallback, minVersion } = spec\n\n if (!addon || !remote || !module) return\n\n // Create a unique key for this module\n const moduleKey = `${addon}/${remote}/${module}`\n\n // Skip if already processed\n if (processedModules.current.has(moduleKey)) return\n\n // Check if this module is already loaded in our results\n if (results[index]?.[1]?.isLoaded) {\n processedModules.current.add(moduleKey)\n return\n }\n\n // Mark as processed\n processedModules.current.add(moduleKey)\n\n const addonInfo = modules.find((m) => m.addonName === addon)\n\n // Handle missing addon\n if (!addonInfo) {\n console.log('Addon not found', { addon, remote, module })\n return\n }\n\n // Check version requirements\n if (minVersion && !semver.gte(addonInfo.addonVersion, minVersion)) {\n updateResultWithOutdated(\n index,\n addon,\n remote,\n module,\n fallback,\n minVersion,\n addonInfo.addonVersion,\n )\n return\n }\n\n // Check if module exists\n if (!addonInfo.modules[remote]) {\n console.log('Module not found', { addon, remote, module })\n return\n }\n\n promises.push(loadModule(remote, module, addon, fallback, minVersion))\n })\n\n // Wait for all promises to resolve\n setIsLoading(true)\n Promise.all(promises)\n .then(() => {\n // all modules loaded\n setIsLoading(false)\n })\n .catch((error) => {\n console.error('Error loading modules', error)\n setIsLoading(false)\n })\n }, [skip, modules, JSON.stringify(moduleSpecs)])\n\n // Helper function to initialize results\n function initializeResults(specs: ModuleSpec<T[number]>[]): ModuleResult<T[number]>[] {\n return specs.map(\n ({ addon = '', remote = '', module = '', fallback, minVersion }): ModuleResult<T[number]> => [\n fallback as T[number],\n {\n isLoaded: false,\n addon,\n remote,\n module,\n minVersion,\n outdated: undefined,\n },\n ],\n )\n }\n\n // Helper to update a result with outdated status\n function updateResultWithOutdated(\n index: number,\n addon: string,\n remote: string,\n module: string,\n fallback: T[number] | undefined,\n requiredVersion: string,\n currentVersion: string,\n ) {\n setResults((prev) => {\n const updated = [...prev]\n if (index >= 0 && index < updated.length) {\n updated[index] = [\n fallback,\n {\n isLoaded: false,\n addon,\n remote,\n module,\n minVersion: requiredVersion,\n outdated: {\n current: currentVersion,\n required: requiredVersion,\n },\n },\n ]\n }\n return updated\n })\n }\n\n // Helper to update a result when module is loaded\n function updateResultWithLoaded(\n addon: string,\n remote: string,\n module: string,\n loadedModule: T[number] | undefined,\n minVersion?: string,\n ) {\n setResults((prev) => {\n const updated = [...prev]\n // Find the corresponding module spec\n const index = moduleSpecs.findIndex(\n (spec) => spec.addon === addon && spec.remote === remote && spec.module === module,\n )\n\n if (index >= 0 && index < updated.length) {\n updated[index] = [\n loadedModule,\n {\n isLoaded: true,\n addon,\n remote,\n module,\n minVersion,\n outdated: undefined,\n },\n ]\n }\n return updated\n })\n }\n\n return { modules: results, isLoading }\n}\n"],"names":["useRef","useState","useEffect","module","loadRemote"],"mappings":"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"}
@@ -0,0 +1,136 @@
1
+ import { r as runtimeExports } from "../../../_virtual/runtime.es.js";
2
+ import { useRef, useState, useEffect } from "react";
3
+ import semver from "../../../_virtual/semver.es.js";
4
+ const useLoadModules = (moduleSpecs, modules, skip) => {
5
+ const processedModules = useRef(/* @__PURE__ */ new Set());
6
+ const [results, setResults] = useState(
7
+ () => initializeResults(moduleSpecs)
8
+ );
9
+ const [isLoading, setIsLoading] = useState(true);
10
+ useEffect(() => {
11
+ if (skip) return;
12
+ processedModules.current = /* @__PURE__ */ new Set();
13
+ setResults(initializeResults(moduleSpecs));
14
+ }, [JSON.stringify(moduleSpecs), skip]);
15
+ const loadModule = async (remote, module, addon, fallback, minVersion) => {
16
+ try {
17
+ const result = await runtimeExports.loadRemote(`${remote}/${module}`, {
18
+ from: "runtime"
19
+ });
20
+ updateResultWithLoaded(addon, remote, module, (result == null ? void 0 : result.default) || fallback, minVersion);
21
+ } catch (error) {
22
+ console.error("Error loading remote module", remote, module, error);
23
+ throw error;
24
+ }
25
+ };
26
+ useEffect(() => {
27
+ if (skip) return;
28
+ console.log("loading modules");
29
+ const promises = [];
30
+ moduleSpecs.forEach((spec, index) => {
31
+ var _a, _b;
32
+ const { addon, remote, module, fallback, minVersion } = spec;
33
+ if (!addon || !remote || !module) return;
34
+ const moduleKey = `${addon}/${remote}/${module}`;
35
+ if (processedModules.current.has(moduleKey)) return;
36
+ if ((_b = (_a = results[index]) == null ? void 0 : _a[1]) == null ? void 0 : _b.isLoaded) {
37
+ processedModules.current.add(moduleKey);
38
+ return;
39
+ }
40
+ processedModules.current.add(moduleKey);
41
+ const addonInfo = modules.find((m) => m.addonName === addon);
42
+ if (!addonInfo) {
43
+ console.log("Addon not found", { addon, remote, module });
44
+ return;
45
+ }
46
+ if (minVersion && !semver.gte(addonInfo.addonVersion, minVersion)) {
47
+ updateResultWithOutdated(
48
+ index,
49
+ addon,
50
+ remote,
51
+ module,
52
+ fallback,
53
+ minVersion,
54
+ addonInfo.addonVersion
55
+ );
56
+ return;
57
+ }
58
+ if (!addonInfo.modules[remote]) {
59
+ console.log("Module not found", { addon, remote, module });
60
+ return;
61
+ }
62
+ promises.push(loadModule(remote, module, addon, fallback, minVersion));
63
+ });
64
+ setIsLoading(true);
65
+ Promise.all(promises).then(() => {
66
+ setIsLoading(false);
67
+ }).catch((error) => {
68
+ console.error("Error loading modules", error);
69
+ setIsLoading(false);
70
+ });
71
+ }, [skip, modules, JSON.stringify(moduleSpecs)]);
72
+ function initializeResults(specs) {
73
+ return specs.map(
74
+ ({ addon = "", remote = "", module = "", fallback, minVersion }) => [
75
+ fallback,
76
+ {
77
+ isLoaded: false,
78
+ addon,
79
+ remote,
80
+ module,
81
+ minVersion,
82
+ outdated: void 0
83
+ }
84
+ ]
85
+ );
86
+ }
87
+ function updateResultWithOutdated(index, addon, remote, module, fallback, requiredVersion, currentVersion) {
88
+ setResults((prev) => {
89
+ const updated = [...prev];
90
+ if (index >= 0 && index < updated.length) {
91
+ updated[index] = [
92
+ fallback,
93
+ {
94
+ isLoaded: false,
95
+ addon,
96
+ remote,
97
+ module,
98
+ minVersion: requiredVersion,
99
+ outdated: {
100
+ current: currentVersion,
101
+ required: requiredVersion
102
+ }
103
+ }
104
+ ];
105
+ }
106
+ return updated;
107
+ });
108
+ }
109
+ function updateResultWithLoaded(addon, remote, module, loadedModule, minVersion) {
110
+ setResults((prev) => {
111
+ const updated = [...prev];
112
+ const index = moduleSpecs.findIndex(
113
+ (spec) => spec.addon === addon && spec.remote === remote && spec.module === module
114
+ );
115
+ if (index >= 0 && index < updated.length) {
116
+ updated[index] = [
117
+ loadedModule,
118
+ {
119
+ isLoaded: true,
120
+ addon,
121
+ remote,
122
+ module,
123
+ minVersion,
124
+ outdated: void 0
125
+ }
126
+ ];
127
+ }
128
+ return updated;
129
+ });
130
+ }
131
+ return { modules: results, isLoading };
132
+ };
133
+ export {
134
+ useLoadModules
135
+ };
136
+ //# sourceMappingURL=useLoadModules.es.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"useLoadModules.es.js","sources":["../../../../src/hooks/useLoadModules.ts"],"sourcesContent":["import { useRemoteModules } from '@shared/context/RemoteModulesContext'\nimport { loadRemote } from '@module-federation/enhanced/runtime'\nimport { useEffect, useRef, useState } from 'react'\nimport semver from 'semver'\nimport { FrontendModuleListItem } from '@shared/api'\n\nexport interface ModuleSpec<T> {\n addon: string\n remote: string\n module: string\n fallback?: T\n debug?: boolean\n minVersion?: string\n}\n\ntype ModuleResult<T> = [\n T,\n {\n isLoaded: boolean\n addon: string\n remote: string\n module: string\n minVersion?: string\n outdated?: {\n current: string\n required: string\n }\n },\n]\n\nexport const useLoadModules = <T extends any[]>(\n moduleSpecs: ModuleSpec<T[number]>[],\n modules: FrontendModuleListItem[],\n skip: boolean,\n): { modules: ModuleResult<T[number]>[]; isLoading: boolean } => {\n // Use a ref to track which modules have been processed\n const processedModules = useRef<Set<string>>(new Set())\n\n // Initialize results state\n const [results, setResults] = useState<ModuleResult<T[number]>[]>(() =>\n initializeResults(moduleSpecs),\n )\n const [isLoading, setIsLoading] = useState(true)\n\n // Reset and reinitialize when moduleSpecs change\n useEffect(() => {\n if (skip) return\n // Reset the processed modules tracker\n processedModules.current = new Set()\n\n // Initialize results with proper structure\n setResults(initializeResults(moduleSpecs))\n }, [JSON.stringify(moduleSpecs), skip])\n\n const loadModule = async (\n remote: string,\n module: string,\n addon: string,\n fallback: T[number] | undefined,\n minVersion?: string,\n ) => {\n try {\n const result = await loadRemote<{ default: T[number] }>(`${remote}/${module}`, {\n from: 'runtime',\n })\n updateResultWithLoaded(addon, remote, module, result?.default || fallback, minVersion)\n } catch (error) {\n console.error('Error loading remote module', remote, module, error)\n throw error\n }\n }\n\n // Load modules when remotes are initialized\n useEffect(() => {\n if (skip) return\n\n console.log('loading modules')\n\n const promises: Promise<void>[] = []\n moduleSpecs.forEach((spec, index) => {\n const { addon, remote, module, fallback, minVersion } = spec\n\n if (!addon || !remote || !module) return\n\n // Create a unique key for this module\n const moduleKey = `${addon}/${remote}/${module}`\n\n // Skip if already processed\n if (processedModules.current.has(moduleKey)) return\n\n // Check if this module is already loaded in our results\n if (results[index]?.[1]?.isLoaded) {\n processedModules.current.add(moduleKey)\n return\n }\n\n // Mark as processed\n processedModules.current.add(moduleKey)\n\n const addonInfo = modules.find((m) => m.addonName === addon)\n\n // Handle missing addon\n if (!addonInfo) {\n console.log('Addon not found', { addon, remote, module })\n return\n }\n\n // Check version requirements\n if (minVersion && !semver.gte(addonInfo.addonVersion, minVersion)) {\n updateResultWithOutdated(\n index,\n addon,\n remote,\n module,\n fallback,\n minVersion,\n addonInfo.addonVersion,\n )\n return\n }\n\n // Check if module exists\n if (!addonInfo.modules[remote]) {\n console.log('Module not found', { addon, remote, module })\n return\n }\n\n promises.push(loadModule(remote, module, addon, fallback, minVersion))\n })\n\n // Wait for all promises to resolve\n setIsLoading(true)\n Promise.all(promises)\n .then(() => {\n // all modules loaded\n setIsLoading(false)\n })\n .catch((error) => {\n console.error('Error loading modules', error)\n setIsLoading(false)\n })\n }, [skip, modules, JSON.stringify(moduleSpecs)])\n\n // Helper function to initialize results\n function initializeResults(specs: ModuleSpec<T[number]>[]): ModuleResult<T[number]>[] {\n return specs.map(\n ({ addon = '', remote = '', module = '', fallback, minVersion }): ModuleResult<T[number]> => [\n fallback as T[number],\n {\n isLoaded: false,\n addon,\n remote,\n module,\n minVersion,\n outdated: undefined,\n },\n ],\n )\n }\n\n // Helper to update a result with outdated status\n function updateResultWithOutdated(\n index: number,\n addon: string,\n remote: string,\n module: string,\n fallback: T[number] | undefined,\n requiredVersion: string,\n currentVersion: string,\n ) {\n setResults((prev) => {\n const updated = [...prev]\n if (index >= 0 && index < updated.length) {\n updated[index] = [\n fallback,\n {\n isLoaded: false,\n addon,\n remote,\n module,\n minVersion: requiredVersion,\n outdated: {\n current: currentVersion,\n required: requiredVersion,\n },\n },\n ]\n }\n return updated\n })\n }\n\n // Helper to update a result when module is loaded\n function updateResultWithLoaded(\n addon: string,\n remote: string,\n module: string,\n loadedModule: T[number] | undefined,\n minVersion?: string,\n ) {\n setResults((prev) => {\n const updated = [...prev]\n // Find the corresponding module spec\n const index = moduleSpecs.findIndex(\n (spec) => spec.addon === addon && spec.remote === remote && spec.module === module,\n )\n\n if (index >= 0 && index < updated.length) {\n updated[index] = [\n loadedModule,\n {\n isLoaded: true,\n addon,\n remote,\n module,\n minVersion,\n outdated: undefined,\n },\n ]\n }\n return updated\n })\n }\n\n return { modules: results, isLoading }\n}\n"],"names":["loadRemote"],"mappings":"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"}
@@ -69,7 +69,10 @@ const useScopedStatuses = (projects, entityTypes) => {
69
69
  let currentStatuses;
70
70
  for (const item of Object.values(response.data)) {
71
71
  const filteredStatuses = item.statuses.filter(
72
- (status) => entityTypes.every((type) => status.scope.includes(type))
72
+ (status) => entityTypes.every((type) => {
73
+ var _a;
74
+ return !status.scope || ((_a = status.scope) == null ? void 0 : _a.includes(type));
75
+ })
73
76
  );
74
77
  if (currentStatuses === void 0) {
75
78
  currentStatuses = filteredStatuses;
@@ -1 +1 @@
1
- {"version":3,"file":"useScopedStatuses.cjs.js","sources":["../../../../src/hooks/useScopedStatuses.ts"],"sourcesContent":["import { useGetProjectsInfoQuery } from '@shared/api'\nimport type { ProjectModel, Status } from '@shared/api'\nimport { intersectionBy } from 'lodash'\n\ntype EntityStatus = Status & {\n scope?: string[]\n}\n\nexport const useScopedStatuses = (projects: string[], entityTypes: string[]) => {\n const response = useGetProjectsInfoQuery({ projects: [...new Set(projects).values()] })\n\n if (!response || !response.data) {\n return []\n }\n\n let currentStatuses: EntityStatus[] | undefined\n for (const item of Object.values(response.data) as ProjectModel[]) {\n const filteredStatuses = item.statuses!.filter((status: EntityStatus) =>\n entityTypes.every((type) => status.scope!.includes(type)),\n )\n if (currentStatuses === undefined) {\n currentStatuses = filteredStatuses\n continue\n }\n currentStatuses = intersectionBy(currentStatuses, filteredStatuses, 'name')\n }\n\n return currentStatuses\n}\n\nexport const filterProjectStatuses = (statuses: EntityStatus[], entityTypes: string[]) => {\n let statusesList: EntityStatus[] = Object.values(statuses || {})\n\n if (statusesList.length == 0 || statusesList[0].scope === undefined) {\n return statusesList\n }\n\n return statusesList.filter((el) => entityTypes.every((type) => el.scope!.includes(type)))\n}\n"],"names":["useGetProjectsInfoQuery","intersectionBy"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQa,MAAA,oBAAoB,CAAC,UAAoB,gBAA0B;AAC9E,QAAM,WAAWA,iBAAAA,wBAAwB,EAAE,UAAU,CAAC,GAAG,IAAI,IAAI,QAAQ,EAAE,OAAQ,CAAA,GAAG;AAEtF,MAAI,CAAC,YAAY,CAAC,SAAS,MAAM;AAC/B,WAAO,CAAC;AAAA,EAAA;AAGN,MAAA;AACJ,aAAW,QAAQ,OAAO,OAAO,SAAS,IAAI,GAAqB;AAC3D,UAAA,mBAAmB,KAAK,SAAU;AAAA,MAAO,CAAC,WAC9C,YAAY,MAAM,CAAC,SAAS,OAAO,MAAO,SAAS,IAAI,CAAC;AAAA,IAC1D;AACA,QAAI,oBAAoB,QAAW;AACf,wBAAA;AAClB;AAAA,IAAA;AAEgB,sBAAAC,OAAA,cAAA,eAAe,iBAAiB,kBAAkB,MAAM;AAAA,EAAA;AAGrE,SAAA;AACT;AAEa,MAAA,wBAAwB,CAAC,UAA0B,gBAA0B;AACxF,MAAI,eAA+B,OAAO,OAAO,YAAY,CAAA,CAAE;AAE/D,MAAI,aAAa,UAAU,KAAK,aAAa,CAAC,EAAE,UAAU,QAAW;AAC5D,WAAA;AAAA,EAAA;AAGT,SAAO,aAAa,OAAO,CAAC,OAAO,YAAY,MAAM,CAAC,SAAS,GAAG,MAAO,SAAS,IAAI,CAAC,CAAC;AAC1F;;;"}
1
+ {"version":3,"file":"useScopedStatuses.cjs.js","sources":["../../../../src/hooks/useScopedStatuses.ts"],"sourcesContent":["import { useGetProjectsInfoQuery } from '@shared/api'\nimport type { ProjectModel, Status } from '@shared/api'\nimport { intersectionBy } from 'lodash'\n\ntype EntityStatus = Status & {\n scope?: string[]\n}\n\nexport const useScopedStatuses = (projects: string[], entityTypes: string[]) => {\n const response = useGetProjectsInfoQuery({ projects: [...new Set(projects).values()] })\n\n if (!response || !response.data) {\n return []\n }\n\n let currentStatuses: EntityStatus[] | undefined\n for (const item of Object.values(response.data) as ProjectModel[]) {\n const filteredStatuses = item.statuses!.filter((status: EntityStatus) =>\n entityTypes.every((type) => (!status.scope || status.scope?.includes(type))),\n )\n if (currentStatuses === undefined) {\n currentStatuses = filteredStatuses\n continue\n }\n currentStatuses = intersectionBy(currentStatuses, filteredStatuses, 'name')\n }\n\n return currentStatuses\n}\n\nexport const filterProjectStatuses = (statuses: EntityStatus[], entityTypes: string[]) => {\n let statusesList: EntityStatus[] = Object.values(statuses || {})\n\n if (statusesList.length == 0 || statusesList[0].scope === undefined) {\n return statusesList\n }\n\n return statusesList.filter((el) => entityTypes.every((type) => el.scope!.includes(type)))\n}\n"],"names":["useGetProjectsInfoQuery","intersectionBy"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQa,MAAA,oBAAoB,CAAC,UAAoB,gBAA0B;AAC9E,QAAM,WAAWA,iBAAAA,wBAAwB,EAAE,UAAU,CAAC,GAAG,IAAI,IAAI,QAAQ,EAAE,OAAQ,CAAA,GAAG;AAEtF,MAAI,CAAC,YAAY,CAAC,SAAS,MAAM;AAC/B,WAAO,CAAC;AAAA,EAAA;AAGN,MAAA;AACJ,aAAW,QAAQ,OAAO,OAAO,SAAS,IAAI,GAAqB;AAC3D,UAAA,mBAAmB,KAAK,SAAU;AAAA,MAAO,CAAC,WAC9C,YAAY,MAAM,CAAC,SAAU;;AAAA,gBAAC,OAAO,WAAS,YAAO,UAAP,mBAAc,SAAS;AAAA,OAAM;AAAA,IAC7E;AACA,QAAI,oBAAoB,QAAW;AACf,wBAAA;AAClB;AAAA,IAAA;AAEgB,sBAAAC,OAAA,cAAA,eAAe,iBAAiB,kBAAkB,MAAM;AAAA,EAAA;AAGrE,SAAA;AACT;AAEa,MAAA,wBAAwB,CAAC,UAA0B,gBAA0B;AACxF,MAAI,eAA+B,OAAO,OAAO,YAAY,CAAA,CAAE;AAE/D,MAAI,aAAa,UAAU,KAAK,aAAa,CAAC,EAAE,UAAU,QAAW;AAC5D,WAAA;AAAA,EAAA;AAGT,SAAO,aAAa,OAAO,CAAC,OAAO,YAAY,MAAM,CAAC,SAAS,GAAG,MAAO,SAAS,IAAI,CAAC,CAAC;AAC1F;;;"}
@@ -67,7 +67,10 @@ const useScopedStatuses = (projects, entityTypes) => {
67
67
  let currentStatuses;
68
68
  for (const item of Object.values(response.data)) {
69
69
  const filteredStatuses = item.statuses.filter(
70
- (status) => entityTypes.every((type) => status.scope.includes(type))
70
+ (status) => entityTypes.every((type) => {
71
+ var _a;
72
+ return !status.scope || ((_a = status.scope) == null ? void 0 : _a.includes(type));
73
+ })
71
74
  );
72
75
  if (currentStatuses === void 0) {
73
76
  currentStatuses = filteredStatuses;
@@ -1 +1 @@
1
- {"version":3,"file":"useScopedStatuses.es.js","sources":["../../../../src/hooks/useScopedStatuses.ts"],"sourcesContent":["import { useGetProjectsInfoQuery } from '@shared/api'\nimport type { ProjectModel, Status } from '@shared/api'\nimport { intersectionBy } from 'lodash'\n\ntype EntityStatus = Status & {\n scope?: string[]\n}\n\nexport const useScopedStatuses = (projects: string[], entityTypes: string[]) => {\n const response = useGetProjectsInfoQuery({ projects: [...new Set(projects).values()] })\n\n if (!response || !response.data) {\n return []\n }\n\n let currentStatuses: EntityStatus[] | undefined\n for (const item of Object.values(response.data) as ProjectModel[]) {\n const filteredStatuses = item.statuses!.filter((status: EntityStatus) =>\n entityTypes.every((type) => status.scope!.includes(type)),\n )\n if (currentStatuses === undefined) {\n currentStatuses = filteredStatuses\n continue\n }\n currentStatuses = intersectionBy(currentStatuses, filteredStatuses, 'name')\n }\n\n return currentStatuses\n}\n\nexport const filterProjectStatuses = (statuses: EntityStatus[], entityTypes: string[]) => {\n let statusesList: EntityStatus[] = Object.values(statuses || {})\n\n if (statusesList.length == 0 || statusesList[0].scope === undefined) {\n return statusesList\n }\n\n return statusesList.filter((el) => entityTypes.every((type) => el.scope!.includes(type)))\n}\n"],"names":["intersectionBy"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQa,MAAA,oBAAoB,CAAC,UAAoB,gBAA0B;AAC9E,QAAM,WAAW,wBAAwB,EAAE,UAAU,CAAC,GAAG,IAAI,IAAI,QAAQ,EAAE,OAAQ,CAAA,GAAG;AAEtF,MAAI,CAAC,YAAY,CAAC,SAAS,MAAM;AAC/B,WAAO,CAAC;AAAA,EAAA;AAGN,MAAA;AACJ,aAAW,QAAQ,OAAO,OAAO,SAAS,IAAI,GAAqB;AAC3D,UAAA,mBAAmB,KAAK,SAAU;AAAA,MAAO,CAAC,WAC9C,YAAY,MAAM,CAAC,SAAS,OAAO,MAAO,SAAS,IAAI,CAAC;AAAA,IAC1D;AACA,QAAI,oBAAoB,QAAW;AACf,wBAAA;AAClB;AAAA,IAAA;AAEgB,sBAAAA,cAAA,eAAe,iBAAiB,kBAAkB,MAAM;AAAA,EAAA;AAGrE,SAAA;AACT;AAEa,MAAA,wBAAwB,CAAC,UAA0B,gBAA0B;AACxF,MAAI,eAA+B,OAAO,OAAO,YAAY,CAAA,CAAE;AAE/D,MAAI,aAAa,UAAU,KAAK,aAAa,CAAC,EAAE,UAAU,QAAW;AAC5D,WAAA;AAAA,EAAA;AAGT,SAAO,aAAa,OAAO,CAAC,OAAO,YAAY,MAAM,CAAC,SAAS,GAAG,MAAO,SAAS,IAAI,CAAC,CAAC;AAC1F;"}
1
+ {"version":3,"file":"useScopedStatuses.es.js","sources":["../../../../src/hooks/useScopedStatuses.ts"],"sourcesContent":["import { useGetProjectsInfoQuery } from '@shared/api'\nimport type { ProjectModel, Status } from '@shared/api'\nimport { intersectionBy } from 'lodash'\n\ntype EntityStatus = Status & {\n scope?: string[]\n}\n\nexport const useScopedStatuses = (projects: string[], entityTypes: string[]) => {\n const response = useGetProjectsInfoQuery({ projects: [...new Set(projects).values()] })\n\n if (!response || !response.data) {\n return []\n }\n\n let currentStatuses: EntityStatus[] | undefined\n for (const item of Object.values(response.data) as ProjectModel[]) {\n const filteredStatuses = item.statuses!.filter((status: EntityStatus) =>\n entityTypes.every((type) => (!status.scope || status.scope?.includes(type))),\n )\n if (currentStatuses === undefined) {\n currentStatuses = filteredStatuses\n continue\n }\n currentStatuses = intersectionBy(currentStatuses, filteredStatuses, 'name')\n }\n\n return currentStatuses\n}\n\nexport const filterProjectStatuses = (statuses: EntityStatus[], entityTypes: string[]) => {\n let statusesList: EntityStatus[] = Object.values(statuses || {})\n\n if (statusesList.length == 0 || statusesList[0].scope === undefined) {\n return statusesList\n }\n\n return statusesList.filter((el) => entityTypes.every((type) => el.scope!.includes(type)))\n}\n"],"names":["intersectionBy"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAQa,MAAA,oBAAoB,CAAC,UAAoB,gBAA0B;AAC9E,QAAM,WAAW,wBAAwB,EAAE,UAAU,CAAC,GAAG,IAAI,IAAI,QAAQ,EAAE,OAAQ,CAAA,GAAG;AAEtF,MAAI,CAAC,YAAY,CAAC,SAAS,MAAM;AAC/B,WAAO,CAAC;AAAA,EAAA;AAGN,MAAA;AACJ,aAAW,QAAQ,OAAO,OAAO,SAAS,IAAI,GAAqB;AAC3D,UAAA,mBAAmB,KAAK,SAAU;AAAA,MAAO,CAAC,WAC9C,YAAY,MAAM,CAAC,SAAU;;AAAA,gBAAC,OAAO,WAAS,YAAO,UAAP,mBAAc,SAAS;AAAA,OAAM;AAAA,IAC7E;AACA,QAAI,oBAAoB,QAAW;AACf,wBAAA;AAClB;AAAA,IAAA;AAEgB,sBAAAA,cAAA,eAAe,iBAAiB,kBAAkB,MAAM;AAAA,EAAA;AAGrE,SAAA;AACT;AAEa,MAAA,wBAAwB,CAAC,UAA0B,gBAA0B;AACxF,MAAI,eAA+B,OAAO,OAAO,YAAY,CAAA,CAAE;AAE/D,MAAI,aAAa,UAAU,KAAK,aAAa,CAAC,EAAE,UAAU,QAAW;AAC5D,WAAA;AAAA,EAAA;AAGT,SAAO,aAAa,OAAO,CAAC,OAAO,YAAY,MAAM,CAAC,SAAS,GAAG,MAAO,SAAS,IAAI,CAAC,CAAC;AAC1F;"}
@@ -1,6 +1,7 @@
1
1
  export declare const Path: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
2
2
  export declare const SegmentWrapper: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
3
3
  export declare const Segment: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>> & string;
4
+ export declare const FinalSegmentLabel: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>, never>> & string;
4
5
  export declare const ActiveSegment: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
5
6
  export declare const MoreModal: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLDivElement>, HTMLDivElement>, never>> & string;
6
7
  export declare const MoreList: import('styled-components/dist/types').IStyledComponentBase<"web", import('styled-components').FastOmit<import('react').DetailedHTMLProps<import('react').HTMLAttributes<HTMLUListElement>, HTMLUListElement>, never>> & string;
@@ -2,5 +2,5 @@ import { DetailsPanelEntityData } from '../../api';
2
2
  type Props = {
3
3
  entities: DetailsPanelEntityData[];
4
4
  };
5
- export declare const RepresentationsList: ({ entities }: Props) => import("react/jsx-runtime").JSX.Element | undefined;
5
+ export declare const RepresentationsList: ({ entities }: Props) => import("react/jsx-runtime").JSX.Element;
6
6
  export {};
@@ -1,5 +1,6 @@
1
1
  export * from './useLocalStorage';
2
2
  export * from './useLoadModule';
3
+ export * from './useLoadModules';
3
4
  export * from './useScopedStatuses';
4
5
  export * from './useEntityUpdate';
5
6
  export * from './useActionTriggers';
@@ -0,0 +1,28 @@
1
+ import { FrontendModuleListItem } from '../api';
2
+ export interface ModuleSpec<T> {
3
+ addon: string;
4
+ remote: string;
5
+ module: string;
6
+ fallback?: T;
7
+ debug?: boolean;
8
+ minVersion?: string;
9
+ }
10
+ type ModuleResult<T> = [
11
+ T,
12
+ {
13
+ isLoaded: boolean;
14
+ addon: string;
15
+ remote: string;
16
+ module: string;
17
+ minVersion?: string;
18
+ outdated?: {
19
+ current: string;
20
+ required: string;
21
+ };
22
+ }
23
+ ];
24
+ export declare const useLoadModules: <T extends any[]>(moduleSpecs: ModuleSpec<T[number]>[], modules: FrontendModuleListItem[], skip: boolean) => {
25
+ modules: ModuleResult<T[number]>[];
26
+ isLoading: boolean;
27
+ };
28
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ynput/ayon-frontend-shared",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Shared React components for AYON frontend",
5
5
  "main": "dist/index.cjs.js",
6
6
  "module": "dist/index.es.js",