phase 0
This commit is contained in:
commit
41573b3c4f
54 changed files with 32839 additions and 0 deletions
47
addin/src/taskpane/components/App.tsx
Normal file
47
addin/src/taskpane/components/App.tsx
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import * as React from "react";
|
||||
import Header from "./Header";
|
||||
import HeroList, { HeroListItem } from "./HeroList";
|
||||
import TextInsertion from "./TextInsertion";
|
||||
import { makeStyles } from "@fluentui/react-components";
|
||||
import { Ribbon24Regular, LockOpen24Regular, DesignIdeas24Regular } from "@fluentui/react-icons";
|
||||
import { insertText } from "../taskpane";
|
||||
|
||||
interface AppProps {
|
||||
title: string;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles({
|
||||
root: {
|
||||
minHeight: "100vh",
|
||||
},
|
||||
});
|
||||
|
||||
const App: React.FC<AppProps> = (props: AppProps) => {
|
||||
const styles = useStyles();
|
||||
// The list items are static and won't change at runtime,
|
||||
// so this should be an ordinary const, not a part of state.
|
||||
const listItems: HeroListItem[] = [
|
||||
{
|
||||
icon: <Ribbon24Regular />,
|
||||
primaryText: "Achieve more with Office integration",
|
||||
},
|
||||
{
|
||||
icon: <LockOpen24Regular />,
|
||||
primaryText: "Unlock features and functionality",
|
||||
},
|
||||
{
|
||||
icon: <DesignIdeas24Regular />,
|
||||
primaryText: "Create and visualize like a pro",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className={styles.root}>
|
||||
<Header logo="assets/logo-filled.png" title={props.title} message="Welcome" />
|
||||
<HeroList message="Discover what this add-in can do for you today!" items={listItems} />
|
||||
<TextInsertion insertText={insertText} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default App;
|
||||
38
addin/src/taskpane/components/Header.tsx
Normal file
38
addin/src/taskpane/components/Header.tsx
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import * as React from "react";
|
||||
import { Image, tokens, makeStyles } from "@fluentui/react-components";
|
||||
|
||||
export interface HeaderProps {
|
||||
title: string;
|
||||
logo: string;
|
||||
message: string;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles({
|
||||
welcome__header: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
paddingBottom: "30px",
|
||||
paddingTop: "100px",
|
||||
backgroundColor: tokens.colorNeutralBackground3,
|
||||
},
|
||||
message: {
|
||||
fontSize: tokens.fontSizeHero900,
|
||||
fontWeight: tokens.fontWeightRegular,
|
||||
fontColor: tokens.colorNeutralBackgroundStatic,
|
||||
},
|
||||
});
|
||||
|
||||
const Header: React.FC<HeaderProps> = (props: HeaderProps) => {
|
||||
const { title, logo, message } = props;
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<section className={styles.welcome__header}>
|
||||
<Image width="90" height="90" src={logo} alt={title} />
|
||||
<h1 className={styles.message}>{message}</h1>
|
||||
</section>
|
||||
);
|
||||
};
|
||||
|
||||
export default Header;
|
||||
62
addin/src/taskpane/components/HeroList.tsx
Normal file
62
addin/src/taskpane/components/HeroList.tsx
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
import * as React from "react";
|
||||
import { tokens, makeStyles } from "@fluentui/react-components";
|
||||
|
||||
export interface HeroListItem {
|
||||
icon: React.JSX.Element;
|
||||
primaryText: string;
|
||||
}
|
||||
|
||||
export interface HeroListProps {
|
||||
message: string;
|
||||
items: HeroListItem[];
|
||||
}
|
||||
|
||||
const useStyles = makeStyles({
|
||||
list: {
|
||||
marginTop: "20px",
|
||||
},
|
||||
listItem: {
|
||||
paddingBottom: "20px",
|
||||
display: "flex",
|
||||
},
|
||||
icon: {
|
||||
marginRight: "10px",
|
||||
},
|
||||
itemText: {
|
||||
fontSize: tokens.fontSizeBase300,
|
||||
fontColor: tokens.colorNeutralBackgroundStatic,
|
||||
},
|
||||
welcome__main: {
|
||||
width: "100%",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
},
|
||||
message: {
|
||||
fontSize: tokens.fontSizeBase500,
|
||||
fontColor: tokens.colorNeutralBackgroundStatic,
|
||||
fontWeight: tokens.fontWeightRegular,
|
||||
paddingLeft: "10px",
|
||||
paddingRight: "10px",
|
||||
},
|
||||
});
|
||||
|
||||
const HeroList: React.FC<HeroListProps> = (props: HeroListProps) => {
|
||||
const { items, message } = props;
|
||||
const styles = useStyles();
|
||||
|
||||
const listItems = items.map((item, index) => (
|
||||
<li className={styles.listItem} key={index}>
|
||||
<i className={styles.icon}>{item.icon}</i>
|
||||
<span className={styles.itemText}>{item.primaryText}</span>
|
||||
</li>
|
||||
));
|
||||
return (
|
||||
<div className={styles.welcome__main}>
|
||||
<h2 className={styles.message}>{message}</h2>
|
||||
<ul className={styles.list}>{listItems}</ul>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default HeroList;
|
||||
57
addin/src/taskpane/components/TextInsertion.tsx
Normal file
57
addin/src/taskpane/components/TextInsertion.tsx
Normal file
|
|
@ -0,0 +1,57 @@
|
|||
import * as React from "react";
|
||||
import { useState } from "react";
|
||||
import { Button, Field, Textarea, tokens, makeStyles } from "@fluentui/react-components";
|
||||
|
||||
/* global HTMLTextAreaElement */
|
||||
|
||||
interface TextInsertionProps {
|
||||
insertText: (text: string) => void;
|
||||
}
|
||||
|
||||
const useStyles = makeStyles({
|
||||
instructions: {
|
||||
fontWeight: tokens.fontWeightSemibold,
|
||||
marginTop: "20px",
|
||||
marginBottom: "10px",
|
||||
},
|
||||
textPromptAndInsertion: {
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
alignItems: "center",
|
||||
},
|
||||
textAreaField: {
|
||||
marginLeft: "20px",
|
||||
marginTop: "30px",
|
||||
marginBottom: "20px",
|
||||
marginRight: "20px",
|
||||
maxWidth: "50%",
|
||||
},
|
||||
});
|
||||
|
||||
const TextInsertion: React.FC<TextInsertionProps> = (props: TextInsertionProps) => {
|
||||
const [text, setText] = useState<string>("Some text.");
|
||||
|
||||
const handleTextInsertion = async () => {
|
||||
await props.insertText(text);
|
||||
};
|
||||
|
||||
const handleTextChange = async (event: React.ChangeEvent<HTMLTextAreaElement>) => {
|
||||
setText(event.target.value);
|
||||
};
|
||||
|
||||
const styles = useStyles();
|
||||
|
||||
return (
|
||||
<div className={styles.textPromptAndInsertion}>
|
||||
<Field className={styles.textAreaField} size="large" label="Enter text to be inserted into the document.">
|
||||
<Textarea size="large" value={text} onChange={handleTextChange} />
|
||||
</Field>
|
||||
<Field className={styles.instructions}>Click the button to insert text.</Field>
|
||||
<Button appearance="primary" disabled={false} size="large" onClick={handleTextInsertion}>
|
||||
Insert text
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default TextInsertion;
|
||||
27
addin/src/taskpane/index.tsx
Normal file
27
addin/src/taskpane/index.tsx
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
import * as React from "react";
|
||||
import { createRoot } from "react-dom/client";
|
||||
import App from "./components/App";
|
||||
import { FluentProvider, webLightTheme } from "@fluentui/react-components";
|
||||
|
||||
/* global document, Office, module, require, HTMLElement */
|
||||
|
||||
const title = "Contoso Task Pane Add-in";
|
||||
|
||||
const rootElement: HTMLElement | null = document.getElementById("container");
|
||||
const root = rootElement ? createRoot(rootElement) : undefined;
|
||||
|
||||
/* Render application after Office initializes */
|
||||
Office.onReady(() => {
|
||||
root?.render(
|
||||
<FluentProvider theme={webLightTheme}>
|
||||
<App title={title} />
|
||||
</FluentProvider>
|
||||
);
|
||||
});
|
||||
|
||||
if ((module as any).hot) {
|
||||
(module as any).hot.accept("./components/App", () => {
|
||||
const NextApp = require("./components/App").default;
|
||||
root?.render(NextApp);
|
||||
});
|
||||
}
|
||||
21
addin/src/taskpane/taskpane.html
Normal file
21
addin/src/taskpane/taskpane.html
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
<!-- Copyright (c) Microsoft Corporation. All rights reserved. Licensed under the MIT license. -->
|
||||
<!-- See LICENSE in the project root for license information -->
|
||||
|
||||
<!doctype html>
|
||||
<html lang="en" data-framework="typescript">
|
||||
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=Edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>Contoso Task Pane Add-in</title>
|
||||
|
||||
<!-- Office JavaScript API -->
|
||||
<script type="text/javascript" src="https://appsforoffice.microsoft.com/lib/1/hosted/office.js"></script>
|
||||
</head>
|
||||
|
||||
<body style="width: 100%; height: 100%; margin: 0; padding: 0;">
|
||||
<div id="container"></div>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
14
addin/src/taskpane/taskpane.ts
Normal file
14
addin/src/taskpane/taskpane.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
/* global Word console */
|
||||
|
||||
export async function insertText(text: string) {
|
||||
// Write text to the document.
|
||||
try {
|
||||
await Word.run(async (context) => {
|
||||
let body = context.document.body;
|
||||
body.insertParagraph(text, Word.InsertLocation.end);
|
||||
await context.sync();
|
||||
});
|
||||
} catch (error) {
|
||||
console.log("Error: " + error);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue