@pnp/spfx-controls-react 3.24.0-beta.2252413 → 3.24.0-beta.2252438
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/CHANGELOG.json +4 -1
- package/CHANGELOG.md +5 -14
- package/lib/common/telemetry/version.js +1 -1
- package/lib/controls/ListToolbar/FlatItem.d.ts +7 -0
- package/lib/controls/ListToolbar/FlatItem.d.ts.map +1 -0
- package/lib/controls/ListToolbar/FlatItem.js +2 -0
- package/lib/controls/ListToolbar/FlatItem.js.map +1 -0
- package/lib/controls/ListToolbar/IListToolbarProps.d.ts +27 -0
- package/lib/controls/ListToolbar/IListToolbarProps.d.ts.map +1 -0
- package/lib/controls/ListToolbar/IListToolbarProps.js +2 -0
- package/lib/controls/ListToolbar/IListToolbarProps.js.map +1 -0
- package/lib/controls/ListToolbar/IToolbarItem.d.ts +36 -0
- package/lib/controls/ListToolbar/IToolbarItem.d.ts.map +1 -0
- package/lib/controls/ListToolbar/IToolbarItem.js +2 -0
- package/lib/controls/ListToolbar/IToolbarItem.js.map +1 -0
- package/lib/controls/ListToolbar/IToolbarItemRendererProps.d.ts +12 -0
- package/lib/controls/ListToolbar/IToolbarItemRendererProps.d.ts.map +1 -0
- package/lib/controls/ListToolbar/IToolbarItemRendererProps.js +2 -0
- package/lib/controls/ListToolbar/IToolbarItemRendererProps.js.map +1 -0
- package/lib/controls/ListToolbar/ListToolbar.d.ts +4 -0
- package/lib/controls/ListToolbar/ListToolbar.d.ts.map +1 -0
- package/lib/controls/ListToolbar/ListToolbar.js +119 -0
- package/lib/controls/ListToolbar/ListToolbar.js.map +1 -0
- package/lib/controls/ListToolbar/ListToolbarControl.d.ts +5 -0
- package/lib/controls/ListToolbar/ListToolbarControl.d.ts.map +1 -0
- package/lib/controls/ListToolbar/ListToolbarControl.js +101 -0
- package/lib/controls/ListToolbar/ListToolbarControl.js.map +1 -0
- package/lib/controls/ListToolbar/README.md +410 -0
- package/lib/controls/ListToolbar/ToolbarItemRenderer.d.ts +7 -0
- package/lib/controls/ListToolbar/ToolbarItemRenderer.d.ts.map +1 -0
- package/lib/controls/ListToolbar/ToolbarItemRenderer.js +19 -0
- package/lib/controls/ListToolbar/ToolbarItemRenderer.js.map +1 -0
- package/lib/controls/ListToolbar/helpers.d.ts +5 -0
- package/lib/controls/ListToolbar/helpers.d.ts.map +1 -0
- package/lib/controls/ListToolbar/helpers.js +42 -0
- package/lib/controls/ListToolbar/helpers.js.map +1 -0
- package/lib/controls/ListToolbar/index.d.ts +4 -0
- package/lib/controls/ListToolbar/index.d.ts.map +1 -0
- package/lib/controls/ListToolbar/index.js +2 -0
- package/lib/controls/ListToolbar/index.js.map +1 -0
- package/lib/controls/ListToolbar/useListToolbarStyles.d.ts +16 -0
- package/lib/controls/ListToolbar/useListToolbarStyles.d.ts.map +1 -0
- package/lib/controls/ListToolbar/useListToolbarStyles.js +36 -0
- package/lib/controls/ListToolbar/useListToolbarStyles.js.map +1 -0
- package/lib/controls/ListToolbar/useOverflowIndex.d.ts +18 -0
- package/lib/controls/ListToolbar/useOverflowIndex.d.ts.map +1 -0
- package/lib/controls/ListToolbar/useOverflowIndex.js +101 -0
- package/lib/controls/ListToolbar/useOverflowIndex.js.map +1 -0
- package/package.json +1 -1
package/CHANGELOG.json
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
{
|
|
4
4
|
"version": "3.24.0",
|
|
5
5
|
"changes": {
|
|
6
|
-
"new": [
|
|
6
|
+
"new": [
|
|
7
|
+
"`KPIControl`: new control `KPIControl` [#2084](https://github.com/pnp/sp-dev-fx-controls-react/pull/2084)"
|
|
8
|
+
],
|
|
7
9
|
"enhancements": [],
|
|
8
10
|
"fixes":[
|
|
9
11
|
"`PeoplePicker`: Improving documentation page about external users search [#323](https://github.com/pnp/sp-dev-fx-controls-react/issues/323)",
|
|
@@ -12,6 +14,7 @@
|
|
|
12
14
|
},
|
|
13
15
|
"contributions": [
|
|
14
16
|
"[Antanina Druzhkina](https://github.com/Ateina)",
|
|
17
|
+
"[joaojmendes](https://github.com/joaojmendes)",
|
|
15
18
|
"[Michaël Maillot](https://github.com/michaelmaillot)",
|
|
16
19
|
"[Nishkalank Bezawada](https://github.com/NishkalankBezawada)"
|
|
17
20
|
]
|
package/CHANGELOG.md
CHANGED
|
@@ -1,28 +1,19 @@
|
|
|
1
1
|
# Releases
|
|
2
|
-
|
|
3
2
|
|
|
4
3
|
## 3.24.0
|
|
5
4
|
|
|
5
|
+
### New control(s)
|
|
6
|
+
|
|
7
|
+
- `KPIControl`: new control `KPIControl` [#2084](https://github.com/pnp/sp-dev-fx-controls-react/pull/2084)
|
|
8
|
+
|
|
6
9
|
### Fixes
|
|
7
10
|
|
|
8
11
|
- `PeoplePicker`: Improving documentation page about external users search [#323](https://github.com/pnp/sp-dev-fx-controls-react/issues/323)
|
|
9
12
|
- `FolderExplorer`: Updated Folder explorer control documentation to correct a typo. [#2072](https://github.com/pnp/sp-dev-fx-controls-react/pull/2072)
|
|
10
|
-
- `ListItemComments`: Multiline comment doesn't display correctly in ListItemComments control due to missing line break [2078](https://github.com/pnp/sp-dev-fx-controls-react/issues/2078)
|
|
11
|
-
- `ImagePicker`: Imagepicker strings fix [2077](https://github.com/pnp/sp-dev-fx-controls-react/pull/2077)
|
|
12
|
-
- `TreeView`: TreeView Item - pass through imageProps of iconProps to TreeItem [#2074](https://github.com/pnp/sp-dev-fx-controls-react/issues/2074)
|
|
13
|
-
|
|
14
|
-
### Enhancements
|
|
15
|
-
|
|
16
|
-
- `ListItemAttachments`: Add render options for ListItemAttachments [2081](https://github.com/pnp/sp-dev-fx-controls-react/pull/2081)
|
|
17
|
-
|
|
18
|
-
### New Control(s)
|
|
19
|
-
|
|
20
|
-
- `GroupPicker`: New GroupPicker Control - select one or multiple M365 Groups [2085](https://github.com/pnp/sp-dev-fx-controls-react/pull/2085)
|
|
21
13
|
|
|
22
14
|
### Contributors
|
|
23
15
|
|
|
24
|
-
Special thanks to our contributors (in alphabetical order): [Antanina Druzhkina](https://github.com/Ateina), [Michaël Maillot](https://github.com/michaelmaillot), [Nishkalank Bezawada](https://github.com/NishkalankBezawada).
|
|
25
|
-
Special thanks to our contributors (in alphabetical order): [Antanina Druzhkina](https://github.com/Ateina),[wuxiaojun514](https://github.com/wuxiaojun514),[Paul Schaeflein](https://github.com/pschaeflein).
|
|
16
|
+
Special thanks to our contributors (in alphabetical order): [Antanina Druzhkina](https://github.com/Ateina), [joaojmendes](https://github.com/joaojmendes), [Michaël Maillot](https://github.com/michaelmaillot), [Nishkalank Bezawada](https://github.com/NishkalankBezawada).
|
|
26
17
|
|
|
27
18
|
## 3.23.0
|
|
28
19
|
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export var version = "3.24.0-beta.
|
|
1
|
+
export var version = "3.24.0-beta.2252438";
|
|
2
2
|
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FlatItem.d.ts","sourceRoot":"","sources":["../../../src/controls/ListToolbar/FlatItem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM9C,MAAM,WAAW,QAAQ;IACvB,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC;IACzB,IAAI,CAAC,EAAE,YAAY,CAAC;IACpB,GAAG,EAAE,MAAM,CAAC;CACb"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"FlatItem.js","sourceRoot":"","sources":["../../../src/controls/ListToolbar/FlatItem.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { BaseComponentContext } from "@microsoft/sp-component-base";
|
|
2
|
+
import { IToolbarItem } from "./IToolbarItem";
|
|
3
|
+
import { Theme } from "@fluentui/react";
|
|
4
|
+
/**
|
|
5
|
+
* Props for the ListToolbar component
|
|
6
|
+
*/
|
|
7
|
+
export interface IListToolbarProps {
|
|
8
|
+
/** Array of toolbar items */
|
|
9
|
+
items: IToolbarItem[];
|
|
10
|
+
/** Far items that appear on the right side of the toolbar */
|
|
11
|
+
farItems?: IToolbarItem[];
|
|
12
|
+
/** Whether the toolbar is in a loading state */
|
|
13
|
+
isLoading?: boolean;
|
|
14
|
+
/** Aria label for the toolbar */
|
|
15
|
+
ariaLabel?: string;
|
|
16
|
+
/** Total count to display (optional) */
|
|
17
|
+
totalCount?: number;
|
|
18
|
+
/** Custom class name */
|
|
19
|
+
className?: string;
|
|
20
|
+
/** Whether to show dividers between groups */
|
|
21
|
+
showGroupDividers?: boolean;
|
|
22
|
+
/** Theme for the toolbar */
|
|
23
|
+
theme?: Theme;
|
|
24
|
+
/** Context for the web part */
|
|
25
|
+
context?: BaseComponentContext;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=IListToolbarProps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IListToolbarProps.d.ts","sourceRoot":"","sources":["../../../src/controls/ListToolbar/IListToolbarProps.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,8BAA8B,CAAC;AACpE,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC;;GAEG;AAEH,MAAM,WAAW,iBAAiB;IAC9B,6BAA6B;IAC7B,KAAK,EAAE,YAAY,EAAE,CAAC;IACtB,6DAA6D;IAC7D,QAAQ,CAAC,EAAE,YAAY,EAAE,CAAC;IAC1B,gDAAgD;IAChD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,iCAAiC;IACjC,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,wBAAwB;IACxB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,8CAA8C;IAC9C,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,4BAA4B;IAC5B,KAAK,CAAC,EAAE,KAAK,CAAC;IACd,+BAA+B;IAC/B,OAAO,CAAC,EAAE,oBAAoB,CAAC;CAClC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IListToolbarProps.js","sourceRoot":"","sources":["../../../src/controls/ListToolbar/IListToolbarProps.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { ToolbarButtonProps } from "@fluentui/react-components";
|
|
2
|
+
import * as React from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Extended toolbar item interface
|
|
5
|
+
*/
|
|
6
|
+
export interface IToolbarItem {
|
|
7
|
+
/** Unique key for the item */
|
|
8
|
+
key: string;
|
|
9
|
+
/** Label text for the button */
|
|
10
|
+
label?: string;
|
|
11
|
+
/** Tooltip content */
|
|
12
|
+
tooltip?: string;
|
|
13
|
+
/** Icon element */
|
|
14
|
+
icon?: React.ReactElement;
|
|
15
|
+
/** Click handler */
|
|
16
|
+
onClick?: () => void;
|
|
17
|
+
/** Whether the item is disabled */
|
|
18
|
+
disabled?: boolean;
|
|
19
|
+
/** Whether to show the item */
|
|
20
|
+
visible?: boolean;
|
|
21
|
+
/** Group name - items with the same group will be grouped together */
|
|
22
|
+
group?: string;
|
|
23
|
+
/** Whether this is a far item (appears on the right side) */
|
|
24
|
+
isFarItem?: boolean;
|
|
25
|
+
/** Button appearance */
|
|
26
|
+
appearance?: ToolbarButtonProps["appearance"];
|
|
27
|
+
/** Custom render function for complete control */
|
|
28
|
+
onRender?: () => React.ReactElement;
|
|
29
|
+
/** Whether to add a divider after this item */
|
|
30
|
+
dividerAfter?: boolean;
|
|
31
|
+
/** Whether to add a divider before this item */
|
|
32
|
+
dividerBefore?: boolean;
|
|
33
|
+
/** Aria label override */
|
|
34
|
+
ariaLabel?: string;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=IToolbarItem.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IToolbarItem.d.ts","sourceRoot":"","sources":["../../../src/controls/ListToolbar/IToolbarItem.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B;;GAEG;AAEH,MAAM,WAAW,YAAY;IACzB,8BAA8B;IAC9B,GAAG,EAAE,MAAM,CAAC;IACZ,gCAAgC;IAChC,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,sBAAsB;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,mBAAmB;IACnB,IAAI,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;IAC1B,oBAAoB;IACpB,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IACrB,mCAAmC;IACnC,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,sEAAsE;IACtE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,6DAA6D;IAC7D,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,wBAAwB;IACxB,UAAU,CAAC,EAAE,kBAAkB,CAAC,YAAY,CAAC,CAAC;IAC9C,kDAAkD;IAClD,QAAQ,CAAC,EAAE,MAAM,KAAK,CAAC,YAAY,CAAC;IACpC,+CAA+C;IAC/C,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,gDAAgD;IAChD,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,0BAA0B;IAC1B,SAAS,CAAC,EAAE,MAAM,CAAC;CACtB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IToolbarItem.js","sourceRoot":"","sources":["../../../src/controls/ListToolbar/IToolbarItem.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { IToolbarItem } from './IToolbarItem';
|
|
2
|
+
export interface IToolbarItemRendererProps {
|
|
3
|
+
/** The toolbar item to render */
|
|
4
|
+
item: IToolbarItem;
|
|
5
|
+
/** Whether the toolbar is in a loading state */
|
|
6
|
+
isLoading?: boolean;
|
|
7
|
+
/** CSS class applied to the button root */
|
|
8
|
+
itemClass?: string;
|
|
9
|
+
/** CSS class applied to the label text (e.g. to hide on mobile) */
|
|
10
|
+
labelClass?: string;
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=IToolbarItemRendererProps.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IToolbarItemRendererProps.d.ts","sourceRoot":"","sources":["../../../src/controls/ListToolbar/IToolbarItemRendererProps.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAG9C,MAAM,WAAW,yBAAyB;IACxC,iCAAiC;IACjC,IAAI,EAAE,YAAY,CAAC;IACnB,gDAAgD;IAChD,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,2CAA2C;IAC3C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mEAAmE;IACnE,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"IToolbarItemRendererProps.js","sourceRoot":"","sources":["../../../src/controls/ListToolbar/IToolbarItemRendererProps.tsx"],"names":[],"mappings":""}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListToolbar.d.ts","sourceRoot":"","sources":["../../../src/controls/ListToolbar/ListToolbar.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAkB/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAuDlE,CAAC"}
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
23
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
+
function step(op) {
|
|
26
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
+
while (g && (g = 0, op[0] && (_ = 0)), _) try {
|
|
28
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
+
switch (op[0]) {
|
|
31
|
+
case 0: case 1: t = op; break;
|
|
32
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
+
default:
|
|
36
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
+
if (t[2]) _.ops.pop();
|
|
41
|
+
_.trys.pop(); continue;
|
|
42
|
+
}
|
|
43
|
+
op = body.call(thisArg, _);
|
|
44
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
/* eslint-disable @typescript-eslint/no-floating-promises */
|
|
49
|
+
/* eslint-disable @typescript-eslint/no-unused-vars */
|
|
50
|
+
import * as React from "react";
|
|
51
|
+
import { Provider } from "jotai";
|
|
52
|
+
import { has } from "lodash";
|
|
53
|
+
import { FluentProvider, IdPrefixProvider, teamsDarkTheme, teamsHighContrastTheme, teamsLightTheme, } from "@fluentui/react-components";
|
|
54
|
+
import { createV9Theme } from "@fluentui/react-migration-v8-v9";
|
|
55
|
+
import { useTheme } from "@fluentui/react-theme-provider";
|
|
56
|
+
import ListToolbarControl from "./ListToolbarControl";
|
|
57
|
+
export var ListToolbar = function (props) {
|
|
58
|
+
var themeV8 = props.theme, context = props.context;
|
|
59
|
+
var _a = React.useState(), theme = _a[0], setTheme = _a[1];
|
|
60
|
+
var currentSPTheme = useTheme();
|
|
61
|
+
var _b = React.useState(false), isInitialized = _b[0], setIsInitialized = _b[1];
|
|
62
|
+
React.useEffect(function () {
|
|
63
|
+
(function () { return __awaiter(void 0, void 0, void 0, function () {
|
|
64
|
+
var teamsContext, teamsTheme, error_1;
|
|
65
|
+
var _a;
|
|
66
|
+
return __generator(this, function (_b) {
|
|
67
|
+
switch (_b.label) {
|
|
68
|
+
case 0:
|
|
69
|
+
_b.trys.push([0, 4, , 5]);
|
|
70
|
+
if (!has(context, "sdks.microsoftTeams.teamsJs.app.getContext")) return [3 /*break*/, 2];
|
|
71
|
+
return [4 /*yield*/, ((_a = context.sdks.microsoftTeams) === null || _a === void 0 ? void 0 : _a.teamsJs.app.getContext())];
|
|
72
|
+
case 1:
|
|
73
|
+
teamsContext = _b.sent();
|
|
74
|
+
teamsTheme = teamsContext.app.theme || "default";
|
|
75
|
+
switch (teamsTheme) {
|
|
76
|
+
case "dark":
|
|
77
|
+
setTheme(teamsDarkTheme);
|
|
78
|
+
break;
|
|
79
|
+
case "contrast":
|
|
80
|
+
setTheme(teamsHighContrastTheme);
|
|
81
|
+
break;
|
|
82
|
+
case "default":
|
|
83
|
+
setTheme(teamsLightTheme);
|
|
84
|
+
break;
|
|
85
|
+
default:
|
|
86
|
+
setTheme(teamsLightTheme);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
return [3 /*break*/, 3];
|
|
90
|
+
case 2:
|
|
91
|
+
if (themeV8 || currentSPTheme) {
|
|
92
|
+
setTheme(createV9Theme(themeV8 !== null && themeV8 !== void 0 ? themeV8 : currentSPTheme));
|
|
93
|
+
}
|
|
94
|
+
else {
|
|
95
|
+
setTheme(teamsLightTheme);
|
|
96
|
+
}
|
|
97
|
+
_b.label = 3;
|
|
98
|
+
case 3: return [3 /*break*/, 5];
|
|
99
|
+
case 4:
|
|
100
|
+
error_1 = _b.sent();
|
|
101
|
+
console.warn("ListToolbar: Failed to resolve theme, using default", error_1);
|
|
102
|
+
setTheme(teamsLightTheme);
|
|
103
|
+
return [3 /*break*/, 5];
|
|
104
|
+
case 5:
|
|
105
|
+
setIsInitialized(true);
|
|
106
|
+
return [2 /*return*/];
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}); })();
|
|
110
|
+
}, [context, currentSPTheme, themeV8]);
|
|
111
|
+
if (!isInitialized)
|
|
112
|
+
return React.createElement(React.Fragment, null);
|
|
113
|
+
return (React.createElement(React.Fragment, null,
|
|
114
|
+
React.createElement(IdPrefixProvider, { value: "userPicker-" },
|
|
115
|
+
React.createElement(FluentProvider, { theme: theme },
|
|
116
|
+
React.createElement(Provider, null,
|
|
117
|
+
React.createElement(ListToolbarControl, __assign({}, props)))))));
|
|
118
|
+
};
|
|
119
|
+
//# sourceMappingURL=ListToolbar.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListToolbar.js","sourceRoot":"","sources":["../../../src/controls/ListToolbar/ListToolbar.tsx"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,4DAA4D;AAC5D,sDAAsD;AACtD,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,GAAG,EAAE,MAAM,QAAQ,CAAC;AAE7B,OAAO,EACL,cAAc,EACd,gBAAgB,EAChB,cAAc,EACd,sBAAsB,EACtB,eAAe,GAEhB,MAAM,4BAA4B,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAChE,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAK1D,OAAO,kBAAkB,MAAM,sBAAsB,CAAC;AAEtD,MAAM,CAAC,IAAM,WAAW,GAA+C,UACrE,KAAmD;IAE3C,IAAO,OAAO,GAAc,KAAK,MAAnB,EAAE,OAAO,GAAK,KAAK,QAAV,CAAW;IACpC,IAAA,KAAoB,KAAK,CAAC,QAAQ,EAAS,EAA1C,KAAK,QAAA,EAAE,QAAQ,QAA2B,CAAC;IAClD,IAAM,cAAc,GAAG,QAAQ,EAAE,CAAC;IAC5B,IAAA,KAAoC,KAAK,CAAC,QAAQ,CAAU,KAAK,CAAC,EAAjE,aAAa,QAAA,EAAE,gBAAgB,QAAkC,CAAC;IAGzE,KAAK,CAAC,SAAS,CAAC;QACd,CAAC;;;;;;;6BAEO,GAAG,CAAC,OAAO,EAAE,4CAA4C,CAAC,EAA1D,wBAA0D;wBACvC,qBAAM,CAAA,MAAC,OAA0B,CAAC,IAAI,CAAC,cAAc,0CAAE,OAAO,CAAC,GAAG,CAAC,UAAU,EAAE,CAAA,EAAA;;wBAA9F,YAAY,GAAG,SAA+E;wBAC9F,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,KAAK,IAAI,SAAS,CAAC;wBACvD,QAAQ,UAAU,EAAE,CAAC;4BACnB,KAAK,MAAM;gCACT,QAAQ,CAAC,cAAc,CAAC,CAAC;gCACzB,MAAM;4BACR,KAAK,UAAU;gCACb,QAAQ,CAAC,sBAAsB,CAAC,CAAC;gCACjC,MAAM;4BACR,KAAK,SAAS;gCACZ,QAAQ,CAAC,eAAe,CAAC,CAAC;gCAC1B,MAAM;4BACR;gCACE,QAAQ,CAAC,eAAe,CAAC,CAAC;gCAC1B,MAAM;wBACV,CAAC;;;wBACI,IAAI,OAAO,IAAI,cAAc,EAAE,CAAC;4BACrC,QAAQ,CAAC,aAAa,CAAC,OAAO,aAAP,OAAO,cAAP,OAAO,GAAI,cAAc,CAAC,CAAC,CAAC;wBACrD,CAAC;6BAAM,CAAC;4BACN,QAAQ,CAAC,eAAe,CAAC,CAAC;wBAC5B,CAAC;;;;;wBAED,OAAO,CAAC,IAAI,CAAC,qDAAqD,EAAE,OAAK,CAAC,CAAC;wBAC3E,QAAQ,CAAC,eAAe,CAAC,CAAC;;;wBAE5B,gBAAgB,CAAC,IAAI,CAAC,CAAC;;;;aACxB,CAAC,EAAE,CAAC;IACP,CAAC,EAAE,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,CAAC,CAAC;IAEvC,IAAI,CAAC,aAAa;QAAE,OAAO,yCAAK,CAAC;IAEjC,OAAO,CACL;QACE,oBAAC,gBAAgB,IAAC,KAAK,EAAC,aAAa;YACrC,oBAAC,cAAc,IAAC,KAAK,EAAE,KAAK;gBAC1B,oBAAC,QAAQ;oBACP,oBAAC,kBAAkB,eAAK,KAAK,EAAI,CACxB,CACI,CACE,CAClB,CACJ,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListToolbarControl.d.ts","sourceRoot":"","sources":["../../../src/controls/ListToolbar/ListToolbarControl.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAgB/B,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AASxD,eAAO,MAAM,WAAW,EAAE,KAAK,CAAC,iBAAiB,CAAC,iBAAiB,CAuMlE,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
|
|
2
|
+
if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
|
|
3
|
+
if (ar || !(i in from)) {
|
|
4
|
+
if (!ar) ar = Array.prototype.slice.call(from, 0, i);
|
|
5
|
+
ar[i] = from[i];
|
|
6
|
+
}
|
|
7
|
+
}
|
|
8
|
+
return to.concat(ar || Array.prototype.slice.call(from));
|
|
9
|
+
};
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
import { ToolbarButton, ToolbarDivider, Tooltip, Badge, Text, Menu, MenuTrigger, MenuPopover, MenuList, MenuItem, } from '@fluentui/react-components';
|
|
12
|
+
import { MoreHorizontalRegular } from '@fluentui/react-icons';
|
|
13
|
+
import { useListToolbarStyles } from './useListToolbarStyles';
|
|
14
|
+
import { useOverflowIndex } from './useOverflowIndex';
|
|
15
|
+
import { ToolbarItemRenderer } from './ToolbarItemRenderer';
|
|
16
|
+
import { groupItems, flattenWithDividers } from './helpers';
|
|
17
|
+
/* ------------------------------------------------------------------ */
|
|
18
|
+
/* ListToolbar — main component */
|
|
19
|
+
/* ------------------------------------------------------------------ */
|
|
20
|
+
export var ListToolbar = function (_a) {
|
|
21
|
+
var items = _a.items, _b = _a.farItems, farItems = _b === void 0 ? [] : _b, _c = _a.isLoading, isLoading = _c === void 0 ? false : _c, _d = _a.ariaLabel, ariaLabel = _d === void 0 ? 'Toolbar' : _d, totalCount = _a.totalCount, className = _a.className, _e = _a.showGroupDividers, showGroupDividers = _e === void 0 ? true : _e;
|
|
22
|
+
var styles = useListToolbarStyles();
|
|
23
|
+
var toolbarRef = React.useRef(null);
|
|
24
|
+
var leftRef = React.useRef(null);
|
|
25
|
+
var rightRef = React.useRef(null);
|
|
26
|
+
var measureRef = React.useRef(null);
|
|
27
|
+
// ---- Separate regular vs far items ----
|
|
28
|
+
var regularItems = React.useMemo(function () { return items.filter(function (i) { return !i.isFarItem && i.visible !== false; }); }, [items]);
|
|
29
|
+
var allFarItems = React.useMemo(function () {
|
|
30
|
+
var fromItems = items.filter(function (i) { return i.isFarItem && i.visible !== false; });
|
|
31
|
+
var fromFar = farItems.filter(function (i) { return i.visible !== false; });
|
|
32
|
+
return __spreadArray(__spreadArray([], fromItems, true), fromFar, true);
|
|
33
|
+
}, [items, farItems]);
|
|
34
|
+
var groupedFarItems = React.useMemo(function () { return groupItems(allFarItems); }, [allFarItems]);
|
|
35
|
+
// ---- Build flat list of regular items (items + dividers) ----
|
|
36
|
+
var flatItems = React.useMemo(function () { return flattenWithDividers(regularItems, showGroupDividers); }, [regularItems, showGroupDividers]);
|
|
37
|
+
// ---- Custom overflow detection ----
|
|
38
|
+
var overflowIndex = useOverflowIndex(toolbarRef, rightRef, measureRef, flatItems.length);
|
|
39
|
+
// Determine which actual items (not dividers) are hidden
|
|
40
|
+
var visibleItemKeys = React.useMemo(function () {
|
|
41
|
+
var keys = new Set();
|
|
42
|
+
for (var i = 0; i < overflowIndex && i < flatItems.length; i++) {
|
|
43
|
+
if (flatItems[i].type === 'item') {
|
|
44
|
+
keys.add(flatItems[i].key);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
return keys;
|
|
48
|
+
}, [flatItems, overflowIndex]);
|
|
49
|
+
var hiddenItems = React.useMemo(function () { return regularItems.filter(function (item) { return !visibleItemKeys.has(item.key); }); }, [regularItems, visibleItemKeys]);
|
|
50
|
+
var hasOverflow = hiddenItems.length > 0;
|
|
51
|
+
// ---- Render far items ----
|
|
52
|
+
var renderFarGroup = function (groupItemsList, groupIndex, isLastGroup) {
|
|
53
|
+
var elements = [];
|
|
54
|
+
for (var _i = 0, groupItemsList_1 = groupItemsList; _i < groupItemsList_1.length; _i++) {
|
|
55
|
+
var item = groupItemsList_1[_i];
|
|
56
|
+
if (item.dividerBefore) {
|
|
57
|
+
elements.push(React.createElement(ToolbarDivider, { key: "".concat(item.key, "-divider-before") }));
|
|
58
|
+
}
|
|
59
|
+
elements.push(React.createElement(ToolbarItemRenderer, { key: item.key, item: item, isLoading: isLoading, itemClass: styles.farItemButton, labelClass: styles.farItemLabel }));
|
|
60
|
+
if (item.dividerAfter) {
|
|
61
|
+
elements.push(React.createElement(ToolbarDivider, { key: "".concat(item.key, "-divider-after") }));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (showGroupDividers && !isLastGroup) {
|
|
65
|
+
elements.push(React.createElement(ToolbarDivider, { key: "group-divider-".concat(groupIndex) }));
|
|
66
|
+
}
|
|
67
|
+
return elements;
|
|
68
|
+
};
|
|
69
|
+
return (React.createElement("div", { ref: toolbarRef, role: "toolbar", "aria-label": ariaLabel, className: "".concat(styles.toolbar, " ").concat(className || '') },
|
|
70
|
+
React.createElement("div", { ref: measureRef, className: styles.measureSection, "aria-hidden": "true" }, flatItems.map(function (flat) {
|
|
71
|
+
if (flat.type === 'divider') {
|
|
72
|
+
return React.createElement(ToolbarDivider, { key: flat.key });
|
|
73
|
+
}
|
|
74
|
+
return (React.createElement(ToolbarItemRenderer, { key: flat.key, item: flat.item, isLoading: isLoading, itemClass: styles.toolbarItem }));
|
|
75
|
+
})),
|
|
76
|
+
React.createElement("div", { ref: leftRef, className: styles.leftSection },
|
|
77
|
+
flatItems.map(function (flat, idx) {
|
|
78
|
+
if (idx >= overflowIndex)
|
|
79
|
+
return null;
|
|
80
|
+
if (flat.type === 'divider') {
|
|
81
|
+
return React.createElement(ToolbarDivider, { key: flat.key });
|
|
82
|
+
}
|
|
83
|
+
return (React.createElement(ToolbarItemRenderer, { key: flat.key, item: flat.item, isLoading: isLoading, itemClass: styles.toolbarItem }));
|
|
84
|
+
}),
|
|
85
|
+
hasOverflow && (React.createElement(Menu, null,
|
|
86
|
+
React.createElement(MenuTrigger, { disableButtonEnhancement: true },
|
|
87
|
+
React.createElement(Tooltip, { content: "".concat(hiddenItems.length, " more actions"), relationship: "label" },
|
|
88
|
+
React.createElement(ToolbarButton, { className: styles.overflowButton, icon: React.createElement(MoreHorizontalRegular, null), "aria-label": "".concat(hiddenItems.length, " more actions") }))),
|
|
89
|
+
React.createElement(MenuPopover, null,
|
|
90
|
+
React.createElement(MenuList, null, hiddenItems.map(function (item) { return (React.createElement(MenuItem, { key: item.key, icon: item.icon, disabled: item.disabled || isLoading, onClick: item.onClick }, item.label || item.tooltip || item.key)); }))))),
|
|
91
|
+
totalCount !== undefined && totalCount > 0 && (React.createElement(Badge, { appearance: "filled", color: "informative", className: styles.countBadge },
|
|
92
|
+
React.createElement(Text, { size: 200 },
|
|
93
|
+
totalCount,
|
|
94
|
+
" items")))),
|
|
95
|
+
React.createElement("div", { ref: rightRef, className: styles.rightGroup }, allFarItems.length > 0 && (React.createElement("div", { className: styles.farItemsContainer }, Array.from(groupedFarItems.entries()).map(function (_a, groupIndex) {
|
|
96
|
+
var _groupName = _a[0], groupItemsList = _a[1];
|
|
97
|
+
return renderFarGroup(groupItemsList, groupIndex, groupIndex === groupedFarItems.size - 1);
|
|
98
|
+
}))))));
|
|
99
|
+
};
|
|
100
|
+
export default ListToolbar;
|
|
101
|
+
//# sourceMappingURL=ListToolbarControl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ListToolbarControl.js","sourceRoot":"","sources":["../../../src/controls/ListToolbar/ListToolbarControl.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,410 @@
|
|
|
1
|
+
# ListToolbar
|
|
2
|
+
|
|
3
|
+
A flexible toolbar component for building list and data grid command bars with support for grouping, far items, and custom rendering.
|
|
4
|
+
|
|
5
|
+
## Description
|
|
6
|
+
|
|
7
|
+
The `ListToolbar` component provides a powerful and flexible toolbar built with Fluent UI 9 components. It supports item grouping, left/right aligned items, dividers, tooltips, automatic overflow menu, responsive design, loading states, and custom rendering - making it ideal for list views, data grids, and any interface that needs a command bar.
|
|
8
|
+
|
|
9
|
+
## Features
|
|
10
|
+
|
|
11
|
+
- ✅ Left and right (far) item alignment
|
|
12
|
+
- ✅ Item grouping with automatic dividers
|
|
13
|
+
- ✅ Individual item dividers (before/after)
|
|
14
|
+
- ✅ Tooltip support
|
|
15
|
+
- ✅ Loading state with disabled items
|
|
16
|
+
- ✅ Custom item rendering
|
|
17
|
+
- ✅ Total count badge display
|
|
18
|
+
- ✅ Visibility control per item
|
|
19
|
+
- ✅ Accessibility support with aria labels
|
|
20
|
+
- ✅ Overflow menu — left items collapse into a "..." menu when space is limited
|
|
21
|
+
- ✅ Responsive design — far item labels auto-hide on small screens
|
|
22
|
+
- ✅ SharePoint & Teams theme support via `theme` and `context` props
|
|
23
|
+
- ✅ Fluent UI 9 theming with automatic Teams dark/high-contrast detection
|
|
24
|
+
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
```tsx
|
|
28
|
+
import { ListToolbar } from '@pnp/spfx-controls-react/lib/controls/ListToolbar';
|
|
29
|
+
import type { IListToolbarProps, IToolbarItem } from '@pnp/spfx-controls-react/lib/controls/ListToolbar';
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Props
|
|
33
|
+
|
|
34
|
+
### IListToolbarProps
|
|
35
|
+
|
|
36
|
+
| Prop | Type | Required | Default | Description |
|
|
37
|
+
|------|------|----------|---------|-------------|
|
|
38
|
+
| `items` | `IToolbarItem[]` | Yes | - | Array of toolbar items |
|
|
39
|
+
| `farItems` | `IToolbarItem[]` | No | `[]` | Items on the right side |
|
|
40
|
+
| `isLoading` | `boolean` | No | `false` | Loading state (disables items) |
|
|
41
|
+
| `ariaLabel` | `string` | No | `'Toolbar'` | Accessibility label |
|
|
42
|
+
| `totalCount` | `number` | No | - | Display item count badge |
|
|
43
|
+
| `className` | `string` | No | - | Additional CSS class |
|
|
44
|
+
| `showGroupDividers` | `boolean` | No | `true` | Show dividers between groups |
|
|
45
|
+
| `theme` | `Theme` | No | - | Fluent UI v8 theme (auto-converted to v9) |
|
|
46
|
+
| `context` | `BaseComponentContext` | No | - | SPFx component context (enables Teams theme detection) |
|
|
47
|
+
|
|
48
|
+
### IToolbarItem
|
|
49
|
+
|
|
50
|
+
| Prop | Type | Required | Default | Description |
|
|
51
|
+
|------|------|----------|---------|-------------|
|
|
52
|
+
| `key` | `string` | Yes | - | Unique identifier |
|
|
53
|
+
| `label` | `string` | No | - | Button text |
|
|
54
|
+
| `tooltip` | `string` | No | - | Tooltip content |
|
|
55
|
+
| `icon` | `ReactElement` | No | - | Icon element |
|
|
56
|
+
| `onClick` | `() => void` | No | - | Click handler |
|
|
57
|
+
| `disabled` | `boolean` | No | `false` | Disable the item |
|
|
58
|
+
| `visible` | `boolean` | No | `true` | Show/hide the item |
|
|
59
|
+
| `group` | `string` | No | `'default'` | Group name for grouping |
|
|
60
|
+
| `isFarItem` | `boolean` | No | `false` | Place on right side |
|
|
61
|
+
| `appearance` | `ToolbarButtonProps['appearance']` | No | - | Button appearance |
|
|
62
|
+
| `onRender` | `() => ReactElement` | No | - | Custom render function |
|
|
63
|
+
| `dividerAfter` | `boolean` | No | `false` | Add divider after item |
|
|
64
|
+
| `dividerBefore` | `boolean` | No | `false` | Add divider before item |
|
|
65
|
+
| `ariaLabel` | `string` | No | - | Accessibility label override |
|
|
66
|
+
|
|
67
|
+
## Usage Examples
|
|
68
|
+
|
|
69
|
+
### Basic Toolbar
|
|
70
|
+
|
|
71
|
+
```tsx
|
|
72
|
+
import { ListToolbar } from '@pnp/spfx-controls-react/lib/controls/ListToolbar';
|
|
73
|
+
import { AddRegular, EditRegular, DeleteRegular } from '@fluentui/react-icons';
|
|
74
|
+
|
|
75
|
+
const BasicToolbar = () => {
|
|
76
|
+
const items = [
|
|
77
|
+
{
|
|
78
|
+
key: 'new',
|
|
79
|
+
label: 'New',
|
|
80
|
+
icon: <AddRegular />,
|
|
81
|
+
onClick: () => console.log('New clicked')
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
key: 'edit',
|
|
85
|
+
label: 'Edit',
|
|
86
|
+
icon: <EditRegular />,
|
|
87
|
+
onClick: () => console.log('Edit clicked')
|
|
88
|
+
},
|
|
89
|
+
{
|
|
90
|
+
key: 'delete',
|
|
91
|
+
label: 'Delete',
|
|
92
|
+
icon: <DeleteRegular />,
|
|
93
|
+
onClick: () => console.log('Delete clicked')
|
|
94
|
+
},
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
return <ListToolbar items={items} />;
|
|
98
|
+
};
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
### With Far Items
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import { ListToolbar } from '@pnp/spfx-controls-react/lib/controls/ListToolbar';
|
|
105
|
+
import {
|
|
106
|
+
AddRegular,
|
|
107
|
+
FilterRegular,
|
|
108
|
+
ArrowSortRegular,
|
|
109
|
+
SettingsRegular
|
|
110
|
+
} from '@fluentui/react-icons';
|
|
111
|
+
|
|
112
|
+
const ToolbarWithFarItems = () => {
|
|
113
|
+
const items = [
|
|
114
|
+
{ key: 'new', label: 'New Item', icon: <AddRegular />, onClick: () => {} },
|
|
115
|
+
];
|
|
116
|
+
|
|
117
|
+
const farItems = [
|
|
118
|
+
{ key: 'filter', label: 'Filter', icon: <FilterRegular />, onClick: () => {} },
|
|
119
|
+
{ key: 'sort', label: 'Sort', icon: <ArrowSortRegular />, onClick: () => {} },
|
|
120
|
+
{ key: 'settings', icon: <SettingsRegular />, tooltip: 'Settings', onClick: () => {} },
|
|
121
|
+
];
|
|
122
|
+
|
|
123
|
+
return <ListToolbar items={items} farItems={farItems} />;
|
|
124
|
+
};
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### With Grouping
|
|
128
|
+
|
|
129
|
+
```tsx
|
|
130
|
+
import { ListToolbar } from '@pnp/spfx-controls-react/lib/controls/ListToolbar';
|
|
131
|
+
import {
|
|
132
|
+
AddRegular,
|
|
133
|
+
EditRegular,
|
|
134
|
+
CopyRegular,
|
|
135
|
+
CutRegular,
|
|
136
|
+
ClipboardPasteRegular,
|
|
137
|
+
DeleteRegular
|
|
138
|
+
} from '@fluentui/react-icons';
|
|
139
|
+
|
|
140
|
+
const GroupedToolbar = () => {
|
|
141
|
+
const items = [
|
|
142
|
+
// File operations group
|
|
143
|
+
{ key: 'new', label: 'New', icon: <AddRegular />, group: 'file', onClick: () => {} },
|
|
144
|
+
{ key: 'edit', label: 'Edit', icon: <EditRegular />, group: 'file', onClick: () => {} },
|
|
145
|
+
|
|
146
|
+
// Clipboard group
|
|
147
|
+
{ key: 'copy', label: 'Copy', icon: <CopyRegular />, group: 'clipboard', onClick: () => {} },
|
|
148
|
+
{ key: 'cut', label: 'Cut', icon: <CutRegular />, group: 'clipboard', onClick: () => {} },
|
|
149
|
+
{ key: 'paste', label: 'Paste', icon: <ClipboardPasteRegular />, group: 'clipboard', onClick: () => {} },
|
|
150
|
+
|
|
151
|
+
// Danger group
|
|
152
|
+
{ key: 'delete', label: 'Delete', icon: <DeleteRegular />, group: 'danger', onClick: () => {} },
|
|
153
|
+
];
|
|
154
|
+
|
|
155
|
+
return <ListToolbar items={items} showGroupDividers={true} />;
|
|
156
|
+
};
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
### With Total Count
|
|
160
|
+
|
|
161
|
+
```tsx
|
|
162
|
+
import { ListToolbar } from '@pnp/spfx-controls-react/lib/controls/ListToolbar';
|
|
163
|
+
import { AddRegular, ArrowSyncRegular } from '@fluentui/react-icons';
|
|
164
|
+
|
|
165
|
+
const ToolbarWithCount = ({ items, totalCount }) => {
|
|
166
|
+
const toolbarItems = [
|
|
167
|
+
{ key: 'new', label: 'New', icon: <AddRegular />, onClick: () => {} },
|
|
168
|
+
{ key: 'refresh', label: 'Refresh', icon: <ArrowSyncRegular />, onClick: () => {} },
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
return (
|
|
172
|
+
<ListToolbar
|
|
173
|
+
items={toolbarItems}
|
|
174
|
+
totalCount={totalCount}
|
|
175
|
+
/>
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Loading State
|
|
181
|
+
|
|
182
|
+
```tsx
|
|
183
|
+
import { ListToolbar } from '@pnp/spfx-controls-react/lib/controls/ListToolbar';
|
|
184
|
+
import { AddRegular, DeleteRegular } from '@fluentui/react-icons';
|
|
185
|
+
import { useState } from 'react';
|
|
186
|
+
|
|
187
|
+
const LoadingToolbar = () => {
|
|
188
|
+
const [isLoading, setIsLoading] = useState(false);
|
|
189
|
+
|
|
190
|
+
const handleAction = async () => {
|
|
191
|
+
setIsLoading(true);
|
|
192
|
+
await performAction();
|
|
193
|
+
setIsLoading(false);
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
const items = [
|
|
197
|
+
{ key: 'new', label: 'New', icon: <AddRegular />, onClick: handleAction },
|
|
198
|
+
{ key: 'delete', label: 'Delete', icon: <DeleteRegular />, onClick: handleAction },
|
|
199
|
+
];
|
|
200
|
+
|
|
201
|
+
return <ListToolbar items={items} isLoading={isLoading} />;
|
|
202
|
+
};
|
|
203
|
+
```
|
|
204
|
+
|
|
205
|
+
### Conditional Visibility
|
|
206
|
+
|
|
207
|
+
```tsx
|
|
208
|
+
import { ListToolbar } from '@pnp/spfx-controls-react/lib/controls/ListToolbar';
|
|
209
|
+
import { EditRegular, DeleteRegular, ShareRegular } from '@fluentui/react-icons';
|
|
210
|
+
|
|
211
|
+
const ConditionalToolbar = ({ selectedItems, canEdit, canDelete }) => {
|
|
212
|
+
const items = [
|
|
213
|
+
{
|
|
214
|
+
key: 'edit',
|
|
215
|
+
label: 'Edit',
|
|
216
|
+
icon: <EditRegular />,
|
|
217
|
+
visible: selectedItems.length === 1 && canEdit,
|
|
218
|
+
onClick: () => {}
|
|
219
|
+
},
|
|
220
|
+
{
|
|
221
|
+
key: 'delete',
|
|
222
|
+
label: 'Delete',
|
|
223
|
+
icon: <DeleteRegular />,
|
|
224
|
+
visible: selectedItems.length > 0 && canDelete,
|
|
225
|
+
onClick: () => {}
|
|
226
|
+
},
|
|
227
|
+
{
|
|
228
|
+
key: 'share',
|
|
229
|
+
label: 'Share',
|
|
230
|
+
icon: <ShareRegular />,
|
|
231
|
+
visible: selectedItems.length > 0,
|
|
232
|
+
onClick: () => {}
|
|
233
|
+
},
|
|
234
|
+
];
|
|
235
|
+
|
|
236
|
+
return <ListToolbar items={items} />;
|
|
237
|
+
};
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
### With Custom Rendering
|
|
241
|
+
|
|
242
|
+
```tsx
|
|
243
|
+
import { ListToolbar } from '@pnp/spfx-controls-react/lib/controls/ListToolbar';
|
|
244
|
+
import { SearchBox, Dropdown, Option } from '@fluentui/react-components';
|
|
245
|
+
import { AddRegular } from '@fluentui/react-icons';
|
|
246
|
+
|
|
247
|
+
const CustomRenderToolbar = ({ onSearch, onFilterChange }) => {
|
|
248
|
+
const items = [
|
|
249
|
+
{ key: 'new', label: 'New', icon: <AddRegular />, onClick: () => {} },
|
|
250
|
+
];
|
|
251
|
+
|
|
252
|
+
const farItems = [
|
|
253
|
+
{
|
|
254
|
+
key: 'filter',
|
|
255
|
+
onRender: () => (
|
|
256
|
+
<Dropdown placeholder="Filter by status" onOptionSelect={onFilterChange}>
|
|
257
|
+
<Option value="all">All</Option>
|
|
258
|
+
<Option value="active">Active</Option>
|
|
259
|
+
<Option value="completed">Completed</Option>
|
|
260
|
+
</Dropdown>
|
|
261
|
+
),
|
|
262
|
+
},
|
|
263
|
+
{
|
|
264
|
+
key: 'search',
|
|
265
|
+
onRender: () => (
|
|
266
|
+
<SearchBox
|
|
267
|
+
placeholder="Search..."
|
|
268
|
+
onChange={(e, data) => onSearch(data.value)}
|
|
269
|
+
/>
|
|
270
|
+
),
|
|
271
|
+
},
|
|
272
|
+
];
|
|
273
|
+
|
|
274
|
+
return <ListToolbar items={items} farItems={farItems} />;
|
|
275
|
+
};
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
### Document Library Toolbar
|
|
279
|
+
|
|
280
|
+
```tsx
|
|
281
|
+
import { ListToolbar } from '@pnp/spfx-controls-react/lib/controls/ListToolbar';
|
|
282
|
+
import {
|
|
283
|
+
AddRegular,
|
|
284
|
+
ArrowUploadRegular,
|
|
285
|
+
FolderAddRegular,
|
|
286
|
+
EditRegular,
|
|
287
|
+
DeleteRegular,
|
|
288
|
+
ShareRegular,
|
|
289
|
+
DownloadRegular,
|
|
290
|
+
GridRegular,
|
|
291
|
+
ListRegular
|
|
292
|
+
} from '@fluentui/react-icons';
|
|
293
|
+
|
|
294
|
+
const DocumentLibraryToolbar = ({ selectedCount, onViewChange, view }) => {
|
|
295
|
+
const items = [
|
|
296
|
+
{ key: 'new', label: 'New', icon: <AddRegular />, group: 'create', onClick: () => {} },
|
|
297
|
+
{ key: 'upload', label: 'Upload', icon: <ArrowUploadRegular />, group: 'create', onClick: () => {} },
|
|
298
|
+
{ key: 'newFolder', label: 'New Folder', icon: <FolderAddRegular />, group: 'create', onClick: () => {} },
|
|
299
|
+
|
|
300
|
+
// Context-sensitive items
|
|
301
|
+
{ key: 'edit', label: 'Edit', icon: <EditRegular />, group: 'actions', visible: selectedCount === 1, onClick: () => {} },
|
|
302
|
+
{ key: 'share', label: 'Share', icon: <ShareRegular />, group: 'actions', visible: selectedCount > 0, onClick: () => {} },
|
|
303
|
+
{ key: 'download', label: 'Download', icon: <DownloadRegular />, group: 'actions', visible: selectedCount > 0, onClick: () => {} },
|
|
304
|
+
{ key: 'delete', label: 'Delete', icon: <DeleteRegular />, group: 'danger', visible: selectedCount > 0, dividerBefore: true, onClick: () => {} },
|
|
305
|
+
];
|
|
306
|
+
|
|
307
|
+
const farItems = [
|
|
308
|
+
{
|
|
309
|
+
key: 'gridView',
|
|
310
|
+
icon: <GridRegular />,
|
|
311
|
+
tooltip: 'Grid view',
|
|
312
|
+
appearance: view === 'grid' ? 'primary' : undefined,
|
|
313
|
+
onClick: () => onViewChange('grid')
|
|
314
|
+
},
|
|
315
|
+
{
|
|
316
|
+
key: 'listView',
|
|
317
|
+
icon: <ListRegular />,
|
|
318
|
+
tooltip: 'List view',
|
|
319
|
+
appearance: view === 'list' ? 'primary' : undefined,
|
|
320
|
+
onClick: () => onViewChange('list')
|
|
321
|
+
},
|
|
322
|
+
];
|
|
323
|
+
|
|
324
|
+
return (
|
|
325
|
+
<ListToolbar
|
|
326
|
+
items={items}
|
|
327
|
+
farItems={farItems}
|
|
328
|
+
totalCount={selectedCount > 0 ? selectedCount : undefined}
|
|
329
|
+
ariaLabel="Document library toolbar"
|
|
330
|
+
/>
|
|
331
|
+
);
|
|
332
|
+
};
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
### With Dividers
|
|
336
|
+
|
|
337
|
+
```tsx
|
|
338
|
+
import { ListToolbar } from '@pnp/spfx-controls-react/lib/controls/ListToolbar';
|
|
339
|
+
import {
|
|
340
|
+
SaveRegular,
|
|
341
|
+
ArrowUndoRegular,
|
|
342
|
+
ArrowRedoRegular,
|
|
343
|
+
TextBoldRegular,
|
|
344
|
+
TextItalicRegular,
|
|
345
|
+
TextUnderlineRegular
|
|
346
|
+
} from '@fluentui/react-icons';
|
|
347
|
+
|
|
348
|
+
const EditorToolbar = () => {
|
|
349
|
+
const items = [
|
|
350
|
+
{ key: 'save', icon: <SaveRegular />, tooltip: 'Save', onClick: () => {}, dividerAfter: true },
|
|
351
|
+
{ key: 'undo', icon: <ArrowUndoRegular />, tooltip: 'Undo', onClick: () => {} },
|
|
352
|
+
{ key: 'redo', icon: <ArrowRedoRegular />, tooltip: 'Redo', onClick: () => {}, dividerAfter: true },
|
|
353
|
+
{ key: 'bold', icon: <TextBoldRegular />, tooltip: 'Bold', onClick: () => {} },
|
|
354
|
+
{ key: 'italic', icon: <TextItalicRegular />, tooltip: 'Italic', onClick: () => {} },
|
|
355
|
+
{ key: 'underline', icon: <TextUnderlineRegular />, tooltip: 'Underline', onClick: () => {} },
|
|
356
|
+
];
|
|
357
|
+
|
|
358
|
+
return <ListToolbar items={items} showGroupDividers={false} />;
|
|
359
|
+
};
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
### SPFx Web Part Integration
|
|
363
|
+
|
|
364
|
+
When used inside a SharePoint Framework web part, pass `context` and `theme` to enable automatic theming (including Teams dark and high-contrast modes):
|
|
365
|
+
|
|
366
|
+
```tsx
|
|
367
|
+
import { ListToolbar } from '@pnp/spfx-controls-react/lib/controls/ListToolbar';
|
|
368
|
+
import { AddRegular, EditRegular } from '@fluentui/react-icons';
|
|
369
|
+
import { BaseComponentContext } from '@microsoft/sp-component-base';
|
|
370
|
+
|
|
371
|
+
interface IMyWebPartProps {
|
|
372
|
+
context: BaseComponentContext;
|
|
373
|
+
}
|
|
374
|
+
|
|
375
|
+
const MyWebPartToolbar: React.FC<IMyWebPartProps> = ({ context }) => {
|
|
376
|
+
const items = [
|
|
377
|
+
{ key: 'new', label: 'New', icon: <AddRegular />, onClick: () => {} },
|
|
378
|
+
{ key: 'edit', label: 'Edit', icon: <EditRegular />, onClick: () => {} },
|
|
379
|
+
];
|
|
380
|
+
|
|
381
|
+
return (
|
|
382
|
+
<ListToolbar
|
|
383
|
+
items={items}
|
|
384
|
+
context={context}
|
|
385
|
+
ariaLabel="My web part toolbar"
|
|
386
|
+
/>
|
|
387
|
+
);
|
|
388
|
+
};
|
|
389
|
+
```
|
|
390
|
+
|
|
391
|
+
> **Note:** When running inside Microsoft Teams, the component automatically detects the Teams theme (default, dark, high-contrast) and applies the matching Fluent UI 9 theme. In SharePoint, it converts the current v8 theme to a v9 theme using `createV9Theme`.
|
|
392
|
+
|
|
393
|
+
## Notes
|
|
394
|
+
|
|
395
|
+
- Items with the same `group` value are grouped together
|
|
396
|
+
- Use `isFarItem: true` or the `farItems` prop for right-aligned items
|
|
397
|
+
- `visible: false` completely hides an item from the toolbar
|
|
398
|
+
- `disabled: true` or `isLoading: true` disables item interaction
|
|
399
|
+
- Use `onRender` for complete control over item rendering
|
|
400
|
+
- Tooltips are automatically applied when `tooltip` is provided
|
|
401
|
+
- When space is limited, left-side items automatically collapse into a **"..." overflow menu**
|
|
402
|
+
- Far item labels are **hidden on small screens** (< 768px), showing only icons
|
|
403
|
+
- Pass `context` from your SPFx web part to enable **Teams theme detection**
|
|
404
|
+
- The component wraps content in a `FluentProvider` — no need to add your own
|
|
405
|
+
|
|
406
|
+
## Related Components
|
|
407
|
+
|
|
408
|
+
- `ButtonMenu` - For dropdown menu buttons
|
|
409
|
+
- `IconButton` - For icon-only buttons
|
|
410
|
+
- `GenericOverflowMenu` - For overflow menus
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { IToolbarItemRendererProps } from './IToolbarItemRendererProps';
|
|
3
|
+
/**
|
|
4
|
+
* Renders a single toolbar button with optional tooltip and label.
|
|
5
|
+
*/
|
|
6
|
+
export declare const ToolbarItemRenderer: React.FC<IToolbarItemRendererProps>;
|
|
7
|
+
//# sourceMappingURL=ToolbarItemRenderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolbarItemRenderer.d.ts","sourceRoot":"","sources":["../../../src/controls/ListToolbar/ToolbarItemRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,OAAO,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAExE;;GAEG;AACH,eAAO,MAAM,mBAAmB,EAAE,KAAK,CAAC,EAAE,CAAC,yBAAyB,CA8CnE,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { ToolbarButton, Tooltip, } from '@fluentui/react-components';
|
|
3
|
+
/**
|
|
4
|
+
* Renders a single toolbar button with optional tooltip and label.
|
|
5
|
+
*/
|
|
6
|
+
export var ToolbarItemRenderer = function (_a) {
|
|
7
|
+
var item = _a.item, isLoading = _a.isLoading, itemClass = _a.itemClass, labelClass = _a.labelClass;
|
|
8
|
+
if (item.visible === false)
|
|
9
|
+
return null;
|
|
10
|
+
if (item.onRender)
|
|
11
|
+
return item.onRender();
|
|
12
|
+
var labelContent = labelClass ? (React.createElement("span", { className: labelClass }, item.label)) : (item.label);
|
|
13
|
+
var button = item.label ? (React.createElement(ToolbarButton, { className: itemClass, "aria-label": item.ariaLabel || item.tooltip || item.label, icon: item.icon, onClick: item.onClick, disabled: item.disabled || isLoading, appearance: item.appearance }, labelContent)) : (React.createElement(ToolbarButton, { className: itemClass, "aria-label": item.ariaLabel || item.tooltip || item.key, icon: item.icon, onClick: item.onClick, disabled: item.disabled || isLoading, appearance: item.appearance }));
|
|
14
|
+
if (item.tooltip) {
|
|
15
|
+
return (React.createElement(Tooltip, { content: item.tooltip, relationship: "label" }, button));
|
|
16
|
+
}
|
|
17
|
+
return button;
|
|
18
|
+
};
|
|
19
|
+
//# sourceMappingURL=ToolbarItemRenderer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ToolbarItemRenderer.js","sourceRoot":"","sources":["../../../src/controls/ListToolbar/ToolbarItemRenderer.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAC/B,OAAO,EACL,aAAa,EACb,OAAO,GACR,MAAM,4BAA4B,CAAC;AAGpC;;GAEG;AACH,MAAM,CAAC,IAAM,mBAAmB,GAAwC,UAAC,EAKxE;QAJC,IAAI,UAAA,EACJ,SAAS,eAAA,EACT,SAAS,eAAA,EACT,UAAU,gBAAA;IAEV,IAAI,IAAI,CAAC,OAAO,KAAK,KAAK;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,IAAI,CAAC,QAAQ;QAAE,OAAO,IAAI,CAAC,QAAQ,EAAE,CAAC;IAE1C,IAAM,YAAY,GAAG,UAAU,CAAC,CAAC,CAAC,CAChC,8BAAM,SAAS,EAAE,UAAU,IAAG,IAAI,CAAC,KAAK,CAAQ,CACjD,CAAC,CAAC,CAAC,CACF,IAAI,CAAC,KAAK,CACX,CAAC;IAEF,IAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAC1B,oBAAC,aAAa,IACZ,SAAS,EAAE,SAAS,gBACR,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,KAAK,EACxD,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,SAAS,EACpC,UAAU,EAAE,IAAI,CAAC,UAAU,IAE1B,YAAY,CACC,CACjB,CAAC,CAAC,CAAC,CACF,oBAAC,aAAa,IACZ,SAAS,EAAE,SAAS,gBACR,IAAI,CAAC,SAAS,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,CAAC,GAAG,EACtD,IAAI,EAAE,IAAI,CAAC,IAAI,EACf,OAAO,EAAE,IAAI,CAAC,OAAO,EACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,SAAS,EACpC,UAAU,EAAE,IAAI,CAAC,UAAU,GAC3B,CACH,CAAC;IAEF,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;QACjB,OAAO,CACL,oBAAC,OAAO,IAAC,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,YAAY,EAAC,OAAO,IACjD,MAAM,CACC,CACX,CAAC;IACJ,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { FlatItem } from './FlatItem';
|
|
2
|
+
import { IToolbarItem } from './IToolbarItem';
|
|
3
|
+
export declare function groupItems(items: IToolbarItem[]): Map<string, IToolbarItem[]>;
|
|
4
|
+
export declare function flattenWithDividers(items: IToolbarItem[], showGroupDividers: boolean): FlatItem[];
|
|
5
|
+
//# sourceMappingURL=helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.d.ts","sourceRoot":"","sources":["../../../src/controls/ListToolbar/helpers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAM9C,wBAAgB,UAAU,CACxB,KAAK,EAAE,YAAY,EAAE,GACpB,GAAG,CAAC,MAAM,EAAE,YAAY,EAAE,CAAC,CAY7B;AAMD,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,YAAY,EAAE,EACrB,iBAAiB,EAAE,OAAO,GACzB,QAAQ,EAAE,CAyBZ"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/* ------------------------------------------------------------------ */
|
|
2
|
+
/* groupItems — groups items by their `group` property */
|
|
3
|
+
/* ------------------------------------------------------------------ */
|
|
4
|
+
export function groupItems(items) {
|
|
5
|
+
var groups = new Map();
|
|
6
|
+
for (var _i = 0, items_1 = items; _i < items_1.length; _i++) {
|
|
7
|
+
var item = items_1[_i];
|
|
8
|
+
var groupName = item.group || 'default';
|
|
9
|
+
if (!groups.has(groupName)) {
|
|
10
|
+
groups.set(groupName, []);
|
|
11
|
+
}
|
|
12
|
+
groups.get(groupName).push(item);
|
|
13
|
+
}
|
|
14
|
+
return groups;
|
|
15
|
+
}
|
|
16
|
+
/* ------------------------------------------------------------------ */
|
|
17
|
+
/* flattenWithDividers — builds a flat render-list from grouped items */
|
|
18
|
+
/* ------------------------------------------------------------------ */
|
|
19
|
+
export function flattenWithDividers(items, showGroupDividers) {
|
|
20
|
+
var result = [];
|
|
21
|
+
var grouped = groupItems(items);
|
|
22
|
+
var groupEntries = Array.from(grouped.entries());
|
|
23
|
+
for (var gi = 0; gi < groupEntries.length; gi++) {
|
|
24
|
+
var _a = groupEntries[gi], groupItemsList = _a[1];
|
|
25
|
+
var isLastGroup = gi === groupEntries.length - 1;
|
|
26
|
+
for (var _i = 0, groupItemsList_1 = groupItemsList; _i < groupItemsList_1.length; _i++) {
|
|
27
|
+
var item = groupItemsList_1[_i];
|
|
28
|
+
if (item.dividerBefore) {
|
|
29
|
+
result.push({ type: 'divider', key: "".concat(item.key, "-div-before") });
|
|
30
|
+
}
|
|
31
|
+
result.push({ type: 'item', item: item, key: item.key });
|
|
32
|
+
if (item.dividerAfter) {
|
|
33
|
+
result.push({ type: 'divider', key: "".concat(item.key, "-div-after") });
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
if (showGroupDividers && !isLastGroup) {
|
|
37
|
+
result.push({ type: 'divider', key: "group-div-".concat(gi) });
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
return result;
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=helpers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"helpers.js","sourceRoot":"","sources":["../../../src/controls/ListToolbar/helpers.ts"],"names":[],"mappings":"AAGA,wEAAwE;AACxE,wEAAwE;AACxE,wEAAwE;AAExE,MAAM,UAAU,UAAU,CACxB,KAAqB;IAErB,IAAM,MAAM,GAAG,IAAI,GAAG,EAA0B,CAAC;IAEjD,KAAmB,UAAK,EAAL,eAAK,EAAL,mBAAK,EAAL,IAAK,EAAE,CAAC;QAAtB,IAAM,IAAI,cAAA;QACb,IAAM,SAAS,GAAG,IAAI,CAAC,KAAK,IAAI,SAAS,CAAC;QAC1C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;YAC3B,MAAM,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAC5B,CAAC;QACD,MAAM,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,wEAAwE;AACxE,yEAAyE;AACzE,wEAAwE;AAExE,MAAM,UAAU,mBAAmB,CACjC,KAAqB,EACrB,iBAA0B;IAE1B,IAAM,MAAM,GAAe,EAAE,CAAC;IAC9B,IAAM,OAAO,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;IAClC,IAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;IAEnD,KAAK,IAAI,EAAE,GAAG,CAAC,EAAE,EAAE,GAAG,YAAY,CAAC,MAAM,EAAE,EAAE,EAAE,EAAE,CAAC;QAC1C,IAAA,KAAqB,YAAY,CAAC,EAAE,CAAC,EAAlC,cAAc,QAAoB,CAAC;QAC5C,IAAM,WAAW,GAAG,EAAE,KAAK,YAAY,CAAC,MAAM,GAAG,CAAC,CAAC;QAEnD,KAAmB,UAAc,EAAd,iCAAc,EAAd,4BAAc,EAAd,IAAc,EAAE,CAAC;YAA/B,IAAM,IAAI,uBAAA;YACb,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;gBACvB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,UAAG,IAAI,CAAC,GAAG,gBAAa,EAAE,CAAC,CAAC;YAClE,CAAC;YACD,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,MAAA,EAAE,GAAG,EAAE,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC;YACnD,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;gBACtB,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,UAAG,IAAI,CAAC,GAAG,eAAY,EAAE,CAAC,CAAC;YACjE,CAAC;QACH,CAAC;QAED,IAAI,iBAAiB,IAAI,CAAC,WAAW,EAAE,CAAC;YACtC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,GAAG,EAAE,oBAAa,EAAE,CAAE,EAAE,CAAC,CAAC;QAC3D,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/controls/ListToolbar/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAC5C,YAAY,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC7D,YAAY,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/controls/ListToolbar/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface IListToolbarStyles {
|
|
2
|
+
toolbar: string;
|
|
3
|
+
leftSection: string;
|
|
4
|
+
measureSection: string;
|
|
5
|
+
rightGroup: string;
|
|
6
|
+
farItemsContainer: string;
|
|
7
|
+
countBadge: string;
|
|
8
|
+
divider: string;
|
|
9
|
+
toolbarItem: string;
|
|
10
|
+
toolbarButtonBase: string;
|
|
11
|
+
overflowButton: string;
|
|
12
|
+
farItemButton: string;
|
|
13
|
+
farItemLabel: string;
|
|
14
|
+
}
|
|
15
|
+
export declare const useListToolbarStyles: () => IListToolbarStyles;
|
|
16
|
+
//# sourceMappingURL=useListToolbarStyles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useListToolbarStyles.d.ts","sourceRoot":"","sources":["../../../src/controls/ListToolbar/useListToolbarStyles.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,EAAE,MAAM,CAAC;IACpB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,eAAO,MAAM,oBAAoB,QAAO,kBAwGvC,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
|
|
2
|
+
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
|
|
3
|
+
return cooked;
|
|
4
|
+
};
|
|
5
|
+
import { css } from "@emotion/css";
|
|
6
|
+
import { tokens } from "@fluentui/react-components";
|
|
7
|
+
export var useListToolbarStyles = function () {
|
|
8
|
+
return {
|
|
9
|
+
/** Outer toolbar container */
|
|
10
|
+
toolbar: css(templateObject_1 || (templateObject_1 = __makeTemplateObject(["\n display: flex !important;\n flex-wrap: nowrap !important;\n align-items: center !important;\n padding: ", " ", ";\n background-color: ", ";\n border-bottom: 1px solid ", ";\n min-height: 48px;\n gap: ", ";\n white-space: nowrap;\n position: relative;\n "], ["\n display: flex !important;\n flex-wrap: nowrap !important;\n align-items: center !important;\n padding: ", " ", ";\n background-color: ", ";\n border-bottom: 1px solid ", ";\n min-height: 48px;\n gap: ", ";\n white-space: nowrap;\n position: relative;\n "])), tokens.spacingVerticalS, tokens.spacingHorizontalM, tokens.colorNeutralBackground1, tokens.colorNeutralStroke2, tokens.spacingHorizontalXS),
|
|
11
|
+
/** Visible container for regular (left-side) items */
|
|
12
|
+
leftSection: css(templateObject_2 || (templateObject_2 = __makeTemplateObject(["\n display: flex !important;\n flex-wrap: nowrap !important;\n align-items: center !important;\n gap: ", ";\n flex: 0 0 auto !important;\n min-width: 0;\n "], ["\n display: flex !important;\n flex-wrap: nowrap !important;\n align-items: center !important;\n gap: ", ";\n flex: 0 0 auto !important;\n min-width: 0;\n "])), tokens.spacingHorizontalXS),
|
|
13
|
+
/** Hidden mirror — renders ALL items for unclipped measurement */
|
|
14
|
+
measureSection: css(templateObject_3 || (templateObject_3 = __makeTemplateObject(["\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n gap: ", ";\n position: absolute;\n top: 0;\n left: 0;\n visibility: hidden;\n pointer-events: none;\n height: 0;\n overflow: visible;\n z-index: -1;\n "], ["\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n gap: ", ";\n position: absolute;\n top: 0;\n left: 0;\n visibility: hidden;\n pointer-events: none;\n height: 0;\n overflow: visible;\n z-index: -1;\n "])), tokens.spacingHorizontalXS),
|
|
15
|
+
/** Far-items group — pushed to the right edge */
|
|
16
|
+
rightGroup: css(templateObject_4 || (templateObject_4 = __makeTemplateObject(["\n display: flex !important;\n flex-wrap: nowrap !important;\n align-items: center !important;\n gap: ", ";\n flex: 0 0 auto !important;\n margin-left: auto;\n white-space: nowrap;\n "], ["\n display: flex !important;\n flex-wrap: nowrap !important;\n align-items: center !important;\n gap: ", ";\n flex: 0 0 auto !important;\n margin-left: auto;\n white-space: nowrap;\n "])), tokens.spacingHorizontalXS),
|
|
17
|
+
/** Inner wrapper for far-items inside rightGroup */
|
|
18
|
+
farItemsContainer: css(templateObject_5 || (templateObject_5 = __makeTemplateObject(["\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n gap: inherit;\n "], ["\n display: flex;\n flex-wrap: nowrap;\n align-items: center;\n gap: inherit;\n "]))),
|
|
19
|
+
/** Base style for all ToolbarButton instances */
|
|
20
|
+
toolbarButtonBase: css(templateObject_6 || (templateObject_6 = __makeTemplateObject(["\n min-width: auto;\n "], ["\n min-width: auto;\n "]))),
|
|
21
|
+
/** "..." overflow menu trigger button */
|
|
22
|
+
overflowButton: css(templateObject_7 || (templateObject_7 = __makeTemplateObject(["\n flex-shrink: 0;\n "], ["\n flex-shrink: 0;\n "]))),
|
|
23
|
+
/** Count badge — hidden on mobile */
|
|
24
|
+
countBadge: css(templateObject_8 || (templateObject_8 = __makeTemplateObject(["\n flex-shrink: 0;\n @media (max-width: 768px) {\n display: none;\n }\n "], ["\n flex-shrink: 0;\n @media (max-width: 768px) {\n display: none;\n }\n "]))),
|
|
25
|
+
/** Divider between groups */
|
|
26
|
+
divider: css(templateObject_9 || (templateObject_9 = __makeTemplateObject(["\n height: 24px;\n margin: 0 ", ";\n "], ["\n height: 24px;\n margin: 0 ", ";\n "])), tokens.spacingHorizontalXS),
|
|
27
|
+
/** Regular toolbar item */
|
|
28
|
+
toolbarItem: css(templateObject_10 || (templateObject_10 = __makeTemplateObject(["\n flex-shrink: 0;\n width: fit-content;\n white-space: nowrap;\n "], ["\n flex-shrink: 0;\n width: fit-content;\n white-space: nowrap;\n "]))),
|
|
29
|
+
/** Far-item button */
|
|
30
|
+
farItemButton: css(templateObject_11 || (templateObject_11 = __makeTemplateObject(["\n flex-shrink: 0;\n "], ["\n flex-shrink: 0;\n "]))),
|
|
31
|
+
/** Label text inside far-item buttons — hidden on mobile */
|
|
32
|
+
farItemLabel: css(templateObject_12 || (templateObject_12 = __makeTemplateObject(["\n @media (max-width: 768px) {\n display: none;\n }\n "], ["\n @media (max-width: 768px) {\n display: none;\n }\n "]))),
|
|
33
|
+
};
|
|
34
|
+
};
|
|
35
|
+
var templateObject_1, templateObject_2, templateObject_3, templateObject_4, templateObject_5, templateObject_6, templateObject_7, templateObject_8, templateObject_9, templateObject_10, templateObject_11, templateObject_12;
|
|
36
|
+
//# sourceMappingURL=useListToolbarStyles.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useListToolbarStyles.js","sourceRoot":"","sources":["../../../src/controls/ListToolbar/useListToolbarStyles.ts"],"names":[],"mappings":";;;;AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,cAAc,CAAC;AACnC,OAAO,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAiBpD,MAAM,CAAC,IAAM,oBAAoB,GAAG;IAClC,OAAO;QACL,8BAA8B;QAC9B,OAAO,EAAE,GAAG,0XAAA,gIAIC,EAAuB,GAAI,EAAyB,6BAC3C,EAA8B,oCACvB,EAA0B,yCAE9C,EAA0B,gEAGlC,KAPY,MAAM,CAAC,gBAAgB,EAAI,MAAM,CAAC,kBAAkB,EAC3C,MAAM,CAAC,uBAAuB,EACvB,MAAM,CAAC,mBAAmB,EAE9C,MAAM,CAAC,mBAAmB,CAGlC;QAED,sDAAsD;QACtD,WAAW,EAAE,GAAG,iQAAA,4HAIP,EAA0B,gEAGlC,KAHQ,MAAM,CAAC,mBAAmB,CAGlC;QAED,kEAAkE;QAClE,cAAc,EAAE,GAAG,2VAAA,2FAIV,EAA0B,2LASlC,KATQ,MAAM,CAAC,mBAAmB,CASlC;QAED,iDAAiD;QACjD,UAAU,EAAE,GAAG,kSAAA,4HAIN,EAA0B,iGAIlC,KAJQ,MAAM,CAAC,mBAAmB,CAIlC;QAED,oDAAoD;QACpD,iBAAiB,EAAE,GAAG,4KAAA,yGAKrB,IAAA;QAED,iDAAiD;QACjD,iBAAiB,EAAE,GAAG,mGAAA,gCAErB,IAAA;QAED,yCAAyC;QACzC,cAAc,EAAE,GAAG,kGAAA,+BAElB,IAAA;QAED,qCAAqC;QACrC,UAAU,EAAE,GAAG,sKAAA,mGAKd,IAAA;QAED,6BAA6B;QAC7B,OAAO,EAAE,GAAG,uHAAA,yCAEE,EAA0B,SACvC,KADa,MAAM,CAAC,mBAAmB,CACvC;QAED,2BAA2B;QAC3B,WAAW,EAAE,GAAG,2JAAA,sFAIf,IAAA;QAED,sBAAsB;QACtB,aAAa,EAAE,GAAG,oGAAA,+BAEjB,IAAA;QAED,4DAA4D;QAC5D,YAAY,EAAE,GAAG,iJAAA,4EAIhB,IAAA;KACF,CAAC;AACJ,CAAC,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Measures how many flat-list children fit inside the available width.
|
|
4
|
+
*
|
|
5
|
+
* Uses three refs:
|
|
6
|
+
* - `toolbarRef` → the outer toolbar; a ResizeObserver watches this
|
|
7
|
+
* for width changes.
|
|
8
|
+
* - `rightRef` → the far-items group; its width is subtracted from
|
|
9
|
+
* the toolbar width to get the available space for
|
|
10
|
+
* regular items.
|
|
11
|
+
* - `measureRef` → a hidden mirror (`visibility:hidden; overflow:visible`)
|
|
12
|
+
* that always renders ALL items so each child's true
|
|
13
|
+
* unclipped width can be read.
|
|
14
|
+
*
|
|
15
|
+
* @returns The index in the flat item list at which items start to overflow.
|
|
16
|
+
*/
|
|
17
|
+
export declare function useOverflowIndex(toolbarRef: React.RefObject<HTMLDivElement>, rightRef: React.RefObject<HTMLDivElement>, measureRef: React.RefObject<HTMLDivElement>, itemCount: number, moreButtonWidth?: number): number;
|
|
18
|
+
//# sourceMappingURL=useOverflowIndex.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOverflowIndex.d.ts","sourceRoot":"","sources":["../../../src/controls/ListToolbar/useOverflowIndex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAqB/B;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,gBAAgB,CAC9B,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,EAC3C,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,EACzC,UAAU,EAAE,KAAK,CAAC,SAAS,CAAC,cAAc,CAAC,EAC3C,SAAS,EAAE,MAAM,EACjB,eAAe,GAAE,MAAW,GAC3B,MAAM,CAgFR"}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
/**
|
|
3
|
+
* Minimum gap breakpoints based on the toolbar's own pixel width.
|
|
4
|
+
* Wider toolbars get a larger minimum gap between regular and far items.
|
|
5
|
+
*/
|
|
6
|
+
var GAP_BREAKPOINTS = [
|
|
7
|
+
{ minWidth: 1280, gap: 100 },
|
|
8
|
+
{ minWidth: 1024, gap: 60 },
|
|
9
|
+
{ minWidth: 768, gap: 40 },
|
|
10
|
+
{ minWidth: 480, gap: 24 },
|
|
11
|
+
{ minWidth: 0, gap: 12 },
|
|
12
|
+
];
|
|
13
|
+
function getMinGap(toolbarWidth) {
|
|
14
|
+
for (var _i = 0, GAP_BREAKPOINTS_1 = GAP_BREAKPOINTS; _i < GAP_BREAKPOINTS_1.length; _i++) {
|
|
15
|
+
var bp = GAP_BREAKPOINTS_1[_i];
|
|
16
|
+
if (toolbarWidth > bp.minWidth)
|
|
17
|
+
return bp.gap;
|
|
18
|
+
}
|
|
19
|
+
return GAP_BREAKPOINTS[GAP_BREAKPOINTS.length - 1].gap;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Measures how many flat-list children fit inside the available width.
|
|
23
|
+
*
|
|
24
|
+
* Uses three refs:
|
|
25
|
+
* - `toolbarRef` → the outer toolbar; a ResizeObserver watches this
|
|
26
|
+
* for width changes.
|
|
27
|
+
* - `rightRef` → the far-items group; its width is subtracted from
|
|
28
|
+
* the toolbar width to get the available space for
|
|
29
|
+
* regular items.
|
|
30
|
+
* - `measureRef` → a hidden mirror (`visibility:hidden; overflow:visible`)
|
|
31
|
+
* that always renders ALL items so each child's true
|
|
32
|
+
* unclipped width can be read.
|
|
33
|
+
*
|
|
34
|
+
* @returns The index in the flat item list at which items start to overflow.
|
|
35
|
+
*/
|
|
36
|
+
export function useOverflowIndex(toolbarRef, rightRef, measureRef, itemCount, moreButtonWidth) {
|
|
37
|
+
if (moreButtonWidth === void 0) { moreButtonWidth = 48; }
|
|
38
|
+
var _a = React.useState(itemCount), overflowIndex = _a[0], setOverflowIndex = _a[1];
|
|
39
|
+
React.useEffect(function () {
|
|
40
|
+
var toolbarEl = toolbarRef.current;
|
|
41
|
+
var rightEl = rightRef.current;
|
|
42
|
+
var measureEl = measureRef.current;
|
|
43
|
+
if (!toolbarEl || !measureEl)
|
|
44
|
+
return;
|
|
45
|
+
var calculate = function () {
|
|
46
|
+
var toolbarWidth = toolbarEl.offsetWidth;
|
|
47
|
+
if (toolbarWidth === 0)
|
|
48
|
+
return;
|
|
49
|
+
var toolbarStyle = getComputedStyle(toolbarEl);
|
|
50
|
+
var paddingLeft = parseFloat(toolbarStyle.paddingLeft || '0');
|
|
51
|
+
var paddingRight = parseFloat(toolbarStyle.paddingRight || '0');
|
|
52
|
+
var toolbarGap = parseFloat(toolbarStyle.columnGap || toolbarStyle.gap || '0');
|
|
53
|
+
var minGap = getMinGap(toolbarWidth);
|
|
54
|
+
var rightWidth = rightEl ? rightEl.offsetWidth : 0;
|
|
55
|
+
var rightReserved = rightWidth > 0 ? rightWidth + minGap + toolbarGap : 0;
|
|
56
|
+
var availableWidth = toolbarWidth - paddingLeft - paddingRight - rightReserved;
|
|
57
|
+
if (availableWidth <= 0)
|
|
58
|
+
return;
|
|
59
|
+
var children = Array.from(measureEl.children);
|
|
60
|
+
if (children.length === 0) {
|
|
61
|
+
setOverflowIndex(itemCount);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
var gap = parseFloat(getComputedStyle(measureEl).columnGap || '0');
|
|
65
|
+
// Total width of all items in the unclipped mirror
|
|
66
|
+
var totalWidth = 0;
|
|
67
|
+
for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
|
|
68
|
+
var child = children_1[_i];
|
|
69
|
+
totalWidth += child.offsetWidth;
|
|
70
|
+
}
|
|
71
|
+
totalWidth += Math.max(0, children.length - 1) * gap;
|
|
72
|
+
// If everything fits, show all
|
|
73
|
+
if (totalWidth <= availableWidth) {
|
|
74
|
+
setOverflowIndex(children.length);
|
|
75
|
+
return;
|
|
76
|
+
}
|
|
77
|
+
// Otherwise, find how many fit leaving room for the "..." button
|
|
78
|
+
var budgetWidth = availableWidth - moreButtonWidth;
|
|
79
|
+
var usedWidth = 0;
|
|
80
|
+
var fitCount = 0;
|
|
81
|
+
for (var i = 0; i < children.length; i++) {
|
|
82
|
+
var childWidth = children[i].offsetWidth;
|
|
83
|
+
var withGap = i > 0 ? gap : 0;
|
|
84
|
+
if (usedWidth + withGap + childWidth > budgetWidth)
|
|
85
|
+
break;
|
|
86
|
+
usedWidth += withGap + childWidth;
|
|
87
|
+
fitCount++;
|
|
88
|
+
}
|
|
89
|
+
setOverflowIndex(Math.max(1, fitCount));
|
|
90
|
+
};
|
|
91
|
+
var rafId = requestAnimationFrame(calculate);
|
|
92
|
+
var ro = new ResizeObserver(calculate);
|
|
93
|
+
ro.observe(toolbarEl);
|
|
94
|
+
return function () {
|
|
95
|
+
cancelAnimationFrame(rafId);
|
|
96
|
+
ro.disconnect();
|
|
97
|
+
};
|
|
98
|
+
}, [toolbarRef, rightRef, measureRef, itemCount, moreButtonWidth]);
|
|
99
|
+
return overflowIndex;
|
|
100
|
+
}
|
|
101
|
+
//# sourceMappingURL=useOverflowIndex.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useOverflowIndex.js","sourceRoot":"","sources":["../../../src/controls/ListToolbar/useOverflowIndex.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED