@microsoft/teamsfx-react 3.0.0-alpha.548abe451.0 → 3.0.0-alpha.557015fcd.0

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/README.md CHANGED
@@ -34,10 +34,19 @@ npm install @microsoft/teamsfx-react
34
34
 
35
35
  Please also install the peer dependencies if you are using npm 6.
36
36
  ```bash
37
- npm install @microsoft/teamsfx@^2.0.0 @microsoft/teams-js@^2.0.0 react@^16.8.6 react-dom@^16.8.6 @fluentui/react-northstar@^0.62.0 msteams-react-base-component@^3.1.1
37
+ npm install @microsoft/teamsfx@^2.0.0 @microsoft/teams-js@^2.0.0 react@^18.2.0 react-dom@^18.2.0 @fluentui/react-components@^9.16.0 @microsoft/microsoft-graph-client@^3.0.1
38
38
  ```
39
39
 
40
- Note that for `@microsoft/teamsfx-react@^2.0.0`, it depends on `@microsoft/teamsfx@^2.0.0` and `@microsoft/teams-js@^2.0.0`. If you wish to use lower versions, please install the peer dependencies as follows:
40
+ #### Note
41
+
42
+ For `@microsoft/teamsfx-react@^3.0.0`, it migrated to use `@fluentui/react-components` and did not support `@fluentui/react-northstar` any longer. If you still wish to use `@fluentui/react-northstar`, please use `@microsoft/teamsfx-react@<3.0.0`. To install the peer dependencies, you could use the following line:
43
+
44
+ ```bash
45
+ npm install @microsoft/teamsfx@^2.0.0 @microsoft/teams-js@^2.0.0 react@^16.8.6 react-dom@^16.8.6 @fluentui/react-northstar@^0.62.0 @microsoft/microsoft-graph-client@^3.0.1
46
+ ```
47
+
48
+ For `@microsoft/teamsfx-react@^2.0.0` and `@microsoft/teamsfx-react@^3.0.0`, they depend on `@microsoft/teamsfx@^2.0.0` and `@microsoft/teams-js@^2.0.0`. If you wish to use lower versions, please install the peer dependencies as follows:
49
+
41
50
  ```bash
42
51
  npm install @microsoft/teamsfx@^0.6.0 react@^16.8.6 @fluentui/react-northstar@^0.60.1 msteams-react-base-component@^3.1.1
43
52
  ```
@@ -111,6 +120,66 @@ return (
111
120
  );
