diff --git a/docs/documentation/docs/assets/ShareDialog.png b/docs/documentation/docs/assets/ShareDialog.png new file mode 100644 index 000000000..3b1d503ab Binary files /dev/null and b/docs/documentation/docs/assets/ShareDialog.png differ diff --git a/docs/documentation/docs/controls/ShareDialog.md b/docs/documentation/docs/controls/ShareDialog.md new file mode 100644 index 000000000..f4c0c4496 --- /dev/null +++ b/docs/documentation/docs/controls/ShareDialog.md @@ -0,0 +1,73 @@ +# ShareDialog Control + +The `ShareDialog` control is a convenient way to integrate Office Online's share dialog into your solution, allowing users to share content such as documents, lists, directly from your application. + +## Example Usage + +Here is how you can use the `ShareDialog` control in your application. + +### Share Button + +![ShareDialog](../assets/ShareDialog.png) + +## How to Use This Control + +### 1. Install the Dependency + +Ensure you have installed the `@pnp/spfx-controls-react` dependency. Refer to the [getting started](../../#getting-started) page for more details on installing the dependency. + +### 2. Import the Control + +Import the `ShareDialog` control into your component: + +```typescript +import { ShareDialog } from "@pnp/spfx-controls-react/lib/ShareDialog"; + + { console.log('Dialog closed'); }} +/> +``` + +## Implementation + +The `ShareDialog` control can be configured with the following properties: + +| Property | Type | Required | Description | +|-----------|----------------|----------|---------------------------------------------------------| +| isOpen | boolean | yes | open or close Dialog | +| options | IDialogOptions | yes | ShareDialog Options | +| onClose | function | yes | Callback function executed when the dialog is closed. | + +### Interface `IDialogOptions` + +| Property | Type | Required | Description | +|----------|----------------|----------|-------------------------------------------| +| siteUrl | string | yes | URL of the site where the item is located.| +| listId | string | yes | ID of the list containing the item. | +| itemId | string/number | yes | ID of the item to be shared. | +| name | string | yes | Name of the item to be shared. | + +### Example `IDialogOptions` Usage + +```typescript +const dialogOptions: IDialogOptions = { + siteUrl: 'https://contoso.sharepoint.com/sites/sitecollection', + listId: 'list-id', + itemId: 123, + name: 'Document Name' +}; + + { console.log('Dialog closed'); }} +/> + +``` + +![](https://telemetry.sharepointpnp.com/sp-dev-fx-controls-react/wiki/controls/ShareDialog) diff --git a/src/ShareDialog.ts b/src/ShareDialog.ts new file mode 100644 index 000000000..7834d9787 --- /dev/null +++ b/src/ShareDialog.ts @@ -0,0 +1 @@ +export * from './controls/shareDialog/index'; diff --git a/src/controls/shareDialog/ShareDialog.tsx b/src/controls/shareDialog/ShareDialog.tsx new file mode 100644 index 000000000..822954697 --- /dev/null +++ b/src/controls/shareDialog/ShareDialog.tsx @@ -0,0 +1,121 @@ +/* eslint-disable @typescript-eslint/explicit-function-return-type */ +import * as React from 'react'; +import { + useCallback, + useEffect, + useRef, + useState, +} from 'react'; + +import { css } from '@emotion/css'; + +import { RenderDialog } from './renderDialog'; + +const useStyles = (iFrameHeight: number) => { + const styles = { + iframe: css({ + width: "100%", + height: iFrameHeight, + border: "none", + }), + }; + return { styles }; +}; + +interface IEventData { + name: string; + command: string; + width: number; + height: number; +} + +interface IDialogOptions { + siteUrl: string; + listId: string; + itemId: string | number; + name: string; +} + +interface ShareDialogProps { + isOpen: boolean; + options: IDialogOptions; + onClose: () => void; +} + +export const ShareDialog: React.FC = ({ isOpen, options, onClose }) => { + const [dialogUrl, setDialogUrl] = useState(undefined); + const iframeRef = useRef(null); + const [iFrameHeight, setIFrameHeight] = useState(400); + + const { siteUrl, listId, itemId, name } = options; + const { styles } = useStyles(iFrameHeight); + + const closeDialog = useCallback(() => { + onClose(); + }, [onClose]); + + const handleIframeMessage = useCallback( + (event: MessageEvent) => { + const { name, height } = JSON.parse(event.data) as IEventData; + switch (name) { + case "share_dismiss": + closeDialog(); + break; + case "share_resize": + setIFrameHeight(height); + break; + case "share_scriptsLoaded": + break; + case "share_uiReady": + break; + case "share_ready": + break; + default: + break; + } + }, + [closeDialog] + ); + + useEffect(() => { + window.addEventListener("message", handleIframeMessage); + return () => { + window.removeEventListener("message", handleIframeMessage); + }; + }, [handleIframeMessage]); + + useEffect(() => { + if (isOpen) { + const clientId = "sharePoint"; + const policyTip = 0; + const folderColor = ""; + const clickTime = new Date().getTime(); + const fullScreenMode = false; + const origin = encodeURIComponent(window.location.origin); + const encodeName = encodeURIComponent(name as string); + + const url = + `${siteUrl}/_layouts/15/sharedialog.aspx` + + `?listId=${listId}` + + `&listItemId=${itemId}` + + `&clientId=${clientId}` + + `&policyTip=${policyTip}` + + `&folderColor=${folderColor}` + + `&clickTime=${clickTime}` + + `&ma=0` + + `&fullScreenMode=${fullScreenMode}` + + `&itemName= ${encodeName}` + + `&channelId=` + + `&origin=${origin}`; + setDialogUrl(url); + } else { + setDialogUrl(undefined); + } + }, [isOpen, siteUrl, listId, itemId]); + + return ( + +