@collabdt/core 0.0.54 → 0.0.56

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 (83) hide show
  1. package/dist/core/components/AppSidebarContent.d.ts.map +1 -1
  2. package/dist/core/components/AppSidebarContent.js +32 -5
  3. package/dist/core/components/AppSidebarContent.js.map +1 -1
  4. package/dist/core/components/authentication/AuthPage.d.ts.map +1 -1
  5. package/dist/core/components/authentication/AuthPage.js +3 -2
  6. package/dist/core/components/authentication/AuthPage.js.map +1 -1
  7. package/dist/core/components/authentication/Signin.d.ts +5 -1
  8. package/dist/core/components/authentication/Signin.d.ts.map +1 -1
  9. package/dist/core/components/authentication/Signin.js +17 -6
  10. package/dist/core/components/authentication/Signin.js.map +1 -1
  11. package/dist/core/components/instance-not-found/src/OrganizationNotFoundSection.d.ts.map +1 -1
  12. package/dist/core/components/instance-not-found/src/OrganizationNotFoundSection.js +152 -156
  13. package/dist/core/components/instance-not-found/src/OrganizationNotFoundSection.js.map +1 -1
  14. package/dist/core/components/organizationConfig/src/organizationConfigContent.d.ts.map +1 -1
  15. package/dist/core/components/organizationConfig/src/organizationConfigContent.js +146 -150
  16. package/dist/core/components/organizationConfig/src/organizationConfigContent.js.map +1 -1
  17. package/dist/core/components/settings/src/OrganizationSettingsPanel.d.ts.map +1 -1
  18. package/dist/core/components/settings/src/OrganizationSettingsPanel.js +4 -2
  19. package/dist/core/components/settings/src/OrganizationSettingsPanel.js.map +1 -1
  20. package/dist/core/components/support/BugReportDialog.d.ts +7 -0
  21. package/dist/core/components/support/BugReportDialog.d.ts.map +1 -0
  22. package/dist/core/components/support/BugReportDialog.js +117 -0
  23. package/dist/core/components/support/BugReportDialog.js.map +1 -0
  24. package/dist/core/components/support/FeatureRequestDialog.d.ts +8 -0
  25. package/dist/core/components/support/FeatureRequestDialog.d.ts.map +1 -0
  26. package/dist/core/components/support/FeatureRequestDialog.js +116 -0
  27. package/dist/core/components/support/FeatureRequestDialog.js.map +1 -0
  28. package/dist/core/components/support/SupportMenu.d.ts +10 -0
  29. package/dist/core/components/support/SupportMenu.d.ts.map +1 -0
  30. package/dist/core/components/support/SupportMenu.js +78 -0
  31. package/dist/core/components/support/SupportMenu.js.map +1 -0
  32. package/dist/core/components/ui/AnimatedBackground.d.ts.map +1 -1
  33. package/dist/core/components/ui/AnimatedBackground.js +3 -1
  34. package/dist/core/components/ui/AnimatedBackground.js.map +1 -1
  35. package/dist/core/components/ui/AppSidebar.d.ts.map +1 -1
  36. package/dist/core/components/ui/AppSidebar.js +11 -11
  37. package/dist/core/components/ui/AppSidebar.js.map +1 -1
  38. package/dist/core/components/ui/Navbar.d.ts.map +1 -1
  39. package/dist/core/components/ui/Navbar.js +15 -23
  40. package/dist/core/components/ui/Navbar.js.map +1 -1
  41. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.d.ts.map +1 -1
  42. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js +3 -1
  43. package/dist/core/components/ui/Sensors/CollapsibleSensorItem.js.map +1 -1
  44. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.d.ts.map +1 -1
  45. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js +4 -2
  46. package/dist/core/components/viewers/bim/src/tools/AddToBim/src/useSensorMarkers.js.map +1 -1
  47. package/dist/core/components/viewers/map/datasets/RowActions.d.ts.map +1 -1
  48. package/dist/core/components/viewers/map/datasets/RowActions.js +3 -1
  49. package/dist/core/components/viewers/map/datasets/RowActions.js.map +1 -1
  50. package/dist/core/components/viewers/map/datasets/index.js +2 -2
  51. package/dist/core/components/viewers/map/datasets/index.js.map +1 -1
  52. package/dist/core/components/viewers/map/datasets/src/minioDatasets.d.ts +1 -1
  53. package/dist/core/components/viewers/map/datasets/src/minioDatasets.d.ts.map +1 -1
  54. package/dist/core/components/viewers/map/datasets/src/minioDatasets.js +3 -5
  55. package/dist/core/components/viewers/map/datasets/src/minioDatasets.js.map +1 -1
  56. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.d.ts.map +1 -1
  57. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js +5 -3
  58. package/dist/core/components/viewers/map/src/MapLayers/src/SensorsLayer/index.js.map +1 -1
  59. package/dist/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.js +1 -1
  60. package/dist/core/components/viewers/map/src/MapSidebar/src/LayersTab/index.js.map +1 -1
  61. package/dist/core/components/viewers/pointcloud/PointCloudViewer.d.ts.map +1 -1
  62. package/dist/core/components/viewers/pointcloud/PointCloudViewer.js +4 -2
  63. package/dist/core/components/viewers/pointcloud/PointCloudViewer.js.map +1 -1
  64. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.d.ts.map +1 -1
  65. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.js +4 -2
  66. package/dist/core/components/viewers/pointcloud/src/PointCloudLoadingState/index.js.map +1 -1
  67. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.d.ts.map +1 -1
  68. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.js +7 -5
  69. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudTable.js.map +1 -1
  70. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.d.ts.map +1 -1
  71. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.js +15 -8
  72. package/dist/core/components/viewers/pointcloud/src/PointCloudManagement/PointCloudUploadPanel.js.map +1 -1
  73. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.d.ts.map +1 -1
  74. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js +13 -12
  75. package/dist/core/components/viewers/pointcloud/src/PointCloudSidebar/src/FileTab/src/PointCloudSection.js.map +1 -1
  76. package/dist/core/components/viewers/pointcloud/utils/potreeLoader.d.ts.map +1 -1
  77. package/dist/core/components/viewers/pointcloud/utils/potreeLoader.js +1 -1
  78. package/dist/core/components/viewers/pointcloud/utils/potreeLoader.js.map +1 -1
  79. package/dist/core/store/AppConfig/context.d.ts +10 -1
  80. package/dist/core/store/AppConfig/context.d.ts.map +1 -1
  81. package/dist/core/store/AppConfig/context.js +26 -5
  82. package/dist/core/store/AppConfig/context.js.map +1 -1
  83. package/package.json +1 -1
