Skip to content

Commit 03f4610

Browse files
committed
docs: Recommend using the dedicated React wrapper in the README
1 parent c37edb5 commit 03f4610

File tree

3 files changed

+30
-135
lines changed

3 files changed

+30
-135
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@googleworkspace/drive-picker-element": patch
3+
---
4+
5+
Update README to point to @googleworkspace/drive-picker-react for React usage.

examples/csp/src/main.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,5 +48,5 @@ picker.addEventListener("picker-canceled", () => {
4848

4949
picker.addEventListener("picker-oauth-error", (e) => {
5050
console.error("OAuth Error", e);
51-
resultDiv.textContent = "OAuth Error: " + JSON.stringify(e);
51+
resultDiv.textContent = `OAuth Error: ${JSON.stringify(e)}`;
5252
});

packages/drive-picker-element/README.md

Lines changed: 24 additions & 134 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ See the framework specific demos:
2525
- [Listening to Events](#listening-to-events)
2626
- [Event Details](#event-details)
2727
- [Controlling Visibility](#controlling-visibility)
28-
- [React and JSX](#react-and-jsx)
28+
- [React](#react)
2929
- [Content Security Policy (CSP)](#content-security-policy-csp)
3030
- [Support](#support)
3131
- [Reference](#reference)
@@ -166,153 +166,43 @@ To make the picker visible, set the `visible` property of the `drive-picker` ele
166166

167167
After the picker dialog has been closed, the `visible` property will be reset to `false`.
168168

169-
### React and JSX
169+
### React
170170

171-
To use the component in a React application, you can extend the global `JSX` namespace as follows:
171+
For React applications, we recommend using the official React wrapper package: [`@googleworkspace/drive-picker-react`](https://www.npmjs.com/package/@googleworkspace/drive-picker-react).
172172

173-
```ts
174-
import type {
175-
DrivePickerElement,
176-
DrivePickerDocsViewElement,
177-
DrivePickerElementProps,
178-
DrivePickerDocsViewElementProps,
179-
} from "@googleworkspace/drive-picker-element";
180-
181-
declare global {
182-
namespace React.JSX {
183-
interface IntrinsicElements {
184-
"drive-picker": React.DetailedHTMLProps<
185-
React.HTMLAttributes<DrivePickerElement> & DrivePickerElementProps,
186-
DrivePickerElement
187-
>;
188-
"drive-picker-docs-view": React.DetailedHTMLProps<
189-
React.HTMLAttributes<DrivePickerDocsViewElement> &
190-
DrivePickerDocsViewElementProps,
191-
DrivePickerDocsViewElement
192-
>;
193-
}
194-
}
195-
}
196-
```
197-
198-
The above snippet can be added to a declaration file (e.g. `app.d.ts`) in your React project.
199-
200-
#### Using Events in React/Next.js
201-
202-
When working with React or Next.js, you need to use `useEffect` and `useRef` to properly attach event listeners to the web component. Here's a complete example:
203-
204-
```tsx
205-
import { useEffect, useRef, useState } from "react";
206-
import type {
207-
DrivePickerElement,
208-
PickerPickedEvent,
209-
} from "@googleworkspace/drive-picker-element";
210-
211-
export default function DrivePicker() {
212-
const pickerRef = useRef<DrivePickerElement>(null);
213-
const [selectedFiles, setSelectedFiles] = useState<any[]>([]);
214-
215-
useEffect(() => {
216-
// Dynamically import the web component
217-
import("@googleworkspace/drive-picker-element");
218-
}, []);
219-
220-
useEffect(() => {
221-
const pickerElement = pickerRef.current;
222-
if (!pickerElement) return;
223-
224-
// Use the non-deprecated event names (with hyphens, not colons)
225-
const handlePicked = (e: Event) => {
226-
const event = e as PickerPickedEvent;
227-
console.log("Files picked:", event.detail);
228-
setSelectedFiles(event.detail.docs || []);
229-
};
230-
231-
const handleCanceled = (e: Event) => {
232-
console.log("Picker canceled");
233-
};
234-
235-
const handleOAuthError = (e: Event) => {
236-
console.error("OAuth error:", e);
237-
};
238-
239-
// Add event listeners
240-
pickerElement.addEventListener("picker-picked", handlePicked);
241-
pickerElement.addEventListener("picker-canceled", handleCanceled);
242-
pickerElement.addEventListener("picker-oauth-error", handleOAuthError);
243-
244-
// Cleanup function to remove event listeners
245-
return () => {
246-
pickerElement.removeEventListener("picker-picked", handlePicked);
247-
pickerElement.removeEventListener("picker-canceled", handleCanceled);
248-
pickerElement.removeEventListener("picker-oauth-error", handleOAuthError);
249-
};
250-
}, []);
251-
252-
return (
253-
<div>
254-
<drive-picker
255-
ref={pickerRef}
256-
client-id="YOUR_CLIENT_ID"
257-
app-id="YOUR_APP_ID"
258-
>
259-
<drive-picker-docs-view></drive-picker-docs-view>
260-
</drive-picker>
261-
262-
{selectedFiles.length > 0 && (
263-
<div>
264-
<h3>Selected Files:</h3>
265-
<ul>
266-
{selectedFiles.map((file) => (
267-
<li key={file.id}>{file.name}</li>
268-
))}
269-
</ul>
270-
</div>
271-
)}
272-
</div>
273-
);
274-
}
275-
```
276-
277-
**Important notes for React/Next.js:**
278-
279-
1. **Dynamic import**: In Next.js, import the component dynamically inside `useEffect` to avoid server-side rendering issues, since web components need to run in the browser.
280-
281-
2. **Proper cleanup**: Always remove event listeners in the cleanup function to prevent memory leaks.
282-
283-
3. **Wait for the element**: Make sure the ref is populated before adding event listeners.
173+
Please refer to the [package documentation](../drive-picker-react/README.md) for usage instructions.
284174

285175
### Content Security Policy (CSP)
286176

287177
This library dynamically loads the Google API scripts (`https://apis.google.com/js/api.js` and `https://accounts.google.com/gsi/client`) if they are not already present. This may violate strict CSP settings that disallow dynamic script injection or restrict script sources.
288178

289179
To use this library in a strict CSP environment:
290180

291-
1. **Pre-load the scripts**: Manually include the Google API scripts in your HTML using `<script>` tags that comply with your CSP (e.g., using a `nonce` or allowing the domain).
181+
1. **Pre-load the scripts**: Manually include the Google API scripts in your HTML using `<script>` tags that comply with your CSP (e.g., using a `nonce` or allowing the domain).
292182

293-
```html
294-
<script src="https://apis.google.com/js/api.js" async defer></script>
295-
<script src="https://accounts.google.com/gsi/client" async defer></script>
296-
```
183+
```html
184+
<script src="https://apis.google.com/js/api.js" async defer></script>
185+
<script src="https://accounts.google.com/gsi/client" async defer></script>
186+
```
297187

298-
2. **Ensure global objects are available**: The library checks for `window.gapi` and `window.google.accounts.oauth2`. If these are present, it skips the dynamic injection.
188+
2. **Ensure global objects are available**: The library checks for `window.gapi` and `window.google.accounts.oauth2`. If these are present, it skips the dynamic injection.
299189

300-
3. **Allow Google domains in CSP**: You must allow the picker's origin and other Google domains in your `Content-Security-Policy`. Here is a complete example:
190+
3. **Allow Google domains in CSP**: You must allow the picker's origin and other Google domains in your `Content-Security-Policy`. Here is a complete example:
301191

302-
```http
303-
Content-Security-Policy:
304-
default-src 'self';
305-
script-src 'self' https://apis.google.com https://accounts.google.com;
306-
frame-src 'self' https://docs.google.com https://drive.google.com https://accounts.google.com;
307-
style-src 'self' 'unsafe-inline';
308-
img-src 'self' https://*.googleusercontent.com;
309-
connect-src 'self' https://*.googleapis.com;
310-
font-src 'self' https://fonts.gstatic.com;
311-
```
192+
```http
193+
Content-Security-Policy:
194+
default-src 'self';
195+
script-src 'self' https://apis.google.com https://accounts.google.com;
196+
frame-src 'self' https://docs.google.com https://drive.google.com https://accounts.google.com;
197+
style-src 'self' 'unsafe-inline';
198+
img-src 'self' https://*.googleusercontent.com;
199+
connect-src 'self' https://*.googleapis.com;
200+
font-src 'self' https://fonts.gstatic.com;
201+
```
312202

313-
**Notes:**
314-
- The `frame-src` domains are required for the Picker iframe and authentication. The exact domains may vary, but these are the most common.
315-
- `style-src: 'unsafe-inline'` may be required for some styles injected by the Picker. For a stricter policy, you can use [nonces](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/style-src#unsafe_inline_styles).
203+
**Notes:**
204+
- The `frame-src` domains are required for the Picker iframe and authentication. The exact domains may vary, but these are the most common.
205+
- `style-src: 'unsafe-inline'` may be required for some styles injected by the Picker. For a stricter policy, you can use [nonces](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/style-src#unsafe_inline_styles).
316206

317207
**Note for Chrome Extensions (Manifest V3):**
318208
The underlying Google Picker API relies on `gapi`, which is [not supported in Manifest V3 extensions](https://github.com/google/google-api-javascript-client/blob/master/docs/start.md#supported-environments). Therefore, this library may not function in that environment regardless of CSP settings.

0 commit comments

Comments
 (0)