112
121
  ```
113
122
 
123
+ ### Building a Dashboard Tab
124
+
125
+ #### 1. Create a new widget
126
+
127
+ Here is an example of creating a new widget:
128
+
129
+ ```tsx
130
+ import { Button, Text } from "@fluentui/react-components";
131
+ import { BaseWidget } from "@microsoft/teamsfx-react";
132
+ import { SampleModel } from "../models/sampleModel";
133
+ import { getSampleData } from "../services/sampleService";
134
+
135
+ interface SampleWidgetState {
136
+ data?: SampleModel;
137
+ }
138
+
139
+ export class SampleWidget extends BaseWidget<any, SampleWidgetState> {
140
+ override async getData(): Promise<SampleWidgetState> {
141
+ return { data: getSampleData() };
142
+ }
143
+
144
+ override header(): JSX.Element | undefined {
145
+ return <Text>Sample Widget</Text>;
146
+ }
147
+
148
+ override body(): JSX.Element | undefined {
149
+ return <div>{this.state.data?.content}</div>;
150
+ }
151
+
152
+ override footer(): JSX.Element | undefined {
153
+ return <Button>View Details</Button>;
154
+ }
155
+ }
156
+ ```
157
+
158
+ #### 2. Create a new dashboard
159
+
160
+ Here is an example of creating a new dashboard:
161
+
162
+ ```tsx
163
+ import { BaseDashboard } from "@microsoft/teamsfx-react";
164
+ import ListWidget from "../widgets/ListWidget";
165
+ import ChartWidget from "../widgets/ChartWidget";
166
+
167
+ export default class YourDashboard extends BaseDashboard<any, any> {
168
+ override styling(): string {
169
+ return "styling-class-name";
170
+ }
171
+
172
+ override layout(): JSX.Element | undefined {
173
+ return (
174
+ <>
175
+ <ListWidget />
176
+ <ChartWidget />
177
+ </>
178
+ );
179
+ }
180
+ }
181
+ ```
182
+
114
183
  ## React Hook list
115
184
 
116
185
  ### useData
@@ -141,6 +210,14 @@ const { loading, theme, themeString, teamsUserCredential } = useTeamsUserCredent
141
210
  This hook function leverage `useData` to call Graph API. It will execute the fetchGraphDataAsync function that the developer passes in first.
142
211
  If user has not consented to the scopes of AAD resources, `useGraph()`, `useGraphWithCredential` will automatically call login function to pop up the consent dialog. So, developers can focus on the business logic of how to fetch Microsoft Graph data.
143
212
 
213
+ ## Dashboard Related Classes
214
+
215
+ ### BaseDashboard
216
+ The BaseDashboard is a React component that provides a basic dashboard layout implementation for developers to quickly build a dashboard tab for Microsoft Teams. You can inherit this class and override some methods to customize your own dashboard. For example, define the layout of the widget in your dashboard by overriding the `layout()` method, and customize the dashboard style by overriding the `styling()` method.
217
+
218
+ ### BaseWidget
219
+ The BaseWidget is a React component that provides a basic widget layout implementation for developers to quickly build a widget. You can inherit this class and override some methods to customize your own widget. For example, define the header of the widget by overriding the `header()` method, and get data needed for the widget by overriding the `getData()` method, etc.
220
+
144
221
  ## Next steps
145
222
 
146
223
  Please take a look at the [Samples](https://github.com/OfficeDev/TeamsFx-Samples) project for detailed examples on how to use this library.
@@ -0,0 +1,59 @@
1
+ import { Component } from "react";
2
+ /**
3
+ * The state interface for the BaseDashboard component.
4
+ */
5
+ interface BaseDashboardState {
6
+ /**
7
+ * A boolean property that indicates whether the dashboard layout should be optimized for mobile devices.
8
+ */
9
+ isMobile?: boolean;
10
+ /**
11
+ * A boolean property that indicates whether the login page should be displayed.
12
+ */
13
+ showLogin?: boolean;
14
+ /**
15
+ * The resize observer for the dashboard.
16
+ * @internal
17
+ */
18
+ observer?: ResizeObserver;
19
+ }
20
+ /**
21
+ * The base component that provides basic functionality to create a dashboard.
22
+ * @typeParam P The type of props.
23
+ * @typeParam S The type of state.
24
+ */
25
+ export declare class BaseDashboard<P, S> extends Component<P, S & BaseDashboardState> {
26
+ /**
27
+ * @internal
28
+ */
29
+ private ref;
30
+ /**
31
+ * Constructor of BaseDashboard.
32
+ * @param {Readonly<P>} props The properties for the dashboard.
33
+ */
34
+ constructor(props: Readonly<P>);
35
+ /**
36
+ * Called after the component is mounted. You can do initialization that requires DOM nodes here. You can also make network requests here if you need to load data from a remote endpoint.
37
+ */
38
+ componentDidMount(): Promise<void>;
39
+ /**
40
+ * Called before the component is unmounted and destroyed. You can do necessary cleanup here, such as invalidating timers, canceling network requests, or removing any DOM elements.
41
+ */
42
+ componentWillUnmount(): void;
43
+ /**
44
+ * Defines the default layout for the dashboard.
45
+ */
46
+ render(): JSX.Element;
47
+ /**
48
+ * Override this method to define the layout of the widget in the dashboard.
49
+ * @returns The layout of the widget in the dashboard.
50
+ */
51
+ protected layout(): JSX.Element | undefined;
52
+ /**
53
+ * Override this method to customize the dashboard style.
54
+ * @returns The className for customizing the dashboard style.
55
+ */
56
+ protected styling(): string;
57
+ }
58
+ export {};
59
+ //# sourceMappingURL=BaseDashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseDashboard.d.ts","sourceRoot":"","sources":["../../src/BaseDashboard.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAoBzC;;GAEG;AACH,UAAU,kBAAkB;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED;;;;GAIG;AACH,qBAAa,aAAa,CAAC,CAAC,EAAE,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,kBAAkB,CAAC;IAC3E;;OAEG;IACH,OAAO,CAAC,GAAG,CAAkC;IAE7C;;;OAGG;gBACgB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IAUrC;;OAEG;IACU,iBAAiB;IAa9B;;OAEG;IACI,oBAAoB,IAAI,IAAI;IAOnC;;OAEG;IACI,MAAM;IAWb;;;OAGG;IACH,SAAS,CAAC,MAAM,IAAI,GAAG,CAAC,OAAO,GAAG,SAAS;IAI3C;;;OAGG;IACH,SAAS,CAAC,OAAO,IAAI,MAAM;CAG5B"}
@@ -0,0 +1,89 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseDashboard = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var react_1 = tslib_1.__importStar(require("react"));
6
+ var react_2 = require("@fluentui/react");
7
+ /**
8
+ * Returns the CSS class name for the dashboard.
9
+ * @returns The CSS class name for the dashboard.
10
+ * @internal
11
+ */
12
+ function dashboardStyle(isMobile) {
13
+ return (0, react_2.mergeStyles)(tslib_1.__assign({ display: "grid", gap: "20px", padding: "20px", gridTemplateRows: "1fr", gridTemplateColumns: "4fr 6fr" }, (isMobile === true ? { gridTemplateColumns: "1fr", gridTemplateRows: "1fr" } : {})));
14
+ }
15
+ /**
16
+ * The base component that provides basic functionality to create a dashboard.
17
+ * @typeParam P The type of props.
18
+ * @typeParam S The type of state.
19
+ */
20
+ var BaseDashboard = /** @class */ (function (_super) {
21
+ tslib_1.__extends(BaseDashboard, _super);
22
+ /**
23
+ * Constructor of BaseDashboard.
24
+ * @param {Readonly<P>} props The properties for the dashboard.
25
+ */
26
+ function BaseDashboard(props) {
27
+ var _this = _super.call(this, props) || this;
28
+ _this.state = {
29
+ isMobile: undefined,
30
+ showLogin: undefined,
31
+ observer: undefined,
32
+ };
33
+ _this.ref = react_1.default.createRef();
34
+ return _this;
35
+ }
36
+ /**
37
+ * Called after the component is mounted. You can do initialization that requires DOM nodes here. You can also make network requests here if you need to load data from a remote endpoint.
38
+ */
39
+ BaseDashboard.prototype.componentDidMount = function () {
40
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
41
+ var observer;
42
+ var _this = this;
43
+ return tslib_1.__generator(this, function (_a) {
44
+ observer = new ResizeObserver(function (entries) {
45
+ for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
46
+ var entry = entries_1[_i];
47
+ if (entry.target === _this.ref.current) {
48
+ var width = entry.contentRect.width;
49
+ _this.setState({ isMobile: width < 600 });
50
+ }
51
+ }
52
+ });
53
+ observer.observe(this.ref.current);
54
+ return [2 /*return*/];
55
+ });
56
+ });
57
+ };
58
+ /**
59
+ * Called before the component is unmounted and destroyed. You can do necessary cleanup here, such as invalidating timers, canceling network requests, or removing any DOM elements.
60
+ */
61
+ BaseDashboard.prototype.componentWillUnmount = function () {
62
+ // Unobserve the dashboard div for resize events
63
+ if (this.state.observer && this.ref.current) {
64
+ this.state.observer.unobserve(this.ref.current);
65
+ }
66
+ };
67
+ /**
68
+ * Defines the default layout for the dashboard.
69
+ */
70
+ BaseDashboard.prototype.render = function () {
71
+ return (react_1.default.createElement("div", { ref: this.ref, className: (0, react_2.mergeStyles)(dashboardStyle(this.state.isMobile), this.styling()) }, this.layout()));
72
+ };
73
+ /**
74
+ * Override this method to define the layout of the widget in the dashboard.
75
+ * @returns The layout of the widget in the dashboard.
76
+ */
77
+ BaseDashboard.prototype.layout = function () {
78
+ return undefined;
79
+ };
80
+ /**
81
+ * Override this method to customize the dashboard style.
82
+ * @returns The className for customizing the dashboard style.
83
+ */
84
+ BaseDashboard.prototype.styling = function () {
85
+ return null;
86
+ };
87
+ return BaseDashboard;
88
+ }(react_1.Component));
89
+ exports.BaseDashboard = BaseDashboard;
@@ -0,0 +1,89 @@
1
+ import { Component } from "react";
2
+ /**
3
+ * Interface for defining the class names of widget elements
4
+ */
5
+ export interface IWidgetClassNames {
6
+ /**
7
+ * The class name for the root part of the widget.
8
+ */
9
+ root?: string;
10
+ /**
11
+ * The class name for the header part of the widget.
12
+ */
13
+ header?: string;
14
+ /**
15
+ * The class name for the body part of the widget.
16
+ */
17
+ body?: string;
18
+ /**
19
+ * The class name for the footer part of the widget.
20
+ */
21
+ footer?: string;
22
+ }
23
+ /**
24
+ * Interface for defining the state of the BaseWidget class
25
+ */
26
+ interface BaseWidgetState {
27
+ loading?: boolean;
28
+ }
29
+ /**
30
+ * The base component that provides basic functionality to create a widget.
31
+ * @param P the type of props.
32
+ * @param S the type of state.
33
+ */
34
+ export declare class BaseWidget<P, S> extends Component<P, S & BaseWidgetState> {
35
+ /**
36
+ * Constructor of BaseWidget.
37
+ * @param {Readonly<P>} props - The props of the component.
38
+ */
39
+ constructor(props: Readonly<P>);
40
+ /**
41
+ * Called after the component is mounted. You can do initialization that requires DOM nodes here. You can also make network requests here if you need to load data from a remote endpoint.
42
+ */
43
+ componentDidMount(): Promise<void>;
44
+ /**
45
+ * Defines the default layout for the widget.
46
+ */
47
+ render(): JSX.Element;
48
+ /**
49
+ * Get data required by the widget
50
+ * @returns data for the widget
51
+ */
52
+ protected getData(): Promise<S>;
53
+ /**
54
+ * The purpose of this method is to provide a way for you to add custom header content to the widget.
55
+ * By overriding this method, you can add additional functionality or styling to the widget's header.
56
+ * If the method is not overridden, the widget will return undefined as the default value for the header, indicating that no custom header content has been defined.
57
+ * @returns An optional JSX.Element representing the header of the widget.
58
+ */
59
+ protected header(): JSX.Element | undefined;
60
+ /**
61
+ * The purpose of this method is to provide a way for you to add custom body content to the widget.
62
+ * By overriding this method, you can add additional functionality or styling to the widget's body.
63
+ * If the method is not overridden, the widget will return undefined as the default value for the body, indicating that no custom body content has been defined.
64
+ * @returns An optional JSX.Element representing the body of the widget.
65
+ */
66
+ protected body(): JSX.Element | undefined;
67
+ /**
68
+ * The purpose of this method is to provide a way for you to add custom footer content to the widget.
69
+ * By overriding this method, you can add additional functionality or styling to the widget's footer.
70
+ * If the method is not overridden, the widget will return undefined as the default value for the footer, indicating that no custom footer content has been defined.
71
+ * @returns An optional JSX.Element representing the footer of the widget.
72
+ */
73
+ protected footer(): JSX.Element | undefined;
74
+ /**
75
+ * This method is typically called when the widget is in the process of fetching data.
76
+ * The `undefined` return value is used to indicate that no loading indicator is required.
77
+ * If a loading indicator is required, the method can return a `JSX.Element` containing the necessary components to render the loading indicator.
78
+ * @returns A JSX element or `undefined` if no loading indicator is required.
79
+ */
80
+ protected loading(): JSX.Element | undefined;
81
+ /**
82
+ * Override this method to returns an object that defines the class names for the different parts of the widget.
83
+ * The returned object conforms to the {@link IWidgetClassNames} interface which defines the possible keys and values for the class names.
84
+ * @returns An object that defines the class names for the different parts of the widget.
85
+ */
86
+ protected styling(): IWidgetClassNames;
87
+ }
88
+ export {};
89
+ //# sourceMappingURL=BaseWidget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseWidget.d.ts","sourceRoot":"","sources":["../../src/BaseWidget.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKzC;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA2CD;;GAEG;AACH,UAAU,eAAe;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;GAIG;AACH,qBAAa,UAAU,CAAC,CAAC,EAAE,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC;IACrE;;;OAGG;gBACgB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IAKrC;;OAEG;IACU,iBAAiB;IAI9B;;OAEG;IACI,MAAM;IAsBb;;;OAGG;cACa,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC;IAIrC;;;;;OAKG;IACH,SAAS,CAAC,MAAM,IAAI,GAAG,CAAC,OAAO,GAAG,SAAS;IAI3C;;;;;OAKG;IACH,SAAS,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,GAAG,SAAS;IAIzC;;;;;OAKG;IACH,SAAS,CAAC,MAAM,IAAI,GAAG,CAAC,OAAO,GAAG,SAAS;IAI3C;;;;;OAKG;IACH,SAAS,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,GAAG,SAAS;IAI5C;;;;OAIG;IACH,SAAS,CAAC,OAAO,IAAI,iBAAiB;CAGvC"}
@@ -0,0 +1,152 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseWidget = void 0;
4
+ var tslib_1 = require("tslib");
5
+ var react_1 = tslib_1.__importStar(require("react"));
6
+ var react_2 = require("@fluentui/react");
7
+ var react_components_1 = require("@fluentui/react-components");
8
+ /**
9
+ * Style definitions for the widget elements
10
+ * @internal
11
+ */
12
+ var classNames = (0, react_2.mergeStyleSets)({
13
+ root: {
14
+ display: "grid",
15
+ padding: "1.25rem 2rem 1.25rem 2rem",
16
+ backgroundColor: react_components_1.tokens.colorNeutralBackground1,
17
+ border: "1px solid var(--colorTransparentStroke)",
18
+ boxShadow: react_components_1.tokens.shadow4,
19
+ borderRadius: react_components_1.tokens.borderRadiusMedium,
20
+ gap: react_components_1.tokens.spacingHorizontalL,
21
+ gridTemplateRows: "max-content 1fr max-content",
22
+ },
23
+ header: {
24
+ display: "grid",
25
+ height: "max-content",
26
+ "& div": {
27
+ display: "grid",
28
+ gap: react_components_1.tokens.spacingHorizontalS,
29
+ alignItems: "center",
30
+ gridTemplateColumns: "min-content 1fr min-content",
31
+ },
32
+ "& svg": {
33
+ height: "1.5rem",
34
+ width: "1.5rem",
35
+ },
36
+ "& span": {
37
+ fontWeight: react_components_1.tokens.fontWeightSemibold,
38
+ lineHeight: react_components_1.tokens.lineHeightBase200,
39
+ fontSize: react_components_1.tokens.fontSizeBase200,
40
+ },
41
+ },
42
+ footer: {
43
+ "& button": {
44
+ width: "fit-content",
45
+ },
46
+ },
47
+ });
48
+ /**
49
+ * The base component that provides basic functionality to create a widget.
50
+ * @param P the type of props.
51
+ * @param S the type of state.
52
+ */
53
+ var BaseWidget = /** @class */ (function (_super) {
54
+ tslib_1.__extends(BaseWidget, _super);
55
+ /**
56
+ * Constructor of BaseWidget.
57
+ * @param {Readonly<P>} props - The props of the component.
58
+ */
59
+ function BaseWidget(props) {
60
+ var _this = _super.call(this, props) || this;
61
+ _this.state = { loading: undefined };
62
+ return _this;
63
+ }
64
+ /**
65
+ * Called after the component is mounted. You can do initialization that requires DOM nodes here. You can also make network requests here if you need to load data from a remote endpoint.
66
+ */
67
+ BaseWidget.prototype.componentDidMount = function () {
68
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
69
+ var _a, _b;
70
+ return tslib_1.__generator(this, function (_c) {
71
+ switch (_c.label) {
72
+ case 0:
73
+ _a = this.setState;
74
+ _b = [{}];
75
+ return [4 /*yield*/, this.getData()];
76
+ case 1:
77
+ _a.apply(this, [tslib_1.__assign.apply(void 0, [tslib_1.__assign.apply(void 0, _b.concat([(_c.sent())])), { loading: false }])]);
78
+ return [2 /*return*/];
79
+ }
80
+ });
81
+ });
82
+ };
83
+ /**
84
+ * Defines the default layout for the widget.
85
+ */
86
+ BaseWidget.prototype.render = function () {
87
+ var _a = this.styling(), root = _a.root, header = _a.header, body = _a.body, footer = _a.footer;
88
+ var showLoading = this.state.loading !== false && this.loading() !== undefined;
89
+ return (react_1.default.createElement("div", { className: (0, react_2.mergeStyles)(classNames.root, root) },
90
+ this.header() && (react_1.default.createElement("div", { className: (0, react_2.mergeStyles)(classNames.header, header) }, this.header())),
91
+ showLoading ? (this.loading()) : (react_1.default.createElement(react_1.default.Fragment, null,
92
+ this.body() !== undefined && react_1.default.createElement("div", { className: body }, this.body()),
93
+ this.footer() !== undefined && (react_1.default.createElement("div", { className: (0, react_2.mergeStyles)(classNames.footer, footer) }, this.footer()))))));
94
+ };
95
+ /**
96
+ * Get data required by the widget
97
+ * @returns data for the widget
98
+ */
99
+ BaseWidget.prototype.getData = function () {
100
+ return tslib_1.__awaiter(this, void 0, void 0, function () {
101
+ return tslib_1.__generator(this, function (_a) {
102
+ return [2 /*return*/, undefined];
103
+ });
104
+ });
105
+ };
106
+ /**
107
+ * The purpose of this method is to provide a way for you to add custom header content to the widget.
108
+ * By overriding this method, you can add additional functionality or styling to the widget's header.
109
+ * If the method is not overridden, the widget will return undefined as the default value for the header, indicating that no custom header content has been defined.
110
+ * @returns An optional JSX.Element representing the header of the widget.
111
+ */
112
+ BaseWidget.prototype.header = function () {
113
+ return undefined;
114
+ };
115
+ /**
116
+ * The purpose of this method is to provide a way for you to add custom body content to the widget.
117
+ * By overriding this method, you can add additional functionality or styling to the widget's body.
118
+ * If the method is not overridden, the widget will return undefined as the default value for the body, indicating that no custom body content has been defined.
119
+ * @returns An optional JSX.Element representing the body of the widget.
120
+ */
121
+ BaseWidget.prototype.body = function () {
122
+ return undefined;
123
+ };
124
+ /**
125
+ * The purpose of this method is to provide a way for you to add custom footer content to the widget.
126
+ * By overriding this method, you can add additional functionality or styling to the widget's footer.
127
+ * If the method is not overridden, the widget will return undefined as the default value for the footer, indicating that no custom footer content has been defined.
128
+ * @returns An optional JSX.Element representing the footer of the widget.
129
+ */
130
+ BaseWidget.prototype.footer = function () {
131
+ return undefined;
132
+ };
133
+ /**
134
+ * This method is typically called when the widget is in the process of fetching data.
135
+ * The `undefined` return value is used to indicate that no loading indicator is required.
136
+ * If a loading indicator is required, the method can return a `JSX.Element` containing the necessary components to render the loading indicator.
137
+ * @returns A JSX element or `undefined` if no loading indicator is required.
138
+ */
139
+ BaseWidget.prototype.loading = function () {
140
+ return undefined;
141
+ };
142
+ /**
143
+ * Override this method to returns an object that defines the class names for the different parts of the widget.
144
+ * The returned object conforms to the {@link IWidgetClassNames} interface which defines the possible keys and values for the class names.
145
+ * @returns An object that defines the class names for the different parts of the widget.
146
+ */
147
+ BaseWidget.prototype.styling = function () {
148
+ return {};
149
+ };
150
+ return BaseWidget;
151
+ }(react_1.Component));
152
+ exports.BaseWidget = BaseWidget;
@@ -3,4 +3,6 @@ export { useData } from "./useData";
3
3
  export { useTeamsFx, TeamsFxContext } from "./useTeamsFx";
4
4
  export { useTeamsUserCredential, TeamsContextWithCredential } from "./useTeamsUserCredential";
5
5
  export { useGraph, useGraphWithCredential } from "./useGraph";
6
+ export { BaseDashboard } from "./BaseDashboard";
7
+ export { BaseWidget, IWidgetClassNames } from "./BaseWidget";
6
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
@@ -2,7 +2,7 @@
2
2
  // Copyright (c) Microsoft Corporation.
3
3
  // Licensed under the MIT license.
4
4
  Object.defineProperty(exports, "__esModule", { value: true });
5
- exports.useGraphWithCredential = exports.useGraph = exports.useTeamsUserCredential = exports.useTeamsFx = exports.useData = exports.useTeams = void 0;
5
+ exports.BaseWidget = exports.BaseDashboard = exports.useGraphWithCredential = exports.useGraph = exports.useTeamsUserCredential = exports.useTeamsFx = exports.useData = exports.useTeams = void 0;
6
6
  var useTeams_1 = require("./useTeams");
7
7
  Object.defineProperty(exports, "useTeams", { enumerable: true, get: function () { return useTeams_1.useTeams; } });
8
8
  var useData_1 = require("./useData");
@@ -14,3 +14,7 @@ Object.defineProperty(exports, "useTeamsUserCredential", { enumerable: true, get
14
14
  var useGraph_1 = require("./useGraph");
15
15
  Object.defineProperty(exports, "useGraph", { enumerable: true, get: function () { return useGraph_1.useGraph; } });
16
16
  Object.defineProperty(exports, "useGraphWithCredential", { enumerable: true, get: function () { return useGraph_1.useGraphWithCredential; } });
17
+ var BaseDashboard_1 = require("./BaseDashboard");
18
+ Object.defineProperty(exports, "BaseDashboard", { enumerable: true, get: function () { return BaseDashboard_1.BaseDashboard; } });
19
+ var BaseWidget_1 = require("./BaseWidget");
20
+ Object.defineProperty(exports, "BaseWidget", { enumerable: true, get: function () { return BaseWidget_1.BaseWidget; } });
@@ -0,0 +1,59 @@
1
+ import { Component } from "react";
2
+ /**
3
+ * The state interface for the BaseDashboard component.
4
+ */
5
+ interface BaseDashboardState {
6
+ /**
7
+ * A boolean property that indicates whether the dashboard layout should be optimized for mobile devices.
8
+ */
9
+ isMobile?: boolean;
10
+ /**
11
+ * A boolean property that indicates whether the login page should be displayed.
12
+ */
13
+ showLogin?: boolean;
14
+ /**
15
+ * The resize observer for the dashboard.
16
+ * @internal
17
+ */
18
+ observer?: ResizeObserver;
19
+ }
20
+ /**
21
+ * The base component that provides basic functionality to create a dashboard.
22
+ * @typeParam P The type of props.
23
+ * @typeParam S The type of state.
24
+ */
25
+ export declare class BaseDashboard<P, S> extends Component<P, S & BaseDashboardState> {
26
+ /**
27
+ * @internal
28
+ */
29
+ private ref;
30
+ /**
31
+ * Constructor of BaseDashboard.
32
+ * @param {Readonly<P>} props The properties for the dashboard.
33
+ */
34
+ constructor(props: Readonly<P>);
35
+ /**
36
+ * Called after the component is mounted. You can do initialization that requires DOM nodes here. You can also make network requests here if you need to load data from a remote endpoint.
37
+ */
38
+ componentDidMount(): Promise<void>;
39
+ /**
40
+ * Called before the component is unmounted and destroyed. You can do necessary cleanup here, such as invalidating timers, canceling network requests, or removing any DOM elements.
41
+ */
42
+ componentWillUnmount(): void;
43
+ /**
44
+ * Defines the default layout for the dashboard.
45
+ */
46
+ render(): JSX.Element;
47
+ /**
48
+ * Override this method to define the layout of the widget in the dashboard.
49
+ * @returns The layout of the widget in the dashboard.
50
+ */
51
+ protected layout(): JSX.Element | undefined;
52
+ /**
53
+ * Override this method to customize the dashboard style.
54
+ * @returns The className for customizing the dashboard style.
55
+ */
56
+ protected styling(): string;
57
+ }
58
+ export {};
59
+ //# sourceMappingURL=BaseDashboard.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseDashboard.d.ts","sourceRoot":"","sources":["../../src/BaseDashboard.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAoBzC;;GAEG;AACH,UAAU,kBAAkB;IAC1B;;OAEG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB;;OAEG;IACH,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB;;;OAGG;IACH,QAAQ,CAAC,EAAE,cAAc,CAAC;CAC3B;AAED;;;;GAIG;AACH,qBAAa,aAAa,CAAC,CAAC,EAAE,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,kBAAkB,CAAC;IAC3E;;OAEG;IACH,OAAO,CAAC,GAAG,CAAkC;IAE7C;;;OAGG;gBACgB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IAUrC;;OAEG;IACU,iBAAiB;IAa9B;;OAEG;IACI,oBAAoB,IAAI,IAAI;IAOnC;;OAEG;IACI,MAAM;IAWb;;;OAGG;IACH,SAAS,CAAC,MAAM,IAAI,GAAG,CAAC,OAAO,GAAG,SAAS;IAI3C;;;OAGG;IACH,SAAS,CAAC,OAAO,IAAI,MAAM;CAG5B"}
@@ -0,0 +1,86 @@
1
+ import { __assign, __awaiter, __extends, __generator } from "tslib";
2
+ import React, { Component } from "react";
3
+ import { mergeStyles } from "@fluentui/react";
4
+ /**
5
+ * Returns the CSS class name for the dashboard.
6
+ * @returns The CSS class name for the dashboard.
7
+ * @internal
8
+ */
9
+ function dashboardStyle(isMobile) {
10
+ return mergeStyles(__assign({ display: "grid", gap: "20px", padding: "20px", gridTemplateRows: "1fr", gridTemplateColumns: "4fr 6fr" }, (isMobile === true ? { gridTemplateColumns: "1fr", gridTemplateRows: "1fr" } : {})));
11
+ }
12
+ /**
13
+ * The base component that provides basic functionality to create a dashboard.
14
+ * @typeParam P The type of props.
15
+ * @typeParam S The type of state.
16
+ */
17
+ var BaseDashboard = /** @class */ (function (_super) {
18
+ __extends(BaseDashboard, _super);
19
+ /**
20
+ * Constructor of BaseDashboard.
21
+ * @param {Readonly<P>} props The properties for the dashboard.
22
+ */
23
+ function BaseDashboard(props) {
24
+ var _this = _super.call(this, props) || this;
25
+ _this.state = {
26
+ isMobile: undefined,
27
+ showLogin: undefined,
28
+ observer: undefined,
29
+ };
30
+ _this.ref = React.createRef();
31
+ return _this;
32
+ }
33
+ /**
34
+ * Called after the component is mounted. You can do initialization that requires DOM nodes here. You can also make network requests here if you need to load data from a remote endpoint.
35
+ */
36
+ BaseDashboard.prototype.componentDidMount = function () {
37
+ return __awaiter(this, void 0, void 0, function () {
38
+ var observer;
39
+ var _this = this;
40
+ return __generator(this, function (_a) {
41
+ observer = new ResizeObserver(function (entries) {
42
+ for (var _i = 0, entries_1 = entries; _i < entries_1.length; _i++) {
43
+ var entry = entries_1[_i];
44
+ if (entry.target === _this.ref.current) {
45
+ var width = entry.contentRect.width;
46
+ _this.setState({ isMobile: width < 600 });
47
+ }
48
+ }
49
+ });
50
+ observer.observe(this.ref.current);
51
+ return [2 /*return*/];
52
+ });
53
+ });
54
+ };
55
+ /**
56
+ * Called before the component is unmounted and destroyed. You can do necessary cleanup here, such as invalidating timers, canceling network requests, or removing any DOM elements.
57
+ */
58
+ BaseDashboard.prototype.componentWillUnmount = function () {
59
+ // Unobserve the dashboard div for resize events
60
+ if (this.state.observer && this.ref.current) {
61
+ this.state.observer.unobserve(this.ref.current);
62
+ }
63
+ };
64
+ /**
65
+ * Defines the default layout for the dashboard.
66
+ */
67
+ BaseDashboard.prototype.render = function () {
68
+ return (React.createElement("div", { ref: this.ref, className: mergeStyles(dashboardStyle(this.state.isMobile), this.styling()) }, this.layout()));
69
+ };
70
+ /**
71
+ * Override this method to define the layout of the widget in the dashboard.
72
+ * @returns The layout of the widget in the dashboard.
73
+ */
74
+ BaseDashboard.prototype.layout = function () {
75
+ return undefined;
76
+ };
77
+ /**
78
+ * Override this method to customize the dashboard style.
79
+ * @returns The className for customizing the dashboard style.
80
+ */
81
+ BaseDashboard.prototype.styling = function () {
82
+ return null;
83
+ };
84
+ return BaseDashboard;
85
+ }(Component));
86
+ export { BaseDashboard };
@@ -0,0 +1,89 @@
1
+ import { Component } from "react";
2
+ /**
3
+ * Interface for defining the class names of widget elements
4
+ */
5
+ export interface IWidgetClassNames {
6
+ /**
7
+ * The class name for the root part of the widget.
8
+ */
9
+ root?: string;
10
+ /**
11
+ * The class name for the header part of the widget.
12
+ */
13
+ header?: string;
14
+ /**
15
+ * The class name for the body part of the widget.
16
+ */
17
+ body?: string;
18
+ /**
19
+ * The class name for the footer part of the widget.
20
+ */
21
+ footer?: string;
22
+ }
23
+ /**
24
+ * Interface for defining the state of the BaseWidget class
25
+ */
26
+ interface BaseWidgetState {
27
+ loading?: boolean;
28
+ }
29
+ /**
30
+ * The base component that provides basic functionality to create a widget.
31
+ * @param P the type of props.
32
+ * @param S the type of state.
33
+ */
34
+ export declare class BaseWidget<P, S> extends Component<P, S & BaseWidgetState> {
35
+ /**
36
+ * Constructor of BaseWidget.
37
+ * @param {Readonly<P>} props - The props of the component.
38
+ */
39
+ constructor(props: Readonly<P>);
40
+ /**
41
+ * Called after the component is mounted. You can do initialization that requires DOM nodes here. You can also make network requests here if you need to load data from a remote endpoint.
42
+ */
43
+ componentDidMount(): Promise<void>;
44
+ /**
45
+ * Defines the default layout for the widget.
46
+ */
47
+ render(): JSX.Element;
48
+ /**
49
+ * Get data required by the widget
50
+ * @returns data for the widget
51
+ */
52
+ protected getData(): Promise<S>;
53
+ /**
54
+ * The purpose of this method is to provide a way for you to add custom header content to the widget.
55
+ * By overriding this method, you can add additional functionality or styling to the widget's header.
56
+ * If the method is not overridden, the widget will return undefined as the default value for the header, indicating that no custom header content has been defined.
57
+ * @returns An optional JSX.Element representing the header of the widget.
58
+ */
59
+ protected header(): JSX.Element | undefined;
60
+ /**
61
+ * The purpose of this method is to provide a way for you to add custom body content to the widget.
62
+ * By overriding this method, you can add additional functionality or styling to the widget's body.
63
+ * If the method is not overridden, the widget will return undefined as the default value for the body, indicating that no custom body content has been defined.
64
+ * @returns An optional JSX.Element representing the body of the widget.
65
+ */
66
+ protected body(): JSX.Element | undefined;
67
+ /**
68
+ * The purpose of this method is to provide a way for you to add custom footer content to the widget.
69
+ * By overriding this method, you can add additional functionality or styling to the widget's footer.
70
+ * If the method is not overridden, the widget will return undefined as the default value for the footer, indicating that no custom footer content has been defined.
71
+ * @returns An optional JSX.Element representing the footer of the widget.
72
+ */
73
+ protected footer(): JSX.Element | undefined;
74
+ /**
75
+ * This method is typically called when the widget is in the process of fetching data.
76
+ * The `undefined` return value is used to indicate that no loading indicator is required.
77
+ * If a loading indicator is required, the method can return a `JSX.Element` containing the necessary components to render the loading indicator.
78
+ * @returns A JSX element or `undefined` if no loading indicator is required.
79
+ */
80
+ protected loading(): JSX.Element | undefined;
81
+ /**
82
+ * Override this method to returns an object that defines the class names for the different parts of the widget.
83
+ * The returned object conforms to the {@link IWidgetClassNames} interface which defines the possible keys and values for the class names.
84
+ * @returns An object that defines the class names for the different parts of the widget.
85
+ */
86
+ protected styling(): IWidgetClassNames;
87
+ }
88
+ export {};
89
+ //# sourceMappingURL=BaseWidget.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"BaseWidget.d.ts","sourceRoot":"","sources":["../../src/BaseWidget.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAKzC;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AA2CD;;GAEG;AACH,UAAU,eAAe;IACvB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED;;;;GAIG;AACH,qBAAa,UAAU,CAAC,CAAC,EAAE,CAAC,CAAE,SAAQ,SAAS,CAAC,CAAC,EAAE,CAAC,GAAG,eAAe,CAAC;IACrE;;;OAGG;gBACgB,KAAK,EAAE,QAAQ,CAAC,CAAC,CAAC;IAKrC;;OAEG;IACU,iBAAiB;IAI9B;;OAEG;IACI,MAAM;IAsBb;;;OAGG;cACa,OAAO,IAAI,OAAO,CAAC,CAAC,CAAC;IAIrC;;;;;OAKG;IACH,SAAS,CAAC,MAAM,IAAI,GAAG,CAAC,OAAO,GAAG,SAAS;IAI3C;;;;;OAKG;IACH,SAAS,CAAC,IAAI,IAAI,GAAG,CAAC,OAAO,GAAG,SAAS;IAIzC;;;;;OAKG;IACH,SAAS,CAAC,MAAM,IAAI,GAAG,CAAC,OAAO,GAAG,SAAS;IAI3C;;;;;OAKG;IACH,SAAS,CAAC,OAAO,IAAI,GAAG,CAAC,OAAO,GAAG,SAAS;IAI5C;;;;OAIG;IACH,SAAS,CAAC,OAAO,IAAI,iBAAiB;CAGvC"}
@@ -0,0 +1,149 @@
1
+ import { __assign, __awaiter, __extends, __generator } from "tslib";
2
+ import React, { Component } from "react";
3
+ import { mergeStyles, mergeStyleSets } from "@fluentui/react";
4
+ import { tokens } from "@fluentui/react-components";
5
+ /**
6
+ * Style definitions for the widget elements
7
+ * @internal
8
+ */
9
+ var classNames = mergeStyleSets({
10
+ root: {
11
+ display: "grid",
12
+ padding: "1.25rem 2rem 1.25rem 2rem",
13
+ backgroundColor: tokens.colorNeutralBackground1,
14
+ border: "1px solid var(--colorTransparentStroke)",
15
+ boxShadow: tokens.shadow4,
16
+ borderRadius: tokens.borderRadiusMedium,
17
+ gap: tokens.spacingHorizontalL,
18
+ gridTemplateRows: "max-content 1fr max-content",
19
+ },
20
+ header: {
21
+ display: "grid",
22
+ height: "max-content",
23
+ "& div": {
24
+ display: "grid",
25
+ gap: tokens.spacingHorizontalS,
26
+ alignItems: "center",
27
+ gridTemplateColumns: "min-content 1fr min-content",
28
+ },
29
+ "& svg": {
30
+ height: "1.5rem",
31
+ width: "1.5rem",
32
+ },
33
+ "& span": {
34
+ fontWeight: tokens.fontWeightSemibold,
35
+ lineHeight: tokens.lineHeightBase200,
36
+ fontSize: tokens.fontSizeBase200,
37
+ },
38
+ },
39
+ footer: {
40
+ "& button": {
41
+ width: "fit-content",
42
+ },
43
+ },
44
+ });
45
+ /**
46
+ * The base component that provides basic functionality to create a widget.
47
+ * @param P the type of props.
48
+ * @param S the type of state.
49
+ */
50
+ var BaseWidget = /** @class */ (function (_super) {
51
+ __extends(BaseWidget, _super);
52
+ /**
53
+ * Constructor of BaseWidget.
54
+ * @param {Readonly<P>} props - The props of the component.
55
+ */
56
+ function BaseWidget(props) {
57
+ var _this = _super.call(this, props) || this;
58
+ _this.state = { loading: undefined };
59
+ return _this;
60
+ }
61
+ /**
62
+ * Called after the component is mounted. You can do initialization that requires DOM nodes here. You can also make network requests here if you need to load data from a remote endpoint.
63
+ */
64
+ BaseWidget.prototype.componentDidMount = function () {
65
+ return __awaiter(this, void 0, void 0, function () {
66
+ var _a, _b;
67
+ return __generator(this, function (_c) {
68
+ switch (_c.label) {
69
+ case 0:
70
+ _a = this.setState;
71
+ _b = [{}];
72
+ return [4 /*yield*/, this.getData()];
73
+ case 1:
74
+ _a.apply(this, [__assign.apply(void 0, [__assign.apply(void 0, _b.concat([(_c.sent())])), { loading: false }])]);
75
+ return [2 /*return*/];
76
+ }
77
+ });
78
+ });
79
+ };
80
+ /**
81
+ * Defines the default layout for the widget.
82
+ */
83
+ BaseWidget.prototype.render = function () {
84
+ var _a = this.styling(), root = _a.root, header = _a.header, body = _a.body, footer = _a.footer;
85
+ var showLoading = this.state.loading !== false && this.loading() !== undefined;
86
+ return (React.createElement("div", { className: mergeStyles(classNames.root, root) },
87
+ this.header() && (React.createElement("div", { className: mergeStyles(classNames.header, header) }, this.header())),
88
+ showLoading ? (this.loading()) : (React.createElement(React.Fragment, null,
89
+ this.body() !== undefined && React.createElement("div", { className: body }, this.body()),
90
+ this.footer() !== undefined && (React.createElement("div", { className: mergeStyles(classNames.footer, footer) }, this.footer()))))));
91
+ };
92
+ /**
93
+ * Get data required by the widget
94
+ * @returns data for the widget
95
+ */
96
+ BaseWidget.prototype.getData = function () {
97
+ return __awaiter(this, void 0, void 0, function () {
98
+ return __generator(this, function (_a) {
99
+ return [2 /*return*/, undefined];
100
+ });
101
+ });
102
+ };
103
+ /**
104
+ * The purpose of this method is to provide a way for you to add custom header content to the widget.
105
+ * By overriding this method, you can add additional functionality or styling to the widget's header.
106
+ * If the method is not overridden, the widget will return undefined as the default value for the header, indicating that no custom header content has been defined.
107
+ * @returns An optional JSX.Element representing the header of the widget.
108
+ */
109
+ BaseWidget.prototype.header = function () {
110
+ return undefined;
111
+ };
112
+ /**
113
+ * The purpose of this method is to provide a way for you to add custom body content to the widget.
114
+ * By overriding this method, you can add additional functionality or styling to the widget's body.
115
+ * If the method is not overridden, the widget will return undefined as the default value for the body, indicating that no custom body content has been defined.
116
+ * @returns An optional JSX.Element representing the body of the widget.
117
+ */
118
+ BaseWidget.prototype.body = function () {
119
+ return undefined;
120
+ };
121
+ /**
122
+ * The purpose of this method is to provide a way for you to add custom footer content to the widget.
123
+ * By overriding this method, you can add additional functionality or styling to the widget's footer.
124
+ * If the method is not overridden, the widget will return undefined as the default value for the footer, indicating that no custom footer content has been defined.
125
+ * @returns An optional JSX.Element representing the footer of the widget.
126
+ */
127
+ BaseWidget.prototype.footer = function () {
128
+ return undefined;
129
+ };
130
+ /**
131
+ * This method is typically called when the widget is in the process of fetching data.
132
+ * The `undefined` return value is used to indicate that no loading indicator is required.
133
+ * If a loading indicator is required, the method can return a `JSX.Element` containing the necessary components to render the loading indicator.
134
+ * @returns A JSX element or `undefined` if no loading indicator is required.
135
+ */
136
+ BaseWidget.prototype.loading = function () {
137
+ return undefined;
138
+ };
139
+ /**
140
+ * Override this method to returns an object that defines the class names for the different parts of the widget.
141
+ * The returned object conforms to the {@link IWidgetClassNames} interface which defines the possible keys and values for the class names.
142
+ * @returns An object that defines the class names for the different parts of the widget.
143
+ */
144
+ BaseWidget.prototype.styling = function () {
145
+ return {};
146
+ };
147
+ return BaseWidget;
148
+ }(Component));
149
+ export { BaseWidget };
@@ -3,4 +3,6 @@ export { useData } from "./useData";
3
3
  export { useTeamsFx, TeamsFxContext } from "./useTeamsFx";
4
4
  export { useTeamsUserCredential, TeamsContextWithCredential } from "./useTeamsUserCredential";
5
5
  export { useGraph, useGraphWithCredential } from "./useGraph";
6
+ export { BaseDashboard } from "./BaseDashboard";
7
+ export { BaseWidget, IWidgetClassNames } from "./BaseWidget";
6
8
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,sBAAsB,EAAE,0BAA0B,EAAE,MAAM,0BAA0B,CAAC;AAC9F,OAAO,EAAE,QAAQ,EAAE,sBAAsB,EAAE,MAAM,YAAY,CAAC;AAC9D,OAAO,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC"}
@@ -5,3 +5,5 @@ export { useData } from "./useData";
5
5
  export { useTeamsFx } from "./useTeamsFx";
6
6
  export { useTeamsUserCredential } from "./useTeamsUserCredential";
7
7
  export { useGraph, useGraphWithCredential } from "./useGraph";
8
+ export { BaseDashboard } from "./BaseDashboard";
9
+ export { BaseWidget } from "./BaseWidget";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@microsoft/teamsfx-react",
3
- "version": "3.0.0-alpha.548abe451.0",
3
+ "version": "3.0.0-alpha.557015fcd.0",
4
4
  "description": "React helper functions for Microsoft TeamsFx",
5
5
  "main": "build/cjs/index.js",
6
6
  "module": "build/esm/index.js",
@@ -30,10 +30,10 @@
30
30
  "devDependencies": {
31
31
  "@fluentui/react-components": "^9.15.0",
32
32
  "@istanbuljs/nyc-config-typescript": "^1.0.2",
33
- "@microsoft/eslint-plugin-teamsfx": "0.0.2-alpha.548abe451.0",
33
+ "@microsoft/eslint-plugin-teamsfx": "0.0.2-alpha.557015fcd.0",
34
34
  "@microsoft/microsoft-graph-client": "^3.0.1",
35
35
  "@microsoft/teams-js": "^2.0.0",
36
- "@microsoft/teamsfx": "2.2.1-alpha.548abe451.0",
36
+ "@microsoft/teamsfx": "2.2.1-alpha.557015fcd.0",
37
37
  "@testing-library/react": "^13.4.0",
38
38
  "@types/enzyme": "^3.10.10",
39
39
  "@types/jest": "^29.4.0",
@@ -77,6 +77,9 @@
77
77
  "react": ">=16.8.0 <19.0.0",
78
78
  "react-dom": ">=16.8.0 <19.0.0"
79
79
  },
80
+ "dependencies": {
81
+ "@fluentui/react": "^8.106.1"
82
+ },
80
83
  "publishConfig": {
81
84
  "access": "public"
82
85
  },
@@ -85,5 +88,5 @@
85
88
  "npx eslint --cache --fix --quiet"
86
89
  ]
87
90
  },
88
- "gitHead": "6e0d11f9dd0476f1e653340bc7d93c03f544d3c6"
91
+ "gitHead": "2b8442c32afce47b853888d39e29d86c87739e88"
89
92
  }