@burdenoff/microfe-files 2026.1017.10 → 2026.1101.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/files/components/ActionMenu.d.ts.map +1 -1
- package/dist/files/components/ActionMenu.js +63 -46
- package/dist/files/components/ActionMenu.js.map +1 -1
- package/dist/files/components/actionMenuPosition.d.ts +15 -0
- package/dist/files/components/actionMenuPosition.d.ts.map +1 -0
- package/dist/files/components/actionMenuPosition.js +12 -0
- package/dist/files/components/actionMenuPosition.js.map +1 -0
- package/dist/files/hooks/useCreateFolderShare.d.ts +7 -20
- package/dist/files/hooks/useCreateFolderShare.d.ts.map +1 -1
- package/dist/files/hooks/useCreateFolderShare.js +48 -21
- package/dist/files/hooks/useCreateFolderShare.js.map +1 -1
- package/dist/files/hooks/useCreateShare.d.ts +18 -19
- package/dist/files/hooks/useCreateShare.d.ts.map +1 -1
- package/dist/files/hooks/useCreateShare.js +51 -22
- package/dist/files/hooks/useCreateShare.js.map +1 -1
- package/dist/generated/wspace-operations.d.ts +61 -210
- package/dist/generated/wspace-operations.d.ts.map +1 -1
- package/dist/generated/wspace-operations.js +675 -402
- package/dist/generated/wspace-operations.js.map +1 -1
- package/dist/generated/wspace-types.d.ts +12 -0
- package/dist/generated/wspace-types.d.ts.map +1 -1
- package/dist/generated/wspace-types.js +3 -7
- package/dist/generated/wspace-types.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionMenu.d.ts","sourceRoot":"","sources":["../../../src/files/components/ActionMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EAAE,
|
|
1
|
+
{"version":3,"file":"ActionMenu.d.ts","sourceRoot":"","sources":["../../../src/files/components/ActionMenu.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,EAAE,EAOR,MAAM,OAAO,CAAC;AAOf,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,KAAK,CAAC,SAAS,CAAC;IACvB,OAAO,EAAE,MAAM,IAAI,CAAC;IACpB,OAAO,CAAC,EAAE,SAAS,GAAG,QAAQ,CAAC;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,UAAU,eAAe;IACvB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC;IACzB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,IAAI,CAAC;CACpC;AAED,eAAO,MAAM,UAAU,EAAE,EAAE,CAAC,eAAe,CAmL1C,CAAC"}
|
|
@@ -1,79 +1,96 @@
|
|
|
1
1
|
import { tWithFallback as e } from "../utils/i18n.js";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
2
|
+
import { actionMenuPosition as t } from "./actionMenuPosition.js";
|
|
3
|
+
import { useCallback as n, useEffect as r, useEffectEvent as i, useLayoutEffect as a, useRef as o, useState as s } from "react";
|
|
4
|
+
import { MoreVertical as c } from "lucide-react";
|
|
5
|
+
import { Fragment as l, jsx as u, jsxs as d } from "react/jsx-runtime";
|
|
6
|
+
import { useI18n as f } from "@burdenoff/fe-libs/shared/providers/shell/I18nProvider";
|
|
7
|
+
import { createPortal as p } from "react-dom";
|
|
7
8
|
//#region src/files/components/ActionMenu.tsx
|
|
8
|
-
var
|
|
9
|
-
let { t:
|
|
10
|
-
|
|
11
|
-
}, [
|
|
12
|
-
|
|
13
|
-
if (
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
9
|
+
var m = ({ items: m, triggerClassName: h = "", menuClassName: g = "", align: _ = "right", isOpen: v, onToggle: y }) => {
|
|
10
|
+
let { t: b } = f(), [x, S] = s(!1), [C, w] = s(null), T = o(null), E = o(null), D = v === void 0 ? x : v, O = n((e) => {
|
|
11
|
+
y ? y(e) : S(e);
|
|
12
|
+
}, [y]);
|
|
13
|
+
a(() => {
|
|
14
|
+
if (!D) return;
|
|
15
|
+
let e = T.current, n = E.current;
|
|
16
|
+
if (!e || !n) return;
|
|
17
|
+
let r = () => {
|
|
18
|
+
let r = t({
|
|
19
|
+
trigger: e.getBoundingClientRect(),
|
|
20
|
+
menuWidth: n.offsetWidth,
|
|
21
|
+
menuHeight: n.offsetHeight,
|
|
22
|
+
viewportWidth: window.innerWidth,
|
|
23
|
+
viewportHeight: window.innerHeight,
|
|
24
|
+
align: _
|
|
18
25
|
});
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
26
|
+
w((e) => e?.top === r.top && e.left === r.left ? e : r);
|
|
27
|
+
};
|
|
28
|
+
r();
|
|
29
|
+
let i = new ResizeObserver(r);
|
|
30
|
+
return i.observe(n), i.observe(e), window.addEventListener("resize", r), window.addEventListener("scroll", r, !0), () => {
|
|
31
|
+
i.disconnect(), window.removeEventListener("resize", r), window.removeEventListener("scroll", r, !0);
|
|
32
|
+
};
|
|
33
|
+
}, [D, _]);
|
|
34
|
+
let k = i(() => {
|
|
35
|
+
O(!1);
|
|
23
36
|
});
|
|
24
|
-
|
|
37
|
+
r(() => {
|
|
25
38
|
let e = (e) => {
|
|
26
|
-
|
|
39
|
+
E.current && !E.current.contains(e.target) && k();
|
|
27
40
|
};
|
|
28
|
-
if (
|
|
41
|
+
if (D) return document.addEventListener("mousedown", e), () => {
|
|
29
42
|
document.removeEventListener("mousedown", e);
|
|
30
43
|
};
|
|
31
|
-
}, [
|
|
44
|
+
}, [D]), r(() => {
|
|
32
45
|
let e = (e) => {
|
|
33
|
-
e.key === "Escape" &&
|
|
46
|
+
e.key === "Escape" && k();
|
|
34
47
|
};
|
|
35
|
-
if (
|
|
48
|
+
if (D) return document.addEventListener("keydown", e), () => {
|
|
36
49
|
document.removeEventListener("keydown", e);
|
|
37
50
|
};
|
|
38
|
-
}, [
|
|
39
|
-
let
|
|
40
|
-
e.onClick(),
|
|
51
|
+
}, [D]);
|
|
52
|
+
let A = (e) => {
|
|
53
|
+
e.onClick(), O(!1);
|
|
41
54
|
};
|
|
42
|
-
return /* @__PURE__ */ l
|
|
55
|
+
return /* @__PURE__ */ d(l, { children: [/* @__PURE__ */ u("button", {
|
|
43
56
|
type: "button",
|
|
44
|
-
ref:
|
|
57
|
+
ref: T,
|
|
45
58
|
onClick: (e) => {
|
|
46
|
-
e.stopPropagation(),
|
|
59
|
+
e.stopPropagation(), O(!D);
|
|
47
60
|
},
|
|
48
|
-
className: `p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors ${
|
|
49
|
-
"aria-label": e(
|
|
50
|
-
title: e(
|
|
51
|
-
"aria-expanded":
|
|
61
|
+
className: `p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors ${h}`,
|
|
62
|
+
"aria-label": e(b, "files.actionMenu.moreActions", "More actions"),
|
|
63
|
+
title: e(b, "files.actionMenu.moreActions", "More actions"),
|
|
64
|
+
"aria-expanded": D,
|
|
52
65
|
"aria-haspopup": "true",
|
|
53
|
-
children: /* @__PURE__ */ c
|
|
54
|
-
}), !
|
|
55
|
-
ref:
|
|
56
|
-
className: `fixed z-[9999]
|
|
66
|
+
children: /* @__PURE__ */ u(c, { className: "size-4 text-text-primary" })
|
|
67
|
+
}), !D || typeof document > "u" ? null : p(/* @__PURE__ */ u("div", {
|
|
68
|
+
ref: E,
|
|
69
|
+
className: `fixed z-[9999] overflow-y-auto bg-bg-elevated rounded-lg shadow-lg border border-border-default py-1 animate-in fade-in-0 zoom-in-95 transition-[opacity,transform] duration-150 ${g}`,
|
|
57
70
|
style: {
|
|
58
|
-
top:
|
|
59
|
-
left:
|
|
71
|
+
top: C?.top ?? 0,
|
|
72
|
+
left: C?.left ?? 0,
|
|
73
|
+
visibility: C ? "visible" : "hidden",
|
|
74
|
+
minWidth: "min(200px, calc(100vw - 20px))",
|
|
75
|
+
maxWidth: "calc(100vw - 20px)",
|
|
76
|
+
maxHeight: "calc(100vh - 20px)"
|
|
60
77
|
},
|
|
61
78
|
role: "menu",
|
|
62
|
-
children:
|
|
79
|
+
children: m.map((e, t) => /* @__PURE__ */ d("div", { children: [e.divider && t > 0 && /* @__PURE__ */ u("div", { className: "h-px bg-border-subtle my-1" }), /* @__PURE__ */ d("button", {
|
|
63
80
|
type: "button",
|
|
64
81
|
onClick: (t) => {
|
|
65
|
-
t.stopPropagation(),
|
|
82
|
+
t.stopPropagation(), A(e);
|
|
66
83
|
},
|
|
67
84
|
className: `w-full flex items-center gap-3 px-4 py-2 text-sm transition-all duration-150 ${e.variant === "danger" ? "text-status-error-text hover:bg-status-error-bg-subtle" : "text-text-primary hover:bg-action-ghost-bg-hover"}`,
|
|
68
85
|
role: "menuitem",
|
|
69
|
-
children: [e.icon && /* @__PURE__ */
|
|
86
|
+
children: [e.icon && /* @__PURE__ */ u("span", {
|
|
70
87
|
className: "flex-shrink-0",
|
|
71
88
|
children: e.icon
|
|
72
|
-
}), /* @__PURE__ */
|
|
89
|
+
}), /* @__PURE__ */ u("span", { children: e.label })]
|
|
73
90
|
})] }, e.label))
|
|
74
91
|
}), document.body)] });
|
|
75
92
|
};
|
|
76
93
|
//#endregion
|
|
77
|
-
export {
|
|
94
|
+
export { m as ActionMenu };
|
|
78
95
|
|
|
79
96
|
//# sourceMappingURL=ActionMenu.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ActionMenu.js","names":["_Fragment","ActionMenu","controlledIsOpen","useI18n","internalIsOpen","setInternalIsOpen","useState","menuPosition","setMenuPosition","buttonRef","useRef","menuRef","isOpen","setIsOpen","useCallback","onToggle","open","
|
|
1
|
+
{"version":3,"file":"ActionMenu.js","names":["_Fragment","ActionMenu","controlledIsOpen","useI18n","internalIsOpen","setInternalIsOpen","useState","menuPosition","setMenuPosition","buttonRef","useRef","menuRef","isOpen","setIsOpen","useCallback","onToggle","open","button","menu","updatePosition","next","actionMenuPosition","previous","observer","align","closeMenu","useEffectEvent","useEffect","handleClickOutside","event","handleEscape","handleItemClick","item","Fragment","triggerClassName","tWithFallback","t","MoreVertical","createPortal","menuClassName","items","index","e"],"sources":["../../../src/files/components/ActionMenu.tsx"],"sourcesContent":["import {\n type FC,\n useState,\n useRef,\n useEffect,\n useLayoutEffect,\n useEffectEvent,\n useCallback,\n} from \"react\";\nimport { createPortal } from \"react-dom\";\nimport { MoreVertical } from \"lucide-react\";\nimport { useI18n } from \"@burdenoff/fe-libs/shared/providers/shell/I18nProvider\";\nimport { tWithFallback } from \"../utils/i18n\";\nimport { actionMenuPosition } from \"./actionMenuPosition\";\n\nexport interface ActionMenuItem {\n label: string;\n icon?: React.ReactNode;\n onClick: () => void;\n variant?: \"default\" | \"danger\";\n divider?: boolean;\n}\n\ninterface ActionMenuProps {\n items: ActionMenuItem[];\n triggerClassName?: string;\n menuClassName?: string;\n align?: \"left\" | \"right\";\n isOpen?: boolean;\n onToggle?: (open: boolean) => void;\n}\n\nexport const ActionMenu: FC<ActionMenuProps> = ({\n items,\n triggerClassName = \"\",\n menuClassName = \"\",\n align = \"right\",\n isOpen: controlledIsOpen,\n onToggle,\n}) => {\n const { t } = useI18n();\n const [internalIsOpen, setInternalIsOpen] = useState(false);\n const [menuPosition, setMenuPosition] = useState<{\n top: number;\n left: number;\n } | null>(null);\n const buttonRef = useRef<HTMLButtonElement>(null);\n const menuRef = useRef<HTMLDivElement>(null);\n\n // Use controlled state if provided, otherwise use internal state\n const isOpen =\n controlledIsOpen !== undefined ? controlledIsOpen : internalIsOpen;\n const setIsOpen = useCallback(\n (open: boolean) => {\n if (onToggle) {\n onToggle(open);\n } else {\n setInternalIsOpen(open);\n }\n },\n [onToggle],\n );\n\n // Mount hidden, then measure before paint. Offset sizes exclude the entrance\n // animation's scale, so the final menu also stays inside the viewport.\n useLayoutEffect(() => {\n if (!isOpen) return;\n const button = buttonRef.current;\n const menu = menuRef.current;\n if (!button || !menu) return;\n\n const updatePosition = () => {\n const next = actionMenuPosition({\n trigger: button.getBoundingClientRect(),\n menuWidth: menu.offsetWidth,\n menuHeight: menu.offsetHeight,\n viewportWidth: window.innerWidth,\n viewportHeight: window.innerHeight,\n align,\n });\n setMenuPosition((previous) =>\n previous?.top === next.top && previous.left === next.left\n ? previous\n : next,\n );\n };\n updatePosition();\n const observer = new ResizeObserver(updatePosition);\n observer.observe(menu);\n observer.observe(button);\n window.addEventListener(\"resize\", updatePosition);\n // Capture scrolls in nested file lists as well as the window.\n window.addEventListener(\"scroll\", updatePosition, true);\n return () => {\n observer.disconnect();\n window.removeEventListener(\"resize\", updatePosition);\n window.removeEventListener(\"scroll\", updatePosition, true);\n };\n }, [isOpen, align]);\n\n const closeMenu = useEffectEvent(() => {\n setIsOpen(false);\n });\n\n // Close menu when clicking outside\n useEffect(() => {\n const handleClickOutside = (event: MouseEvent) => {\n if (menuRef.current && !menuRef.current.contains(event.target as Node)) {\n closeMenu();\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"mousedown\", handleClickOutside);\n return () => {\n document.removeEventListener(\"mousedown\", handleClickOutside);\n };\n }\n }, [isOpen]);\n\n // Close menu on Escape key\n useEffect(() => {\n const handleEscape = (event: KeyboardEvent) => {\n if (event.key === \"Escape\") {\n closeMenu();\n }\n };\n\n if (isOpen) {\n document.addEventListener(\"keydown\", handleEscape);\n return () => {\n document.removeEventListener(\"keydown\", handleEscape);\n };\n }\n }, [isOpen]);\n\n const handleItemClick = (item: ActionMenuItem) => {\n item.onClick();\n setIsOpen(false);\n };\n\n // Render menu dropdown\n const renderMenu = () => {\n if (!isOpen || typeof document === \"undefined\") return null;\n\n return createPortal(\n <div\n ref={menuRef}\n className={`fixed z-[9999] overflow-y-auto bg-bg-elevated rounded-lg shadow-lg border border-border-default py-1 animate-in fade-in-0 zoom-in-95 transition-[opacity,transform] duration-150 ${menuClassName}`}\n style={{\n top: menuPosition?.top ?? 0,\n left: menuPosition?.left ?? 0,\n visibility: menuPosition ? \"visible\" : \"hidden\",\n minWidth: \"min(200px, calc(100vw - 20px))\",\n maxWidth: \"calc(100vw - 20px)\",\n maxHeight: \"calc(100vh - 20px)\",\n }}\n role=\"menu\"\n >\n {items.map((item, index) => (\n <div key={item.label}>\n {item.divider && index > 0 && (\n <div className=\"h-px bg-border-subtle my-1\" />\n )}\n <button\n type=\"button\"\n onClick={(e) => {\n e.stopPropagation();\n handleItemClick(item);\n }}\n className={`w-full flex items-center gap-3 px-4 py-2 text-sm transition-all duration-150 ${\n item.variant === \"danger\"\n ? \"text-status-error-text hover:bg-status-error-bg-subtle\"\n : \"text-text-primary hover:bg-action-ghost-bg-hover\"\n }`}\n role=\"menuitem\"\n >\n {item.icon && <span className=\"flex-shrink-0\">{item.icon}</span>}\n <span>{item.label}</span>\n </button>\n </div>\n ))}\n </div>,\n document.body,\n );\n };\n\n return (\n <>\n <button\n type=\"button\"\n ref={buttonRef}\n onClick={(e) => {\n e.stopPropagation();\n setIsOpen(!isOpen);\n }}\n className={`p-1.5 hover:bg-action-ghost-bg-hover rounded transition-colors ${triggerClassName}`}\n aria-label={tWithFallback(\n t,\n \"files.actionMenu.moreActions\",\n \"More actions\",\n )}\n title={tWithFallback(t, \"files.actionMenu.moreActions\", \"More actions\")}\n aria-expanded={isOpen}\n aria-haspopup=\"true\"\n >\n <MoreVertical className=\"size-4 text-text-primary\" />\n </button>\n {renderMenu()}\n </>\n );\n};\n"],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
interface MenuGeometry {
|
|
2
|
+
trigger: Pick<DOMRect, "top" | "bottom" | "left" | "right">;
|
|
3
|
+
menuWidth: number;
|
|
4
|
+
menuHeight: number;
|
|
5
|
+
viewportWidth: number;
|
|
6
|
+
viewportHeight: number;
|
|
7
|
+
align: "left" | "right";
|
|
8
|
+
}
|
|
9
|
+
/** Fixed-position coordinates for a measured menu, with the same 10px edge inset as its CSS. */
|
|
10
|
+
export declare function actionMenuPosition({ trigger, menuWidth, menuHeight, viewportWidth, viewportHeight, align, }: MenuGeometry): {
|
|
11
|
+
top: number;
|
|
12
|
+
left: number;
|
|
13
|
+
};
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=actionMenuPosition.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actionMenuPosition.d.ts","sourceRoot":"","sources":["../../../src/files/components/actionMenuPosition.ts"],"names":[],"mappings":"AAAA,UAAU,YAAY;IACpB,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC,CAAC;IAC5D,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACzB;AAED,gGAAgG;AAChG,wBAAgB,kBAAkB,CAAC,EACjC,OAAO,EACP,SAAS,EACT,UAAU,EACV,aAAa,EACb,cAAc,EACd,KAAK,GACN,EAAE,YAAY,GAAG;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAa9C"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
//#region src/files/components/actionMenuPosition.ts
|
|
2
|
+
function e({ trigger: e, menuWidth: t, menuHeight: n, viewportWidth: r, viewportHeight: i, align: a }) {
|
|
3
|
+
let o = e.bottom + 4, s = o + n <= i - 10 ? o : e.top - n - 4, c = a === "right" ? e.right - t : e.left;
|
|
4
|
+
return {
|
|
5
|
+
top: Math.max(10, Math.min(s, i - n - 10)),
|
|
6
|
+
left: Math.max(10, Math.min(c, r - t - 10))
|
|
7
|
+
};
|
|
8
|
+
}
|
|
9
|
+
//#endregion
|
|
10
|
+
export { e as actionMenuPosition };
|
|
11
|
+
|
|
12
|
+
//# sourceMappingURL=actionMenuPosition.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"actionMenuPosition.js","names":["actionMenuPosition","below","trigger","top","menuHeight","viewportHeight","left","align","menuWidth","viewportWidth"],"sources":["../../../src/files/components/actionMenuPosition.ts"],"sourcesContent":["interface MenuGeometry {\n trigger: Pick<DOMRect, \"top\" | \"bottom\" | \"left\" | \"right\">;\n menuWidth: number;\n menuHeight: number;\n viewportWidth: number;\n viewportHeight: number;\n align: \"left\" | \"right\";\n}\n\n/** Fixed-position coordinates for a measured menu, with the same 10px edge inset as its CSS. */\nexport function actionMenuPosition({\n trigger,\n menuWidth,\n menuHeight,\n viewportWidth,\n viewportHeight,\n align,\n}: MenuGeometry): { top: number; left: number } {\n const inset = 10;\n const gap = 4;\n const below = trigger.bottom + gap;\n const top =\n below + menuHeight <= viewportHeight - inset\n ? below\n : trigger.top - menuHeight - gap;\n const left = align === \"right\" ? trigger.right - menuWidth : trigger.left;\n return {\n top: Math.max(inset, Math.min(top, viewportHeight - menuHeight - inset)),\n left: Math.max(inset, Math.min(left, viewportWidth - menuWidth - inset)),\n };\n}\n"],"mappings":";AAUA,SAAgBA,EAAmB,EACjC,YACA,cACA,eACA,kBACA,mBACA,YAC8C;CAC9C,IAEMC,IAAQC,EAAQ,SAAS,GACzBC,IACJF,IAAQG,KAAcC,IAAiB,KACnCJ,IACAC,EAAQ,MAAME,IAAa,GAC3BE,IAAOC,MAAU,UAAUL,EAAQ,QAAQM,IAAYN,EAAQ;CACrE,OAAO;EACL,KAAK,KAAK,IAAI,IAAO,KAAK,IAAIC,GAAKE,IAAiBD,IAAa,EAAK,CAAC;EACvE,MAAM,KAAK,IAAI,IAAO,KAAK,IAAIE,GAAMG,IAAgBD,IAAY,EAAK,CAAC;CACzE;AACF"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ShareCreationResult } from './useCreateShare';
|
|
2
2
|
export interface CreateFolderShareInput {
|
|
3
3
|
folderId: string;
|
|
4
4
|
shareType: "PUBLIC_LINK" | "EMAIL_INVITE" | "GROUP_SHARE";
|
|
@@ -9,26 +9,13 @@ export interface CreateFolderShareInput {
|
|
|
9
9
|
invitedEmail?: string;
|
|
10
10
|
invitedUserIds?: string[];
|
|
11
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Create a folder share through the consolidated ShareGrant stack (BOFF-5302).
|
|
14
|
+
* Same cutover as useCreateShare: public links become PUBLIC_LINK grants,
|
|
15
|
+
* email invites become PENDING grants + accept email.
|
|
16
|
+
*/
|
|
12
17
|
export declare const useCreateFolderShare: () => {
|
|
13
|
-
mutateAsync: (input: CreateFolderShareInput) => Promise<
|
|
14
|
-
id: string;
|
|
15
|
-
folderId: string;
|
|
16
|
-
shareType: FileShareType;
|
|
17
|
-
accessLevel: FileShareAccessLevel;
|
|
18
|
-
token: string | null;
|
|
19
|
-
invitedEmail: string | null;
|
|
20
|
-
requiresPassword: boolean;
|
|
21
|
-
expiresAt: string | null;
|
|
22
|
-
maxDownloads: number | null;
|
|
23
|
-
accessCount: number;
|
|
24
|
-
downloadCount: number;
|
|
25
|
-
lastAccessedAt: string | null;
|
|
26
|
-
revokedAt: string | null;
|
|
27
|
-
revokedBy: string | null;
|
|
28
|
-
createdById: string;
|
|
29
|
-
createdAt: string;
|
|
30
|
-
updatedAt: string;
|
|
31
|
-
} | undefined>;
|
|
18
|
+
mutateAsync: (input: CreateFolderShareInput) => Promise<ShareCreationResult>;
|
|
32
19
|
isPending: boolean;
|
|
33
20
|
error: import('@apollo/client').ErrorLike | undefined;
|
|
34
21
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCreateFolderShare.d.ts","sourceRoot":"","sources":["../../../src/files/hooks/useCreateFolderShare.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useCreateFolderShare.d.ts","sourceRoot":"","sources":["../../../src/files/hooks/useCreateFolderShare.ts"],"names":[],"mappings":"AAcA,OAAO,EAAqB,KAAK,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,MAAM,WAAW,sBAAsB;IACrC,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,EAAE,aAAa,GAAG,cAAc,GAAG,aAAa,CAAC;IAC1D,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAgBD;;;;GAIG;AACH,eAAO,MAAM,oBAAoB;yBAWpB,sBAAsB,KAC5B,OAAO,CAAC,mBAAmB,CAAC;;;CAgDlC,CAAC"}
|
|
@@ -1,29 +1,56 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { CreateFolderShareLinkDocument as e, ShareFolderDocument as t } from "../../generated/wspace-operations.js";
|
|
2
|
+
import { extractShareToken as n } from "./useCreateShare.js";
|
|
3
3
|
import { useMutation as r } from "@apollo/client/react";
|
|
4
4
|
//#region src/files/hooks/useCreateFolderShare.ts
|
|
5
|
-
|
|
6
|
-
|
|
5
|
+
function i(e) {
|
|
6
|
+
switch (e) {
|
|
7
|
+
case "COMMENT": return "COMMENTER";
|
|
8
|
+
case "EDIT": return "EDITOR";
|
|
9
|
+
default: return "VIEWER";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
var a = () => {
|
|
13
|
+
let [a, { loading: o, error: s }] = r(t), [c, { loading: l, error: u }] = r(e);
|
|
7
14
|
return {
|
|
8
|
-
mutateAsync: async (e) =>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
15
|
+
mutateAsync: async (e) => {
|
|
16
|
+
let t = e.accessLevel.toUpperCase();
|
|
17
|
+
if (e.shareType === "PUBLIC_LINK") {
|
|
18
|
+
let r = {
|
|
19
|
+
input: {
|
|
20
|
+
resourceId: e.folderId,
|
|
21
|
+
role: i(e.accessLevel),
|
|
22
|
+
expiresAt: e.expiresAt ?? null
|
|
23
|
+
},
|
|
24
|
+
options: {
|
|
25
|
+
password: e.password ?? null,
|
|
26
|
+
maxDownloads: e.maxDownloads ?? null,
|
|
27
|
+
accessLevel: t
|
|
28
|
+
}
|
|
29
|
+
}, a = await c({ variables: r });
|
|
30
|
+
return { token: n(a.data?.createFolderShareLink.shareUrl ?? "") };
|
|
31
|
+
}
|
|
32
|
+
if (e.shareType !== "EMAIL_INVITE" || !e.invitedEmail) throw Error("Email invite shares require an invitedEmail");
|
|
33
|
+
let r = {
|
|
34
|
+
input: {
|
|
35
|
+
resourceId: e.folderId,
|
|
36
|
+
email: e.invitedEmail,
|
|
37
|
+
role: i(e.accessLevel),
|
|
38
|
+
message: null,
|
|
39
|
+
expiresAt: e.expiresAt ?? null
|
|
40
|
+
},
|
|
41
|
+
options: {
|
|
42
|
+
password: e.password ?? null,
|
|
43
|
+
maxDownloads: e.maxDownloads ?? null,
|
|
44
|
+
accessLevel: t
|
|
45
|
+
}
|
|
46
|
+
};
|
|
47
|
+
return await a({ variables: r }), { token: "" };
|
|
48
|
+
},
|
|
49
|
+
isPending: o || l,
|
|
50
|
+
error: s ?? u
|
|
24
51
|
};
|
|
25
52
|
};
|
|
26
53
|
//#endregion
|
|
27
|
-
export {
|
|
54
|
+
export { a as useCreateFolderShare };
|
|
28
55
|
|
|
29
56
|
//# sourceMappingURL=useCreateFolderShare.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCreateFolderShare.js","names":["useCreateFolderShare","
|
|
1
|
+
{"version":3,"file":"useCreateFolderShare.js","names":["toShareRole","accessLevel","useCreateFolderShare","shareFolderMutation","inviteLoading","inviteError","useMutation","ShareFolderDocument","createLinkMutation","linkLoading","linkError","CreateFolderShareLinkDocument","input","variables","result","extractShareToken"],"sources":["../../../src/files/hooks/useCreateFolderShare.ts"],"sourcesContent":["import { useMutation } from \"@apollo/client/react\";\n\nimport {\n CreateFolderShareLinkDocument,\n ShareFolderDocument,\n} from \"../../generated/wspace-operations\";\nimport type {\n FileShareAccessLevel,\n ShareRole,\n} from \"../../generated/wspace-types\";\nimport type {\n CreateFolderShareLinkMutationVariables,\n ShareFolderMutationVariables,\n} from \"../../generated/wspace-operations\";\nimport { extractShareToken, type ShareCreationResult } from \"./useCreateShare\";\n\nexport interface CreateFolderShareInput {\n folderId: string;\n shareType: \"PUBLIC_LINK\" | \"EMAIL_INVITE\" | \"GROUP_SHARE\";\n accessLevel: \"VIEW\" | \"COMMENT\" | \"DOWNLOAD\" | \"EDIT\";\n expiresAt?: string;\n password?: string;\n maxDownloads?: number;\n invitedEmail?: string;\n invitedUserIds?: string[];\n}\n\n/** Generic ShareRole for the legacy access levels (DOWNLOAD has no dedicated role). */\nfunction toShareRole(\n accessLevel: CreateFolderShareInput[\"accessLevel\"],\n): ShareRole {\n switch (accessLevel) {\n case \"COMMENT\":\n return \"COMMENTER\" as ShareRole;\n case \"EDIT\":\n return \"EDITOR\" as ShareRole;\n default:\n return \"VIEWER\" as ShareRole;\n }\n}\n\n/**\n * Create a folder share through the consolidated ShareGrant stack (BOFF-5302).\n * Same cutover as useCreateShare: public links become PUBLIC_LINK grants,\n * email invites become PENDING grants + accept email.\n */\nexport const useCreateFolderShare = () => {\n const [shareFolderMutation, { loading: inviteLoading, error: inviteError }] =\n useMutation(ShareFolderDocument);\n const [createLinkMutation, { loading: linkLoading, error: linkError }] =\n useMutation(CreateFolderShareLinkDocument);\n\n const loading = inviteLoading || linkLoading;\n const error = inviteError ?? linkError;\n\n return {\n mutateAsync: async (\n input: CreateFolderShareInput,\n ): Promise<ShareCreationResult> => {\n const accessLevel = input.accessLevel.toUpperCase() as\n \"VIEW\" | \"COMMENT\" | \"DOWNLOAD\" | \"EDIT\";\n if (input.shareType === \"PUBLIC_LINK\") {\n const variables: CreateFolderShareLinkMutationVariables = {\n input: {\n resourceId: input.folderId,\n role: toShareRole(input.accessLevel),\n expiresAt: input.expiresAt ?? null,\n },\n options: {\n password: input.password ?? null,\n maxDownloads: input.maxDownloads ?? null,\n accessLevel: accessLevel as unknown as FileShareAccessLevel,\n },\n };\n const result = await createLinkMutation({ variables });\n return {\n token: extractShareToken(\n result.data?.createFolderShareLink.shareUrl ?? \"\",\n ),\n };\n }\n\n if (input.shareType !== \"EMAIL_INVITE\" || !input.invitedEmail) {\n throw new Error(\"Email invite shares require an invitedEmail\");\n }\n\n const variables: ShareFolderMutationVariables = {\n input: {\n resourceId: input.folderId,\n email: input.invitedEmail,\n role: toShareRole(input.accessLevel),\n message: null,\n expiresAt: input.expiresAt ?? null,\n },\n options: {\n password: input.password ?? null,\n maxDownloads: input.maxDownloads ?? null,\n accessLevel: accessLevel as unknown as FileShareAccessLevel,\n },\n };\n await shareFolderMutation({ variables });\n return { token: \"\" };\n },\n isPending: loading,\n error,\n };\n};\n"],"mappings":";;;;AA4BA,SAASA,EACP,GACW;CACX,QAAQC,GAAR;EACE,KAAK,WACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAOA,IAAaC,UAA6B;CACxC,IAAM,CAACC,GAAqB,EAAE,SAASC,GAAe,OAAOC,OAC3DC,EAAYC,CAAmB,GAC3B,CAACC,GAAoB,EAAE,SAASC,GAAa,OAAOC,OACxDJ,EAAYK,CAA6B;CAK3C,OAAO;EACL,aAAa,OACX,MACiC;GACjC,IAAMV,IAAcW,EAAM,YAAY,YAAY;GAElD,IAAIA,EAAM,cAAc,eAAe;IACrC,IAAMC,IAAoD;KACxD,OAAO;MACL,YAAYD,EAAM;MAClB,MAAMZ,EAAYY,EAAM,WAAW;MACnC,WAAWA,EAAM,aAAa;KAChC;KACA,SAAS;MACP,UAAUA,EAAM,YAAY;MAC5B,cAAcA,EAAM,gBAAgB;MACvB;KACf;IACF,GACME,IAAS,MAAMN,EAAmB,EAAE,aAAU,CAAC;IACrD,OAAO,EACL,OAAOO,EACLD,EAAO,MAAM,sBAAsB,YAAY,EACjD,EACF;GACF;GAEA,IAAIF,EAAM,cAAc,kBAAkB,CAACA,EAAM,cAC/C,MAAU,MAAM,6CAA6C;GAG/D,IAAMC,IAA0C;IAC9C,OAAO;KACL,YAAYD,EAAM;KAClB,OAAOA,EAAM;KACb,MAAMZ,EAAYY,EAAM,WAAW;KACnC,SAAS;KACT,WAAWA,EAAM,aAAa;IAChC;IACA,SAAS;KACP,UAAUA,EAAM,YAAY;KAC5B,cAAcA,EAAM,gBAAgB;KACvB;IACf;GACF;GAEA,OADA,MAAMT,EAAoB,EAAE,aAAU,CAAC,GAChC,EAAE,OAAO,GAAG;EACrB;EACA,WAnDcC,KAAiBK;EAoD/B,OAnDYJ,KAAeK;CAoD7B;AACF"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { FileShareAccessLevel, FileShareType } from '../../generated/wspace-types';
|
|
2
1
|
export interface CreateShareInput {
|
|
3
2
|
fileId: string;
|
|
4
3
|
shareType: "PUBLIC_LINK" | "EMAIL_INVITE" | "GROUP_SHARE";
|
|
@@ -9,25 +8,25 @@ export interface CreateShareInput {
|
|
|
9
8
|
invitedEmail?: string;
|
|
10
9
|
invitedUserIds?: string[];
|
|
11
10
|
}
|
|
11
|
+
export interface ShareCreationResult {
|
|
12
|
+
/** Raw share token (public links only) — drives the `/files/share/:token` URL. */
|
|
13
|
+
token: string;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Extract the raw share token from a grant `shareUrl`
|
|
17
|
+
* (`{origin}/share/accept/{token}`). Falls back to the trimmed whole string
|
|
18
|
+
* when no path segment is present.
|
|
19
|
+
*/
|
|
20
|
+
export declare function extractShareToken(shareUrl: string): string;
|
|
21
|
+
/**
|
|
22
|
+
* Create a file share through the consolidated ShareGrant stack (BOFF-5302).
|
|
23
|
+
* Public links become PUBLIC_LINK grants; email invites become PENDING
|
|
24
|
+
* grants + a `resource-shared` accept email from the service. The legacy
|
|
25
|
+
* access level is preserved on the grant so the token-access path keeps
|
|
26
|
+
* issuing download URLs for DOWNLOAD shares.
|
|
27
|
+
*/
|
|
12
28
|
export declare const useCreateShare: () => {
|
|
13
|
-
mutateAsync: (input: CreateShareInput) => Promise<
|
|
14
|
-
id: string;
|
|
15
|
-
fileId: string;
|
|
16
|
-
shareType: FileShareType;
|
|
17
|
-
accessLevel: FileShareAccessLevel;
|
|
18
|
-
token: string | null;
|
|
19
|
-
invitedEmail: string | null;
|
|
20
|
-
requiresPassword: boolean;
|
|
21
|
-
expiresAt: string | null;
|
|
22
|
-
maxDownloads: number | null;
|
|
23
|
-
accessCount: number;
|
|
24
|
-
downloadCount: number;
|
|
25
|
-
lastAccessedAt: string | null;
|
|
26
|
-
revokedAt: string | null;
|
|
27
|
-
createdById: string;
|
|
28
|
-
createdAt: string;
|
|
29
|
-
updatedAt: string;
|
|
30
|
-
} | undefined>;
|
|
29
|
+
mutateAsync: (input: CreateShareInput) => Promise<ShareCreationResult>;
|
|
31
30
|
isPending: boolean;
|
|
32
31
|
error: import('@apollo/client').ErrorLike | undefined;
|
|
33
32
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCreateShare.d.ts","sourceRoot":"","sources":["../../../src/files/hooks/useCreateShare.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useCreateShare.d.ts","sourceRoot":"","sources":["../../../src/files/hooks/useCreateShare.ts"],"names":[],"mappings":"AAeA,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,aAAa,GAAG,cAAc,GAAG,aAAa,CAAC;IAC1D,WAAW,EAAE,MAAM,GAAG,SAAS,GAAG,UAAU,GAAG,MAAM,CAAC;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,cAAc,CAAC,EAAE,MAAM,EAAE,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC,kFAAkF;IAClF,KAAK,EAAE,MAAM,CAAC;CACf;AAcD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAG1D;AAED;;;;;;GAMG;AACH,eAAO,MAAM,cAAc;yBAWd,gBAAgB,KACtB,OAAO,CAAC,mBAAmB,CAAC;;;CAiDlC,CAAC"}
|
|
@@ -1,29 +1,58 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
import { useMutation as r } from "@apollo/client/react";
|
|
1
|
+
import { CreateFileShareLinkDocument as e, ShareFileDocument as t } from "../../generated/wspace-operations.js";
|
|
2
|
+
import { useMutation as n } from "@apollo/client/react";
|
|
4
3
|
//#region src/files/hooks/useCreateShare.ts
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
function r(e) {
|
|
5
|
+
switch (e) {
|
|
6
|
+
case "COMMENT": return "COMMENTER";
|
|
7
|
+
case "EDIT": return "EDITOR";
|
|
8
|
+
default: return "VIEWER";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
function i(e) {
|
|
12
|
+
return (e.match(/\/share\/accept\/([^/?#]+)$/)?.[1] ?? e).trim();
|
|
13
|
+
}
|
|
14
|
+
var a = () => {
|
|
15
|
+
let [a, { loading: o, error: s }] = n(t), [c, { loading: l, error: u }] = n(e);
|
|
7
16
|
return {
|
|
8
|
-
mutateAsync: async (e) =>
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
17
|
+
mutateAsync: async (e) => {
|
|
18
|
+
let t = e.accessLevel.toUpperCase();
|
|
19
|
+
if (e.shareType === "PUBLIC_LINK") {
|
|
20
|
+
let n = {
|
|
21
|
+
input: {
|
|
22
|
+
resourceId: e.fileId,
|
|
23
|
+
role: r(e.accessLevel),
|
|
24
|
+
expiresAt: e.expiresAt ?? null
|
|
25
|
+
},
|
|
26
|
+
options: {
|
|
27
|
+
password: e.password ?? null,
|
|
28
|
+
maxDownloads: e.maxDownloads ?? null,
|
|
29
|
+
accessLevel: t
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
return { token: i((await c({ variables: n })).data?.createFileShareLink.shareUrl ?? "") };
|
|
33
|
+
}
|
|
34
|
+
if (e.shareType !== "EMAIL_INVITE" || !e.invitedEmail) throw Error("Email invite shares require an invitedEmail");
|
|
35
|
+
let n = {
|
|
36
|
+
input: {
|
|
37
|
+
resourceId: e.fileId,
|
|
38
|
+
email: e.invitedEmail,
|
|
39
|
+
role: r(e.accessLevel),
|
|
40
|
+
message: null,
|
|
41
|
+
expiresAt: e.expiresAt ?? null
|
|
42
|
+
},
|
|
43
|
+
options: {
|
|
44
|
+
password: e.password ?? null,
|
|
45
|
+
maxDownloads: e.maxDownloads ?? null,
|
|
46
|
+
accessLevel: t
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
return await a({ variables: n }), { token: "" };
|
|
50
|
+
},
|
|
51
|
+
isPending: o || l,
|
|
52
|
+
error: s ?? u
|
|
24
53
|
};
|
|
25
54
|
};
|
|
26
55
|
//#endregion
|
|
27
|
-
export { i as useCreateShare };
|
|
56
|
+
export { i as extractShareToken, a as useCreateShare };
|
|
28
57
|
|
|
29
58
|
//# sourceMappingURL=useCreateShare.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useCreateShare.js","names":["useCreateShare","
|
|
1
|
+
{"version":3,"file":"useCreateShare.js","names":["toShareRole","accessLevel","extractShareToken","shareUrl","useCreateShare","shareFileMutation","inviteLoading","inviteError","useMutation","ShareFileDocument","createLinkMutation","linkLoading","linkError","CreateFileShareLinkDocument","input","variables"],"sources":["../../../src/files/hooks/useCreateShare.ts"],"sourcesContent":["import { useMutation } from \"@apollo/client/react\";\n\nimport {\n CreateFileShareLinkDocument,\n ShareFileDocument,\n} from \"../../generated/wspace-operations\";\nimport type {\n FileShareAccessLevel,\n ShareRole,\n} from \"../../generated/wspace-types\";\nimport type {\n CreateFileShareLinkMutationVariables,\n ShareFileMutationVariables,\n} from \"../../generated/wspace-operations\";\n\nexport interface CreateShareInput {\n fileId: string;\n shareType: \"PUBLIC_LINK\" | \"EMAIL_INVITE\" | \"GROUP_SHARE\";\n accessLevel: \"VIEW\" | \"COMMENT\" | \"DOWNLOAD\" | \"EDIT\";\n expiresAt?: string;\n password?: string;\n maxDownloads?: number;\n invitedEmail?: string;\n invitedUserIds?: string[];\n}\n\nexport interface ShareCreationResult {\n /** Raw share token (public links only) — drives the `/files/share/:token` URL. */\n token: string;\n}\n\n/** Generic ShareRole for the legacy access levels (DOWNLOAD has no dedicated role). */\nfunction toShareRole(accessLevel: CreateShareInput[\"accessLevel\"]): ShareRole {\n switch (accessLevel) {\n case \"COMMENT\":\n return \"COMMENTER\" as ShareRole;\n case \"EDIT\":\n return \"EDITOR\" as ShareRole;\n default:\n return \"VIEWER\" as ShareRole;\n }\n}\n\n/**\n * Extract the raw share token from a grant `shareUrl`\n * (`{origin}/share/accept/{token}`). Falls back to the trimmed whole string\n * when no path segment is present.\n */\nexport function extractShareToken(shareUrl: string): string {\n const match = shareUrl.match(/\\/share\\/accept\\/([^/?#]+)$/);\n return (match?.[1] ?? shareUrl).trim();\n}\n\n/**\n * Create a file share through the consolidated ShareGrant stack (BOFF-5302).\n * Public links become PUBLIC_LINK grants; email invites become PENDING\n * grants + a `resource-shared` accept email from the service. The legacy\n * access level is preserved on the grant so the token-access path keeps\n * issuing download URLs for DOWNLOAD shares.\n */\nexport const useCreateShare = () => {\n const [shareFileMutation, { loading: inviteLoading, error: inviteError }] =\n useMutation(ShareFileDocument);\n const [createLinkMutation, { loading: linkLoading, error: linkError }] =\n useMutation(CreateFileShareLinkDocument);\n\n const loading = inviteLoading || linkLoading;\n const error = inviteError ?? linkError;\n\n return {\n mutateAsync: async (\n input: CreateShareInput,\n ): Promise<ShareCreationResult> => {\n const accessLevel = input.accessLevel.toUpperCase() as\n \"VIEW\" | \"COMMENT\" | \"DOWNLOAD\" | \"EDIT\";\n if (input.shareType === \"PUBLIC_LINK\") {\n const variables: CreateFileShareLinkMutationVariables = {\n input: {\n resourceId: input.fileId,\n role: toShareRole(input.accessLevel),\n expiresAt: input.expiresAt ?? null,\n },\n options: {\n password: input.password ?? null,\n maxDownloads: input.maxDownloads ?? null,\n accessLevel: accessLevel as unknown as FileShareAccessLevel,\n },\n };\n const result = await createLinkMutation({ variables });\n return {\n token: extractShareToken(\n result.data?.createFileShareLink.shareUrl ?? \"\",\n ),\n };\n }\n\n if (input.shareType !== \"EMAIL_INVITE\" || !input.invitedEmail) {\n throw new Error(\"Email invite shares require an invitedEmail\");\n }\n\n const variables: ShareFileMutationVariables = {\n input: {\n resourceId: input.fileId,\n email: input.invitedEmail,\n role: toShareRole(input.accessLevel),\n message: null,\n expiresAt: input.expiresAt ?? null,\n },\n options: {\n password: input.password ?? null,\n maxDownloads: input.maxDownloads ?? null,\n accessLevel: accessLevel as unknown as FileShareAccessLevel,\n },\n };\n await shareFileMutation({ variables });\n // Invites are opened through the accept flow, not a public URL.\n return { token: \"\" };\n },\n isPending: loading,\n error,\n };\n};\n"],"mappings":";;;AAgCA,SAASA,EAAY,GAAyD;CAC5E,QAAQC,GAAR;EACE,KAAK,WACH,OAAO;EACT,KAAK,QACH,OAAO;EACT,SACE,OAAO;CACX;AACF;AAOA,SAAgBC,EAAkB,GAA0B;CAE1D,QADcC,EAAS,MAAM,6BACrB,CAAA,GAAQ,MAAMA,EAAA,CAAU,KAAK;AACvC;AASA,IAAaC,UAAuB;CAClC,IAAM,CAACC,GAAmB,EAAE,SAASC,GAAe,OAAOC,OACzDC,EAAYC,CAAiB,GACzB,CAACC,GAAoB,EAAE,SAASC,GAAa,OAAOC,OACxDJ,EAAYK,CAA2B;CAKzC,OAAO;EACL,aAAa,OACX,MACiC;GACjC,IAAMZ,IAAca,EAAM,YAAY,YAAY;GAElD,IAAIA,EAAM,cAAc,eAAe;IACrC,IAAMC,IAAkD;KACtD,OAAO;MACL,YAAYD,EAAM;MAClB,MAAMd,EAAYc,EAAM,WAAW;MACnC,WAAWA,EAAM,aAAa;KAChC;KACA,SAAS;MACP,UAAUA,EAAM,YAAY;MAC5B,cAAcA,EAAM,gBAAgB;MACvB;KACf;IACF;IAEA,OAAO,EACL,OAAOZ,GACL,MAHiBQ,EAAmB,EAAE,aAAU,CAAC,EAAA,CAG1C,MAAM,oBAAoB,YAAY,EAC/C,EACF;GACF;GAEA,IAAII,EAAM,cAAc,kBAAkB,CAACA,EAAM,cAC/C,MAAU,MAAM,6CAA6C;GAG/D,IAAMC,IAAwC;IAC5C,OAAO;KACL,YAAYD,EAAM;KAClB,OAAOA,EAAM;KACb,MAAMd,EAAYc,EAAM,WAAW;KACnC,SAAS;KACT,WAAWA,EAAM,aAAa;IAChC;IACA,SAAS;KACP,UAAUA,EAAM,YAAY;KAC5B,cAAcA,EAAM,gBAAgB;KACvB;IACf;GACF;GAGA,OAFA,MAAMT,EAAkB,EAAE,aAAU,CAAC,GAE9B,EAAE,OAAO,GAAG;EACrB;EACA,WApDcC,KAAiBK;EAqD/B,OApDYJ,KAAeK;CAqD7B;AACF"}
|