Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add sample add-on with Vite 6 #53

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions addons-web-sdk/samples/hello-world-react-ts-vite/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# React TypeScript example

This "hello, world!" add-on is built using React, TypeScript, and [Vite](https://vite.dev/) in order to show how a React app can be deployed as a static site to be used as an add-on. It is very similar to the sample at <https://github.com/googleworkspace/meet/tree/main/addons-web-sdk/samples/hello-world>, but the basic structure is a multi-page React app. Please see our other [samples](https://github.com/googleworkspace/meet/tree/main/addons-web-sdk/samples) to learn more advanced functionality!

This add-on is deployed with GitHub pages, so that you can view the live versions of its [Side Panel](https://googleworkspace.github.io/meet/hello-world-react-ts-vite/sidepanel) and [Main Stage](https://googleworkspace.github.io/meet/hello-world-react-ts-vite/mainstage).
26 changes: 26 additions & 0 deletions addons-web-sdk/samples/hello-world-react-ts-vite/package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
{
"name": "hello-world-react-ts-vite",
"description": "This add-on is built using React and TypeScript in order to show how a React app can be modified to work as an add-on.",
"keywords": [
"Google Meet"
],
"author": "teddyward",
"license": "Apache-2.0",
"scripts": {
"start": "vite",
"build": "npm install && vite build",
"preview": "vite preview"
},
"dependencies": {
"@googleworkspace/meet-addons": "^1.1.1",
"react": "^18",
"react-dom": "^18"
},
"devDependencies": {
"@types/react": "^18",
"@types/react-dom": "^18",
"@vitejs/plugin-react": "^4.3.4",
"typescript": "^5",
"vite": "^6"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<!-- See: https://developers.google.com/meet/add-ons/guides/overview#main-stage -->
<head>
<title>Meet Add-on Main Stage in Vite-React-TS</title>
</head>

<body>
<div id="root"></div>
<script type="module" src="/mainStage.tsx"></script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<!DOCTYPE html>
<html>
<!-- See: https://developers.google.com/meet/add-ons/guides/overview#side-panel -->
<head>
<title>Meet Add-on Side Panel in Vite-React-TS</title>
</head>

<body>
<div id="root"></div>
<script type="module" src="/sidePanel.tsx"></script>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

export const CLOUD_PROJECT_NUMBER: string = '989911054302';
export const MAIN_STAGE_URL: string =
'https://googleworkspace.github.io/meet/hello-world-react-ts-vite/mainstage';
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import { StrictMode } from 'react';
import { createRoot } from 'react-dom/client';
import { useEffect } from 'react';
import { meet } from '@googleworkspace/meet-addons/meet.addons';
import { CLOUD_PROJECT_NUMBER } from './constants';

/**
* See: https://developers.google.com/meet/add-ons/guides/overview#main-stage
*/
function MainStage() {
/**
* Prepares the Add-on Main Stage Client, which signals that the add-on has
* successfully launched in the main stage.
*/
useEffect(() => {
(async () => {
const session = await meet.addon.createAddonSession({
cloudProjectNumber: CLOUD_PROJECT_NUMBER,
});
await session.createMainStageClient();
})();
}, []);

return (
<>
<div>
This is the Add-on Main Stage. Everyone in the call can see this.
</div>
<div>Hello, world!</div>
</>
);
}

// Renders the MainStage as a React component.
createRoot(document.getElementById('root')!).render(
<StrictMode>
<MainStage />
</StrictMode>
);
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { StrictMode } from 'react';
import { useEffect, useState } from 'react';
import {
meet,
MeetSidePanelClient,
} from '@googleworkspace/meet-addons/meet.addons';
import { CLOUD_PROJECT_NUMBER, MAIN_STAGE_URL } from './constants';
import { createRoot } from 'react-dom/client';

/**
* See: https://developers.google.com/meet/add-ons/guides/overview#side-panel
*/
function SidePanel() {
const [sidePanelClient, setSidePanelClient] = useState<MeetSidePanelClient>();

// Launches the main stage when the main button is clicked.
async function startActivity(e) {
if (!sidePanelClient) {
throw new Error('Side Panel is not yet initialized!');
}
await sidePanelClient.startActivity({ mainStageUrl: MAIN_STAGE_URL });
}

/**
* Prepares the Add-on Side Panel Client.
*/
useEffect(() => {
(async () => {
const session = await meet.addon.createAddonSession({
cloudProjectNumber: CLOUD_PROJECT_NUMBER,
});
setSidePanelClient(await session.createSidePanelClient());
})();
}, []);

return (
<>
<div>This is the Add-on Side Panel. Only you can see this.</div>
<button onClick={startActivity}>Launch Activity in Main Stage.</button>
</>
);
}

// Renders the SidePanel as a React component.
createRoot(document.getElementById('root')!).render(
<StrictMode>
<SidePanel />
</StrictMode>
);
14 changes: 14 additions & 0 deletions addons-web-sdk/samples/hello-world-react-ts-vite/tsconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"compilerOptions": {
"allowImportingTsExtensions": true,
"isolatedModules": true,
"jsx": "react-jsx",
"lib": ["ES2023", "DOM"],
"module": "ESNext",
"moduleResolution": "bundler",
"moduleDetection": "force",
"noEmit": true,
"target": "ES2023"
},
"include": ["src"]
}
43 changes: 43 additions & 0 deletions addons-web-sdk/samples/hello-world-react-ts-vite/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// Copyright 2024 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

import { resolve } from 'path';
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

import { fileURLToPath } from 'node:url';
const externalId = fileURLToPath(
new URL(
'node_modules/@googleworkspace/meet-addons/meet.addons.js',
import.meta.url
)
);
console.log(externalId);

// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
base: '/meet/hello-world-react-ts-vite',
root: 'src',
build: {
outDir: '../../dist/hello-world-react-ts-vite',
emptyOutDir: true,
rollupOptions: {
input: {
main: resolve(__dirname, 'src/SidePanel.html'),
mainStage: resolve(__dirname, 'src/MainStage.html'),
},
},
},
});
Loading
Loading