@@ -0,0 +1,7 @@
1
+ import * as React from "react";
2
+ export declare function BugReportDialog({ open, onOpenChange, onCaptureScreenshot, }: {
3
+ open: boolean;
4
+ onOpenChange: (v: boolean) => void;
5
+ onCaptureScreenshot?: () => Promise<string | null>;
6
+ }): React.JSX.Element;
7
+ //# sourceMappingURL=BugReportDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BugReportDialog.d.ts","sourceRoot":"","sources":["../../../../src/core/components/support/BugReportDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAe/B,wBAAgB,eAAe,CAAC,EAC9B,IAAI,EACJ,YAAY,EACZ,mBAAmB,GACpB,EAAE;IACD,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,CAAC,EAAE,OAAO,KAAK,IAAI,CAAC;IACnC,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;CACpD,qBAwGA"}
@@ -0,0 +1,117 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { useTranslations } from "next-intl";
5
+ import {
6
+ Dialog,
7
+ DialogContent,
8
+ DialogHeader,
9
+ DialogTitle
10
+ } from "../ui/Dialog";
11
+ import { Button } from "../ui/Button";
12
+ import { Textarea } from "../ui/Textarea";
13
+ import { Input } from "../ui/Input";
14
+ import * as LR from "lucide-react";
15
+ function BugReportDialog({
16
+ open,
17
+ onOpenChange,
18
+ onCaptureScreenshot
19
+ }) {
20
+ const t = useTranslations("supportDialog");
21
+ const [title, setTitle] = React.useState("");
22
+ const [description, setDescription] = React.useState("");
23
+ const [repro, setRepro] = React.useState("");
24
+ const [screenshot, setScreenshot] = React.useState(null);
25
+ const reset = () => {
26
+ setTitle("");
27
+ setDescription("");
28
+ setRepro("");
29
+ setScreenshot(null);
30
+ };
31
+ const capture = async () => {
32
+ if (!onCaptureScreenshot) return;
33
+ const img = await onCaptureScreenshot();
34
+ setScreenshot(img);
35
+ };
36
+ const submit = async () => {
37
+ await fetch("/api/github-issue", {
38
+ method: "POST",
39
+ headers: { "Content-Type": "application/json" },
40
+ body: JSON.stringify({
41
+ title,
42
+ description,
43
+ type: "bug",
44
+ labels: ["bug"],
45
+ meta: {
46
+ url: window.location.href,
47
+ userAgent: navigator.userAgent,
48
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
49
+ viewer: "Map"
50
+ }
51
+ })
52
+ });
53
+ reset();
54
+ onOpenChange(false);
55
+ };
56
+ return /* @__PURE__ */ jsx(
57
+ Dialog,
58
+ {
59
+ open,
60
+ onOpenChange: (v) => {
61
+ onOpenChange(v);
62
+ if (!v) reset();
63
+ },
64
+ children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-[520px]", children: [
65
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
66
+ /* @__PURE__ */ jsx(LR.Bug, { className: "h-5 w-5" }),
67
+ t("bugTitle")
68
+ ] }) }),
69
+ /* @__PURE__ */ jsxs("div", { className: "space-y-3", children: [
70
+ /* @__PURE__ */ jsx(
71
+ Input,
72
+ {
73
+ placeholder: t("bugTitle"),
74
+ value: title,
75
+ onChange: (e) => setTitle(e.target.value)
76
+ }
77
+ ),
78
+ /* @__PURE__ */ jsx(
79
+ Textarea,
80
+ {
81
+ placeholder: t("descriptionPlaceholder"),
82
+ value: description,
83
+ onChange: (e) => setDescription(e.target.value)
84
+ }
85
+ ),
86
+ /* @__PURE__ */ jsx(
87
+ Textarea,
88
+ {
89
+ placeholder: t("reproPlaceholder"),
90
+ value: repro,
91
+ onChange: (e) => setRepro(e.target.value)
92
+ }
93
+ ),
94
+ /* @__PURE__ */ jsxs("div", { className: "flex gap-2 items-center", children: [
95
+ /* @__PURE__ */ jsx(Button, { onClick: capture, variant: "secondary", children: t("captureScreenshot") }),
96
+ screenshot && /* @__PURE__ */ jsx("span", { className: "text-sm text-muted-foreground", children: t("screenshotAttached") })
97
+ ] }),
98
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
99
+ /* @__PURE__ */ jsx(
100
+ Button,
101
+ {
102
+ variant: "secondary",
103
+ onClick: () => onOpenChange(false),
104
+ children: t("cancel")
105
+ }
106
+ ),
107
+ /* @__PURE__ */ jsx(Button, { onClick: submit, children: t("submit") })
108
+ ] })
109
+ ] })
110
+ ] })
111
+ }
112
+ );
113
+ }
114
+ export {
115
+ BugReportDialog
116
+ };
117
+ //# sourceMappingURL=BugReportDialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/core/components/support/BugReportDialog.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { useTranslations } from \"next-intl\";\r\n\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n} from \"../ui/Dialog\";\r\n\r\nimport { Button } from \"../ui/Button\";\r\nimport { Textarea } from \"../ui/Textarea\";\r\nimport { Input } from \"../ui/Input\";\r\n\r\nimport * as LR from \"lucide-react\";\r\nexport function BugReportDialog({\r\n open,\r\n onOpenChange,\r\n onCaptureScreenshot,\r\n}: {\r\n open: boolean;\r\n onOpenChange: (v: boolean) => void;\r\n onCaptureScreenshot?: () => Promise<string | null>;\r\n}) {\r\n const t = useTranslations(\"supportDialog\");\r\n\r\n const [title, setTitle] = React.useState(\"\");\r\n const [description, setDescription] = React.useState(\"\");\r\n const [repro, setRepro] = React.useState(\"\");\r\n const [screenshot, setScreenshot] = React.useState<string | null>(null);\r\n\r\n const reset = () => {\r\n setTitle(\"\");\r\n setDescription(\"\");\r\n setRepro(\"\");\r\n setScreenshot(null);\r\n };\r\n\r\n const capture = async () => {\r\n if (!onCaptureScreenshot) return;\r\n const img = await onCaptureScreenshot();\r\n setScreenshot(img);\r\n };\r\n\r\n const submit = async () => {\r\n await fetch(\"/api/github-issue\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({\r\n title,\r\n description,\r\n type: \"bug\",\r\n labels: [\"bug\"],\r\n meta: {\r\n url: window.location.href,\r\n userAgent: navigator.userAgent,\r\n timestamp: new Date().toISOString(),\r\n viewer: \"Map\",\r\n },\r\n }),\r\n });\r\n\r\n reset();\r\n onOpenChange(false);\r\n };\r\n\r\n return (\r\n <Dialog\r\n open={open}\r\n onOpenChange={(v) => {\r\n onOpenChange(v);\r\n if (!v) reset();\r\n }}\r\n >\r\n <DialogContent className=\"sm:max-w-[520px]\">\r\n <DialogHeader>\r\n <DialogTitle className=\"flex items-center gap-2\">\r\n <LR.Bug className=\"h-5 w-5\" />\r\n {t(\"bugTitle\")}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n <div className=\"space-y-3\">\r\n <Input\r\n placeholder={t(\"bugTitle\")}\r\n value={title}\r\n onChange={(e) => setTitle(e.target.value)}\r\n />\r\n\r\n <Textarea\r\n placeholder={t(\"descriptionPlaceholder\")}\r\n value={description}\r\n onChange={(e) => setDescription(e.target.value)}\r\n />\r\n\r\n <Textarea\r\n placeholder={t(\"reproPlaceholder\")}\r\n value={repro}\r\n onChange={(e) => setRepro(e.target.value)}\r\n />\r\n\r\n <div className=\"flex gap-2 items-center\"> \r\n <Button onClick={capture} variant=\"secondary\"> \r\n {t(\"captureScreenshot\")} \r\n </Button> \r\n {screenshot && ( \r\n <span className=\"text-sm text-muted-foreground\"> \r\n {t(\"screenshotAttached\")} \r\n </span> )} \r\n </div>\r\n\r\n <div className=\"flex justify-end gap-2\">\r\n <Button\r\n variant=\"secondary\"\r\n onClick={() => onOpenChange(false)}\r\n >\r\n {t(\"cancel\")}\r\n </Button>\r\n\r\n <Button onClick={submit}>\r\n {t(\"submit\")}\r\n </Button>\r\n </div>\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}"],"mappings":"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","names":[]}
@@ -0,0 +1,8 @@
1
+ import * as React from "react";
2
+ type Props = {
3
+ open: boolean;
4
+ onOpenChange: (open: boolean) => void;
5
+ };
6
+ export declare function FeatureRequestDialog({ open, onOpenChange }: Props): React.JSX.Element;
7
+ export {};
8
+ //# sourceMappingURL=FeatureRequestDialog.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FeatureRequestDialog.d.ts","sourceRoot":"","sources":["../../../../src/core/components/support/FeatureRequestDialog.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAgB/B,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,OAAO,CAAC;IACd,YAAY,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACvC,CAAC;AAEF,wBAAgB,oBAAoB,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,EAAE,KAAK,qBAoGjE"}
@@ -0,0 +1,116 @@
1
+ "use client";
2
+ import { jsx, jsxs } from "react/jsx-runtime";
3
+ import * as React from "react";
4
+ import { useTranslations } from "next-intl";
5
+ import {
6
+ Dialog,
7
+ DialogContent,
8
+ DialogHeader,
9
+ DialogTitle
10
+ } from "../ui/Dialog";
11
+ import { Button } from "../ui/Button";
12
+ import { Input } from "../ui/Input";
13
+ import { Textarea } from "../ui/Textarea";
14
+ import * as LR from "lucide-react";
15
+ function FeatureRequestDialog({ open, onOpenChange }) {
16
+ const t = useTranslations("supportDialog");
17
+ const [title, setTitle] = React.useState("");
18
+ const [description, setDescription] = React.useState("");
19
+ const [loading, setLoading] = React.useState(false);
20
+ const reset = () => {
21
+ setTitle("");
22
+ setDescription("");
23
+ };
24
+ const submit = async () => {
25
+ if (!title.trim() || !description.trim()) return;
26
+ try {
27
+ setLoading(true);
28
+ await fetch("/api/github-issue", {
29
+ method: "POST",
30
+ headers: { "Content-Type": "application/json" },
31
+ body: JSON.stringify({
32
+ title,
33
+ description,
34
+ type: "feature",
35
+ labels: ["feature"],
36
+ meta: {
37
+ url: window.location.href,
38
+ userAgent: navigator.userAgent,
39
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
40
+ viewer: "BIM"
41
+ }
42
+ })
43
+ });
44
+ reset();
45
+ onOpenChange(false);
46
+ } catch (err) {
47
+ console.error("Feature request failed:", err);
48
+ } finally {
49
+ setLoading(false);
50
+ }
51
+ };
52
+ return /* @__PURE__ */ jsx(
53
+ Dialog,
54
+ {
55
+ open,
56
+ onOpenChange: (v) => {
57
+ onOpenChange(v);
58
+ if (!v) reset();
59
+ },
60
+ children: /* @__PURE__ */ jsxs(DialogContent, { className: "sm:max-w-[520px]", children: [
61
+ /* @__PURE__ */ jsx(DialogHeader, { children: /* @__PURE__ */ jsxs(DialogTitle, { className: "flex items-center gap-2", children: [
62
+ /* @__PURE__ */ jsx(LR.SquarePlus, { className: "h-5 w-5" }),
63
+ t("featureTitle")
64
+ ] }) }),
65
+ /* @__PURE__ */ jsxs("div", { className: "space-y-4 mt-2", children: [
66
+ /* @__PURE__ */ jsx(
67
+ Input,
68
+ {
69
+ placeholder: t("featureTitle"),
70
+ value: title,
71
+ onChange: (e) => setTitle(e.target.value)
72
+ }
73
+ ),
74
+ /* @__PURE__ */ jsx(
75
+ Textarea,
76
+ {
77
+ placeholder: t("descriptionPlaceholder"),
78
+ value: description,
79
+ onChange: (e) => setDescription(e.target.value),
80
+ rows: 5
81
+ }
82
+ ),
83
+ /* @__PURE__ */ jsxs("div", { className: "text-sm text-muted-foreground", children: [
84
+ " ",
85
+ t("wantToBuild"),
86
+ " ",
87
+ /* @__PURE__ */ jsx("a", { href: "https://docs.collabdt.org/docs/plugins/overview", target: "_blank", rel: "noreferrer", className: "underline hover:text-foreground", children: t("pluginDocumentation") })
88
+ ] }),
89
+ /* @__PURE__ */ jsxs("div", { className: "flex justify-end gap-2", children: [
90
+ /* @__PURE__ */ jsx(
91
+ Button,
92
+ {
93
+ variant: "secondary",
94
+ onClick: () => onOpenChange(false),
95
+ disabled: loading,
96
+ children: t("cancel")
97
+ }
98
+ ),
99
+ /* @__PURE__ */ jsx(
100
+ Button,
101
+ {
102
+ onClick: submit,
103
+ disabled: !title.trim() || !description.trim() || loading,
104
+ children: loading ? "..." : t("submit")
105
+ }
106
+ )
107
+ ] })
108
+ ] })
109
+ ] })
110
+ }
111
+ );
112
+ }
113
+ export {
114
+ FeatureRequestDialog
115
+ };
116
+ //# sourceMappingURL=FeatureRequestDialog.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/core/components/support/FeatureRequestDialog.tsx"],"sourcesContent":["\"use client\";\r\n\r\nimport * as React from \"react\";\r\nimport { useTranslations } from \"next-intl\";\r\n\r\nimport {\r\n Dialog,\r\n DialogContent,\r\n DialogHeader,\r\n DialogTitle,\r\n} from \"../ui/Dialog\";\r\n\r\nimport { Button } from \"../ui/Button\";\r\nimport { Input } from \"../ui/Input\";\r\nimport { Textarea } from \"../ui/Textarea\";\r\n\r\nimport * as LR from \"lucide-react\";\r\n\r\ntype Props = {\r\n open: boolean;\r\n onOpenChange: (open: boolean) => void;\r\n};\r\n\r\nexport function FeatureRequestDialog({ open, onOpenChange }: Props) {\r\n const t = useTranslations(\"supportDialog\");\r\n\r\n const [title, setTitle] = React.useState(\"\");\r\n const [description, setDescription] = React.useState(\"\");\r\n const [loading, setLoading] = React.useState(false);\r\n\r\n const reset = () => {\r\n setTitle(\"\");\r\n setDescription(\"\");\r\n };\r\n\r\n const submit = async () => {\r\n if (!title.trim() || !description.trim()) return;\r\n\r\n try {\r\n setLoading(true);\r\n\r\n await fetch(\"/api/github-issue\", {\r\n method: \"POST\",\r\n headers: { \"Content-Type\": \"application/json\" },\r\n body: JSON.stringify({\r\n title,\r\n description,\r\n type: \"feature\",\r\n labels: [\"feature\"],\r\n meta: {\r\n url: window.location.href,\r\n userAgent: navigator.userAgent,\r\n timestamp: new Date().toISOString(),\r\n viewer: \"BIM\",\r\n },\r\n }),\r\n });\r\n\r\n reset();\r\n onOpenChange(false);\r\n } catch (err) {\r\n console.error(\"Feature request failed:\", err);\r\n } finally {\r\n setLoading(false);\r\n }\r\n };\r\n\r\n return (\r\n <Dialog\r\n open={open}\r\n onOpenChange={(v) => {\r\n onOpenChange(v);\r\n if (!v) reset();\r\n }}\r\n >\r\n <DialogContent className=\"sm:max-w-[520px]\">\r\n <DialogHeader>\r\n <DialogTitle className=\"flex items-center gap-2\">\r\n <LR.SquarePlus className=\"h-5 w-5\" />\r\n {t(\"featureTitle\")}\r\n </DialogTitle>\r\n </DialogHeader>\r\n\r\n <div className=\"space-y-4 mt-2\">\r\n <Input\r\n placeholder={t(\"featureTitle\")}\r\n value={title}\r\n onChange={(e) => setTitle(e.target.value)}\r\n />\r\n\r\n <Textarea\r\n placeholder={t(\"descriptionPlaceholder\")}\r\n value={description}\r\n onChange={(e) => setDescription(e.target.value)}\r\n rows={5}\r\n />\r\n\r\n <div className=\"text-sm text-muted-foreground\"> {t(\"wantToBuild\")}{\" \"} \r\n <a href=\"https://docs.collabdt.org/docs/plugins/overview\" target=\"_blank\" rel=\"noreferrer\" className=\"underline hover:text-foreground\" > \r\n {t(\"pluginDocumentation\")}\r\n </a> \r\n </div>\r\n\r\n <div className=\"flex justify-end gap-2\">\r\n <Button\r\n variant=\"secondary\"\r\n onClick={() => onOpenChange(false)}\r\n disabled={loading}\r\n >\r\n {t(\"cancel\")}\r\n </Button>\r\n\r\n <Button\r\n onClick={submit}\r\n disabled={!title.trim() || !description.trim() || loading}\r\n >\r\n {loading ? \"...\" : t(\"submit\")}\r\n </Button>\r\n </div>\r\n </div>\r\n </DialogContent>\r\n </Dialog>\r\n );\r\n}"],"mappings":"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","names":[]}
@@ -0,0 +1,10 @@
1
+ import * as React from "react";
2
+ type Props = {
3
+ item: any;
4
+ isCollapsed: boolean;
5
+ onOpenBug: () => void;
6
+ onOpenFeature: () => void;
7
+ };
8
+ export declare function SupportMenu({ item, isCollapsed, onOpenBug, onOpenFeature, }: Props): React.JSX.Element;
9
+ export {};
10
+ //# sourceMappingURL=SupportMenu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SupportMenu.d.ts","sourceRoot":"","sources":["../../../../src/core/components/support/SupportMenu.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAY/B,KAAK,KAAK,GAAG;IACX,IAAI,EAAE,GAAG,CAAC;IACV,WAAW,EAAE,OAAO,CAAC;IACrB,SAAS,EAAE,MAAM,IAAI,CAAC;IACtB,aAAa,EAAE,MAAM,IAAI,CAAC;CAC3B,CAAC;AAEF,wBAAgB,WAAW,CAAC,EAC1B,IAAI,EACJ,WAAW,EACX,SAAS,EACT,aAAa,GACd,EAAE,KAAK,qBA2DP"}
@@ -0,0 +1,78 @@
1
+ import { jsx, jsxs } from "react/jsx-runtime";
2
+ import * as LR from "lucide-react";
3
+ import * as React from "react";
4
+ import { useTranslations } from "next-intl";
5
+ import {
6
+ DropdownMenu,
7
+ DropdownMenuTrigger,
8
+ DropdownMenuContent,
9
+ DropdownMenuItem
10
+ } from "../ui/DropdownMenu";
11
+ import { SidebarMenuButton } from "../ui/Sidebar";
12
+ function SupportMenu({
13
+ item,
14
+ isCollapsed,
15
+ onOpenBug,
16
+ onOpenFeature
17
+ }) {
18
+ const t = useTranslations("supportMenu");
19
+ const [menuOpen, setMenuOpen] = React.useState(false);
20
+ const openDialogAfterMenuCloses = (callback) => {
21
+ setMenuOpen(false);
22
+ requestAnimationFrame(() => {
23
+ callback();
24
+ });
25
+ };
26
+ return /* @__PURE__ */ jsxs(DropdownMenu, { open: menuOpen, onOpenChange: setMenuOpen, children: [
27
+ /* @__PURE__ */ jsx(DropdownMenuTrigger, { asChild: true, children: /* @__PURE__ */ jsxs(
28
+ SidebarMenuButton,
29
+ {
30
+ title: item.tooltip,
31
+ className: `text-xs flex items-center gap-2 w-full ${isCollapsed ? "justify-center p-2" : "justify-start p-2"}`,
32
+ children: [
33
+ /* @__PURE__ */ jsx(LR.LifeBuoy, { className: "h-4 w-4" }),
34
+ !isCollapsed && /* @__PURE__ */ jsx("span", { children: item.title })
35
+ ]
36
+ }
37
+ ) }),
38
+ /* @__PURE__ */ jsxs(DropdownMenuContent, { align: "start", children: [
39
+ /* @__PURE__ */ jsxs(
40
+ DropdownMenuItem,
41
+ {
42
+ onSelect: () => window.open(
43
+ "mailto:support@collabdt.org?subject=Support Request",
44
+ "_self"
45
+ ),
46
+ children: [
47
+ /* @__PURE__ */ jsx(LR.Send, { className: "mr-2 h-4 w-4" }),
48
+ t("contactTeam")
49
+ ]
50
+ }
51
+ ),
52
+ /* @__PURE__ */ jsxs(
53
+ DropdownMenuItem,
54
+ {
55
+ onSelect: () => openDialogAfterMenuCloses(onOpenFeature),
56
+ children: [
57
+ /* @__PURE__ */ jsx(LR.SquarePlus, { className: "mr-2 h-4 w-4" }),
58
+ t("suggestFeature")
59
+ ]
60
+ }
61
+ ),
62
+ /* @__PURE__ */ jsxs(
63
+ DropdownMenuItem,
64
+ {
65
+ onSelect: () => openDialogAfterMenuCloses(onOpenBug),
66
+ children: [
67
+ /* @__PURE__ */ jsx(LR.Bug, { className: "mr-2 h-4 w-4" }),
68
+ t("reportBug")
69
+ ]
70
+ }
71
+ )
72
+ ] })
73
+ ] });
74
+ }
75
+ export {
76
+ SupportMenu
77
+ };
78
+ //# sourceMappingURL=SupportMenu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../../src/core/components/support/SupportMenu.tsx"],"sourcesContent":["import * as LR from \"lucide-react\";\r\nimport * as React from \"react\";\r\nimport { useTranslations } from \"next-intl\";\r\n\r\nimport {\r\n DropdownMenu,\r\n DropdownMenuTrigger,\r\n DropdownMenuContent,\r\n DropdownMenuItem,\r\n} from \"../ui/DropdownMenu\";\r\n\r\nimport { SidebarMenuButton } from \"../ui/Sidebar\";\r\n\r\ntype Props = {\r\n item: any;\r\n isCollapsed: boolean;\r\n onOpenBug: () => void;\r\n onOpenFeature: () => void;\r\n};\r\n\r\nexport function SupportMenu({\r\n item,\r\n isCollapsed,\r\n onOpenBug,\r\n onOpenFeature,\r\n}: Props) {\r\n const t = useTranslations(\"supportMenu\");\r\n const [menuOpen, setMenuOpen] = React.useState(false);\r\n\r\n const openDialogAfterMenuCloses = (callback: () => void) => {\r\n setMenuOpen(false);\r\n\r\n requestAnimationFrame(() => {\r\n callback();\r\n });\r\n };\r\n\r\n return (\r\n <DropdownMenu open={menuOpen} onOpenChange={setMenuOpen}>\r\n <DropdownMenuTrigger asChild>\r\n <SidebarMenuButton\r\n title={item.tooltip}\r\n className={`text-xs flex items-center gap-2 w-full ${\r\n isCollapsed ? \"justify-center p-2\" : \"justify-start p-2\"\r\n }`}\r\n >\r\n <LR.LifeBuoy className=\"h-4 w-4\" />\r\n {!isCollapsed && <span>{item.title}</span>}\r\n </SidebarMenuButton>\r\n </DropdownMenuTrigger>\r\n\r\n <DropdownMenuContent align=\"start\">\r\n <DropdownMenuItem\r\n onSelect={() =>\r\n window.open(\r\n \"mailto:support@collabdt.org?subject=Support Request\",\r\n \"_self\"\r\n )\r\n }\r\n >\r\n <LR.Send className=\"mr-2 h-4 w-4\" />\r\n {t(\"contactTeam\")}\r\n </DropdownMenuItem>\r\n\r\n <DropdownMenuItem\r\n onSelect={() =>\r\n openDialogAfterMenuCloses(onOpenFeature)\r\n }\r\n >\r\n <LR.SquarePlus className=\"mr-2 h-4 w-4\" />\r\n {t(\"suggestFeature\")}\r\n </DropdownMenuItem>\r\n\r\n <DropdownMenuItem\r\n onSelect={() =>\r\n openDialogAfterMenuCloses(onOpenBug)\r\n }\r\n >\r\n <LR.Bug className=\"mr-2 h-4 w-4\" />\r\n {t(\"reportBug\")}\r\n </DropdownMenuItem>\r\n </DropdownMenuContent>\r\n </DropdownMenu>\r\n );\r\n}\r\n\r\n"],"mappings":"AAwCQ,SAME,KANF;AAxCR,YAAY,QAAQ;AACpB,YAAY,WAAW;AACvB,SAAS,uBAAuB;AAEhC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAEP,SAAS,yBAAyB;AAS3B,SAAS,YAAY;AAAA,EAC1B;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,GAAU;AACR,QAAM,IAAI,gBAAgB,aAAa;AACvC,QAAM,CAAC,UAAU,WAAW,IAAI,MAAM,SAAS,KAAK;AAEpD,QAAM,4BAA4B,CAAC,aAAyB;AAC1D,gBAAY,KAAK;AAEjB,0BAAsB,MAAM;AAC1B,eAAS;AAAA,IACX,CAAC;AAAA,EACH;AAEA,SACE,qBAAC,gBAAa,MAAM,UAAU,cAAc,aAC1C;AAAA,wBAAC,uBAAoB,SAAO,MAC1B;AAAA,MAAC;AAAA;AAAA,QACC,OAAO,KAAK;AAAA,QACZ,WAAW,0CACT,cAAc,uBAAuB,mBACvC;AAAA,QAEA;AAAA,8BAAC,GAAG,UAAH,EAAY,WAAU,WAAU;AAAA,UAChC,CAAC,eAAe,oBAAC,UAAM,eAAK,OAAM;AAAA;AAAA;AAAA,IACrC,GACF;AAAA,IAEA,qBAAC,uBAAoB,OAAM,SACzB;AAAA;AAAA,QAAC;AAAA;AAAA,UACC,UAAU,MACR,OAAO;AAAA,YACL;AAAA,YACA;AAAA,UACF;AAAA,UAGF;AAAA,gCAAC,GAAG,MAAH,EAAQ,WAAU,gBAAe;AAAA,YACjC,EAAE,aAAa;AAAA;AAAA;AAAA,MAClB;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,UAAU,MACR,0BAA0B,aAAa;AAAA,UAGzC;AAAA,gCAAC,GAAG,YAAH,EAAc,WAAU,gBAAe;AAAA,YACvC,EAAE,gBAAgB;AAAA;AAAA;AAAA,MACrB;AAAA,MAEA;AAAA,QAAC;AAAA;AAAA,UACC,UAAU,MACR,0BAA0B,SAAS;AAAA,UAGrC;AAAA,gCAAC,GAAG,KAAH,EAAO,WAAU,gBAAe;AAAA,YAChC,EAAE,WAAW;AAAA;AAAA;AAAA,MAChB;AAAA,OACF;AAAA,KACF;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"AnimatedBackground.d.ts","sourceRoot":"","sources":["../../../../src/core/components/ui/AnimatedBackground.tsx"],"names":[],"mappings":"AAQA,UAAU,KAAK;IACb,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;CACzB;AAED,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EAAE,KAAK,EAAE,GAAE,KAAU,+BA6O/D"}
1
+ {"version":3,"file":"AnimatedBackground.d.ts","sourceRoot":"","sources":["../../../../src/core/components/ui/AnimatedBackground.tsx"],"names":[],"mappings":"AASA,UAAU,KAAK;IACb,KAAK,CAAC,EAAE,OAAO,GAAG,MAAM,CAAA;CACzB;AAED,MAAM,CAAC,OAAO,UAAU,kBAAkB,CAAC,EAAE,KAAK,EAAE,GAAE,KAAU,+BA8O/D"}
@@ -2,6 +2,7 @@
2
2
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
3
3
  import { useEffect, useRef, useState } from "react";
4
4
  import { useMotionValue, useSpring } from "framer-motion";
5
+ import { useAppConfigContext } from "../../store/AppConfig/context";
5
6
  function AnimatedBackground({ theme } = {}) {
6
7
  const canvasRef = useRef(null);
7
8
  const mouseX = useMotionValue(0);
@@ -156,7 +157,8 @@ function AnimatedBackground({ theme } = {}) {
156
157
  window.removeEventListener("resize", resize);
157
158
  };
158
159
  }, [smoothMouseX, smoothMouseY, isDark]);
159
- const assetsUrl = process.env.NEXT_PUBLIC_MINIO_BUCKET_URL || "";
160
+ const { state: { runtimeConfig: { minioUrl } } } = useAppConfigContext();
161
+ const assetsUrl = minioUrl || "";
160
162
  return /* @__PURE__ */ jsxs(Fragment, { children: [
161
163
  /* @__PURE__ */ jsx("div", { className: "absolute top-0 right-0 inset-0 z-10 w-screen", children: /* @__PURE__ */ jsx(
162
164
  "img",
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/components/ui/AnimatedBackground.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport { useEffect, useRef, useState } from 'react'\r\nimport { useMotionValue, useSpring } from 'framer-motion'\r\n\r\ninterface Props {\r\n theme?: 'light' | 'dark'\r\n}\r\n\r\nexport default function AnimatedBackground({ theme }: Props = {}) {\r\n const canvasRef = useRef<HTMLCanvasElement>(null)\r\n const mouseX = useMotionValue(0)\r\n const mouseY = useMotionValue(0)\r\n const smoothMouseX = useSpring(mouseX, { stiffness: 50, damping: 20 })\r\n const smoothMouseY = useSpring(mouseY, { stiffness: 50, damping: 20 })\r\n const [isDark, setIsDark] = useState(theme !== undefined ? theme === 'dark' : true)\r\n\r\n useEffect(() => {\r\n // If theme is controlled externally, just sync and skip the observer\r\n if (theme !== undefined) {\r\n setIsDark(theme === 'dark')\r\n return\r\n }\r\n\r\n // Auto-detect from document for standalone usage (hero section)\r\n setIsDark(document.documentElement.classList.contains('dark'))\r\n const observer = new MutationObserver(() => {\r\n setIsDark(document.documentElement.classList.contains('dark'))\r\n })\r\n observer.observe(document.documentElement, {\r\n attributes: true,\r\n attributeFilter: ['class']\r\n })\r\n return () => observer.disconnect()\r\n }, [theme])\r\n\r\n useEffect(() => {\r\n const handleMouseMove = (e: MouseEvent) => {\r\n mouseX.set(e.clientX)\r\n mouseY.set(e.clientY)\r\n }\r\n\r\n window.addEventListener('mousemove', handleMouseMove)\r\n return () => window.removeEventListener('mousemove', handleMouseMove)\r\n }, [mouseX, mouseY])\r\n\r\n useEffect(() => {\r\n const canvas = canvasRef.current\r\n if (!canvas) return\r\n\r\n const ctx = canvas.getContext('2d')\r\n if (!ctx) return\r\n\r\n const resize = () => {\r\n canvas.width = window.innerWidth\r\n canvas.height = window.innerHeight\r\n }\r\n resize()\r\n window.addEventListener('resize', resize)\r\n\r\n let animationFrameId: number\r\n let time = 0\r\n let offsetX = 0\r\n\r\n interface DataNode {\r\n x: number\r\n y: number\r\n baseX: number\r\n baseY: number\r\n connections: number[]\r\n pulse: number\r\n }\r\n\r\n const dataNodes: DataNode[] = []\r\n const gridSize = 100\r\n const nodeSpacing = 150\r\n // Render extra columns for seamless wrap\r\n const nodeCols = Math.ceil(canvas.width / nodeSpacing) + 2\r\n const nodeRows = Math.ceil(canvas.height / nodeSpacing)\r\n\r\n for (let row = 0; row < nodeRows; row++) {\r\n for (let col = 0; col < nodeCols; col++) {\r\n const index = row * nodeCols + col\r\n const baseX = col * nodeSpacing + nodeSpacing / 2\r\n const baseY = row * nodeSpacing + nodeSpacing / 2\r\n dataNodes.push({\r\n x: baseX,\r\n y: baseY,\r\n baseX,\r\n baseY,\r\n connections: [],\r\n pulse: (row + col) * 0.5\r\n })\r\n }\r\n }\r\n\r\n dataNodes.forEach((node, i) => {\r\n const col = i % nodeCols\r\n const row = Math.floor(i / nodeCols)\r\n if (col < nodeCols - 1) {\r\n node.connections.push(i + 1)\r\n }\r\n if (row < nodeRows - 1) {\r\n node.connections.push(i + nodeCols)\r\n }\r\n })\r\n\r\n const draw = () => {\r\n time += 0.008\r\n // Move left slowly\r\n offsetX += 0.1 // Lower for slower movement\r\n // Loop offsetX to avoid overflow and create infinite effect\r\n if (offsetX > nodeSpacing) offsetX -= nodeSpacing\r\n\r\n ctx.clearRect(0, 0, canvas.width, canvas.height)\r\n\r\n // Theme-aware colors\r\n const bgGradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height)\r\n if (isDark) {\r\n bgGradient.addColorStop(0, 'rgba(239, 145, 97, 0.025)')\r\n bgGradient.addColorStop(1, 'rgba(180, 90, 40, 0.02)')\r\n } else {\r\n bgGradient.addColorStop(0, 'rgba(239, 146, 98, 0.08)')\r\n bgGradient.addColorStop(1, 'rgba(239, 146, 98, 0.06)')\r\n }\r\n ctx.fillStyle = bgGradient\r\n ctx.fillRect(0, 0, canvas.width, canvas.height)\r\n\r\n // Animate node positions with floating effect\r\n dataNodes.forEach((node, i) => {\r\n const floatX = Math.sin(time * 0.3 + node.pulse) * 2\r\n const floatY = Math.cos(time * 0.2 + node.pulse) * 2\r\n // Shift node baseX by offsetX for infinite left movement\r\n let x = node.baseX - offsetX + floatX\r\n // Wrap node.x to the right if it goes off the left edge\r\n x = ((x + nodeCols * nodeSpacing) % (nodeCols * nodeSpacing))\r\n node.x = x\r\n node.y = node.baseY + floatY\r\n })\r\n\r\n // Theme-aware grid lines\r\n ctx.strokeStyle = isDark ? 'rgba(239, 145, 97, 0.08)' : 'rgba(239, 146, 98, 0.3)'\r\n ctx.lineWidth = 0.5\r\n \r\n for (let y = canvas.height; y > canvas.height * 0.3; y -= gridSize) {\r\n ctx.beginPath()\r\n ctx.moveTo(0, y)\r\n ctx.lineTo(canvas.width, y)\r\n ctx.stroke()\r\n }\r\n \r\n const verticalSpacing = gridSize * 1.5\r\n // Render extra vertical grid lines for seamless wrap\r\n const gridCols = Math.ceil(canvas.width / verticalSpacing) + 2\r\n for (let i = 0; i < gridCols; i++) {\r\n // Shift grid lines by offsetX for infinite left movement\r\n let x = i * verticalSpacing - offsetX % verticalSpacing - verticalSpacing\r\n // Wrap x for seamless effect\r\n x = ((x + gridCols * verticalSpacing) % (gridCols * verticalSpacing))\r\n ctx.beginPath()\r\n ctx.moveTo(x, canvas.height)\r\n ctx.lineTo(x + (x - canvas.width / 2) * 0.3, canvas.height * 0.3)\r\n ctx.stroke()\r\n }\r\n\r\n // Theme-aware connections with data flow\r\n ctx.lineWidth = 0.8\r\n dataNodes.forEach((node, i) => {\r\n node.connections.forEach(targetIndex => {\r\n const target = dataNodes[targetIndex]\r\n const pulse = (Math.sin(time + node.pulse) + 1) / 2\r\n \r\n ctx.beginPath()\r\n ctx.moveTo(node.x, node.y)\r\n ctx.lineTo(target.x, target.y)\r\n ctx.strokeStyle = isDark\r\n ? `rgba(239, 145, 97, ${0.1 + pulse * 0.08})`\r\n : `rgba(239, 146, 98, ${0.35 + pulse * 0.2})`\r\n ctx.stroke()\r\n\r\n // Animated data particles flowing along connections\r\n const flowProgress = (time * 0.3 + node.pulse) % 1\r\n const particleX = node.x + (target.x - node.x) * flowProgress\r\n const particleY = node.y + (target.y - node.y) * flowProgress\r\n\r\n ctx.beginPath()\r\n ctx.arc(particleX, particleY, 1.5, 0, Math.PI * 2)\r\n ctx.fillStyle = isDark\r\n ? `rgba(239, 145, 97, ${0.5 + pulse * 0.3})`\r\n : `rgba(239, 146, 98, ${0.7 + pulse * 0.3})`\r\n ctx.fill()\r\n })\r\n })\r\n\r\n // Theme-aware nodes\r\n dataNodes.forEach(node => {\r\n const pulse = (Math.sin(time + node.pulse) + 1) / 2\r\n const size = 2.5 + pulse * 1\r\n \r\n ctx.beginPath()\r\n ctx.arc(node.x, node.y, size * 2, 0, Math.PI * 2)\r\n ctx.fillStyle = isDark\r\n ? `rgba(239, 145, 97, ${0.12 + pulse * 0.1})`\r\n : `rgba(239, 146, 98, ${0.3 + pulse * 0.15})`\r\n ctx.fill()\r\n\r\n ctx.beginPath()\r\n ctx.arc(node.x, node.y, size, 0, Math.PI * 2)\r\n ctx.fillStyle = isDark\r\n ? `rgba(239, 145, 97, ${0.55 + pulse * 0.25})`\r\n : `rgba(239, 146, 98, ${0.75 + pulse * 0.2})`\r\n ctx.fill()\r\n })\r\n\r\n animationFrameId = requestAnimationFrame(draw)\r\n }\r\n\r\n draw()\r\n\r\n return () => {\r\n cancelAnimationFrame(animationFrameId)\r\n window.removeEventListener('resize', resize)\r\n }\r\n }, [smoothMouseX, smoothMouseY, isDark])\r\n\r\n const assetsUrl = process.env.NEXT_PUBLIC_MINIO_BUCKET_URL || ''\r\n\r\n return (\r\n <>\r\n <div className=\"absolute top-0 right-0 inset-0 z-10 w-screen\">\r\n <img\r\n src={`${assetsUrl}/cdt-homepage/home-bg.png`}\r\n alt=\"Background\"\r\n className=\"object-cover opacity-10 w-screen\"\r\n style={{ filter: isDark ? 'invert(0)' : 'invert(1)' }}\r\n />\r\n </div>\r\n <div className=\"absolute w-screen inset-0 bg-gradient-to-br from-background/10 via-background/5 to-primary/5\" />\r\n <canvas\r\n ref={canvasRef}\r\n className=\"absolute inset-0 w-full h-full opacity-30\"\r\n style={{ mixBlendMode: isDark ? 'screen' : 'multiply' }}\r\n />\r\n <div className=\"absolute inset-0 bg-gradient-to-t from-background/30 via-background/10 to-transparent\" />\r\n </>\r\n )\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/components/ui/AnimatedBackground.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport { useEffect, useRef, useState } from 'react'\r\nimport { useMotionValue, useSpring } from 'framer-motion'\r\nimport { useAppConfigContext } from '../../store/AppConfig/context'\r\n\r\ninterface Props {\r\n theme?: 'light' | 'dark'\r\n}\r\n\r\nexport default function AnimatedBackground({ theme }: Props = {}) {\r\n const canvasRef = useRef<HTMLCanvasElement>(null)\r\n const mouseX = useMotionValue(0)\r\n const mouseY = useMotionValue(0)\r\n const smoothMouseX = useSpring(mouseX, { stiffness: 50, damping: 20 })\r\n const smoothMouseY = useSpring(mouseY, { stiffness: 50, damping: 20 })\r\n const [isDark, setIsDark] = useState(theme !== undefined ? theme === 'dark' : true)\r\n\r\n useEffect(() => {\r\n // If theme is controlled externally, just sync and skip the observer\r\n if (theme !== undefined) {\r\n setIsDark(theme === 'dark')\r\n return\r\n }\r\n\r\n // Auto-detect from document for standalone usage (hero section)\r\n setIsDark(document.documentElement.classList.contains('dark'))\r\n const observer = new MutationObserver(() => {\r\n setIsDark(document.documentElement.classList.contains('dark'))\r\n })\r\n observer.observe(document.documentElement, {\r\n attributes: true,\r\n attributeFilter: ['class']\r\n })\r\n return () => observer.disconnect()\r\n }, [theme])\r\n\r\n useEffect(() => {\r\n const handleMouseMove = (e: MouseEvent) => {\r\n mouseX.set(e.clientX)\r\n mouseY.set(e.clientY)\r\n }\r\n\r\n window.addEventListener('mousemove', handleMouseMove)\r\n return () => window.removeEventListener('mousemove', handleMouseMove)\r\n }, [mouseX, mouseY])\r\n\r\n useEffect(() => {\r\n const canvas = canvasRef.current\r\n if (!canvas) return\r\n\r\n const ctx = canvas.getContext('2d')\r\n if (!ctx) return\r\n\r\n const resize = () => {\r\n canvas.width = window.innerWidth\r\n canvas.height = window.innerHeight\r\n }\r\n resize()\r\n window.addEventListener('resize', resize)\r\n\r\n let animationFrameId: number\r\n let time = 0\r\n let offsetX = 0\r\n\r\n interface DataNode {\r\n x: number\r\n y: number\r\n baseX: number\r\n baseY: number\r\n connections: number[]\r\n pulse: number\r\n }\r\n\r\n const dataNodes: DataNode[] = []\r\n const gridSize = 100\r\n const nodeSpacing = 150\r\n // Render extra columns for seamless wrap\r\n const nodeCols = Math.ceil(canvas.width / nodeSpacing) + 2\r\n const nodeRows = Math.ceil(canvas.height / nodeSpacing)\r\n\r\n for (let row = 0; row < nodeRows; row++) {\r\n for (let col = 0; col < nodeCols; col++) {\r\n const index = row * nodeCols + col\r\n const baseX = col * nodeSpacing + nodeSpacing / 2\r\n const baseY = row * nodeSpacing + nodeSpacing / 2\r\n dataNodes.push({\r\n x: baseX,\r\n y: baseY,\r\n baseX,\r\n baseY,\r\n connections: [],\r\n pulse: (row + col) * 0.5\r\n })\r\n }\r\n }\r\n\r\n dataNodes.forEach((node, i) => {\r\n const col = i % nodeCols\r\n const row = Math.floor(i / nodeCols)\r\n if (col < nodeCols - 1) {\r\n node.connections.push(i + 1)\r\n }\r\n if (row < nodeRows - 1) {\r\n node.connections.push(i + nodeCols)\r\n }\r\n })\r\n\r\n const draw = () => {\r\n time += 0.008\r\n // Move left slowly\r\n offsetX += 0.1 // Lower for slower movement\r\n // Loop offsetX to avoid overflow and create infinite effect\r\n if (offsetX > nodeSpacing) offsetX -= nodeSpacing\r\n\r\n ctx.clearRect(0, 0, canvas.width, canvas.height)\r\n\r\n // Theme-aware colors\r\n const bgGradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height)\r\n if (isDark) {\r\n bgGradient.addColorStop(0, 'rgba(239, 145, 97, 0.025)')\r\n bgGradient.addColorStop(1, 'rgba(180, 90, 40, 0.02)')\r\n } else {\r\n bgGradient.addColorStop(0, 'rgba(239, 146, 98, 0.08)')\r\n bgGradient.addColorStop(1, 'rgba(239, 146, 98, 0.06)')\r\n }\r\n ctx.fillStyle = bgGradient\r\n ctx.fillRect(0, 0, canvas.width, canvas.height)\r\n\r\n // Animate node positions with floating effect\r\n dataNodes.forEach((node, i) => {\r\n const floatX = Math.sin(time * 0.3 + node.pulse) * 2\r\n const floatY = Math.cos(time * 0.2 + node.pulse) * 2\r\n // Shift node baseX by offsetX for infinite left movement\r\n let x = node.baseX - offsetX + floatX\r\n // Wrap node.x to the right if it goes off the left edge\r\n x = ((x + nodeCols * nodeSpacing) % (nodeCols * nodeSpacing))\r\n node.x = x\r\n node.y = node.baseY + floatY\r\n })\r\n\r\n // Theme-aware grid lines\r\n ctx.strokeStyle = isDark ? 'rgba(239, 145, 97, 0.08)' : 'rgba(239, 146, 98, 0.3)'\r\n ctx.lineWidth = 0.5\r\n \r\n for (let y = canvas.height; y > canvas.height * 0.3; y -= gridSize) {\r\n ctx.beginPath()\r\n ctx.moveTo(0, y)\r\n ctx.lineTo(canvas.width, y)\r\n ctx.stroke()\r\n }\r\n \r\n const verticalSpacing = gridSize * 1.5\r\n // Render extra vertical grid lines for seamless wrap\r\n const gridCols = Math.ceil(canvas.width / verticalSpacing) + 2\r\n for (let i = 0; i < gridCols; i++) {\r\n // Shift grid lines by offsetX for infinite left movement\r\n let x = i * verticalSpacing - offsetX % verticalSpacing - verticalSpacing\r\n // Wrap x for seamless effect\r\n x = ((x + gridCols * verticalSpacing) % (gridCols * verticalSpacing))\r\n ctx.beginPath()\r\n ctx.moveTo(x, canvas.height)\r\n ctx.lineTo(x + (x - canvas.width / 2) * 0.3, canvas.height * 0.3)\r\n ctx.stroke()\r\n }\r\n\r\n // Theme-aware connections with data flow\r\n ctx.lineWidth = 0.8\r\n dataNodes.forEach((node, i) => {\r\n node.connections.forEach(targetIndex => {\r\n const target = dataNodes[targetIndex]\r\n const pulse = (Math.sin(time + node.pulse) + 1) / 2\r\n \r\n ctx.beginPath()\r\n ctx.moveTo(node.x, node.y)\r\n ctx.lineTo(target.x, target.y)\r\n ctx.strokeStyle = isDark\r\n ? `rgba(239, 145, 97, ${0.1 + pulse * 0.08})`\r\n : `rgba(239, 146, 98, ${0.35 + pulse * 0.2})`\r\n ctx.stroke()\r\n\r\n // Animated data particles flowing along connections\r\n const flowProgress = (time * 0.3 + node.pulse) % 1\r\n const particleX = node.x + (target.x - node.x) * flowProgress\r\n const particleY = node.y + (target.y - node.y) * flowProgress\r\n\r\n ctx.beginPath()\r\n ctx.arc(particleX, particleY, 1.5, 0, Math.PI * 2)\r\n ctx.fillStyle = isDark\r\n ? `rgba(239, 145, 97, ${0.5 + pulse * 0.3})`\r\n : `rgba(239, 146, 98, ${0.7 + pulse * 0.3})`\r\n ctx.fill()\r\n })\r\n })\r\n\r\n // Theme-aware nodes\r\n dataNodes.forEach(node => {\r\n const pulse = (Math.sin(time + node.pulse) + 1) / 2\r\n const size = 2.5 + pulse * 1\r\n \r\n ctx.beginPath()\r\n ctx.arc(node.x, node.y, size * 2, 0, Math.PI * 2)\r\n ctx.fillStyle = isDark\r\n ? `rgba(239, 145, 97, ${0.12 + pulse * 0.1})`\r\n : `rgba(239, 146, 98, ${0.3 + pulse * 0.15})`\r\n ctx.fill()\r\n\r\n ctx.beginPath()\r\n ctx.arc(node.x, node.y, size, 0, Math.PI * 2)\r\n ctx.fillStyle = isDark\r\n ? `rgba(239, 145, 97, ${0.55 + pulse * 0.25})`\r\n : `rgba(239, 146, 98, ${0.75 + pulse * 0.2})`\r\n ctx.fill()\r\n })\r\n\r\n animationFrameId = requestAnimationFrame(draw)\r\n }\r\n\r\n draw()\r\n\r\n return () => {\r\n cancelAnimationFrame(animationFrameId)\r\n window.removeEventListener('resize', resize)\r\n }\r\n }, [smoothMouseX, smoothMouseY, isDark])\r\n\r\n const { state: { runtimeConfig: { minioUrl } } } = useAppConfigContext()\r\n const assetsUrl = minioUrl || ''\r\n\r\n return (\r\n <>\r\n <div className=\"absolute top-0 right-0 inset-0 z-10 w-screen\">\r\n <img\r\n src={`${assetsUrl}/cdt-homepage/home-bg.png`}\r\n alt=\"Background\"\r\n className=\"object-cover opacity-10 w-screen\"\r\n style={{ filter: isDark ? 'invert(0)' : 'invert(1)' }}\r\n />\r\n </div>\r\n <div className=\"absolute w-screen inset-0 bg-gradient-to-br from-background/10 via-background/5 to-primary/5\" />\r\n <canvas\r\n ref={canvasRef}\r\n className=\"absolute inset-0 w-full h-full opacity-30\"\r\n style={{ mixBlendMode: isDark ? 'screen' : 'multiply' }}\r\n />\r\n <div className=\"absolute inset-0 bg-gradient-to-t from-background/30 via-background/10 to-transparent\" />\r\n </>\r\n )\r\n}\r\n"],"mappings":"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","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"AppSidebar.d.ts","sourceRoot":"","sources":["../../../../src/core/components/ui/AppSidebar.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAY9B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,WAAW,EACnB,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,SAAS,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,EACjE,eAAe,GAAG,SAYnB,CAAA;AAED,UAAU,eAAe;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAClF;AAED,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,eAAe,qBA4FhE"}
1
+ {"version":3,"file":"AppSidebar.d.ts","sourceRoot":"","sources":["../../../../src/core/components/ui/AppSidebar.tsx"],"names":[],"mappings":"AAKA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAA;AAY9B,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AAGzC,eAAO,MAAM,kBAAkB,GAC7B,QAAQ,WAAW,EACnB,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,iBAAiB,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,EAC1D,SAAS,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,GAAG,QAAQ,CAAC,CAAC,EACjE,eAAe,GAAG,SAYnB,CAAA;AAED,UAAU,eAAe;IACvB,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,CAAA;IAC1B,OAAO,EAAE,CAAC,OAAO,CAAC,EAAE;QAAE,UAAU,CAAC,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,EAAE,OAAO,CAAA;KAAE,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;CAClF;AAED,wBAAgB,UAAU,CAAC,EAAE,QAAQ,EAAE,OAAO,EAAE,EAAE,eAAe,qBAmFhE"}
@@ -50,30 +50,30 @@ function AppSidebar({ children, signOut }) {
50
50
  /* @__PURE__ */ jsxs(
51
51
  "div",
52
52
  {
53
- className: `w-full flex flex-col ${sidebarState === "expanded" ? "items-center justify-center" : "justify-center"}`,
53
+ className: `w-full flex flex-col ${sidebarState === "expanded" ? "items-center justify-center" : "justify-center pb-4"}`,
54
54
  children: [
55
55
  /* @__PURE__ */ jsx(NavUser, { signOut }),
56
- /* @__PURE__ */ jsx(
56
+ !isCollapsed ? /* @__PURE__ */ jsx(
57
57
  Link,
58
58
  {
59
59
  href: "https://collabdt.org/",
60
- className: sidebarState === "expanded" ? "w-full" : "",
61
60
  target: "_blank",
62
61
  rel: "noopener noreferrer",
63
- children: /* @__PURE__ */ jsx(
62
+ className: "w-full",
63
+ children: /* @__PURE__ */ jsxs(
64
64
  Button,
65
65
  {
66
- title: isCollapsed ? t("home") : void 0,
66
+ title: t("home"),
67
67
  variant: "ghost",
68
- className: `text-xs scale-[85%] py-0 my-0 w-full ${sidebarState === "expanded" ? "flex flex-row items-center justify-center gap-2" : "flex flex-col items-center"}`,
69
- children: /* @__PURE__ */ jsxs(Fragment, { children: [
70
- /* @__PURE__ */ jsx("div", { className: isCollapsed ? "scale-75" : "", children: /* @__PURE__ */ jsx(CdtIcon, { monochromatic: true }) }),
71
- !isCollapsed && /* @__PURE__ */ jsx("span", { children: t("home") })
72
- ] })
68
+ className: "text-xs scale-[85%] py-0 my-0 w-full flex flex-row items-center justify-center gap-2",
69
+ children: [
70
+ /* @__PURE__ */ jsx(CdtIcon, { monochromatic: true }),
71
+ /* @__PURE__ */ jsx("span", { children: t("home") })
72
+ ]
73
73
  }
74
74
  )
75
75
  }
76
- )
76
+ ) : null
77
77
  ]
78
78
  }
79
79
  )
@@ -1 +1 @@
1
- {"version":3,"sources":["../../../../src/core/components/ui/AppSidebar.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from 'react'\r\n\r\n// Dependencies\r\nimport { Button } from './Button'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\nimport { useTranslations } from 'next-intl'\r\nimport { CdtIcon } from './Icons/CdtIcon'\r\nimport Link from 'next/link'\r\nimport { Sidebar, useSidebar, NavUser } from './'\r\nimport { ViewerNames } from '../../types'\r\nimport { useMenusContext } from '../../store'\r\n\r\nexport const handleChangeViewer = (\r\n viewer: ViewerNames,\r\n setSelectedItem: React.Dispatch<React.SetStateAction<any>>,\r\n setSelectedSite: React.Dispatch<React.SetStateAction<any>>,\r\n setSelectedFile: React.Dispatch<React.SetStateAction<any>>,\r\n setView: React.Dispatch<React.SetStateAction<'table' | 'detail'>>,\r\n menusDispatch: any,\r\n) => {\r\n // Reset selected item, file, & view when changing viewer\r\n setSelectedItem(null)\r\n setSelectedSite(null)\r\n setSelectedFile(null)\r\n setView('table')\r\n\r\n menusDispatch({\r\n type: 'SET_VIEWER',\r\n payload: { currentViewer: viewer },\r\n })\r\n}\r\n\r\ninterface AppSidebarProps {\r\n children?: React.ReactNode\r\n signOut: (options?: { redirectTo?: string; redirect?: boolean }) => Promise<void>\r\n}\r\n\r\nexport function AppSidebar({ children, signOut }: AppSidebarProps) {\r\n // Translations\r\n const t = useTranslations('AppSidebar')\r\n\r\n const { state: menusState } = useMenusContext()\r\n\r\n const { sidebarState, isMobile, openMobile, toggleMenuSidebar } = useSidebar()\r\n\r\n const { currentViewer } = menusState.menus\r\n\r\n // On mobile, treat the sheet open as expanded so labels render when the drawer is visible\r\n const isCollapsed = isMobile ? !openMobile : sidebarState === 'collapsed'\r\n\r\n // Determine the collapsible type based on the current viewer\r\n const collapsibleType = currentViewer === ViewerNames.auth ? 'offcanvas' : 'icon'\r\n\r\n return (\r\n <>\r\n {/* Always show toggle button on mobile when collapsed */}\r\n {isMobile && isCollapsed && (\r\n <div id='sidebar-toggle-button-mobile' className='fixed left-0 top-1/2 -translate-y-1/2 z-[100] flex items-center justify-center pointer-events-auto'>\r\n <button\r\n onClick={toggleMenuSidebar}\r\n className=\"text-muted-foreground hover:text-primary p-[2px] rounded-r-md bg-sidebar\"\r\n style={{ border: '1px solid rgba(128,128,128,0.2)', borderLeft: 'none', boxShadow: '4px 0 8px -4px rgba(0,0,0,0.12)' }}\r\n >\r\n <LR.ChevronRight className=\"w-5\" />\r\n </button>\r\n </div>\r\n )}\r\n <Sidebar collapsible={collapsibleType} className=\"border-none z-50 shadow-md relative\" >\r\n {/* Sidebar toggle button - right side inside Sidebar */}\r\n {(sidebarState === 'expanded') && (\r\n <div id='sidebar-toggle-button' className={`absolute right-2 top-2 flex items-center justify-center pointer-events-auto z-50 ${isMobile ? '' : ''}`}>\r\n <button onClick={toggleMenuSidebar} className='text-muted-foreground hover:text-primary p-1'>\r\n <LR.X className='w-5' />\r\n </button>\r\n </div>\r\n )}\r\n {/* Show collapsed toggle only on desktop */}\r\n {!isMobile && sidebarState !== 'expanded' && (\r\n <div id='sidebar-toggle-button' className='absolute -right-1 max-h-1 top-1/2 -translate-y-1/2 flex items-center justify-center pointer-events-auto z-50'>\r\n <button\r\n onClick={toggleMenuSidebar}\r\n className=\"text-muted-foreground hover:text-primary p-0 rounded-md bg-sidebar\"\r\n style={{ borderRight: '1px solid rgba(128,128,128,0.2)', boxShadow: '4px 0 8px -4px rgba(0,0,0,0.12)' }}\r\n >\r\n <LR.ChevronRight className=\"w-4\" />\r\n </button>\r\n </div>\r\n )}\r\n {children}\r\n <div\r\n className={`w-full flex flex-col ${\r\n sidebarState === 'expanded'\r\n ? 'items-center justify-center'\r\n : 'justify-center'\r\n }`}\r\n >\r\n {/* Nav User */}\r\n <NavUser signOut={signOut} />\r\n\r\n <Link\r\n href=\"https://collabdt.org/\"\r\n className={sidebarState === 'expanded' ? 'w-full' : ''}\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n >\r\n <Button\r\n title={isCollapsed ? t('home') : undefined}\r\n variant=\"ghost\"\r\n className={`text-xs scale-[85%] py-0 my-0 w-full ${\r\n sidebarState === 'expanded'\r\n ? 'flex flex-row items-center justify-center gap-2'\r\n : 'flex flex-col items-center'\r\n }`}\r\n >\r\n <>\r\n <div className={isCollapsed ? 'scale-75' : ''}>\r\n <CdtIcon monochromatic />\r\n </div>\r\n\r\n {!isCollapsed && (\r\n <span>{t('home')}</span>\r\n )}\r\n </>\r\n </Button>\r\n </Link>\r\n </div>\r\n </Sidebar>\r\n </>\r\n )\r\n}"],"mappings":";AAuEY,SAmDI,UAnDJ,KAmDI,YAnDJ;AA/DZ,SAAS,cAAc;AAGvB,YAAY,QAAQ;AAEpB,SAAS,uBAAuB;AAChC,SAAS,eAAe;AACxB,OAAO,UAAU;AACjB,SAAS,SAAS,YAAY,eAAe;AAC7C,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAEzB,MAAM,qBAAqB,CAChC,QACA,iBACA,iBACA,iBACA,SACA,kBACG;AAEH,kBAAgB,IAAI;AACpB,kBAAgB,IAAI;AACpB,kBAAgB,IAAI;AACpB,UAAQ,OAAO;AAEf,gBAAc;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,EAAE,eAAe,OAAO;AAAA,EACnC,CAAC;AACH;AAOO,SAAS,WAAW,EAAE,UAAU,QAAQ,GAAoB;AAEjE,QAAM,IAAI,gBAAgB,YAAY;AAEtC,QAAM,EAAE,OAAO,WAAW,IAAI,gBAAgB;AAE9C,QAAM,EAAE,cAAc,UAAU,YAAY,kBAAkB,IAAI,WAAW;AAE7E,QAAM,EAAE,cAAc,IAAI,WAAW;AAGrC,QAAM,cAAc,WAAW,CAAC,aAAa,iBAAiB;AAG9D,QAAM,kBAAkB,kBAAkB,YAAY,OAAO,cAAc;AAE3E,SACE,iCAEG;AAAA,gBAAY,eACX,oBAAC,SAAI,IAAG,gCAA+B,WAAU,sGAC/C;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAU;AAAA,QACV,OAAO,EAAE,QAAQ,mCAAmC,YAAY,QAAQ,WAAW,kCAAkC;AAAA,QAErH,8BAAC,GAAG,cAAH,EAAgB,WAAU,OAAM;AAAA;AAAA,IACnC,GACF;AAAA,IAEF,qBAAC,WAAQ,aAAa,iBAAiB,WAAU,uCAE7C;AAAA,uBAAiB,cACjB,oBAAC,SAAI,IAAG,yBAAwB,WAAW,oFAAoF,WAAW,KAAK,EAAE,IAC/I,8BAAC,YAAO,SAAS,mBAAmB,WAAU,gDAC5C,8BAAC,GAAG,GAAH,EAAK,WAAU,OAAM,GACxB,GACF;AAAA,MAGD,CAAC,YAAY,iBAAiB,cAC7B,oBAAC,SAAI,IAAG,yBAAwB,WAAU,gHACxC;AAAA,QAAC;AAAA;AAAA,UACC,SAAS;AAAA,UACT,WAAU;AAAA,UACV,OAAO,EAAE,aAAa,mCAAmC,WAAW,kCAAkC;AAAA,UAEtG,8BAAC,GAAG,cAAH,EAAgB,WAAU,OAAM;AAAA;AAAA,MACnC,GACF;AAAA,MAED;AAAA,MACD;AAAA,QAAC;AAAA;AAAA,UACG,WAAW,wBACT,iBAAiB,aACb,gCACA,gBACN;AAAA,UAGA;AAAA,gCAAC,WAAQ,SAAkB;AAAA,YAE3B;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,WAAW,iBAAiB,aAAa,WAAW;AAAA,gBACpD,QAAO;AAAA,gBACP,KAAI;AAAA,gBAEJ;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO,cAAc,EAAE,MAAM,IAAI;AAAA,oBACjC,SAAQ;AAAA,oBACR,WAAW,wCACT,iBAAiB,aACb,oDACA,4BACN;AAAA,oBAEA,2CACA;AAAA,0CAAC,SAAI,WAAW,cAAc,aAAa,IACzC,8BAAC,WAAQ,eAAa,MAAC,GACzB;AAAA,sBAEC,CAAC,eACA,oBAAC,UAAM,YAAE,MAAM,GAAE;AAAA,uBAErB;AAAA;AAAA,gBACA;AAAA;AAAA,YACF;AAAA;AAAA;AAAA,MACF;AAAA,OACJ;AAAA,KACF;AAEJ;","names":[]}
1
+ {"version":3,"sources":["../../../../src/core/components/ui/AppSidebar.tsx"],"sourcesContent":["'use client'\r\n\r\n// SPDX-License-Identifier: AGPL-3.0-or-later\r\n// Copyright (C) 2025 Collab Digital Twins\r\n\r\nimport * as React from 'react'\r\n\r\n// Dependencies\r\nimport { Button } from './Button'\r\n\r\n// Icons\r\nimport * as LR from 'lucide-react'\r\n\r\nimport { useTranslations } from 'next-intl'\r\nimport { CdtIcon } from './Icons/CdtIcon'\r\nimport Link from 'next/link'\r\nimport { Sidebar, useSidebar, NavUser } from './'\r\nimport { ViewerNames } from '../../types'\r\nimport { useMenusContext } from '../../store'\r\n\r\nexport const handleChangeViewer = (\r\n viewer: ViewerNames,\r\n setSelectedItem: React.Dispatch<React.SetStateAction<any>>,\r\n setSelectedSite: React.Dispatch<React.SetStateAction<any>>,\r\n setSelectedFile: React.Dispatch<React.SetStateAction<any>>,\r\n setView: React.Dispatch<React.SetStateAction<'table' | 'detail'>>,\r\n menusDispatch: any,\r\n) => {\r\n // Reset selected item, file, & view when changing viewer\r\n setSelectedItem(null)\r\n setSelectedSite(null)\r\n setSelectedFile(null)\r\n setView('table')\r\n\r\n menusDispatch({\r\n type: 'SET_VIEWER',\r\n payload: { currentViewer: viewer },\r\n })\r\n}\r\n\r\ninterface AppSidebarProps {\r\n children?: React.ReactNode\r\n signOut: (options?: { redirectTo?: string; redirect?: boolean }) => Promise<void>\r\n}\r\n\r\nexport function AppSidebar({ children, signOut }: AppSidebarProps) {\r\n // Translations\r\n const t = useTranslations('AppSidebar')\r\n\r\n const { state: menusState } = useMenusContext()\r\n\r\n const { sidebarState, isMobile, openMobile, toggleMenuSidebar } = useSidebar()\r\n\r\n const { currentViewer } = menusState.menus\r\n\r\n // On mobile, treat the sheet open as expanded so labels render when the drawer is visible\r\n const isCollapsed = isMobile ? !openMobile : sidebarState === 'collapsed'\r\n\r\n // Determine the collapsible type based on the current viewer\r\n const collapsibleType = currentViewer === ViewerNames.auth ? 'offcanvas' : 'icon'\r\n\r\n return (\r\n <>\r\n {/* Always show toggle button on mobile when collapsed */}\r\n {isMobile && isCollapsed && (\r\n <div id='sidebar-toggle-button-mobile' className='fixed left-0 top-1/2 -translate-y-1/2 z-[100] flex items-center justify-center pointer-events-auto'>\r\n <button\r\n onClick={toggleMenuSidebar}\r\n className=\"text-muted-foreground hover:text-primary p-[2px] rounded-r-md bg-sidebar\"\r\n style={{ border: '1px solid rgba(128,128,128,0.2)', borderLeft: 'none', boxShadow: '4px 0 8px -4px rgba(0,0,0,0.12)' }}\r\n >\r\n <LR.ChevronRight className=\"w-5\" />\r\n </button>\r\n </div>\r\n )}\r\n <Sidebar collapsible={collapsibleType} className=\"border-none z-50 shadow-md relative\" >\r\n {/* Sidebar toggle button - right side inside Sidebar */}\r\n {(sidebarState === 'expanded') && (\r\n <div id='sidebar-toggle-button' className={`absolute right-2 top-2 flex items-center justify-center pointer-events-auto z-50 ${isMobile ? '' : ''}`}>\r\n <button onClick={toggleMenuSidebar} className='text-muted-foreground hover:text-primary p-1'>\r\n <LR.X className='w-5' />\r\n </button>\r\n </div>\r\n )}\r\n {/* Show collapsed toggle only on desktop */}\r\n {!isMobile && sidebarState !== 'expanded' && (\r\n <div id='sidebar-toggle-button' className='absolute -right-1 max-h-1 top-1/2 -translate-y-1/2 flex items-center justify-center pointer-events-auto z-50'>\r\n <button\r\n onClick={toggleMenuSidebar}\r\n className=\"text-muted-foreground hover:text-primary p-0 rounded-md bg-sidebar\"\r\n style={{ borderRight: '1px solid rgba(128,128,128,0.2)', boxShadow: '4px 0 8px -4px rgba(0,0,0,0.12)' }}\r\n >\r\n <LR.ChevronRight className=\"w-4\" />\r\n </button>\r\n </div>\r\n )}\r\n {children}\r\n <div\r\n className={`w-full flex flex-col ${\r\n sidebarState === 'expanded'\r\n ? 'items-center justify-center'\r\n : 'justify-center pb-4'\r\n }`}\r\n >\r\n {/* Nav User */}\r\n <NavUser signOut={signOut} />\r\n\r\n {!isCollapsed ? (\r\n <Link\r\n href=\"https://collabdt.org/\"\r\n target=\"_blank\"\r\n rel=\"noopener noreferrer\"\r\n className=\"w-full\"\r\n >\r\n <Button\r\n title={t('home')}\r\n variant=\"ghost\"\r\n className=\"text-xs scale-[85%] py-0 my-0 w-full flex flex-row items-center justify-center gap-2\"\r\n >\r\n <CdtIcon monochromatic />\r\n <span>{t('home')}</span>\r\n </Button>\r\n </Link>\r\n ) : null}\r\n </div>\r\n </Sidebar>\r\n </>\r\n )\r\n}"],"mappings":";AA8DI,mBASQ,KA2CI,YApDZ;AAtDJ,SAAS,cAAc;AAGvB,YAAY,QAAQ;AAEpB,SAAS,uBAAuB;AAChC,SAAS,eAAe;AACxB,OAAO,UAAU;AACjB,SAAS,SAAS,YAAY,eAAe;AAC7C,SAAS,mBAAmB;AAC5B,SAAS,uBAAuB;AAEzB,MAAM,qBAAqB,CAChC,QACA,iBACA,iBACA,iBACA,SACA,kBACG;AAEH,kBAAgB,IAAI;AACpB,kBAAgB,IAAI;AACpB,kBAAgB,IAAI;AACpB,UAAQ,OAAO;AAEf,gBAAc;AAAA,IACZ,MAAM;AAAA,IACN,SAAS,EAAE,eAAe,OAAO;AAAA,EACnC,CAAC;AACH;AAOO,SAAS,WAAW,EAAE,UAAU,QAAQ,GAAoB;AAEjE,QAAM,IAAI,gBAAgB,YAAY;AAEtC,QAAM,EAAE,OAAO,WAAW,IAAI,gBAAgB;AAE9C,QAAM,EAAE,cAAc,UAAU,YAAY,kBAAkB,IAAI,WAAW;AAE7E,QAAM,EAAE,cAAc,IAAI,WAAW;AAGrC,QAAM,cAAc,WAAW,CAAC,aAAa,iBAAiB;AAG9D,QAAM,kBAAkB,kBAAkB,YAAY,OAAO,cAAc;AAE3E,SACE,iCAEG;AAAA,gBAAY,eACX,oBAAC,SAAI,IAAG,gCAA+B,WAAU,sGAC/C;AAAA,MAAC;AAAA;AAAA,QACC,SAAS;AAAA,QACT,WAAU;AAAA,QACV,OAAO,EAAE,QAAQ,mCAAmC,YAAY,QAAQ,WAAW,kCAAkC;AAAA,QAErH,8BAAC,GAAG,cAAH,EAAgB,WAAU,OAAM;AAAA;AAAA,IACnC,GACF;AAAA,IAEF,qBAAC,WAAQ,aAAa,iBAAiB,WAAU,uCAE7C;AAAA,uBAAiB,cACjB,oBAAC,SAAI,IAAG,yBAAwB,WAAW,oFAAoF,WAAW,KAAK,EAAE,IAC/I,8BAAC,YAAO,SAAS,mBAAmB,WAAU,gDAC5C,8BAAC,GAAG,GAAH,EAAK,WAAU,OAAM,GACxB,GACF;AAAA,MAGD,CAAC,YAAY,iBAAiB,cAC7B,oBAAC,SAAI,IAAG,yBAAwB,WAAU,gHACxC;AAAA,QAAC;AAAA;AAAA,UACC,SAAS;AAAA,UACT,WAAU;AAAA,UACV,OAAO,EAAE,aAAa,mCAAmC,WAAW,kCAAkC;AAAA,UAEtG,8BAAC,GAAG,cAAH,EAAgB,WAAU,OAAM;AAAA;AAAA,MACnC,GACF;AAAA,MAED;AAAA,MACD;AAAA,QAAC;AAAA;AAAA,UACC,WAAW,wBACT,iBAAiB,aACb,gCACA,qBACN;AAAA,UAGE;AAAA,gCAAC,WAAQ,SAAkB;AAAA,YAE1B,CAAC,cACA;AAAA,cAAC;AAAA;AAAA,gBACC,MAAK;AAAA,gBACL,QAAO;AAAA,gBACP,KAAI;AAAA,gBACJ,WAAU;AAAA,gBAEV;AAAA,kBAAC;AAAA;AAAA,oBACC,OAAO,EAAE,MAAM;AAAA,oBACf,SAAQ;AAAA,oBACR,WAAU;AAAA,oBAEV;AAAA,0CAAC,WAAQ,eAAa,MAAC;AAAA,sBACvB,oBAAC,UAAM,YAAE,MAAM,GAAE;AAAA;AAAA;AAAA,gBACnB;AAAA;AAAA,YACF,IACE;AAAA;AAAA;AAAA,MACN;AAAA,OACJ;AAAA,KACF;AAEJ;","names":[]}
@@ -1 +1 @@
1
- {"version":3,"file":"Navbar.d.ts","sourceRoot":"","sources":["../../../../src/core/components/ui/Navbar.tsx"],"names":[],"mappings":"AAaA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAE9C,UAAU,WAAW;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;IACvB,MAAM,EAAE,QAAQ,CAAA;IAChB,UAAU,CAAC,EAAE,GAAG,CAAA;IAChB,IAAI,EAAE,GAAG,CAAA;IACT,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,gBAAgB,EAAE,MAAM,IAAI,CAAA;IAC5B,iBAAiB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC7B,aAAa,EACb,KAAK,EACL,MAAM,EACN,UAAU,EACV,IAAI,EACJ,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,cAAqB,GACtB,EAAE,WAAW,+BAoLb"}
1
+ {"version":3,"file":"Navbar.d.ts","sourceRoot":"","sources":["../../../../src/core/components/ui/Navbar.tsx"],"names":[],"mappings":"AAYA,OAAO,EAAE,QAAQ,EAAE,MAAM,qBAAqB,CAAA;AAE9C,UAAU,WAAW;IACnB,aAAa,EAAE,MAAM,CAAA;IACrB,KAAK,EAAE,OAAO,GAAG,MAAM,CAAA;IACvB,MAAM,EAAE,QAAQ,CAAA;IAChB,UAAU,CAAC,EAAE,GAAG,CAAA;IAChB,IAAI,EAAE,GAAG,CAAA;IACT,aAAa,EAAE,MAAM,IAAI,CAAA;IACzB,gBAAgB,EAAE,MAAM,IAAI,CAAA;IAC5B,iBAAiB,EAAE,CAAC,EAAE,EAAE,MAAM,KAAK,IAAI,CAAA;IACvC,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB;AAED,MAAM,CAAC,OAAO,UAAU,MAAM,CAAC,EAC7B,aAAa,EACb,KAAK,EACL,MAAM,EACN,UAAU,EACV,IAAI,EACJ,aAAa,EACb,gBAAgB,EAChB,iBAAiB,EACjB,cAAqB,GACtB,EAAE,WAAW,+BA8Kb"}