@eccenca/gui-elements 23.7.0-rc.0 → 23.7.0-rc.1
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.md +7 -0
- package/dist/cjs/common/index.js +2 -0
- package/dist/cjs/common/index.js.map +1 -1
- package/dist/cjs/common/utils/getScrollParent.js +24 -0
- package/dist/cjs/common/utils/getScrollParent.js.map +1 -0
- package/dist/cjs/components/AutocompleteField/AutoCompleteField.js +19 -2
- package/dist/cjs/components/AutocompleteField/AutoCompleteField.js.map +1 -1
- package/dist/cjs/components/MultiSelect/MultiSelect.js +3 -4
- package/dist/cjs/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/cjs/components/Sticky/StickyTarget.js +85 -0
- package/dist/cjs/components/Sticky/StickyTarget.js.map +1 -0
- package/dist/cjs/components/Sticky/index.js +14 -0
- package/dist/cjs/components/Sticky/index.js.map +1 -0
- package/dist/cjs/components/index.js +1 -0
- package/dist/cjs/components/index.js.map +1 -1
- package/dist/esm/common/index.js +2 -0
- package/dist/esm/common/index.js.map +1 -1
- package/dist/esm/common/utils/getScrollParent.js +20 -0
- package/dist/esm/common/utils/getScrollParent.js.map +1 -0
- package/dist/esm/components/AutocompleteField/AutoCompleteField.js +27 -2
- package/dist/esm/components/AutocompleteField/AutoCompleteField.js.map +1 -1
- package/dist/esm/components/MultiSelect/MultiSelect.js +3 -4
- package/dist/esm/components/MultiSelect/MultiSelect.js.map +1 -1
- package/dist/esm/components/Sticky/StickyTarget.js +89 -0
- package/dist/esm/components/Sticky/StickyTarget.js.map +1 -0
- package/dist/esm/components/Sticky/index.js +2 -0
- package/dist/esm/components/Sticky/index.js.map +1 -0
- package/dist/esm/components/index.js +1 -0
- package/dist/esm/components/index.js.map +1 -1
- package/dist/types/common/index.d.ts +2 -0
- package/dist/types/common/utils/getScrollParent.d.ts +9 -0
- package/dist/types/components/AutocompleteField/AutoCompleteField.d.ts +2 -0
- package/dist/types/components/Sticky/StickyTarget.d.ts +32 -0
- package/dist/types/components/Sticky/index.d.ts +1 -0
- package/dist/types/components/index.d.ts +1 -0
- package/package.json +1 -1
- package/src/common/index.ts +3 -0
- package/src/common/utils/getScrollParent.ts +20 -0
- package/src/components/AutocompleteField/AutoCompleteField.tsx +28 -0
- package/src/components/AutocompleteField/autocompletefield.scss +1 -1
- package/src/components/MultiSelect/MultiSelect.tsx +3 -4
- package/src/components/MultiSuggestField/MultiSuggestField.stories.tsx +76 -1
- package/src/components/MultiSuggestField/tests/MultiSuggestField.test.tsx +297 -109
- package/src/components/Sticky/StickyTarget.tsx +119 -0
- package/src/components/Sticky/index.ts +1 -0
- package/src/components/Sticky/sticky.scss +69 -0
- package/src/components/Sticky/stories/StickyTarget.stories.tsx +63 -0
- package/src/components/index.scss +1 -0
- package/src/components/index.ts +1 -0
|
@@ -0,0 +1,89 @@
|
|
|
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 __rest = (this && this.__rest) || function (s, e) {
|
|
13
|
+
var t = {};
|
|
14
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
15
|
+
t[p] = s[p];
|
|
16
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
17
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
18
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
19
|
+
t[p[i]] = s[p[i]];
|
|
20
|
+
}
|
|
21
|
+
return t;
|
|
22
|
+
};
|
|
23
|
+
import React from "react";
|
|
24
|
+
import { utils } from "../../common/index.js";
|
|
25
|
+
import { CLASSPREFIX as eccgui } from "../../configuration/constants.js";
|
|
26
|
+
/**
|
|
27
|
+
* Element wraps the content that need to be displayed sticky.
|
|
28
|
+
* The content then offset relative to its nearest scrolling ancestor and containing block (nearest block-level ancestor).
|
|
29
|
+
*/
|
|
30
|
+
export var StickyTarget = function (_a) {
|
|
31
|
+
var className = _a.className, _b = _a.to, to = _b === void 0 ? "top" : _b, _c = _a.local, local = _c === void 0 ? false : _c, _d = _a.background, background = _d === void 0 ? "transparent" : _d, offset = _a.offset, style = _a.style, getConnectedElement = _a.getConnectedElement, otherDivProps = __rest(_a, ["className", "to", "local", "background", "offset", "style", "getConnectedElement"]);
|
|
32
|
+
var stickyTargetRef = React.useRef(null);
|
|
33
|
+
var offsetStyle = {};
|
|
34
|
+
if (typeof offset !== "undefined") {
|
|
35
|
+
offsetStyle = __assign(__assign({}, style), { "--eccgui-sticky-target-localoffset": offset });
|
|
36
|
+
}
|
|
37
|
+
var connectedOffset = 0;
|
|
38
|
+
React.useEffect(function () {
|
|
39
|
+
/**
|
|
40
|
+
* If the target should be sticky to a defined element then:
|
|
41
|
+
* * check for the element and its scroll parent
|
|
42
|
+
* * listen to scroll events and use the elements position as offset
|
|
43
|
+
*/
|
|
44
|
+
if (getConnectedElement && stickyTargetRef) {
|
|
45
|
+
var stickyConnection_1 = getConnectedElement(stickyTargetRef);
|
|
46
|
+
if (stickyConnection_1) {
|
|
47
|
+
var scrollParent_1 = utils.getScrollParent(stickyConnection_1);
|
|
48
|
+
var scrollParentFallback_1 = !scrollParent_1 ? document.documentElement : false;
|
|
49
|
+
if (scrollParent_1 || scrollParentFallback_1) {
|
|
50
|
+
var updateTargetOffset_1 = function () {
|
|
51
|
+
var _a;
|
|
52
|
+
var scrollParentPosition = (scrollParent_1 || scrollParentFallback_1).getBoundingClientRect();
|
|
53
|
+
var stickyConnectionPosition = stickyConnection_1.getBoundingClientRect();
|
|
54
|
+
if (to === "top") {
|
|
55
|
+
connectedOffset =
|
|
56
|
+
stickyConnectionPosition.top -
|
|
57
|
+
Math.max(0, scrollParentPosition.top) +
|
|
58
|
+
stickyConnectionPosition.height;
|
|
59
|
+
}
|
|
60
|
+
if (to === "bottom") {
|
|
61
|
+
connectedOffset =
|
|
62
|
+
Math.max(scrollParentPosition.height, scrollParentPosition.bottom) -
|
|
63
|
+
stickyConnectionPosition.bottom +
|
|
64
|
+
stickyConnectionPosition.height;
|
|
65
|
+
}
|
|
66
|
+
(_a = stickyTargetRef.current) === null || _a === void 0 ? void 0 : _a.style.setProperty("--eccgui-sticky-target-applicationoffset", "".concat(connectedOffset, "px"));
|
|
67
|
+
};
|
|
68
|
+
updateTargetOffset_1();
|
|
69
|
+
var eventListeningTarget_1 = scrollParent_1 || window;
|
|
70
|
+
var eventListeningMethod_1 = function (_event) {
|
|
71
|
+
updateTargetOffset_1();
|
|
72
|
+
};
|
|
73
|
+
eventListeningTarget_1.addEventListener("scroll", eventListeningMethod_1);
|
|
74
|
+
return function () {
|
|
75
|
+
eventListeningTarget_1.removeEventListener("scroll", eventListeningMethod_1);
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return;
|
|
81
|
+
}, [getConnectedElement, stickyTargetRef, to]);
|
|
82
|
+
return (React.createElement("div", __assign({ ref: stickyTargetRef, className: "".concat(eccgui, "-sticky__target") +
|
|
83
|
+
(to ? " ".concat(eccgui, "-sticky__target--").concat(to) : "") +
|
|
84
|
+
(local ? " ".concat(eccgui, "-sticky__target--localscrollarea") : "") +
|
|
85
|
+
(background ? " ".concat(eccgui, "-sticky__target--bg-").concat(background) : "") +
|
|
86
|
+
(className ? " ".concat(className) : ""), style: offset ? offsetStyle : style }, otherDivProps)));
|
|
87
|
+
};
|
|
88
|
+
export default StickyTarget;
|
|
89
|
+
//# sourceMappingURL=StickyTarget.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"StickyTarget.js","sourceRoot":"","sources":["../../../../src/components/Sticky/StickyTarget.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/components/Sticky/index.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC"}
|
|
@@ -36,6 +36,7 @@ export * from "./Separation/Divider.js";
|
|
|
36
36
|
export * from "./Separation/Spacing.js";
|
|
37
37
|
export * from "./Skeleton/Skeleton.js";
|
|
38
38
|
export * from "./Spinner/Spinner.js";
|
|
39
|
+
export * from "./Sticky/index.js";
|
|
39
40
|
export * from "./Structure/index.js";
|
|
40
41
|
export * from "./Switch/Switch.js";
|
|
41
42
|
export * from "./Table/index.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,QAAQ,CAAC;AACvB,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,6BAA6B,CAAC;AAC5C,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,mCAAmC,CAAC;AAClD,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,QAAQ,CAAC;AACvB,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uCAAuC,CAAC;AACtD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAE5B,cAAc,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/components/index.ts"],"names":[],"mappings":"AAAA,cAAc,aAAa,CAAC;AAC5B,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,yBAAyB,CAAC;AACxC,cAAc,eAAe,CAAC;AAC9B,cAAc,cAAc,CAAC;AAC7B,cAAc,iBAAiB,CAAC;AAChC,cAAc,QAAQ,CAAC;AACvB,cAAc,qBAAqB,CAAC;AACpC,cAAc,kBAAkB,CAAC;AACjC,cAAc,uBAAuB,CAAC;AACtC,cAAc,UAAU,CAAC;AACzB,cAAc,QAAQ,CAAC;AACvB,cAAc,QAAQ,CAAC;AACvB,cAAc,6BAA6B,CAAC;AAC5C,cAAc,QAAQ,CAAC;AACvB,cAAc,UAAU,CAAC;AACzB,cAAc,mCAAmC,CAAC;AAClD,cAAc,eAAe,CAAC;AAC9B,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC;AAC5B,cAAc,QAAQ,CAAC;AACvB,cAAc,2BAA2B,CAAC;AAC1C,cAAc,uCAAuC,CAAC;AACtD,cAAc,gBAAgB,CAAC;AAC/B,cAAc,6BAA6B,CAAC;AAC5C,cAAc,gBAAgB,CAAC;AAC/B,cAAc,yBAAyB,CAAC;AACxC,cAAc,eAAe,CAAC;AAC9B,cAAc,qBAAqB,CAAC;AACpC,cAAc,2BAA2B,CAAC;AAC1C,cAAc,iBAAiB,CAAC;AAChC,cAAc,sBAAsB,CAAC;AACrC,cAAc,sBAAsB,CAAC;AACrC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,UAAU,CAAC;AACzB,cAAc,aAAa,CAAC;AAC5B,cAAc,iBAAiB,CAAC;AAChC,cAAc,SAAS,CAAC;AACxB,cAAc,QAAQ,CAAC;AACvB,cAAc,OAAO,CAAC;AACtB,cAAc,aAAa,CAAC;AAC5B,cAAc,WAAW,CAAC;AAC1B,cAAc,mBAAmB,CAAC;AAClC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,aAAa,CAAC;AAE5B,cAAc,cAAc,CAAC"}
|
|
@@ -21,6 +21,7 @@ export declare const utils: {
|
|
|
21
21
|
};
|
|
22
22
|
getGlobalVar: (varname: string) => Window;
|
|
23
23
|
setGlobalVar: (varname: string, value: any) => any;
|
|
24
|
+
getScrollParent: (element: Element) => false | HTMLElement;
|
|
24
25
|
};
|
|
25
26
|
export declare const Utilities: {
|
|
26
27
|
openInNewTab: (event: import("react").MouseEvent<HTMLAnchorElement, MouseEvent>, handler?: ((e: import("react").MouseEvent<HTMLAnchorElement, MouseEvent>) => void) | undefined, url?: string | undefined) => void;
|
|
@@ -44,4 +45,5 @@ export declare const Utilities: {
|
|
|
44
45
|
};
|
|
45
46
|
getGlobalVar: (varname: string) => Window;
|
|
46
47
|
setGlobalVar: (varname: string, value: any) => any;
|
|
48
|
+
getScrollParent: (element: Element) => false | HTMLElement;
|
|
47
49
|
};
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find the scroll parent of an element, returns `false` if it cannot be found.
|
|
3
|
+
* In case of a `false` return the very probably `document.documentElement` is the parent.
|
|
4
|
+
* In this case `window` object should be used for scroll event listeners.
|
|
5
|
+
* See `src/components/Sticky/StickyTarget.tsx` for an usage example.
|
|
6
|
+
* @param element
|
|
7
|
+
* @returns HTMLElement | false
|
|
8
|
+
*/
|
|
9
|
+
export declare const getScrollParent: (element: Element) => HTMLElement | false;
|
|
@@ -109,6 +109,8 @@ export interface AutoCompleteFieldProps<T, UPDATE_VALUE> {
|
|
|
109
109
|
* Use the full available width of the parent container.
|
|
110
110
|
*/
|
|
111
111
|
fill?: boolean;
|
|
112
|
+
/** Utility that fetches more options when clicked*/
|
|
113
|
+
loadMoreResults?: () => Promise<T[]>;
|
|
112
114
|
}
|
|
113
115
|
export declare type IAutoCompleteFieldProps<T, UPDATE_VALUE> = AutoCompleteFieldProps<T, UPDATE_VALUE>;
|
|
114
116
|
/**
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
export interface StickyTargetProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
3
|
+
/**
|
|
4
|
+
* Set the side the element need to be sticky on.
|
|
5
|
+
*/
|
|
6
|
+
to?: "top" | "bottom";
|
|
7
|
+
/**
|
|
8
|
+
* The sticky area is positioned relatively to a local scroll area.
|
|
9
|
+
* The application header is not taken into offset calculation
|
|
10
|
+
*/
|
|
11
|
+
local?: boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Set the background color used for the sticky area.
|
|
14
|
+
* As it can overlay other content readability could be harmed if the overlayed content is shining through.
|
|
15
|
+
*/
|
|
16
|
+
background?: "card" | "application" | "transparent";
|
|
17
|
+
/**
|
|
18
|
+
* Set additional distance to original sticky position.
|
|
19
|
+
*/
|
|
20
|
+
offset?: `${number}${string}`;
|
|
21
|
+
/**
|
|
22
|
+
* Callback that returns an DOM element.
|
|
23
|
+
* The position of `StickyTarget` is then calculated relative to that element.
|
|
24
|
+
*/
|
|
25
|
+
getConnectedElement?: (ref: React.MutableRefObject<HTMLDivElement | null>) => Element | false;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Element wraps the content that need to be displayed sticky.
|
|
29
|
+
* The content then offset relative to its nearest scrolling ancestor and containing block (nearest block-level ancestor).
|
|
30
|
+
*/
|
|
31
|
+
export declare const StickyTarget: ({ className, to, local, background, offset, style, getConnectedElement, ...otherDivProps }: StickyTargetProps) => React.JSX.Element;
|
|
32
|
+
export default StickyTarget;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./StickyTarget";
|
|
@@ -36,6 +36,7 @@ export * from "./Separation/Divider";
|
|
|
36
36
|
export * from "./Separation/Spacing";
|
|
37
37
|
export * from "./Skeleton/Skeleton";
|
|
38
38
|
export * from "./Spinner/Spinner";
|
|
39
|
+
export * from "./Sticky";
|
|
39
40
|
export * from "./Structure";
|
|
40
41
|
export * from "./Switch/Switch";
|
|
41
42
|
export * from "./Table";
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@eccenca/gui-elements",
|
|
3
3
|
"description": "GUI elements based on other libraries, usable in React application, written in Typescript.",
|
|
4
|
-
"version": "23.7.0-rc.
|
|
4
|
+
"version": "23.7.0-rc.1",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://github.com/eccenca/gui-elements",
|
|
7
7
|
"bugs": "https://github.com/eccenca/gui-elements/issues",
|
package/src/common/index.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { invisibleZeroWidthCharacters } from "./utils/characters";
|
|
2
2
|
import decideContrastColorValue from "./utils/colorDecideContrastvalue";
|
|
3
3
|
import getColorConfiguration from "./utils/getColorConfiguration";
|
|
4
|
+
import { getScrollParent } from "./utils/getScrollParent";
|
|
4
5
|
import { getGlobalVar, setGlobalVar } from "./utils/globalVars";
|
|
5
6
|
import { openInNewTab } from "./utils/openInNewTab";
|
|
6
7
|
|
|
@@ -11,6 +12,8 @@ export const utils = {
|
|
|
11
12
|
invisibleZeroWidthCharacters,
|
|
12
13
|
getGlobalVar,
|
|
13
14
|
setGlobalVar,
|
|
15
|
+
getScrollParent,
|
|
14
16
|
};
|
|
17
|
+
|
|
15
18
|
// @deprecated use `utils`
|
|
16
19
|
export const Utilities = utils;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Find the scroll parent of an element, returns `false` if it cannot be found.
|
|
3
|
+
* In case of a `false` return the very probably `document.documentElement` is the parent.
|
|
4
|
+
* In this case `window` object should be used for scroll event listeners.
|
|
5
|
+
* See `src/components/Sticky/StickyTarget.tsx` for an usage example.
|
|
6
|
+
* @param element
|
|
7
|
+
* @returns HTMLElement | false
|
|
8
|
+
*/
|
|
9
|
+
export const getScrollParent = (element: Element): HTMLElement | false => {
|
|
10
|
+
let scrollParent = element.parentElement;
|
|
11
|
+
while (scrollParent) {
|
|
12
|
+
const { overflow } = window.getComputedStyle(scrollParent);
|
|
13
|
+
if (overflow.split(" ").every((value) => value === "auto" || value === "scroll")) {
|
|
14
|
+
return scrollParent;
|
|
15
|
+
}
|
|
16
|
+
scrollParent = scrollParent.parentElement;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return false;
|
|
20
|
+
};
|
|
@@ -156,6 +156,8 @@ export interface AutoCompleteFieldProps<T, UPDATE_VALUE> {
|
|
|
156
156
|
* Use the full available width of the parent container.
|
|
157
157
|
*/
|
|
158
158
|
fill?: boolean;
|
|
159
|
+
/** Utility that fetches more options when clicked*/
|
|
160
|
+
loadMoreResults?: () => Promise<T[]>;
|
|
159
161
|
}
|
|
160
162
|
|
|
161
163
|
export type IAutoCompleteFieldProps<T, UPDATE_VALUE> = AutoCompleteFieldProps<T, UPDATE_VALUE>;
|
|
@@ -195,6 +197,7 @@ export function AutoCompleteField<T, UPDATE_VALUE>(props: AutoCompleteFieldProps
|
|
|
195
197
|
requestErrorPrefix,
|
|
196
198
|
hasBackDrop,
|
|
197
199
|
fill,
|
|
200
|
+
loadMoreResults,
|
|
198
201
|
...otherProps
|
|
199
202
|
} = props;
|
|
200
203
|
const [selectedItem, setSelectedItem] = useState<T | undefined>(initialValue);
|
|
@@ -334,6 +337,7 @@ export function AutoCompleteField<T, UPDATE_VALUE>(props: AutoCompleteFieldProps
|
|
|
334
337
|
disabled: modifiers.disabled,
|
|
335
338
|
highlightingEnabled: highlightingEnabled,
|
|
336
339
|
};
|
|
340
|
+
|
|
337
341
|
const renderedItem = itemRenderer(item, query, relevantModifiers, handleClick);
|
|
338
342
|
if (typeof renderedItem === "string") {
|
|
339
343
|
return (
|
|
@@ -442,6 +446,26 @@ export function AutoCompleteField<T, UPDATE_VALUE>(props: AutoCompleteFieldProps
|
|
|
442
446
|
createNewItemPosition,
|
|
443
447
|
}
|
|
444
448
|
: {};
|
|
449
|
+
|
|
450
|
+
const handleMenuScroll = React.useCallback(
|
|
451
|
+
async (event: any) => {
|
|
452
|
+
const menu = event.target;
|
|
453
|
+
const { scrollTop, scrollHeight, clientHeight } = menu;
|
|
454
|
+
// Check if scrolled to the bottom of the list
|
|
455
|
+
if (scrollTop + clientHeight >= scrollHeight && loadMoreResults) {
|
|
456
|
+
const results = await loadMoreResults();
|
|
457
|
+
if (results) {
|
|
458
|
+
setFiltered((prev) => [...prev, ...results]);
|
|
459
|
+
setTimeout(() => {
|
|
460
|
+
menu.scrollTop = scrollHeight; //safari adaptation
|
|
461
|
+
menu.scrollTo({ left: 0, top: scrollHeight, behavior: "auto" });
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
},
|
|
466
|
+
[loadMoreResults]
|
|
467
|
+
);
|
|
468
|
+
|
|
445
469
|
return (
|
|
446
470
|
<BlueprintSuggest<T>
|
|
447
471
|
className={`${eccgui}-autocompletefield__input` + (className ? ` ${className}` : "")}
|
|
@@ -455,7 +479,11 @@ export function AutoCompleteField<T, UPDATE_VALUE>(props: AutoCompleteFieldProps
|
|
|
455
479
|
noResults={<MenuItem disabled={true} text={noResultText} />}
|
|
456
480
|
onItemSelect={onSelectionChange}
|
|
457
481
|
onQueryChange={(q) => setQuery(q)}
|
|
482
|
+
resetOnQuery={false}
|
|
458
483
|
closeOnSelect={true}
|
|
484
|
+
menuProps={{
|
|
485
|
+
onScroll: handleMenuScroll,
|
|
486
|
+
}}
|
|
459
487
|
query={query}
|
|
460
488
|
// This leads to odd compile errors without "as any"
|
|
461
489
|
popoverProps={updatedContextOverlayProps as any}
|
|
@@ -229,16 +229,15 @@ export function MultiSelect<T>({
|
|
|
229
229
|
]);
|
|
230
230
|
|
|
231
231
|
/**
|
|
232
|
-
* Update selected items if
|
|
233
|
-
* new selected items from outside
|
|
232
|
+
* Update selected items if we get new selected items from outside
|
|
234
233
|
*/
|
|
235
234
|
React.useEffect(() => {
|
|
236
|
-
if (!
|
|
235
|
+
if (!externalSelectedItems) {
|
|
237
236
|
return;
|
|
238
237
|
}
|
|
239
238
|
|
|
240
239
|
setSelectedItems(externalSelectedItems);
|
|
241
|
-
}, [
|
|
240
|
+
}, [externalSelectedItems]);
|
|
242
241
|
|
|
243
242
|
/**
|
|
244
243
|
* using the equality prop specified checks if an item has already been selected
|
|
@@ -2,7 +2,7 @@ import React, { useCallback, useMemo, useState } from "react";
|
|
|
2
2
|
import { loremIpsum } from "react-lorem-ipsum";
|
|
3
3
|
import { Meta, StoryFn } from "@storybook/react";
|
|
4
4
|
|
|
5
|
-
import { MultiSelectSelectionProps, MultiSuggestField } from "./../../../index";
|
|
5
|
+
import { MultiSelectSelectionProps, MultiSuggestField, SimpleDialog } from "./../../../index";
|
|
6
6
|
|
|
7
7
|
const testLabels = loremIpsum({
|
|
8
8
|
p: 1,
|
|
@@ -78,6 +78,40 @@ predefinedNotControlledValues.args = {
|
|
|
78
78
|
itemLabel: (item) => item.testLabel,
|
|
79
79
|
};
|
|
80
80
|
|
|
81
|
+
const DeferredSelectionTemplate: StoryFn = () => {
|
|
82
|
+
const initialSelected: Array<{ testId: string; testLabel: string }> = [];
|
|
83
|
+
const [loaded, setLoaded] = useState(false);
|
|
84
|
+
|
|
85
|
+
const selected = loaded ? selectedItems : initialSelected;
|
|
86
|
+
|
|
87
|
+
const identity = useCallback((item: string): string => item, []);
|
|
88
|
+
|
|
89
|
+
return (
|
|
90
|
+
<>
|
|
91
|
+
<div>Selected items loaded: {loaded.toString()}</div>
|
|
92
|
+
|
|
93
|
+
<br />
|
|
94
|
+
|
|
95
|
+
<MultiSuggestField<string>
|
|
96
|
+
items={items.map(({ testId }) => testId)}
|
|
97
|
+
selectedItems={selected.map(({ testId }) => testId)}
|
|
98
|
+
itemId={identity}
|
|
99
|
+
itemLabel={(itemId) => items.find(({ testId }) => testId === itemId)?.testLabel ?? itemId}
|
|
100
|
+
createNewItemFromQuery={(query) => query}
|
|
101
|
+
/>
|
|
102
|
+
|
|
103
|
+
<br />
|
|
104
|
+
|
|
105
|
+
<button onClick={() => setLoaded((prev) => !prev)}>Toggle selected</button>
|
|
106
|
+
</>
|
|
107
|
+
);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
*
|
|
112
|
+
*/
|
|
113
|
+
export const deferredSelection = DeferredSelectionTemplate.bind({});
|
|
114
|
+
|
|
81
115
|
/**
|
|
82
116
|
* New item creation, add to a existing list
|
|
83
117
|
*/
|
|
@@ -160,3 +194,44 @@ const WithResetButton: StoryFn = () => {
|
|
|
160
194
|
* Reset values
|
|
161
195
|
*/
|
|
162
196
|
export const withResetItemAndCreation = WithResetButton.bind({});
|
|
197
|
+
|
|
198
|
+
const WithinModal = (): JSX.Element => {
|
|
199
|
+
const [isOpen, setIsOpen] = useState(false);
|
|
200
|
+
|
|
201
|
+
const copy: Array<{ testLabel: string; testId: string }> = [items[2]];
|
|
202
|
+
|
|
203
|
+
const [selected, setSelected] = useState(copy);
|
|
204
|
+
|
|
205
|
+
const handleOnSelect = useCallback((params) => {
|
|
206
|
+
const items = params.selectedItems;
|
|
207
|
+
setSelected(items);
|
|
208
|
+
}, []);
|
|
209
|
+
|
|
210
|
+
const handleReset = (): void => {
|
|
211
|
+
setSelected(copy);
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
return (
|
|
215
|
+
<>
|
|
216
|
+
<button onClick={() => setIsOpen(true)}>open modal</button>
|
|
217
|
+
|
|
218
|
+
<SimpleDialog isOpen={isOpen} onClose={() => setIsOpen(false)} canOutsideClickClose>
|
|
219
|
+
<div>
|
|
220
|
+
<button onClick={handleReset}>Reset</button>
|
|
221
|
+
<br />
|
|
222
|
+
<br />
|
|
223
|
+
<MultiSuggestField<{ testLabel: string; testId: string }>
|
|
224
|
+
items={items}
|
|
225
|
+
selectedItems={selected}
|
|
226
|
+
onSelection={handleOnSelect}
|
|
227
|
+
itemId={({ testId }) => testId}
|
|
228
|
+
itemLabel={({ testLabel }) => testLabel}
|
|
229
|
+
createNewItemFromQuery={(query) => ({ testId: `${query}-id`, testLabel: query })}
|
|
230
|
+
/>
|
|
231
|
+
</div>
|
|
232
|
+
</SimpleDialog>
|
|
233
|
+
</>
|
|
234
|
+
);
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
export const withinModal = WithinModal.bind({});
|