@gooddata/sdk-ui-kit 11.52.0-alpha.4 → 11.52.0-alpha.5
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/esm/@ui/UiAsyncTable/UiAsyncTable/UiAsyncTableBody.d.ts.map +1 -1
- package/esm/@ui/UiAsyncTable/UiAsyncTable/UiAsyncTableBody.js +9 -6
- package/esm/@ui/UiAsyncTable/UiAsyncTable/UiAsyncTableRow.d.ts.map +1 -1
- package/esm/@ui/UiAsyncTable/UiAsyncTable/UiAsyncTableRow.js +13 -2
- package/esm/@ui/UiAsyncTable/UiAsyncTable/asyncTableGridContext.d.ts +4 -0
- package/esm/@ui/UiAsyncTable/UiAsyncTable/asyncTableGridContext.d.ts.map +1 -0
- package/esm/@ui/UiAsyncTable/UiAsyncTable/asyncTableGridContext.js +12 -0
- package/esm/Dialog/StylingEditorDialog/StylingEditorDialog.d.ts +9 -0
- package/esm/Dialog/StylingEditorDialog/StylingEditorDialog.d.ts.map +1 -1
- package/esm/Dialog/StylingEditorDialog/StylingEditorDialog.js +33 -28
- package/esm/Dropdown/DropdownButton.d.ts.map +1 -1
- package/esm/Dropdown/DropdownButton.js +5 -0
- package/esm/Header/Header.d.ts.map +1 -1
- package/esm/Header/Header.js +2 -2
- package/esm/Header/HeaderChatButton.d.ts +9 -1
- package/esm/Header/HeaderChatButton.d.ts.map +1 -1
- package/esm/Header/HeaderChatButton.js +12 -1
- package/esm/Header/typings.d.ts +5 -0
- package/esm/Header/typings.d.ts.map +1 -1
- package/esm/Header/typings.js +1 -1
- package/esm/Timezone/TimezoneSelect.d.ts +10 -2
- package/esm/Timezone/TimezoneSelect.d.ts.map +1 -1
- package/esm/Timezone/TimezoneSelect.js +4 -3
- package/esm/index.d.ts +1 -1
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -1
- package/esm/sdk-ui-kit.d.ts +31 -1
- package/package.json +11 -11
- package/styles/css/main.css +3 -0
- package/styles/css/main.css.map +1 -1
- package/styles/css/stylingEditorDialog.css +3 -0
- package/styles/css/stylingEditorDialog.css.map +1 -1
- package/styles/scss/stylingEditorDialog.scss +4 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UiAsyncTableBody.d.ts","sourceRoot":"","sources":["../../../../src/@ui/UiAsyncTable/UiAsyncTable/UiAsyncTableBody.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAKlD,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"UiAsyncTableBody.d.ts","sourceRoot":"","sources":["../../../../src/@ui/UiAsyncTable/UiAsyncTable/UiAsyncTableBody.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAKlD,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,aAAa,CAAC;AAM1D,wBAAgB,gBAAgB,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,EACzE,KAAK,EACL,SAAS,EACT,UAAU,EACV,kBAAkB,EAClB,WAAW,EACX,SAAS,EACT,WAAW,EACX,YAAY,EACZ,OAAO,EACP,WAAW,EACX,aAAa,EACb,UAAU,EACV,kBAAkB,EAClB,UAAU,EACb,EAAE,sBAAsB,CAAC,CAAC,CAAC,2CAyD3B"}
|
|
@@ -4,10 +4,12 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react";
|
|
|
4
4
|
import { isEnterKey } from "../../../utils/events.js";
|
|
5
5
|
import { makeGridKeyboardNavigation } from "../../@utils/keyboardNavigation.js";
|
|
6
6
|
import { UiPagedVirtualList } from "../../UiPagedVirtualList/UiPagedVirtualList.js";
|
|
7
|
+
import { AsyncTableGridRefProvider } from "./asyncTableGridContext.js";
|
|
7
8
|
import { useSkeletonItem } from "./SkeletonItemFactory.js";
|
|
8
9
|
import { getCellId, getItemKey, getRowId } from "./utils.js";
|
|
9
10
|
export function UiAsyncTableBody({ items, maxHeight, itemHeight, skeletonItemsCount, hasNextPage, isLoading, onItemClick, loadNextPage, columns, bulkActions, scrollToIndex, isLargeRow, shouldLoadNextPage, renderItem, }) {
|
|
10
11
|
const SkeletonItem = useSkeletonItem(columns, bulkActions, isLargeRow ?? false);
|
|
12
|
+
const gridRef = useRef(null);
|
|
11
13
|
const { handleKeyDown, handleFocus, focusedRowIndex, focusedColumnIndex, focusedItemRef } = useAsyncTableBodyKeyboardNavigation(items.length, columns.length, !!bulkActions, scrollToIndex);
|
|
12
14
|
const activeDescendantId = useMemo(() => {
|
|
13
15
|
if (focusedRowIndex === undefined || focusedRowIndex < 0 || focusedRowIndex >= items.length) {
|
|
@@ -19,12 +21,13 @@ export function UiAsyncTableBody({ items, maxHeight, itemHeight, skeletonItemsCo
|
|
|
19
21
|
}
|
|
20
22
|
return getRowId(itemId);
|
|
21
23
|
}, [focusedRowIndex, focusedColumnIndex, items]);
|
|
22
|
-
return (_jsx(UiPagedVirtualList, { maxHeight: maxHeight, itemHeight: itemHeight, itemsGap: 0, itemPadding: 0, items: items, skeletonItemsCount: skeletonItemsCount, hasNextPage: hasNextPage, isLoading: isLoading, onKeyDownSelect: onItemClick, loadNextPage: loadNextPage, SkeletonItem: SkeletonItem, scrollbarHoverEffect: true, scrollToIndex: scrollToIndex ?? focusedRowIndex, shouldLoadNextPage: shouldLoadNextPage, tabIndex: items.length ? 0 : -1, customKeyboardNavigationHandler: handleKeyDown, onFocus: handleFocus, listboxProps: {
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
return (_jsx(AsyncTableGridRefProvider, { value: gridRef, children: _jsx(UiPagedVirtualList, { maxHeight: maxHeight, itemHeight: itemHeight, itemsGap: 0, itemPadding: 0, items: items, skeletonItemsCount: skeletonItemsCount, hasNextPage: hasNextPage, isLoading: isLoading, onKeyDownSelect: onItemClick, loadNextPage: loadNextPage, SkeletonItem: SkeletonItem, scrollbarHoverEffect: true, scrollToIndex: scrollToIndex ?? focusedRowIndex, shouldLoadNextPage: shouldLoadNextPage, tabIndex: items.length ? 0 : -1, customKeyboardNavigationHandler: handleKeyDown, onFocus: handleFocus, listboxProps: {
|
|
25
|
+
"aria-activedescendant": activeDescendantId,
|
|
26
|
+
ref: gridRef,
|
|
27
|
+
}, children: (item, focusedIndex) => {
|
|
28
|
+
const itemIndex = focusedIndex ?? 0;
|
|
29
|
+
return renderItem(item, itemIndex, focusedItemRef, itemIndex === focusedRowIndex, focusedColumnIndex);
|
|
30
|
+
} }) }));
|
|
28
31
|
}
|
|
29
32
|
const useAsyncTableBodyKeyboardNavigation = (rowsLength, definedColumnsLength, hasBulkActions, scrollToIndex) => {
|
|
30
33
|
const [focusedRowIndex, setFocusedRowIndex] = useState(undefined);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UiAsyncTableRow.d.ts","sourceRoot":"","sources":["../../../../src/@ui/UiAsyncTable/UiAsyncTable/UiAsyncTableRow.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAKlD,OAAO,EAGH,KAAK,qBAAqB,EAE7B,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"UiAsyncTableRow.d.ts","sourceRoot":"","sources":["../../../../src/@ui/UiAsyncTable/UiAsyncTable/UiAsyncTableRow.tsx"],"names":[],"mappings":"AAIA,OAAO,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAKlD,OAAO,EAGH,KAAK,qBAAqB,EAE7B,MAAM,aAAa,CAAC;AAQrB,wBAAgB,eAAe,CAAC,CAAC,SAAS;IAAE,EAAE,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,EAAE,EACxE,IAAI,EACJ,SAAS,EACT,OAAO,EACP,QAAQ,EACR,OAAO,EACP,UAAU,EACV,WAAW,EACX,OAAO,EACP,SAAS,EACT,kBAAkB,EAClB,iBAAiB,EACjB,mBAAmB,EACtB,EAAE,qBAAqB,CAAC,CAAC,CAAC,2CA4E1B"}
|
|
@@ -4,6 +4,7 @@ import { useCallback } from "react";
|
|
|
4
4
|
import { Dropdown } from "../../../Dropdown/Dropdown.js";
|
|
5
5
|
import { UiIconButton } from "../../UiIconButton/UiIconButton.js";
|
|
6
6
|
import { e } from "../asyncTableBem.js";
|
|
7
|
+
import { useAsyncTableGridRef } from "./asyncTableGridContext.js";
|
|
7
8
|
import { UiAsyncTableCheckbox } from "./UiAsyncTableCheckbox.js";
|
|
8
9
|
import { UiAsyncTableIconRenderer } from "./UiAsyncTableIconRenderer.js";
|
|
9
10
|
import { getCellId, getColumnWidth, getItemKey, getRowId, getRowLabelId } from "./utils.js";
|
|
@@ -43,6 +44,16 @@ export function UiAsyncTableRow({ item, itemIndex, columns, onSelect, onClick, i
|
|
|
43
44
|
})] }));
|
|
44
45
|
}
|
|
45
46
|
const useRenderCellContent = ({ isLarge, }) => {
|
|
47
|
+
const gridRef = useAsyncTableGridRef();
|
|
48
|
+
// Put focus back on the grid before the menu closes. Callers routinely close the menu and open a
|
|
49
|
+
// dialog in the same tick (flushSync(closeDropdown) then setState); that dialog captures whatever is
|
|
50
|
+
// focused as its own return target, and the dropdown's restore is deferred to a microtask, so it would
|
|
51
|
+
// land after the snapshot was taken and the dialog would return focus to <body> - i.e. the page top.
|
|
52
|
+
// Restoring here keeps it synchronous, and the deferred restore then correctly sees nothing to do.
|
|
53
|
+
const closeMenuAndRestoreFocus = useCallback((closeDropdown) => {
|
|
54
|
+
gridRef?.current?.focus();
|
|
55
|
+
closeDropdown();
|
|
56
|
+
}, [gridRef]);
|
|
46
57
|
const renderRoleIconWithWrapper = useCallback((renderRoleIcon, item) => {
|
|
47
58
|
return (_jsx(UiAsyncTableIconRenderer, { renderIcon: renderRoleIcon, className: e("role-icon"), item: item }));
|
|
48
59
|
}, []);
|
|
@@ -64,8 +75,8 @@ const useRenderCellContent = ({ isLarge, }) => {
|
|
|
64
75
|
ariaExpanded: isOpen,
|
|
65
76
|
ariaLabel: label,
|
|
66
77
|
}, ref: isCellFocused ? focusedElementRef : undefined }));
|
|
67
|
-
}, alignPoints: [{ align: "br tr" }, { align: "tr br" }], renderBody: ({ closeDropdown }) => renderMenu(item, closeDropdown) }));
|
|
68
|
-
}, [isLarge]);
|
|
78
|
+
}, alignPoints: [{ align: "br tr" }, { align: "tr br" }], renderBody: ({ closeDropdown }) => renderMenu(item, () => closeMenuAndRestoreFocus(closeDropdown)) }));
|
|
79
|
+
}, [isLarge, closeMenuAndRestoreFocus]);
|
|
69
80
|
const renderTextContent = useCallback((item, key, labelId, getTextContent, getMultiLineTextContent, renderSuffixIcon) => {
|
|
70
81
|
if (getMultiLineTextContent) {
|
|
71
82
|
return getMultiLineTextContent(item).map((line, index) => {
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type RefObject } from "react";
|
|
2
|
+
export declare const AsyncTableGridRefProvider: import("react").Provider<RefObject<HTMLElement | null> | null>;
|
|
3
|
+
export declare const useAsyncTableGridRef: () => RefObject<HTMLElement | null> | null;
|
|
4
|
+
//# sourceMappingURL=asyncTableGridContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"asyncTableGridContext.d.ts","sourceRoot":"","sources":["../../../../src/@ui/UiAsyncTable/UiAsyncTable/asyncTableGridContext.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,SAAS,EAA6B,MAAM,OAAO,CAAC;AAWlE,eAAO,MAAM,yBAAyB,gEAAoC,CAAC;AAE3E,eAAO,MAAM,oBAAoB,4CAA6C,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// (C) 2026 GoodData Corporation
|
|
2
|
+
import { createContext, useContext } from "react";
|
|
3
|
+
/**
|
|
4
|
+
* Ref to the grid element that holds the table's real DOM focus.
|
|
5
|
+
*
|
|
6
|
+
* The table is a composite widget: the grid is its single tab stop and the active row/cell is tracked
|
|
7
|
+
* virtually via aria-activedescendant (row controls are kept out of the tab order). Layers opened from a
|
|
8
|
+
* row therefore return focus here rather than to the control that opened them.
|
|
9
|
+
*/
|
|
10
|
+
const AsyncTableGridRefContext = createContext(null);
|
|
11
|
+
export const AsyncTableGridRefProvider = AsyncTableGridRefContext.Provider;
|
|
12
|
+
export const useAsyncTableGridRef = () => useContext(AsyncTableGridRefContext);
|
|
@@ -34,6 +34,15 @@ export interface IStylingEditorDialogProps<T extends StylingPickerItemContent> e
|
|
|
34
34
|
* submission and display it, or undefined when the content is valid.
|
|
35
35
|
*/
|
|
36
36
|
validateDefinition?: (content: T) => string | undefined;
|
|
37
|
+
/**
|
|
38
|
+
* Optional non-blocking check of the parsed definition content.
|
|
39
|
+
*
|
|
40
|
+
* @remarks
|
|
41
|
+
* Called only when the definition is valid JSON. Return a localized message to display it as a
|
|
42
|
+
* warning, or undefined when there is nothing to report. Unlike {@link IStylingEditorDialogProps.validateDefinition}
|
|
43
|
+
* this never prevents submission — use it for content that applies but degrades the result.
|
|
44
|
+
*/
|
|
45
|
+
validateDefinitionWarning?: (content: T) => string | undefined;
|
|
37
46
|
}
|
|
38
47
|
/**
|
|
39
48
|
* @internal
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"StylingEditorDialog.d.ts","sourceRoot":"","sources":["../../../src/Dialog/StylingEditorDialog/StylingEditorDialog.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"StylingEditorDialog.d.ts","sourceRoot":"","sources":["../../../src/Dialog/StylingEditorDialog/StylingEditorDialog.tsx"],"names":[],"mappings":"AAOA,OAAO,EAAE,KAAK,aAAa,EAAE,KAAK,MAAM,EAAE,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAQnF,OAAO,EAAE,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAGtD,OAAO,EAEH,KAAK,+BAA+B,EACvC,MAAM,gCAAgC,CAAC;AAGxC;;GAEG;AACH,MAAM,MAAM,wBAAwB,GAAG,MAAM,GAAG,aAAa,CAAC;AAE9D;;GAEG;AACH,MAAM,WAAW,kBAAkB,CAAC,CAAC,SAAS,wBAAwB;IAClE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,CAAC,CAAC;CACd;AAED;;GAEG;AACH,MAAM,WAAW,yBAAyB,CAAC,CAAC,SAAS,wBAAwB,CACzE,SAAQ,+BAA+B,EAAE,IAAI,CAAC,gBAAgB,EAAE,SAAS,GAAG,WAAW,CAAC;IACxF,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,CAAC;IACpC,QAAQ,CAAC,EAAE,kBAAkB,CAAC,CAAC,CAAC,EAAE,CAAC;IACnC,qBAAqB,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,MAAM,EAAE,CAAC;IACjD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,mBAAmB,CAAC,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,IAAI,CAAC;IAC5C,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB;;;;;;OAMG;IACH,kBAAkB,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;IACxD;;;;;;;OAOG;IACH,yBAAyB,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,KAAK,MAAM,GAAG,SAAS,CAAC;CAClE;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,CAAC,SAAS,wBAAwB,EAAE,KAAK,EAAE,yBAAyB,CAAC,CAAC,CAAC,2CAM1G"}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
// (C) 2022-2026 GoodData Corporation
|
|
3
|
-
import { useMemo, useState } from "react";
|
|
3
|
+
import { useCallback, useMemo, useState } from "react";
|
|
4
4
|
import cx from "classnames";
|
|
5
5
|
import { useIntl } from "react-intl";
|
|
6
6
|
import { IntlWrapper } from "@gooddata/sdk-ui";
|
|
7
7
|
import { Button } from "../../Button/Button.js";
|
|
8
|
+
import { Message } from "../../Messages/Message.js";
|
|
8
9
|
import { Typography } from "../../Typography/Typography.js";
|
|
9
10
|
import { useId } from "../../utils/useId.js";
|
|
10
11
|
import { Dialog } from "../Dialog.js";
|
|
@@ -17,49 +18,48 @@ import { StylingExample } from "./StylingExample.js";
|
|
|
17
18
|
export function StylingEditorDialog(props) {
|
|
18
19
|
return (_jsx(IntlWrapper, { locale: props.locale, children: _jsx(StylingEditorDialogCore, { ...props }) }));
|
|
19
20
|
}
|
|
20
|
-
function StylingEditorDialogCore({ title, tooltip, link, stylingItem, examples, exampleToColorPreview, onClose, onSubmit, onCancel, disableSubmit, showProgressIndicator, showBackButton, onHelpClick, onExit = () => { }, className, onInvalidDefinition = () => { }, validateDefinition, }) {
|
|
21
|
+
function StylingEditorDialogCore({ title, tooltip, link, stylingItem, examples, exampleToColorPreview, onClose, onSubmit, onCancel, disableSubmit, showProgressIndicator, showBackButton, onHelpClick, onExit = () => { }, className, onInvalidDefinition = () => { }, validateDefinition, validateDefinitionWarning, }) {
|
|
21
22
|
const intl = useIntl();
|
|
22
23
|
const providedExamples = !!examples && examples.length !== 0 && !!exampleToColorPreview;
|
|
23
24
|
const initialNameField = stylingItem?.name ?? "";
|
|
24
25
|
const initialDefinitionField = stylingItem?.content ? JSON.stringify(stylingItem?.content, null, 4) : "";
|
|
25
26
|
const [nameField, setNameField] = useState(initialNameField);
|
|
26
27
|
const [definitionField, setDefinitionField] = useState(initialDefinitionField);
|
|
27
|
-
const
|
|
28
|
+
const parsedDefinition = useMemo(() => {
|
|
28
29
|
try {
|
|
29
|
-
|
|
30
|
-
const formattedDefinition = JSON.stringify(parsedDefinition, null, 4);
|
|
31
|
-
return nameField !== initialNameField || formattedDefinition !== initialDefinitionField;
|
|
30
|
+
return { ok: true, content: JSON.parse(definitionField) };
|
|
32
31
|
}
|
|
33
32
|
catch {
|
|
33
|
+
return { ok: false };
|
|
34
|
+
}
|
|
35
|
+
}, [definitionField]);
|
|
36
|
+
const fieldsChanged = useMemo(() => {
|
|
37
|
+
if (!parsedDefinition.ok) {
|
|
34
38
|
// initial state of the fields is presumed to be valid,
|
|
35
39
|
// so if JSON throws error, definition was changed
|
|
36
40
|
return true;
|
|
37
41
|
}
|
|
38
|
-
|
|
42
|
+
const formattedDefinition = JSON.stringify(parsedDefinition.content, null, 4);
|
|
43
|
+
return nameField !== initialNameField || formattedDefinition !== initialDefinitionField;
|
|
44
|
+
}, [parsedDefinition, nameField, initialNameField, initialDefinitionField]);
|
|
39
45
|
const validName = useMemo(() => nameField !== "", [nameField]);
|
|
40
|
-
const validDefinition =
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
catch {
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
}, [definitionField]);
|
|
49
|
-
// Content-level validation (e.g. theme color values) runs only on well-formed JSON.
|
|
50
|
-
const definitionContentError = useMemo(() => {
|
|
51
|
-
if (!validateDefinition || !validDefinition) {
|
|
46
|
+
const validDefinition = parsedDefinition.ok;
|
|
47
|
+
// A callback that throws must not crash the dialog, so it degrades to "nothing to report" and
|
|
48
|
+
// the user can keep working.
|
|
49
|
+
const runContentCheck = useCallback((check, name) => {
|
|
50
|
+
if (!check || !parsedDefinition.ok) {
|
|
52
51
|
return undefined;
|
|
53
52
|
}
|
|
54
53
|
try {
|
|
55
|
-
return
|
|
54
|
+
return check(parsedDefinition.content);
|
|
56
55
|
}
|
|
57
56
|
catch (error) {
|
|
58
|
-
|
|
59
|
-
console.error("StylingEditorDialog: the provided validateDefinition callback threw.", error);
|
|
57
|
+
console.error(`StylingEditorDialog: the provided ${name} callback threw.`, error);
|
|
60
58
|
return undefined;
|
|
61
59
|
}
|
|
62
|
-
}, [
|
|
60
|
+
}, [parsedDefinition]);
|
|
61
|
+
const definitionContentError = useMemo(() => runContentCheck(validateDefinition, "validateDefinition"), [runContentCheck, validateDefinition]);
|
|
62
|
+
const definitionContentWarning = useMemo(() => runContentCheck(validateDefinitionWarning, "validateDefinitionWarning"), [runContentCheck, validateDefinitionWarning]);
|
|
63
63
|
const validFields = useMemo(() => validName && validDefinition && !definitionContentError, [validName, validDefinition, definitionContentError]);
|
|
64
64
|
const isSubmitDisabled = useMemo(() => !validFields || !fieldsChanged || disableSubmit, [validFields, fieldsChanged, disableSubmit]);
|
|
65
65
|
const emptyDefinition = useMemo(() => definitionField === "", [definitionField]);
|
|
@@ -89,10 +89,10 @@ function StylingEditorDialogCore({ title, tooltip, link, stylingItem, examples,
|
|
|
89
89
|
stylingItem?.ref,
|
|
90
90
|
intl,
|
|
91
91
|
]);
|
|
92
|
-
const getFinalStylingItem = (original,
|
|
92
|
+
const getFinalStylingItem = (original, content, name) => {
|
|
93
93
|
return {
|
|
94
94
|
...(original || {}),
|
|
95
|
-
content
|
|
95
|
+
content,
|
|
96
96
|
name,
|
|
97
97
|
};
|
|
98
98
|
};
|
|
@@ -111,13 +111,18 @@ function StylingEditorDialogCore({ title, tooltip, link, stylingItem, examples,
|
|
|
111
111
|
_jsxs("form", { className: "gd-styling-editor-dialog-content-form", onSubmit: (e) => e.preventDefault(), children: [
|
|
112
112
|
_jsxs("label", { className: "gd-styling-editor-dialog-content-form-input", children: [intl.formatMessage({ id: "stylingEditor.dialog.name" }), _jsx("input", { "aria-label": "Styling item name", className: "gd-input-field s-input-field", type: "text", value: nameField, onChange: (e) => setNameField(e.target.value) })
|
|
113
113
|
] }), _jsxs("label", { className: "gd-styling-editor-dialog-content-form-textarea", children: [intl.formatMessage({ id: "stylingEditor.dialog.definition" }), _jsx("textarea", { "aria-label": "Styling item definition", className: "gd-input-field s-textarea-field", wrap: "off", value: definitionField, onChange: (e) => setDefinitionField(e.target.value) })
|
|
114
|
-
] })
|
|
115
|
-
] }), providedExamples ? (_jsxs("div", { className: cx("gd-styling-editor-dialog-content-examples", "s-gd-styling-editor-dialog-content-examples"), children: [
|
|
114
|
+
] }), definitionContentWarning && !definitionContentError ? (_jsx(Message, { type: "warning", className: "gd-styling-editor-dialog-content-form-warning s-styling-editor-warning", children: definitionContentWarning })) : null] }), providedExamples ? (_jsxs("div", { className: cx("gd-styling-editor-dialog-content-examples", "s-gd-styling-editor-dialog-content-examples"), children: [
|
|
116
115
|
_jsx(BubbleHeaderSeparator, { title: intl.formatMessage({ id: "stylingEditor.dialog.examples" }), message: tooltip }), _jsx("div", { className: "gd-styling-editor-dialog-content-examples-list", children: examples.map((example, index) => (_jsx(StylingExample, { name: example.name ?? "", colors: exampleToColorPreview(example.content), onClick: () => {
|
|
117
116
|
setNameField(example.name ?? "");
|
|
118
117
|
setDefinitionField(JSON.stringify(example.content, null, 4));
|
|
119
118
|
} }, index))) })
|
|
120
|
-
] })) : null] }), _jsx(StylingEditorDialogFooter, { disableSubmit: isSubmitDisabled, showProgressIndicator: showProgressIndicator, link: link, errorMessage: errorMessage, onSubmit: () =>
|
|
119
|
+
] })) : null] }), _jsx(StylingEditorDialogFooter, { disableSubmit: isSubmitDisabled, showProgressIndicator: showProgressIndicator, link: link, errorMessage: errorMessage, onSubmit: () => {
|
|
120
|
+
// Submission is disabled while the definition does not parse, so this only
|
|
121
|
+
// narrows the type rather than guarding a reachable state.
|
|
122
|
+
if (parsedDefinition.ok) {
|
|
123
|
+
onSubmit?.(getFinalStylingItem(stylingItem, parsedDefinition.content, nameField));
|
|
124
|
+
}
|
|
125
|
+
}, onCancel: () => {
|
|
121
126
|
onExit?.(nameField, definitionField);
|
|
122
127
|
onCancel?.();
|
|
123
128
|
}, onHelpClick: onHelpClick })
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DropdownButton.d.ts","sourceRoot":"","sources":["../../src/Dropdown/DropdownButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAMvF,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAE5E;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mBAAmB,CAAC,EAAE,wBAAwB,GAAG;QAAE,SAAS,CAAC,EAAE,cAAc,CAAC,eAAe,CAAC,CAAA;KAAE,CAAC;IAEjG,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IAElC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC3B,EAAE,EACF,SAAS,EACT,mBAAmB,EAEnB,KAAK,EACL,KAAa,EACb,QAAQ,EAER,MAAM,EACN,OAAc,EACd,QAAQ,EACR,WAAmB,EACnB,OAAO,EACP,QAAQ,EACR,UAAU,EACV,SAAS,EACZ,EAAE,oBAAoB,
|
|
1
|
+
{"version":3,"file":"DropdownButton.d.ts","sourceRoot":"","sources":["../../src/Dropdown/DropdownButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,cAAc,EAAE,KAAK,UAAU,EAAE,KAAK,SAAS,EAAE,KAAK,GAAG,EAAE,MAAM,OAAO,CAAC;AAMvF,OAAO,EAAE,KAAK,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAE5E;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACjC,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,mBAAmB,CAAC,EAAE,wBAAwB,GAAG;QAAE,SAAS,CAAC,EAAE,cAAc,CAAC,eAAe,CAAC,CAAA;KAAE,CAAC;IAEjG,KAAK,CAAC,EAAE,SAAS,CAAC;IAClB,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB,OAAO,CAAC,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;IAElC,QAAQ,CAAC,EAAE,SAAS,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,SAAS,CAAC,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;CAChC;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC3B,EAAE,EACF,SAAS,EACT,mBAAmB,EAEnB,KAAK,EACL,KAAa,EACb,QAAQ,EAER,MAAM,EACN,OAAc,EACd,QAAQ,EACR,WAAmB,EACnB,OAAO,EACP,QAAQ,EACR,UAAU,EACV,SAAS,EACZ,EAAE,oBAAoB,2CA4DtB"}
|
|
@@ -29,6 +29,11 @@ export function DropdownButton({ id, className, accessibilityConfig, value, titl
|
|
|
29
29
|
ariaLabel,
|
|
30
30
|
ariaLabelledBy,
|
|
31
31
|
ariaDescribedBy,
|
|
32
|
+
// Without a dropdownId the popup id is unknown, but the trigger is still a combobox,
|
|
33
|
+
// so it has to expose its expanded state - callers commonly pass only isOpen - along
|
|
34
|
+
// with any explicitly controlled id.
|
|
35
|
+
ariaExpanded: effectiveAriaExpanded,
|
|
36
|
+
ariaControls,
|
|
32
37
|
role: role ?? "combobox",
|
|
33
38
|
});
|
|
34
39
|
return (_jsx(Button, { id: id, accessibilityConfig: buttonAccessibilityConfig, title: title && typeof title === "string" ? title : undefined, className: buttonClasses, value: value, iconLeft: iconLeft, iconRight: isOpen ? "gd-icon-navigateup" : "gd-icon-navigatedown", disabled: disabled, onClick: onClick, ref: buttonRef, children: children }));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/Header/Header.tsx"],"names":[],"mappings":"AA2BA,OAAO,EAAE,KAAK,eAAe,EAA8C,MAAM,cAAc,CAAC;AAyBhG;;GAEG;AACH,eAAO,MAAM,SAAS,
|
|
1
|
+
{"version":3,"file":"Header.d.ts","sourceRoot":"","sources":["../../src/Header/Header.tsx"],"names":[],"mappings":"AA2BA,OAAO,EAAE,KAAK,eAAe,EAA8C,MAAM,cAAc,CAAC;AAyBhG;;GAEG;AACH,eAAO,MAAM,SAAS,kGAskBpB,CAAC"}
|
package/esm/Header/Header.js
CHANGED
|
@@ -42,7 +42,7 @@ const HEADER_HELP_MENU_ITEM_ID = defineMessage({ id: "gs.header.help" }).id;
|
|
|
42
42
|
/**
|
|
43
43
|
* @internal
|
|
44
44
|
*/
|
|
45
|
-
export const AppHeader = withTheme(function AppHeader({ logoHref = "/", accountMenuItems = [], helpMenuItems = [], menuItemsGroups = [], search, notificationsPanel, workspacePicker, isAccessibilityCompliant, logoUrl, logoTitle, organizationName, className, activeColor, headerColor, headerTextColor, documentationUrl, expiredDate, showUpsellButton, onUpsellButtonClick, badges, showStaticHelpMenu, userName, theme, helpMenuDropdownAlignPoints: helpDropdownAlign, disableHelpDropdown, onHelpClick, helpRedirectUrl, showChatItem, onChatItemClick, onLogoClick, onMenuItemClick, }) {
|
|
45
|
+
export const AppHeader = withTheme(function AppHeader({ logoHref = "/", accountMenuItems = [], helpMenuItems = [], menuItemsGroups = [], search, notificationsPanel, workspacePicker, isAccessibilityCompliant, logoUrl, logoTitle, organizationName, className, activeColor, headerColor, headerTextColor, documentationUrl, expiredDate, showUpsellButton, onUpsellButtonClick, badges, showStaticHelpMenu, userName, theme, helpMenuDropdownAlignPoints: helpDropdownAlign, disableHelpDropdown, onHelpClick, helpRedirectUrl, showChatItem, isChatOpen, onChatItemClick, onLogoClick, onMenuItemClick, }) {
|
|
46
46
|
const intl = useIntl();
|
|
47
47
|
const [state, setState] = useState({
|
|
48
48
|
childrenWidth: 0,
|
|
@@ -345,7 +345,7 @@ export const AppHeader = withTheme(function AppHeader({ logoHref = "/", accountM
|
|
|
345
345
|
};
|
|
346
346
|
const renderStandardNav = () => {
|
|
347
347
|
return (_jsxs("div", { className: "gd-header-stretch gd-header-menu-wrapper", children: [
|
|
348
|
-
_jsx(HeaderMenu, { onMenuItemClick: onMenuItemClick, sections: menuItemsGroups, className: "gd-header-menu-horizontal" }), renderTrialItems(), showChatItem ? (_jsx(HeaderChatButton, { title: intl.formatMessage(messages.aiChat), onClick: onChatItemClick ?? (() => { }) })) : null, notificationsPanel
|
|
348
|
+
_jsx(HeaderMenu, { onMenuItemClick: onMenuItemClick, sections: menuItemsGroups, className: "gd-header-menu-horizontal" }), renderTrialItems(), showChatItem ? (_jsx(HeaderChatButton, { title: intl.formatMessage(messages.aiChat), isOpen: isChatOpen, onClick: onChatItemClick ?? (() => { }) })) : null, notificationsPanel
|
|
349
349
|
? notificationsPanel({
|
|
350
350
|
isMobile: false,
|
|
351
351
|
closeNotificationsOverlay: closeNotificationsMenu,
|
|
@@ -1,12 +1,20 @@
|
|
|
1
1
|
import { type MouseEvent } from "react";
|
|
2
2
|
type HeaderChatButtonProps = {
|
|
3
3
|
title?: string;
|
|
4
|
+
isOpen?: boolean;
|
|
4
5
|
onClick: (e: MouseEvent) => void;
|
|
5
6
|
};
|
|
6
7
|
/**
|
|
7
8
|
* @internal
|
|
8
9
|
*/
|
|
9
10
|
export declare const HEADER_CHAT_BUTTON_ID = "gd-header-chat-button";
|
|
10
|
-
|
|
11
|
+
/**
|
|
12
|
+
* Id of the assistant panel this button opens. Set on the chat dialog so the button can reference it
|
|
13
|
+
* through aria-controls.
|
|
14
|
+
*
|
|
15
|
+
* @internal
|
|
16
|
+
*/
|
|
17
|
+
export declare const HEADER_CHAT_PANEL_ID = "gd-header-chat-panel";
|
|
18
|
+
export declare function HeaderChatButton({ title, isOpen, onClick }: HeaderChatButtonProps): import("react/jsx-runtime").JSX.Element;
|
|
11
19
|
export {};
|
|
12
20
|
//# sourceMappingURL=HeaderChatButton.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"HeaderChatButton.d.ts","sourceRoot":"","sources":["../../src/Header/HeaderChatButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,OAAO,CAAC;AAOxC,KAAK,qBAAqB,GAAG;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;CACpC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,qBAAqB,
|
|
1
|
+
{"version":3,"file":"HeaderChatButton.d.ts","sourceRoot":"","sources":["../../src/Header/HeaderChatButton.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,OAAO,CAAC;AAOxC,KAAK,qBAAqB,GAAG;IACzB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,CAAC,CAAC,EAAE,UAAU,KAAK,IAAI,CAAC;CACpC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,qBAAqB,0BAA0B,CAAC;AAE7D;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,yBAAyB,CAAC;AAE3D,wBAAgB,gBAAgB,CAAC,EAAE,KAAK,EAAE,MAAc,EAAE,OAAO,EAAE,EAAE,qBAAqB,2CAoBzF"}
|
|
@@ -6,10 +6,21 @@ import { Button } from "../Button/Button.js";
|
|
|
6
6
|
* @internal
|
|
7
7
|
*/
|
|
8
8
|
export const HEADER_CHAT_BUTTON_ID = "gd-header-chat-button";
|
|
9
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Id of the assistant panel this button opens. Set on the chat dialog so the button can reference it
|
|
11
|
+
* through aria-controls.
|
|
12
|
+
*
|
|
13
|
+
* @internal
|
|
14
|
+
*/
|
|
15
|
+
export const HEADER_CHAT_PANEL_ID = "gd-header-chat-panel";
|
|
16
|
+
export function HeaderChatButton({ title, isOpen = false, onClick }) {
|
|
10
17
|
const classNames = cx("gd-header-measure", "gd-header-button", "gd-header-chat");
|
|
11
18
|
// The text is not l18n-ed because it is not final
|
|
12
19
|
return (_jsx(Button, { id: HEADER_CHAT_BUTTON_ID, title: title, className: classNames, onClick: onClick, accessibilityConfig: {
|
|
13
20
|
ariaLabel: title,
|
|
21
|
+
ariaHaspopup: "dialog",
|
|
22
|
+
ariaExpanded: isOpen,
|
|
23
|
+
// The panel is mounted only while open, so reference it only then.
|
|
24
|
+
ariaControls: isOpen ? HEADER_CHAT_PANEL_ID : undefined,
|
|
14
25
|
}, children: _jsx(UiIcon, { type: "genai", size: 16 }) }));
|
|
15
26
|
}
|
package/esm/Header/typings.d.ts
CHANGED
|
@@ -53,6 +53,11 @@ export interface IAppHeaderProps {
|
|
|
53
53
|
closeNotificationsOverlay: () => void;
|
|
54
54
|
}) => ReactNode;
|
|
55
55
|
showChatItem?: boolean;
|
|
56
|
+
/**
|
|
57
|
+
* Whether the assistant panel opened by the chat button is currently open. Keeps the button's
|
|
58
|
+
* aria-expanded and aria-controls in sync with the panel.
|
|
59
|
+
*/
|
|
60
|
+
isChatOpen?: boolean;
|
|
56
61
|
onChatItemClick?: (e: MouseEvent) => void;
|
|
57
62
|
}
|
|
58
63
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"typings.d.ts","sourceRoot":"","sources":["../../src/Header/typings.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"typings.d.ts","sourceRoot":"","sources":["../../src/Header/typings.ts"],"names":[],"mappings":"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"}
|
package/esm/Header/typings.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
// (C) 2021-
|
|
1
|
+
// (C) 2021-2026 GoodData Corporation
|
|
2
2
|
export {};
|
|
@@ -17,6 +17,10 @@ export interface ITimezoneSelectSpecialItem {
|
|
|
17
17
|
* Display label of the item.
|
|
18
18
|
*/
|
|
19
19
|
label: string;
|
|
20
|
+
/**
|
|
21
|
+
* Tooltip of the item.
|
|
22
|
+
*/
|
|
23
|
+
tooltip?: string;
|
|
20
24
|
}
|
|
21
25
|
/**
|
|
22
26
|
* Render props passed to a custom trigger renderer of {@link TimezoneSelect}.
|
|
@@ -83,6 +87,10 @@ export interface ITimezoneSelectProps {
|
|
|
83
87
|
* Optional content rendered above the search input (e.g. a dialog-like header).
|
|
84
88
|
*/
|
|
85
89
|
header?: ReactNode;
|
|
90
|
+
/**
|
|
91
|
+
* Whether to show tooltip for list items. Default is false.
|
|
92
|
+
*/
|
|
93
|
+
showTooltip?: boolean;
|
|
86
94
|
/**
|
|
87
95
|
* Custom renderer of the dropdown trigger. When not provided, a standard dropdown
|
|
88
96
|
* button showing the current selection is rendered.
|
|
@@ -95,7 +103,7 @@ export interface ITimezoneSelectProps {
|
|
|
95
103
|
renderButton?: (props: ITimezoneSelectButtonRenderProps) => ReactNode;
|
|
96
104
|
}
|
|
97
105
|
type TimezoneListItemData = string | undefined;
|
|
98
|
-
export declare function buildListboxItems(specialItems: ITimezoneSelectSpecialItem[], searchString: string): IUiListboxItem<TimezoneListItemData>[];
|
|
106
|
+
export declare function buildListboxItems(specialItems: ITimezoneSelectSpecialItem[], searchString: string, showTooltip: boolean): IUiListboxItem<TimezoneListItemData>[];
|
|
99
107
|
export declare function getSelectedItemId(value: string | undefined, specialItems: ITimezoneSelectSpecialItem[]): string | undefined;
|
|
100
108
|
/**
|
|
101
109
|
* Searchable dropdown for picking a timezone from the curated list, with optional special
|
|
@@ -103,6 +111,6 @@ export declare function getSelectedItemId(value: string | undefined, specialItem
|
|
|
103
111
|
*
|
|
104
112
|
* @internal
|
|
105
113
|
*/
|
|
106
|
-
export declare function TimezoneSelect({ value, onChange, specialItems, placeholder, searchPlaceholder, ariaLabel, noMatchLabel, isDisabled, header, renderButton }: ITimezoneSelectProps): ReactElement;
|
|
114
|
+
export declare function TimezoneSelect({ value, onChange, specialItems, placeholder, searchPlaceholder, ariaLabel, noMatchLabel, isDisabled, header, showTooltip, renderButton }: ITimezoneSelectProps): ReactElement;
|
|
107
115
|
export {};
|
|
108
116
|
//# sourceMappingURL=TimezoneSelect.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"TimezoneSelect.d.ts","sourceRoot":"","sources":["../../src/Timezone/TimezoneSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAC;AAE7E,OAAO,EAAkC,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEhG,OAAO,EAAY,KAAK,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAapF;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IACvC;;;OAGG;IACH,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC;IAEvB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"TimezoneSelect.d.ts","sourceRoot":"","sources":["../../src/Timezone/TimezoneSelect.tsx"],"names":[],"mappings":"AAEA,OAAO,EAAE,KAAK,YAAY,EAAE,KAAK,SAAS,EAAqB,MAAM,OAAO,CAAC;AAE7E,OAAO,EAAkC,KAAK,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAEhG,OAAO,EAAY,KAAK,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAapF;;;;;GAKG;AACH,MAAM,WAAW,0BAA0B;IACvC;;;OAGG;IACH,EAAE,EAAE,MAAM,GAAG,SAAS,CAAC;IAEvB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IAEd;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,MAAM,WAAW,gCAAiC,SAAQ,0BAA0B;IAChF;;;;OAIG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IAE1B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACxB;AAED;;;;;GAKG;AACH,MAAM,WAAW,oBAAoB;IACjC;;OAEG;IACH,KAAK,CAAC,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,QAAQ,EAAE,CAAC,EAAE,EAAE,MAAM,GAAG,SAAS,KAAK,IAAI,CAAC;IAE3C;;OAEG;IACH,YAAY,CAAC,EAAE,0BAA0B,EAAE,CAAC;IAE5C;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB;;OAEG;IACH,iBAAiB,EAAE,MAAM,CAAC;IAE1B;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,YAAY,EAAE,MAAM,CAAC;IAErB,UAAU,CAAC,EAAE,OAAO,CAAC;IAErB;;OAEG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IAEnB;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC;IAEtB;;;;;;;;OAQG;IACH,YAAY,CAAC,EAAE,CAAC,KAAK,EAAE,gCAAgC,KAAK,SAAS,CAAC;CACzE;AAED,KAAK,oBAAoB,GAAG,MAAM,GAAG,SAAS,CAAC;AAM/C,wBAAgB,iBAAiB,CAC7B,YAAY,EAAE,0BAA0B,EAAE,EAC1C,YAAY,EAAE,MAAM,EACpB,WAAW,EAAE,OAAO,GACrB,cAAc,CAAC,oBAAoB,CAAC,EAAE,CAqCxC;AAGD,wBAAgB,iBAAiB,CAC7B,KAAK,EAAE,MAAM,GAAG,SAAS,EACzB,YAAY,EAAE,0BAA0B,EAAE,GAC3C,MAAM,GAAG,SAAS,CAMpB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,EAC3B,KAAK,EACL,QAAQ,EACR,YAAiB,EACjB,WAAgB,EAChB,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,UAAU,EACV,MAAM,EACN,WAAmB,EACnB,YAAY,EACf,EAAE,oBAAoB,GAAG,YAAY,CAiGrC"}
|
|
@@ -14,7 +14,7 @@ const LIST_MAX_HEIGHT = 280;
|
|
|
14
14
|
// special items may carry an undefined id, so listbox entries need a synthetic unique id
|
|
15
15
|
const SPECIAL_ITEM_ID_PREFIX = "special-item-";
|
|
16
16
|
// exported for tests
|
|
17
|
-
export function buildListboxItems(specialItems, searchString) {
|
|
17
|
+
export function buildListboxItems(specialItems, searchString, showTooltip) {
|
|
18
18
|
const search = searchString.trim().toLowerCase();
|
|
19
19
|
const specialListItems = specialItems
|
|
20
20
|
// keep the pre-filter index — getSelectedItemId derives the selected id from the
|
|
@@ -25,6 +25,7 @@ export function buildListboxItems(specialItems, searchString) {
|
|
|
25
25
|
type: "interactive",
|
|
26
26
|
id: `${SPECIAL_ITEM_ID_PREFIX}${index}`,
|
|
27
27
|
stringTitle: item.label,
|
|
28
|
+
tooltip: showTooltip ? item.tooltip : undefined,
|
|
28
29
|
data: item.id,
|
|
29
30
|
}));
|
|
30
31
|
const timezoneListItems = getTimezones()
|
|
@@ -62,7 +63,7 @@ export function getSelectedItemId(value, specialItems) {
|
|
|
62
63
|
*
|
|
63
64
|
* @internal
|
|
64
65
|
*/
|
|
65
|
-
export function TimezoneSelect({ value, onChange, specialItems = [], placeholder = "", searchPlaceholder, ariaLabel, noMatchLabel, isDisabled, header, renderButton, }) {
|
|
66
|
+
export function TimezoneSelect({ value, onChange, specialItems = [], placeholder = "", searchPlaceholder, ariaLabel, noMatchLabel, isDisabled, header, showTooltip = false, renderButton, }) {
|
|
66
67
|
const [searchString, setSearchString] = useState("");
|
|
67
68
|
const selectedSpecialItem = specialItems.find((item) => item.id === value);
|
|
68
69
|
const buttonLabel = selectedSpecialItem
|
|
@@ -70,7 +71,7 @@ export function TimezoneSelect({ value, onChange, specialItems = [], placeholder
|
|
|
70
71
|
: value === undefined
|
|
71
72
|
? placeholder
|
|
72
73
|
: getTimezoneDisplayLabel(value);
|
|
73
|
-
const items = useMemo(() => buildListboxItems(specialItems, searchString), [specialItems, searchString]);
|
|
74
|
+
const items = useMemo(() => buildListboxItems(specialItems, searchString, showTooltip), [specialItems, searchString, showTooltip]);
|
|
74
75
|
const hasNoMatchingData = items.length === 0;
|
|
75
76
|
return (_jsx(Dropdown, { closeOnParentScroll: true, closeOnOutsideClick: true, alignPoints: DROPDOWN_ALIGN_POINTS, className: "gd-timezone-select s-timezone-select", onOpenStateChanged: (isOpen) => {
|
|
76
77
|
if (!isOpen) {
|
package/esm/index.d.ts
CHANGED
|
@@ -89,7 +89,7 @@ export { HEADER_ITEM_ID_DASHBOARDS, HEADER_ITEM_ID_REPORTS, HEADER_ITEM_ID_KPIS_
|
|
|
89
89
|
export { activateHeaderMenuItems } from "./Header/activateHeaderMenuItems.js";
|
|
90
90
|
export type { IHeaderMenuItem, IAppHeaderProps, IAppHeaderState, IHeaderAccountProps, IHeaderAccountState, IHeaderMenuProps, IHeaderUpsellButtonProps, TUTMContent, } from "./Header/typings.js";
|
|
91
91
|
export { type HeaderSearchContext, HeaderSearchProvider, useHeaderSearch, } from "./Header/headerSearchContext.js";
|
|
92
|
-
export { HEADER_CHAT_BUTTON_ID } from "./Header/HeaderChatButton.js";
|
|
92
|
+
export { HEADER_CHAT_BUTTON_ID, HEADER_CHAT_PANEL_ID } from "./Header/HeaderChatButton.js";
|
|
93
93
|
export type { MessageType, FormatMessageParams, IMessageDefinition, IMessage, IMessageProps, } from "./Messages/typings.js";
|
|
94
94
|
export { Message } from "./Messages/Message.js";
|
|
95
95
|
export { useToastMessage, type IUseToastMessageType, type AddMessageType, type MessageParameters, } from "./Messages/toasts/useToastMessage.js";
|