@itwin/presentation-hierarchies-react 2.0.0-alpha.47 → 2.0.0-alpha.49

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.
Files changed (45) hide show
  1. package/CHANGELOG.md +126 -0
  2. package/README.md +2 -40
  3. package/lib/esm/presentation-hierarchies-react/Utils.d.ts +4 -1
  4. package/lib/esm/presentation-hierarchies-react/Utils.d.ts.map +1 -1
  5. package/lib/esm/presentation-hierarchies-react/Utils.js +16 -0
  6. package/lib/esm/presentation-hierarchies-react/Utils.js.map +1 -1
  7. package/lib/esm/presentation-hierarchies-react/stratakit/FlatTreeNode.d.ts +2 -0
  8. package/lib/esm/presentation-hierarchies-react/stratakit/FlatTreeNode.d.ts.map +1 -1
  9. package/lib/esm/presentation-hierarchies-react/stratakit/FlatTreeNode.js +15 -0
  10. package/lib/esm/presentation-hierarchies-react/stratakit/FlatTreeNode.js.map +1 -1
  11. package/lib/esm/presentation-hierarchies-react/stratakit/LocalizationContext.d.ts +10 -0
  12. package/lib/esm/presentation-hierarchies-react/stratakit/LocalizationContext.d.ts.map +1 -1
  13. package/lib/esm/presentation-hierarchies-react/stratakit/LocalizationContext.js +2 -0
  14. package/lib/esm/presentation-hierarchies-react/stratakit/LocalizationContext.js.map +1 -1
  15. package/lib/esm/presentation-hierarchies-react/stratakit/TreeErrorRenderer.d.ts.map +1 -1
  16. package/lib/esm/presentation-hierarchies-react/stratakit/TreeErrorRenderer.js +6 -1
  17. package/lib/esm/presentation-hierarchies-react/stratakit/TreeErrorRenderer.js.map +1 -1
  18. package/lib/esm/presentation-hierarchies-react/stratakit/{FilterAction.d.ts → TreeNodeFilterAction.d.ts} +8 -7
  19. package/lib/esm/presentation-hierarchies-react/stratakit/TreeNodeFilterAction.d.ts.map +1 -0
  20. package/lib/esm/presentation-hierarchies-react/stratakit/{FilterAction.js → TreeNodeFilterAction.js} +8 -2
  21. package/lib/esm/presentation-hierarchies-react/stratakit/TreeNodeFilterAction.js.map +1 -0
  22. package/lib/esm/presentation-hierarchies-react/stratakit/TreeNodeRenameAction.d.ts +57 -0
  23. package/lib/esm/presentation-hierarchies-react/stratakit/TreeNodeRenameAction.d.ts.map +1 -0
  24. package/lib/esm/presentation-hierarchies-react/stratakit/TreeNodeRenameAction.js +71 -0
  25. package/lib/esm/presentation-hierarchies-react/stratakit/TreeNodeRenameAction.js.map +1 -0
  26. package/lib/esm/presentation-hierarchies-react/stratakit/TreeNodeRenderer.css +25 -0
  27. package/lib/esm/presentation-hierarchies-react/stratakit/TreeNodeRenderer.d.ts +24 -34
  28. package/lib/esm/presentation-hierarchies-react/stratakit/TreeNodeRenderer.d.ts.map +1 -1
  29. package/lib/esm/presentation-hierarchies-react/stratakit/TreeNodeRenderer.js +69 -87
  30. package/lib/esm/presentation-hierarchies-react/stratakit/TreeNodeRenderer.js.map +1 -1
  31. package/lib/esm/presentation-hierarchies-react/stratakit/TreeRenderer.d.ts +21 -16
  32. package/lib/esm/presentation-hierarchies-react/stratakit/TreeRenderer.d.ts.map +1 -1
  33. package/lib/esm/presentation-hierarchies-react/stratakit/TreeRenderer.js +91 -32
  34. package/lib/esm/presentation-hierarchies-react/stratakit/TreeRenderer.js.map +1 -1
  35. package/lib/esm/presentation-hierarchies-react.d.ts +3 -4
  36. package/lib/esm/presentation-hierarchies-react.d.ts.map +1 -1
  37. package/lib/esm/presentation-hierarchies-react.js +2 -3
  38. package/lib/esm/presentation-hierarchies-react.js.map +1 -1
  39. package/package.json +9 -9
  40. package/lib/esm/presentation-hierarchies-react/stratakit/FilterAction.d.ts.map +0 -1
  41. package/lib/esm/presentation-hierarchies-react/stratakit/FilterAction.js.map +0 -1
  42. package/lib/esm/presentation-hierarchies-react/stratakit/RenameAction.d.ts +0 -21
  43. package/lib/esm/presentation-hierarchies-react/stratakit/RenameAction.d.ts.map +0 -1
  44. package/lib/esm/presentation-hierarchies-react/stratakit/RenameAction.js +0 -36
  45. package/lib/esm/presentation-hierarchies-react/stratakit/RenameAction.js.map +0 -1
@@ -0,0 +1,71 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ /*---------------------------------------------------------------------------------------------
3
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
+ * See LICENSE.md in the project root for license terms and full copyright notice.
5
+ *--------------------------------------------------------------------------------------------*/
6
+ import { createContext, memo, useCallback, useContext, useMemo, useState } from "react";
7
+ import renameSvg from "@stratakit/icons/rename.svg";
8
+ import { useLocalizationContext } from "./LocalizationContext.js";
9
+ import { TreeActionBase } from "./TreeAction.js";
10
+ /**
11
+ * React component that renders a rename action for a tree item.
12
+ *
13
+ * The tree component must have `getEditingProps.onLabelChanged` prop set to enable renaming functionality. When
14
+ * rename is completed, the `onLabelChanged` function is called to make the actual data update.
15
+ *
16
+ * @see `getMenuActions`, `getInlineActions`, `getContextMenuActions` props of `TreeRenderer` to add this action
17
+ * to tree items.
18
+ *
19
+ * @alpha
20
+ */
21
+ export const TreeNodeRenameAction = memo(function TreeNodeRenameAction({ node, ...actionAttributes }) {
22
+ const { localizedStrings } = useLocalizationContext();
23
+ const context = useTreeNodeRenameContext();
24
+ const { rename } = localizedStrings;
25
+ const canRename = context?.canRename(node) ?? false;
26
+ const startRename = context?.startRename;
27
+ const handleClick = useCallback(() => {
28
+ startRename?.(node);
29
+ }, [startRename, node]);
30
+ return _jsx(TreeActionBase, { ...actionAttributes, label: rename, onClick: handleClick, icon: renameSvg, hide: !canRename });
31
+ });
32
+ const treeNodeRenameContext = createContext(undefined);
33
+ /** @internal */
34
+ export const useTreeNodeRenameContext = () => {
35
+ return useContext(treeNodeRenameContext);
36
+ };
37
+ /** @internal */
38
+ export function TreeNodeRenameContextProvider({ value, children }) {
39
+ return _jsx(treeNodeRenameContext.Provider, { value: value, children: children });
40
+ }
41
+ /** @internal */
42
+ export function useTreeNodeRenameContextValue({ getEditingProps, }) {
43
+ const [renameParameters, setRenameParameters] = useState(undefined);
44
+ const startRename = useCallback((node) => {
45
+ const { onLabelChanged, labelValidationHint, validate } = getEditingProps?.(node) ?? {};
46
+ if (onLabelChanged) {
47
+ setRenameParameters({
48
+ nodeId: node.id,
49
+ commit: (newLabel) => {
50
+ onLabelChanged(newLabel);
51
+ setRenameParameters(undefined);
52
+ },
53
+ labelValidationHint,
54
+ validate,
55
+ });
56
+ }
57
+ }, [getEditingProps]);
58
+ const cancelRename = useCallback(() => {
59
+ setRenameParameters(undefined);
60
+ }, []);
61
+ const canRename = useCallback((node) => {
62
+ return getEditingProps?.(node)?.onLabelChanged !== undefined;
63
+ }, [getEditingProps]);
64
+ return useMemo(() => ({
65
+ renameParameters,
66
+ cancelRename,
67
+ startRename,
68
+ canRename,
69
+ }), [renameParameters, canRename, startRename, cancelRename]);
70
+ }
71
+ //# sourceMappingURL=TreeNodeRenameAction.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"TreeNodeRenameAction.js","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/stratakit/TreeNodeRenameAction.tsx"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport { createContext, memo, PropsWithChildren, useCallback, useContext, useMemo, useState } from \"react\";\nimport renameSvg from \"@stratakit/icons/rename.svg\";\nimport { PresentationHierarchyNode } from \"../TreeNode.js\";\nimport { useLocalizationContext } from \"./LocalizationContext.js\";\nimport { TreeActionBase, TreeActionBaseAttributes } from \"./TreeAction.js\";\n\n/**\n * React component that renders a rename action for a tree item.\n *\n * The tree component must have `getEditingProps.onLabelChanged` prop set to enable renaming functionality. When\n * rename is completed, the `onLabelChanged` function is called to make the actual data update.\n *\n * @see `getMenuActions`, `getInlineActions`, `getContextMenuActions` props of `TreeRenderer` to add this action\n * to tree items.\n *\n * @alpha\n */\nexport const TreeNodeRenameAction = memo(function TreeNodeRenameAction({\n node,\n ...actionAttributes\n}: TreeActionBaseAttributes & { node: PresentationHierarchyNode }) {\n const { localizedStrings } = useLocalizationContext();\n const context = useTreeNodeRenameContext();\n const { rename } = localizedStrings;\n\n const canRename = context?.canRename(node) ?? false;\n const startRename = context?.startRename;\n const handleClick = useCallback(() => {\n startRename?.(node);\n }, [startRename, node]);\n\n return <TreeActionBase {...actionAttributes} label={rename} onClick={handleClick} icon={renameSvg} hide={!canRename} />;\n});\n\n/** @alpha */\nexport interface TreeNodeEditingProps {\n /**\n * A callback that is invoked when node label is changed. Should be used together\n * with `<TreeNodeRenameAction />` to enter label editing mode.\n */\n onLabelChanged: (newLabel: string) => void;\n labelValidationHint?: string;\n validate?: (newLabel: string) => boolean;\n}\n\n/** @internal */\nexport interface RenameParameters {\n nodeId: string;\n commit: (newLabel: string) => void;\n labelValidationHint?: string;\n validate?: (newLabel: string) => boolean;\n}\n\ninterface TreeNodeRenameContext {\n renameParameters?: RenameParameters;\n startRename: (node: PresentationHierarchyNode) => void;\n canRename: (node: PresentationHierarchyNode) => boolean;\n cancelRename: () => void;\n}\n\nconst treeNodeRenameContext = createContext<TreeNodeRenameContext | undefined>(undefined);\n\n/** @internal */\nexport const useTreeNodeRenameContext = () => {\n return useContext(treeNodeRenameContext);\n};\n\n/** @internal */\nexport function TreeNodeRenameContextProvider({ value, children }: PropsWithChildren<{ value: TreeNodeRenameContext }>) {\n return <treeNodeRenameContext.Provider value={value}>{children}</treeNodeRenameContext.Provider>;\n}\n\n/** @internal */\nexport function useTreeNodeRenameContextValue({\n getEditingProps,\n}: {\n getEditingProps?: (node: PresentationHierarchyNode) => TreeNodeEditingProps | undefined;\n}) {\n const [renameParameters, setRenameParameters] = useState<RenameParameters | undefined>(undefined);\n\n const startRename = useCallback(\n (node: PresentationHierarchyNode) => {\n const { onLabelChanged, labelValidationHint, validate } = getEditingProps?.(node) ?? {};\n if (onLabelChanged) {\n setRenameParameters({\n nodeId: node.id,\n commit: (newLabel) => {\n onLabelChanged(newLabel);\n setRenameParameters(undefined);\n },\n labelValidationHint,\n validate,\n });\n }\n },\n [getEditingProps],\n );\n\n const cancelRename = useCallback(() => {\n setRenameParameters(undefined);\n }, []);\n\n const canRename = useCallback(\n (node: PresentationHierarchyNode) => {\n return getEditingProps?.(node)?.onLabelChanged !== undefined;\n },\n [getEditingProps],\n );\n\n return useMemo(\n () => ({\n renameParameters,\n cancelRename,\n startRename,\n canRename,\n }),\n [renameParameters, canRename, startRename, cancelRename],\n );\n}\n"]}
@@ -0,0 +1,25 @@
1
+ /*---------------------------------------------------------------------------------------------
2
+ * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
3
+ * See LICENSE.md in the project root for license terms and full copyright notice.
4
+ *--------------------------------------------------------------------------------------------*/
5
+
6
+ .phr-node-label-editor {
7
+ padding: var(--stratakit-space-x1);
8
+ width: 300px;
9
+ display: grid;
10
+ gap: var(--stratakit-space-x1);
11
+ grid-template-rows: auto auto;
12
+
13
+ .phr-node-label-editor-input-row {
14
+ display: grid;
15
+ gap: var(--stratakit-space-x1);
16
+ grid-template-columns: 1fr auto auto;
17
+
18
+ .with-error {
19
+ outline-color: var(--stratakit-color-border-critical-base);
20
+ &::before {
21
+ border-color: var(--stratakit-color-border-critical-base);
22
+ }
23
+ }
24
+ }
25
+ }
@@ -1,56 +1,46 @@
1
- import { ComponentPropsWithoutRef, FC, PropsWithRef, ReactElement, ReactNode, RefAttributes } from "react";
1
+ import "./TreeNodeRenderer.css";
2
+ import { ComponentPropsWithoutRef, FC, PropsWithRef, ReactNode, RefAttributes } from "react";
2
3
  import { Tree } from "@stratakit/structures";
3
4
  import { TreeRendererProps } from "../Renderers.js";
4
5
  import { PresentationHierarchyNode } from "../TreeNode.js";
5
- /** @alpha */
6
- type TreeNodeProps = ComponentPropsWithoutRef<typeof Tree.Item>;
7
- /** @alpha */
8
- export interface TreeNodeRendererOwnProps {
6
+ /** @internal */
7
+ interface TreeNodeRendererOwnProps extends Pick<TreeRendererProps, "expandNode" | "reloadTree"> {
9
8
  /** Node that is rendered. */
10
9
  node: PresentationHierarchyNode;
11
- /** Returns the class name for a given node. */
12
- getClassName?: (node: PresentationHierarchyNode) => string | undefined;
13
- /** Returns a label for a given node. */
14
- getLabel?: (node: PresentationHierarchyNode) => ReactElement | undefined;
15
- /** Returns sublabel for a given node. */
16
- getSublabel?: (node: PresentationHierarchyNode) => ReactElement | undefined;
17
- /** Action to perform when the node is clicked. */
18
- onNodeClick?: (node: PresentationHierarchyNode, isSelected: boolean, event: React.MouseEvent<HTMLElement>) => void;
19
- /** Action to perform when a key is pressed when the node is hovered on. */
20
- onNodeKeyDown?: (node: PresentationHierarchyNode, isSelected: boolean, event: React.KeyboardEvent<HTMLElement>) => void;
21
- /**
22
- * Used to render elements between expander and label.
23
- * E.g. icons, color picker, etc.
24
- */
25
- getDecorations?: (node: PresentationHierarchyNode) => ReactNode;
26
10
  /**
27
- * Callback that returns menu actions for tree item.
28
- * Must return an array of `<TreeActionBase />` or `<Divider />` elements.
11
+ * Menu actions for tree item.
12
+ * Must be an array of `<TreeActionBase />` or `<Divider />` elements.
29
13
  */
30
- getMenuActions?: (node: PresentationHierarchyNode) => ReactNode[];
14
+ menuActions?: ReactNode[];
31
15
  /**
32
- * Callback that returns inline actions for tree item.
33
- * Must return an array of `<TreeActionBase />` elements.
16
+ * Inline actions for tree item.
17
+ * Must be an array of `<TreeActionBase />` elements.
34
18
  * Max 2 items.
35
19
  */
36
- getInlineActions?: (node: PresentationHierarchyNode) => ReactNode[];
20
+ inlineActions?: ReactNode[];
37
21
  /**
38
- * Callback that returns actions for tree item context menu.
39
- * Must return an array of `<TreeActionBase />` or `<Divider />` elements.
22
+ * Context menu actions for tree item.
23
+ * Must be an array of `<TreeActionBase />` or `<Divider />` elements.
40
24
  */
41
- getContextMenuActions?: (node: PresentationHierarchyNode) => ReactNode[];
25
+ contextMenuActions?: ReactNode[];
42
26
  }
43
27
  /** @alpha */
44
- type TreeNodeRendererProps = Pick<TreeRendererProps, "expandNode" | "reloadTree"> & Omit<TreeNodeProps, "actions" | "label" | "expanded" | "unstable_decorations" | "error"> & TreeNodeRendererOwnProps;
28
+ export type StrataKitTreeItemProps = Omit<ComponentPropsWithoutRef<typeof Tree.Item>, "actions" | "inlineActions" | "expanded" | "onExpandedChange" | "icon" | "unstable_decorations" | "error"> & {
29
+ /**
30
+ * Used to render elements between expander and label.
31
+ * E.g. icons, color picker, etc.
32
+ */
33
+ decorations?: ReactNode;
34
+ };
35
+ /** @internal */
36
+ export type TreeNodeRendererProps = StrataKitTreeItemProps & TreeNodeRendererOwnProps;
45
37
  /**
46
38
  * A component that renders given `FlatTreeNode` using the `Tree.Item` component from `@itwin/itwinui-react`. The
47
39
  * `FlatTreeNode` objects for this renderer are generally created using the `useFlatTreeNodeList` hook.
48
40
  *
49
- * @see `TreeRenderer`
50
- * @see https://itwinui.bentley.com/docs/tree
51
- * @public
41
+ * @internal
52
42
  */
53
43
  export declare const StrataKitTreeNodeRenderer: FC<PropsWithRef<TreeNodeRendererProps & RefAttributes<HTMLElement>>>;
54
- export declare const PlaceholderNode: FC<PropsWithRef<Omit<TreeNodeProps, "onExpanded" | "label" | "actions" | "icon" | "error"> & RefAttributes<HTMLElement>>>;
44
+ export declare const PlaceholderNode: FC<PropsWithRef<Pick<StrataKitTreeItemProps, "style" | "aria-level" | "aria-posinset" | "aria-setsize"> & RefAttributes<HTMLElement>>>;
55
45
  export {};
56
46
  //# sourceMappingURL=TreeNodeRenderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TreeNodeRenderer.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/stratakit/TreeNodeRenderer.tsx"],"names":[],"mappings":"AAKA,OAAO,EAEL,wBAAwB,EACxB,EAAE,EAMF,YAAY,EACZ,YAAY,EACZ,SAAS,EAET,aAAa,EAMd,MAAM,OAAO,CAAC;AAGf,OAAO,EAAgB,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAK3D,aAAa;AACb,KAAK,aAAa,GAAG,wBAAwB,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC;AAEhE,aAAa;AACb,MAAM,WAAW,wBAAwB;IACvC,6BAA6B;IAC7B,IAAI,EAAE,yBAAyB,CAAC;IAChC,+CAA+C;IAC/C,YAAY,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,MAAM,GAAG,SAAS,CAAC;IACvE,wCAAwC;IACxC,QAAQ,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,YAAY,GAAG,SAAS,CAAC;IACzE,yCAAyC;IACzC,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,YAAY,GAAG,SAAS,CAAC;IAC5E,kDAAkD;IAClD,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,UAAU,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACnH,2EAA2E;IAC3E,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,EAAE,UAAU,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,CAAC,aAAa,CAAC,WAAW,CAAC,KAAK,IAAI,CAAC;IACxH;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,SAAS,CAAC;IAChE;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,SAAS,EAAE,CAAC;IAClE;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,SAAS,EAAE,CAAC;IACpE;;;OAGG;IACH,qBAAqB,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,SAAS,EAAE,CAAC;CAC1E;AAED,aAAa;AACb,KAAK,qBAAqB,GAAG,IAAI,CAAC,iBAAiB,EAAE,YAAY,GAAG,YAAY,CAAC,GAC/E,IAAI,CAAC,aAAa,EAAE,SAAS,GAAG,OAAO,GAAG,UAAU,GAAG,sBAAsB,GAAG,OAAO,CAAC,GACxF,wBAAwB,CAAC;AAE3B;;;;;;;GAOG;AACH,eAAO,MAAM,yBAAyB,EAAE,EAAE,CAAC,YAAY,CAAC,qBAAqB,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC,CAsK1G,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,EAAE,CAAC,YAAY,CAAC,IAAI,CAAC,aAAa,EAAE,YAAY,GAAG,OAAO,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,CAAC,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC,CAKrJ,CAAC"}
1
+ {"version":3,"file":"TreeNodeRenderer.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/stratakit/TreeNodeRenderer.tsx"],"names":[],"mappings":"AAKA,OAAO,wBAAwB,CAAC;AAEhC,OAAO,EAEL,wBAAwB,EACxB,EAAE,EAIF,YAAY,EACZ,SAAS,EACT,aAAa,EAOd,MAAM,OAAO,CAAC;AAKf,OAAO,EAA6C,IAAI,EAAE,MAAM,uBAAuB,CAAC;AACxF,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAK3D,gBAAgB;AAChB,UAAU,wBAAyB,SAAQ,IAAI,CAAC,iBAAiB,EAAE,YAAY,GAAG,YAAY,CAAC;IAC7F,6BAA6B;IAC7B,IAAI,EAAE,yBAAyB,CAAC;IAChC;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,EAAE,CAAC;IAC1B;;;;OAIG;IACH,aAAa,CAAC,EAAE,SAAS,EAAE,CAAC;IAC5B;;;OAGG;IACH,kBAAkB,CAAC,EAAE,SAAS,EAAE,CAAC;CAClC;AAED,aAAa;AACb,MAAM,MAAM,sBAAsB,GAAG,IAAI,CACvC,wBAAwB,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,EAC1C,SAAS,GAAG,eAAe,GAAG,UAAU,GAAG,kBAAkB,GAAG,MAAM,GAAG,sBAAsB,GAAG,OAAO,CAC1G,GAAG;IACF;;;OAGG;IACH,WAAW,CAAC,EAAE,SAAS,CAAC;CACzB,CAAC;AAEF,gBAAgB;AAChB,MAAM,MAAM,qBAAqB,GAAG,sBAAsB,GAAG,wBAAwB,CAAC;AAEtF;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,EAAE,EAAE,CAAC,YAAY,CAAC,qBAAqB,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC,CA2H1G,CAAC;AAEF,eAAO,MAAM,eAAe,EAAE,EAAE,CAC9B,YAAY,CAAC,IAAI,CAAC,sBAAsB,EAAE,OAAO,GAAG,YAAY,GAAG,eAAe,GAAG,cAAc,CAAC,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC,CAgBnI,CAAC"}
@@ -3,48 +3,45 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
3
3
  * Copyright (c) Bentley Systems, Incorporated. All rights reserved.
4
4
  * See LICENSE.md in the project root for license terms and full copyright notice.
5
5
  *--------------------------------------------------------------------------------------------*/
6
- import { cloneElement, forwardRef, isValidElement, memo, useCallback, useEffect, useMemo, useRef, useState, } from "react";
7
- import { Spinner, TextBox } from "@stratakit/bricks";
6
+ import "./TreeNodeRenderer.css";
7
+ import { cloneElement, forwardRef, isValidElement, memo, useCallback, useEffect, useId, useMemo, useRef, useState, } from "react";
8
+ import { Description, IconButton, Spinner, Text, TextBox } from "@stratakit/bricks";
9
+ import checkmarkSvg from "@stratakit/icons/checkmark.svg";
10
+ import dismissSvg from "@stratakit/icons/dismiss.svg";
8
11
  import refreshSvg from "@stratakit/icons/refresh.svg";
9
- import { DropdownMenu, Tree } from "@stratakit/structures";
12
+ import { DropdownMenu, unstable_Popover as Popover, Tree } from "@stratakit/structures";
10
13
  import { useLocalizationContext } from "./LocalizationContext.js";
11
- import { useRenameContext } from "./RenameAction.js";
12
14
  import { TreeActionBase } from "./TreeAction.js";
15
+ import { useTreeNodeRenameContext } from "./TreeNodeRenameAction.js";
13
16
  /**
14
17
  * A component that renders given `FlatTreeNode` using the `Tree.Item` component from `@itwin/itwinui-react`. The
15
18
  * `FlatTreeNode` objects for this renderer are generally created using the `useFlatTreeNodeList` hook.
16
19
  *
17
- * @see `TreeRenderer`
18
- * @see https://itwinui.bentley.com/docs/tree
19
- * @public
20
+ * @internal
20
21
  */
21
- export const StrataKitTreeNodeRenderer = memo(forwardRef(function HierarchyNode({ node, selected, expandNode, onNodeClick, onNodeKeyDown, reloadTree, getClassName, getLabel, getSublabel, getMenuActions, getInlineActions, getDecorations, getContextMenuActions, ...treeItemProps }, forwardedRef) {
22
- const nodeRef = useRef(null);
23
- const ref = useMergedRefs(forwardedRef, nodeRef);
22
+ export const StrataKitTreeNodeRenderer = memo(forwardRef(function HierarchyNode(props, forwardedRef) {
23
+ const { node, decorations, inlineActions, menuActions, contextMenuActions, expandNode, reloadTree, ...treeItemProps } = props;
24
24
  const { localizedStrings } = useLocalizationContext();
25
- const renameContext = useRenameContext();
25
+ const renameContext = useTreeNodeRenameContext();
26
26
  const [contextMenuProps, setContextMenuProps] = useState(undefined);
27
- const className = useMemo(() => getClassName?.(node), [getClassName, node]);
28
- const label = useMemo(() => (getLabel ? getLabel(node) : node.label), [getLabel, node]);
29
- const description = useMemo(() => (getSublabel ? getSublabel(node) : undefined), [getSublabel, node]);
30
- const decorations = useMemo(() => getDecorations?.(node), [getDecorations, node]);
31
- const inlineActions = useMemo(() => {
27
+ const label = treeItemProps.label ?? node.label;
28
+ const inlineActionItems = useMemo(() => {
32
29
  if (node.error !== undefined && node.error.type === "ChildrenLoad") {
33
30
  return [
34
31
  _jsx(TreeActionBase, { label: localizedStrings.retry, onClick: () => reloadTree({ parentNodeId: node.id, state: "reset" }), visible: true, icon: refreshSvg, variant: "inline" }, "retry"),
35
32
  ];
36
33
  }
37
- if (!getInlineActions) {
38
- return [];
34
+ if (!inlineActions) {
35
+ return undefined;
39
36
  }
40
- return injectActionVariant(getInlineActions(node), "inline");
41
- }, [node, getInlineActions, localizedStrings.retry, reloadTree]);
42
- const menuItems = useMemo(() => {
43
- if (!getMenuActions) {
37
+ return injectActionVariant(inlineActions, "inline");
38
+ }, [node, inlineActions, localizedStrings.retry, reloadTree]);
39
+ const menuActionItems = useMemo(() => {
40
+ if (!menuActions) {
44
41
  return undefined;
45
42
  }
46
- return injectActionVariant(getMenuActions(node), "default");
47
- }, [getMenuActions, node]);
43
+ return injectActionVariant(menuActions, "default");
44
+ }, [menuActions]);
48
45
  const expanded = useMemo(() => {
49
46
  if (node.error) {
50
47
  return undefined;
@@ -54,43 +51,30 @@ export const StrataKitTreeNodeRenderer = memo(forwardRef(function HierarchyNode(
54
51
  }
55
52
  return undefined;
56
53
  }, [node.children, node.error, node.isExpanded]);
57
- const isDisabled = treeItemProps["aria-disabled"] === true;
58
- const { onLabelChanged, setIsRenaming, isRenaming } = renameContext ?? {};
59
- const labelEditor = isRenaming ? (_jsx(LabelEditor, { initialLabel: node.label, onChange: (newLabel) => {
60
- onLabelChanged?.(newLabel);
61
- setIsRenaming?.(false);
62
- }, onCancel: () => {
63
- setIsRenaming?.(false);
64
- } })) : undefined;
65
- return (_jsxs(_Fragment, { children: [_jsx(Tree.Item, { ...treeItemProps, ref: ref, className: className, label: labelEditor ?? label, description: description, selected: selected, expanded: expanded, onExpandedChange: useCallback((isExpanded) => {
66
- expandNode(node.id, isExpanded);
67
- }, [node, expandNode]), onClick: useCallback((event) => {
68
- if (isDisabled) {
69
- return;
70
- }
71
- onNodeClick?.(node, !selected, event);
72
- }, [node, isDisabled, selected, onNodeClick]), onKeyDown: useCallback((event) => {
73
- // Ignore if it is called on the element inside, e.g. checkbox or expander
74
- if (!isDisabled && event.target === nodeRef.current) {
75
- onNodeKeyDown?.(node, !selected, event);
76
- }
77
- }, [onNodeKeyDown, selected, isDisabled, node]), inlineActions: inlineActions, actions: menuItems, unstable_decorations: decorations, error: node.error ? node.error.id : undefined, onContextMenu: (e) => {
78
- if (!getContextMenuActions) {
79
- return;
80
- }
81
- e.preventDefault();
82
- const contextMenuActions = injectActionVariant(getContextMenuActions(node), "context-menu");
83
- if (contextMenuActions.length === 0) {
84
- return;
85
- }
86
- setContextMenuProps({
87
- position: {
88
- x: e.clientX,
89
- y: e.clientY,
90
- },
91
- actions: contextMenuActions,
92
- });
93
- } }), _jsxs(DropdownMenu.Provider, { open: contextMenuProps !== undefined, setOpen: (open) => {
54
+ const { renameParameters, cancelRename } = renameContext ?? {};
55
+ const labelEditor = (_jsx(LabelEditor, { initialLabel: node.label, onChange: renameParameters?.commit, onCancel: cancelRename, labelValidationHint: renameParameters?.labelValidationHint, validate: renameParameters?.validate }));
56
+ return (_jsxs(_Fragment, { children: [_jsx(Popover, { content: labelEditor, placement: "bottom", open: renameParameters?.nodeId === node.id, setOpen: cancelRename, unmountOnHide: true, children: _jsx(Tree.Item, { ...treeItemProps, ref: forwardedRef, label: label, expanded: expanded, onExpandedChange: useCallback((isExpanded) => {
57
+ expandNode(node.id, isExpanded);
58
+ }, [node, expandNode]), inlineActions: inlineActionItems, actions: menuActionItems, unstable_decorations: decorations, error: node.error ? node.error.id : undefined, onContextMenu: (e) => {
59
+ if (treeItemProps.onContextMenu) {
60
+ treeItemProps.onContextMenu(e);
61
+ }
62
+ if (!contextMenuActions) {
63
+ return;
64
+ }
65
+ e.preventDefault();
66
+ const actions = injectActionVariant(contextMenuActions, "context-menu");
67
+ if (actions.length === 0) {
68
+ return;
69
+ }
70
+ setContextMenuProps({
71
+ position: {
72
+ x: e.clientX,
73
+ y: e.clientY,
74
+ },
75
+ actions,
76
+ });
77
+ } }) }), _jsxs(DropdownMenu.Provider, { open: contextMenuProps !== undefined, setOpen: (open) => {
94
78
  if (!open) {
95
79
  setContextMenuProps(undefined);
96
80
  }
@@ -98,21 +82,27 @@ export const StrataKitTreeNodeRenderer = memo(forwardRef(function HierarchyNode(
98
82
  }));
99
83
  export const PlaceholderNode = memo(forwardRef(function PlaceholderNode({ ...props }, forwardedRef) {
100
84
  const { localizedStrings } = useLocalizationContext();
101
- return _jsx(Tree.Item, { ...props, ref: forwardedRef, label: localizedStrings.loading, icon: _jsx(Spinner, { size: "small", title: localizedStrings.loading }) });
85
+ return (_jsx(Tree.Item, { ...props, ref: forwardedRef, label: localizedStrings.loading, unstable_decorations: _jsx(Spinner, { size: "small", title: localizedStrings.loading }) }));
102
86
  }));
103
- function LabelEditor({ initialLabel, onChange, onCancel }) {
87
+ function LabelEditor({ initialLabel, labelValidationHint, onChange, onCancel, validate, }) {
88
+ const { localizedStrings } = useLocalizationContext();
104
89
  const inputRef = useRef(null);
105
90
  const [newLabelValue, setNewLabelValue] = useState(initialLabel);
91
+ const [hasError, setHasError] = useState(false);
106
92
  const handleLabelChange = () => {
93
+ if (validate && !validate(newLabelValue)) {
94
+ setHasError(true);
95
+ return;
96
+ }
107
97
  if (initialLabel !== newLabelValue) {
108
- onChange(newLabelValue);
98
+ onChange?.(newLabelValue);
109
99
  return;
110
100
  }
111
- onCancel();
101
+ onCancel?.();
112
102
  };
113
103
  const cancelLabelChange = () => {
114
104
  setNewLabelValue(initialLabel);
115
- onCancel();
105
+ onCancel?.();
116
106
  };
117
107
  useEffect(() => {
118
108
  if (inputRef.current) {
@@ -120,31 +110,23 @@ function LabelEditor({ initialLabel, onChange, onCancel }) {
120
110
  inputRef.current.select();
121
111
  }
122
112
  }, []);
123
- return (_jsx(TextBox.Root, { children: _jsx(TextBox.Input, { ref: inputRef, value: newLabelValue, onChange: (event) => setNewLabelValue(event.target.value), onBlur: handleLabelChange, onKeyDown: (event) => {
124
- if (event.key === "Enter") {
125
- handleLabelChange();
126
- }
127
- else if (event.key === "Escape") {
128
- cancelLabelChange();
129
- }
130
- } }) }));
113
+ const canRename = newLabelValue && newLabelValue !== initialLabel && !hasError;
114
+ const inputId = useId();
115
+ return (_jsxs("div", { className: "phr-node-label-editor", children: [_jsxs("div", { className: "phr-node-label-editor-input-row", children: [_jsx(TextBox.Root, { style: { width: "100%" }, className: hasError ? "with-error" : undefined, children: _jsx(TextBox.Input, { id: inputId, ref: inputRef, value: newLabelValue, onChange: (event) => {
116
+ setNewLabelValue(event.target.value);
117
+ setHasError(false);
118
+ }, onKeyDown: (event) => {
119
+ if (event.key === "Enter") {
120
+ handleLabelChange();
121
+ }
122
+ else if (event.key === "Escape") {
123
+ cancelLabelChange();
124
+ }
125
+ } }) }), _jsx(IconButton, { icon: dismissSvg, label: localizedStrings.cancel, onClick: cancelLabelChange }), _jsx(IconButton, { icon: checkmarkSvg, label: localizedStrings.confirm, onClick: handleLabelChange, disabled: !canRename })] }), labelValidationHint !== undefined ? (_jsx(Description, { id: inputId, tone: hasError ? "critical" : "neutral", style: { display: "flex" }, children: _jsx(Text, { variant: "caption-lg", children: labelValidationHint }) })) : undefined] }, initialLabel));
131
126
  }
132
127
  function injectActionVariant(actions, variant) {
133
128
  return actions
134
129
  .filter((action) => isValidElement(action))
135
130
  .map((action) => cloneElement(action, { variant }));
136
131
  }
137
- function useMergedRefs(...refs) {
138
- return useCallback((instance) => {
139
- refs.forEach((ref) => {
140
- if (typeof ref === "function") {
141
- ref(instance);
142
- }
143
- else if (ref) {
144
- ref.current = instance;
145
- }
146
- });
147
- }, // eslint-disable-next-line react-hooks/exhaustive-deps
148
- [...refs]);
149
- }
150
132
  //# sourceMappingURL=TreeNodeRenderer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"TreeNodeRenderer.js","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/stratakit/TreeNodeRenderer.tsx"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport {\n cloneElement,\n ComponentPropsWithoutRef,\n FC,\n forwardRef,\n isValidElement,\n LegacyRef,\n memo,\n MutableRefObject,\n PropsWithRef,\n ReactElement,\n ReactNode,\n Ref,\n RefAttributes,\n useCallback,\n useEffect,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { Spinner, TextBox } from \"@stratakit/bricks\";\nimport refreshSvg from \"@stratakit/icons/refresh.svg\";\nimport { DropdownMenu, Tree } from \"@stratakit/structures\";\nimport { TreeRendererProps } from \"../Renderers.js\";\nimport { PresentationHierarchyNode } from \"../TreeNode.js\";\nimport { useLocalizationContext } from \"./LocalizationContext.js\";\nimport { useRenameContext } from \"./RenameAction.js\";\nimport { TreeActionBase, TreeActionBaseAttributes } from \"./TreeAction.js\";\n\n/** @alpha */\ntype TreeNodeProps = ComponentPropsWithoutRef<typeof Tree.Item>;\n\n/** @alpha */\nexport interface TreeNodeRendererOwnProps {\n /** Node that is rendered. */\n node: PresentationHierarchyNode;\n /** Returns the class name for a given node. */\n getClassName?: (node: PresentationHierarchyNode) => string | undefined;\n /** Returns a label for a given node. */\n getLabel?: (node: PresentationHierarchyNode) => ReactElement | undefined;\n /** Returns sublabel for a given node. */\n getSublabel?: (node: PresentationHierarchyNode) => ReactElement | undefined;\n /** Action to perform when the node is clicked. */\n onNodeClick?: (node: PresentationHierarchyNode, isSelected: boolean, event: React.MouseEvent<HTMLElement>) => void;\n /** Action to perform when a key is pressed when the node is hovered on. */\n onNodeKeyDown?: (node: PresentationHierarchyNode, isSelected: boolean, event: React.KeyboardEvent<HTMLElement>) => void;\n /**\n * Used to render elements between expander and label.\n * E.g. icons, color picker, etc.\n */\n getDecorations?: (node: PresentationHierarchyNode) => ReactNode;\n /**\n * Callback that returns menu actions for tree item.\n * Must return an array of `<TreeActionBase />` or `<Divider />` elements.\n */\n getMenuActions?: (node: PresentationHierarchyNode) => ReactNode[];\n /**\n * Callback that returns inline actions for tree item.\n * Must return an array of `<TreeActionBase />` elements.\n * Max 2 items.\n */\n getInlineActions?: (node: PresentationHierarchyNode) => ReactNode[];\n /**\n * Callback that returns actions for tree item context menu.\n * Must return an array of `<TreeActionBase />` or `<Divider />` elements.\n */\n getContextMenuActions?: (node: PresentationHierarchyNode) => ReactNode[];\n}\n\n/** @alpha */\ntype TreeNodeRendererProps = Pick<TreeRendererProps, \"expandNode\" | \"reloadTree\"> &\n Omit<TreeNodeProps, \"actions\" | \"label\" | \"expanded\" | \"unstable_decorations\" | \"error\"> &\n TreeNodeRendererOwnProps;\n\n/**\n * A component that renders given `FlatTreeNode` using the `Tree.Item` component from `@itwin/itwinui-react`. The\n * `FlatTreeNode` objects for this renderer are generally created using the `useFlatTreeNodeList` hook.\n *\n * @see `TreeRenderer`\n * @see https://itwinui.bentley.com/docs/tree\n * @public\n */\nexport const StrataKitTreeNodeRenderer: FC<PropsWithRef<TreeNodeRendererProps & RefAttributes<HTMLElement>>> = memo(\n forwardRef<HTMLElement, TreeNodeRendererProps>(function HierarchyNode(\n {\n node,\n selected,\n expandNode,\n onNodeClick,\n onNodeKeyDown,\n reloadTree,\n getClassName,\n getLabel,\n getSublabel,\n getMenuActions,\n getInlineActions,\n getDecorations,\n getContextMenuActions,\n ...treeItemProps\n },\n forwardedRef,\n ) {\n const nodeRef = useRef<HTMLElement>(null);\n const ref = useMergedRefs(forwardedRef, nodeRef);\n const { localizedStrings } = useLocalizationContext();\n const renameContext = useRenameContext();\n const [contextMenuProps, setContextMenuProps] = useState<{ position: { x: number; y: number }; actions: ReactNode[] } | undefined>(undefined);\n\n const className = useMemo(() => getClassName?.(node), [getClassName, node]);\n const label = useMemo(() => (getLabel ? getLabel(node) : node.label), [getLabel, node]);\n const description = useMemo(() => (getSublabel ? getSublabel(node) : undefined), [getSublabel, node]);\n const decorations = useMemo(() => getDecorations?.(node), [getDecorations, node]);\n const inlineActions = useMemo(() => {\n if (node.error !== undefined && node.error.type === \"ChildrenLoad\") {\n return [\n <TreeActionBase\n key=\"retry\"\n label={localizedStrings.retry}\n onClick={() => reloadTree({ parentNodeId: node.id, state: \"reset\" })}\n visible={true}\n icon={refreshSvg}\n variant=\"inline\"\n />,\n ];\n }\n if (!getInlineActions) {\n return [];\n }\n return injectActionVariant(getInlineActions(node), \"inline\");\n }, [node, getInlineActions, localizedStrings.retry, reloadTree]);\n\n const menuItems = useMemo(() => {\n if (!getMenuActions) {\n return undefined;\n }\n return injectActionVariant(getMenuActions(node), \"default\");\n }, [getMenuActions, node]);\n\n const expanded = useMemo(() => {\n if (node.error) {\n return undefined;\n }\n\n if (node.isExpanded || node.children === true || node.children.length > 0) {\n return node.isExpanded;\n }\n\n return undefined;\n }, [node.children, node.error, node.isExpanded]);\n\n const isDisabled = treeItemProps[\"aria-disabled\"] === true;\n\n const { onLabelChanged, setIsRenaming, isRenaming } = renameContext ?? {};\n const labelEditor = isRenaming ? (\n <LabelEditor\n initialLabel={node.label}\n onChange={(newLabel) => {\n onLabelChanged?.(newLabel);\n setIsRenaming?.(false);\n }}\n onCancel={() => {\n setIsRenaming?.(false);\n }}\n />\n ) : undefined;\n\n return (\n <>\n <Tree.Item\n {...treeItemProps}\n ref={ref}\n className={className}\n label={labelEditor ?? label}\n description={description}\n selected={selected}\n expanded={expanded}\n onExpandedChange={useCallback(\n (isExpanded: boolean) => {\n expandNode(node.id, isExpanded);\n },\n [node, expandNode],\n )}\n onClick={useCallback<Required<TreeNodeProps>[\"onClick\"]>(\n (event) => {\n if (isDisabled) {\n return;\n }\n\n onNodeClick?.(node, !selected, event);\n },\n [node, isDisabled, selected, onNodeClick],\n )}\n onKeyDown={useCallback<Required<TreeNodeProps>[\"onKeyDown\"]>(\n (event) => {\n // Ignore if it is called on the element inside, e.g. checkbox or expander\n if (!isDisabled && event.target === nodeRef.current) {\n onNodeKeyDown?.(node, !selected, event);\n }\n },\n [onNodeKeyDown, selected, isDisabled, node],\n )}\n inlineActions={inlineActions}\n actions={menuItems}\n unstable_decorations={decorations}\n error={node.error ? node.error.id : undefined}\n onContextMenu={(e) => {\n if (!getContextMenuActions) {\n return;\n }\n\n e.preventDefault();\n const contextMenuActions = injectActionVariant(getContextMenuActions(node), \"context-menu\");\n if (contextMenuActions.length === 0) {\n return;\n }\n\n setContextMenuProps({\n position: {\n x: e.clientX,\n y: e.clientY,\n },\n actions: contextMenuActions,\n });\n }}\n />\n <DropdownMenu.Provider\n open={contextMenuProps !== undefined}\n setOpen={(open) => {\n if (!open) {\n setContextMenuProps(undefined);\n }\n }}\n key={`${node.id}-${contextMenuProps?.position.x ?? \"\"}-${contextMenuProps?.position.y ?? \"\"}`}\n >\n {contextMenuProps ? (\n <DropdownMenu.Button style={{ position: \"fixed\", top: contextMenuProps.position.y, left: contextMenuProps.position.x }} render={<div />} />\n ) : null}\n {/* `autoFocus` prop is coming from ariakit and is not native HTML `autoFocus` prop. */}\n {/* `focusable` is needed for `autoFocus` to work. StrataKit exposes only `autoFocus` and does not set `focusable` internally. */}\n {/* eslint-disable jsx-a11y/no-autofocus */}\n {/* @ts-expect-error focusable is passed through */}\n <DropdownMenu.Content focusable autoFocus={true}>\n {contextMenuProps?.actions}\n </DropdownMenu.Content>\n </DropdownMenu.Provider>\n </>\n );\n }),\n);\n\nexport const PlaceholderNode: FC<PropsWithRef<Omit<TreeNodeProps, \"onExpanded\" | \"label\" | \"actions\" | \"icon\" | \"error\"> & RefAttributes<HTMLElement>>> = memo(\n forwardRef<HTMLElement, Omit<TreeNodeProps, \"onExpanded\" | \"label\" | \"actions\" | \"icon\" | \"error\">>(function PlaceholderNode({ ...props }, forwardedRef) {\n const { localizedStrings } = useLocalizationContext();\n return <Tree.Item {...props} ref={forwardedRef} label={localizedStrings.loading} icon={<Spinner size={\"small\"} title={localizedStrings.loading} />} />;\n }),\n);\n\nfunction LabelEditor({ initialLabel, onChange, onCancel }: { initialLabel: string; onChange: (newLabel: string) => void; onCancel: () => void }) {\n const inputRef = useRef<HTMLInputElement>(null);\n const [newLabelValue, setNewLabelValue] = useState(initialLabel);\n const handleLabelChange = () => {\n if (initialLabel !== newLabelValue) {\n onChange(newLabelValue);\n return;\n }\n onCancel();\n };\n\n const cancelLabelChange = () => {\n setNewLabelValue(initialLabel);\n onCancel();\n };\n\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n inputRef.current.select();\n }\n }, []);\n\n return (\n <TextBox.Root>\n <TextBox.Input\n ref={inputRef}\n value={newLabelValue}\n onChange={(event) => setNewLabelValue(event.target.value)}\n onBlur={handleLabelChange}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n handleLabelChange();\n } else if (event.key === \"Escape\") {\n cancelLabelChange();\n }\n }}\n />\n </TextBox.Root>\n );\n}\n\nfunction injectActionVariant(actions: ReactNode[], variant: TreeActionBaseAttributes[\"variant\"]) {\n return actions\n .filter((action) => isValidElement<TreeActionBaseAttributes>(action))\n .map((action) => cloneElement<TreeActionBaseAttributes>(action, { variant }));\n}\n\nfunction useMergedRefs<T>(...refs: ReadonlyArray<Ref<T> | LegacyRef<T> | undefined | null>) {\n return useCallback(\n (instance: T | null) => {\n refs.forEach((ref) => {\n if (typeof ref === \"function\") {\n ref(instance);\n } else if (ref) {\n (ref as MutableRefObject<T | null>).current = instance;\n }\n });\n }, // eslint-disable-next-line react-hooks/exhaustive-deps\n [...refs],\n );\n}\n"]}
1
+ {"version":3,"file":"TreeNodeRenderer.js","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/stratakit/TreeNodeRenderer.tsx"],"names":[],"mappings":"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","sourcesContent":["/*---------------------------------------------------------------------------------------------\n * Copyright (c) Bentley Systems, Incorporated. All rights reserved.\n * See LICENSE.md in the project root for license terms and full copyright notice.\n *--------------------------------------------------------------------------------------------*/\n\nimport \"./TreeNodeRenderer.css\";\n\nimport {\n cloneElement,\n ComponentPropsWithoutRef,\n FC,\n forwardRef,\n isValidElement,\n memo,\n PropsWithRef,\n ReactNode,\n RefAttributes,\n useCallback,\n useEffect,\n useId,\n useMemo,\n useRef,\n useState,\n} from \"react\";\nimport { Description, IconButton, Spinner, Text, TextBox } from \"@stratakit/bricks\";\nimport checkmarkSvg from \"@stratakit/icons/checkmark.svg\";\nimport dismissSvg from \"@stratakit/icons/dismiss.svg\";\nimport refreshSvg from \"@stratakit/icons/refresh.svg\";\nimport { DropdownMenu, unstable_Popover as Popover, Tree } from \"@stratakit/structures\";\nimport { TreeRendererProps } from \"../Renderers.js\";\nimport { PresentationHierarchyNode } from \"../TreeNode.js\";\nimport { useLocalizationContext } from \"./LocalizationContext.js\";\nimport { TreeActionBase, TreeActionBaseAttributes } from \"./TreeAction.js\";\nimport { useTreeNodeRenameContext } from \"./TreeNodeRenameAction.js\";\n\n/** @internal */\ninterface TreeNodeRendererOwnProps extends Pick<TreeRendererProps, \"expandNode\" | \"reloadTree\"> {\n /** Node that is rendered. */\n node: PresentationHierarchyNode;\n /**\n * Menu actions for tree item.\n * Must be an array of `<TreeActionBase />` or `<Divider />` elements.\n */\n menuActions?: ReactNode[];\n /**\n * Inline actions for tree item.\n * Must be an array of `<TreeActionBase />` elements.\n * Max 2 items.\n */\n inlineActions?: ReactNode[];\n /**\n * Context menu actions for tree item.\n * Must be an array of `<TreeActionBase />` or `<Divider />` elements.\n */\n contextMenuActions?: ReactNode[];\n}\n\n/** @alpha */\nexport type StrataKitTreeItemProps = Omit<\n ComponentPropsWithoutRef<typeof Tree.Item>,\n \"actions\" | \"inlineActions\" | \"expanded\" | \"onExpandedChange\" | \"icon\" | \"unstable_decorations\" | \"error\"\n> & {\n /**\n * Used to render elements between expander and label.\n * E.g. icons, color picker, etc.\n */\n decorations?: ReactNode;\n};\n\n/** @internal */\nexport type TreeNodeRendererProps = StrataKitTreeItemProps & TreeNodeRendererOwnProps;\n\n/**\n * A component that renders given `FlatTreeNode` using the `Tree.Item` component from `@itwin/itwinui-react`. The\n * `FlatTreeNode` objects for this renderer are generally created using the `useFlatTreeNodeList` hook.\n *\n * @internal\n */\nexport const StrataKitTreeNodeRenderer: FC<PropsWithRef<TreeNodeRendererProps & RefAttributes<HTMLElement>>> = memo(\n forwardRef<HTMLElement, TreeNodeRendererProps>(function HierarchyNode(props, forwardedRef) {\n const { node, decorations, inlineActions, menuActions, contextMenuActions, expandNode, reloadTree, ...treeItemProps } = props;\n const { localizedStrings } = useLocalizationContext();\n const renameContext = useTreeNodeRenameContext();\n const [contextMenuProps, setContextMenuProps] = useState<{ position: { x: number; y: number }; actions: ReactNode[] } | undefined>(undefined);\n\n const label = treeItemProps.label ?? node.label;\n const inlineActionItems = useMemo(() => {\n if (node.error !== undefined && node.error.type === \"ChildrenLoad\") {\n return [\n <TreeActionBase\n key=\"retry\"\n label={localizedStrings.retry}\n onClick={() => reloadTree({ parentNodeId: node.id, state: \"reset\" })}\n visible={true}\n icon={refreshSvg}\n variant=\"inline\"\n />,\n ];\n }\n if (!inlineActions) {\n return undefined;\n }\n return injectActionVariant(inlineActions, \"inline\");\n }, [node, inlineActions, localizedStrings.retry, reloadTree]);\n\n const menuActionItems = useMemo(() => {\n if (!menuActions) {\n return undefined;\n }\n return injectActionVariant(menuActions, \"default\");\n }, [menuActions]);\n\n const expanded = useMemo(() => {\n if (node.error) {\n return undefined;\n }\n\n if (node.isExpanded || node.children === true || node.children.length > 0) {\n return node.isExpanded;\n }\n\n return undefined;\n }, [node.children, node.error, node.isExpanded]);\n\n const { renameParameters, cancelRename } = renameContext ?? {};\n const labelEditor = (\n <LabelEditor\n initialLabel={node.label}\n onChange={renameParameters?.commit}\n onCancel={cancelRename}\n labelValidationHint={renameParameters?.labelValidationHint}\n validate={renameParameters?.validate}\n />\n );\n\n return (\n <>\n <Popover content={labelEditor} placement=\"bottom\" open={renameParameters?.nodeId === node.id} setOpen={cancelRename} unmountOnHide>\n <Tree.Item\n {...treeItemProps}\n ref={forwardedRef}\n label={label}\n expanded={expanded}\n onExpandedChange={useCallback(\n (isExpanded: boolean) => {\n expandNode(node.id, isExpanded);\n },\n [node, expandNode],\n )}\n inlineActions={inlineActionItems}\n actions={menuActionItems}\n unstable_decorations={decorations}\n error={node.error ? node.error.id : undefined}\n onContextMenu={(e) => {\n if (treeItemProps.onContextMenu) {\n treeItemProps.onContextMenu(e);\n }\n\n if (!contextMenuActions) {\n return;\n }\n\n e.preventDefault();\n const actions = injectActionVariant(contextMenuActions, \"context-menu\");\n if (actions.length === 0) {\n return;\n }\n\n setContextMenuProps({\n position: {\n x: e.clientX,\n y: e.clientY,\n },\n actions,\n });\n }}\n />\n </Popover>\n <DropdownMenu.Provider\n open={contextMenuProps !== undefined}\n setOpen={(open) => {\n if (!open) {\n setContextMenuProps(undefined);\n }\n }}\n key={`${node.id}-${contextMenuProps?.position.x ?? \"\"}-${contextMenuProps?.position.y ?? \"\"}`}\n >\n {contextMenuProps ? (\n <DropdownMenu.Button style={{ position: \"fixed\", top: contextMenuProps.position.y, left: contextMenuProps.position.x }} render={<div />} />\n ) : null}\n {/* `autoFocus` prop is coming from ariakit and is not native HTML `autoFocus` prop. */}\n {/* `focusable` is needed for `autoFocus` to work. StrataKit exposes only `autoFocus` and does not set `focusable` internally. */}\n {/* eslint-disable jsx-a11y/no-autofocus */}\n {/* @ts-expect-error focusable is passed through */}\n <DropdownMenu.Content focusable autoFocus={true}>\n {contextMenuProps?.actions}\n </DropdownMenu.Content>\n </DropdownMenu.Provider>\n </>\n );\n }),\n);\n\nexport const PlaceholderNode: FC<\n PropsWithRef<Pick<StrataKitTreeItemProps, \"style\" | \"aria-level\" | \"aria-posinset\" | \"aria-setsize\"> & RefAttributes<HTMLElement>>\n> = memo(\n forwardRef<HTMLElement, Pick<StrataKitTreeItemProps, \"style\" | \"aria-level\" | \"aria-posinset\" | \"aria-setsize\">>(function PlaceholderNode(\n { ...props },\n forwardedRef,\n ) {\n const { localizedStrings } = useLocalizationContext();\n return (\n <Tree.Item\n {...props}\n ref={forwardedRef}\n label={localizedStrings.loading}\n unstable_decorations={<Spinner size={\"small\"} title={localizedStrings.loading} />}\n />\n );\n }),\n);\n\nfunction LabelEditor({\n initialLabel,\n labelValidationHint,\n onChange,\n onCancel,\n validate,\n}: {\n initialLabel: string;\n labelValidationHint?: string;\n onChange?: (newLabel: string) => void;\n onCancel?: () => void;\n validate?: (newLabel: string) => boolean;\n}) {\n const { localizedStrings } = useLocalizationContext();\n const inputRef = useRef<HTMLInputElement>(null);\n const [newLabelValue, setNewLabelValue] = useState(initialLabel);\n const [hasError, setHasError] = useState<boolean>(false);\n const handleLabelChange = () => {\n if (validate && !validate(newLabelValue)) {\n setHasError(true);\n return;\n }\n\n if (initialLabel !== newLabelValue) {\n onChange?.(newLabelValue);\n return;\n }\n onCancel?.();\n };\n\n const cancelLabelChange = () => {\n setNewLabelValue(initialLabel);\n onCancel?.();\n };\n\n useEffect(() => {\n if (inputRef.current) {\n inputRef.current.focus();\n inputRef.current.select();\n }\n }, []);\n\n const canRename = newLabelValue && newLabelValue !== initialLabel && !hasError;\n const inputId = useId();\n\n return (\n <div key={initialLabel} className=\"phr-node-label-editor\">\n <div className=\"phr-node-label-editor-input-row\">\n <TextBox.Root style={{ width: \"100%\" }} className={hasError ? \"with-error\" : undefined}>\n <TextBox.Input\n id={inputId}\n ref={inputRef}\n value={newLabelValue}\n onChange={(event) => {\n setNewLabelValue(event.target.value);\n setHasError(false);\n }}\n onKeyDown={(event) => {\n if (event.key === \"Enter\") {\n handleLabelChange();\n } else if (event.key === \"Escape\") {\n cancelLabelChange();\n }\n }}\n />\n </TextBox.Root>\n <IconButton icon={dismissSvg} label={localizedStrings.cancel} onClick={cancelLabelChange} />\n <IconButton icon={checkmarkSvg} label={localizedStrings.confirm} onClick={handleLabelChange} disabled={!canRename} />\n </div>\n {labelValidationHint !== undefined ? (\n <Description id={inputId} tone={hasError ? \"critical\" : \"neutral\"} style={{ display: \"flex\" }}>\n <Text variant=\"caption-lg\">{labelValidationHint}</Text>\n </Description>\n ) : undefined}\n </div>\n );\n}\n\nfunction injectActionVariant(actions: ReactNode[], variant: TreeActionBaseAttributes[\"variant\"]) {\n return actions\n .filter((action) => isValidElement<TreeActionBaseAttributes>(action))\n .map((action) => cloneElement<TreeActionBaseAttributes>(action, { variant }));\n}\n"]}
@@ -1,17 +1,15 @@
1
- import { ComponentPropsWithoutRef, ReactElement, ReactNode } from "react";
1
+ import { ComponentProps, ComponentPropsWithoutRef, FC, PropsWithoutRef, ReactElement, ReactNode, RefAttributes } from "react";
2
2
  import { Tree } from "@stratakit/structures";
3
3
  import { TreeRendererProps } from "../Renderers.js";
4
4
  import { PresentationHierarchyNode } from "../TreeNode.js";
5
5
  import { SelectionMode } from "../UseSelectionHandler.js";
6
6
  import { LocalizationContextProvider } from "./LocalizationContext.js";
7
7
  import { TreeErrorRendererProps } from "./TreeErrorRenderer.js";
8
- import { StrataKitTreeNodeRenderer } from "./TreeNodeRenderer.js";
9
- /** @alpha */
10
- export type TreeProps = ComponentPropsWithoutRef<typeof Tree.Root>;
11
- /** @alpha */
12
- export type TreeNodeRendererProps = ComponentPropsWithoutRef<typeof StrataKitTreeNodeRenderer>;
8
+ import { TreeNodeEditingProps } from "./TreeNodeRenameAction.js";
9
+ import { StrataKitTreeItemProps } from "./TreeNodeRenderer.js";
13
10
  /** @alpha */
14
11
  interface TreeRendererOwnProps {
12
+ id?: string;
15
13
  /**
16
14
  * A user friendly display label of the tree. Should be unique within the consuming application,
17
15
  * as it's used for accessibility purposes.
@@ -22,14 +20,11 @@ interface TreeRendererOwnProps {
22
20
  /** A render function for errors' display component. Defaults to `<TreeErrorRenderer />`. */
23
21
  errorRenderer?: (props: TreeErrorRendererProps) => ReactElement;
24
22
  /** Props that defines if current node supports editing. */
25
- getEditingProps?: (node: PresentationHierarchyNode) => {
26
- /**
27
- * A callback that is invoked when node label is changed. Should be used together
28
- * with `<RenameAction />` to enter label editing mode. Node label is not editable
29
- * when this is not supplied.
30
- */
31
- onLabelChanged?: (newLabel: string) => void;
32
- };
23
+ getEditingProps?: (node: PresentationHierarchyNode) => TreeNodeEditingProps | undefined;
24
+ /** Custom props for the root Tree component. */
25
+ treeRootProps?: Partial<Omit<ComponentProps<typeof Tree.Root>, "style">>;
26
+ /** A callback that returns tree item props for specific node. */
27
+ getTreeItemProps?: (node: PresentationHierarchyNode) => Partial<Omit<StrataKitTreeItemProps, "selected" | "aria-level" | "aria-posinset" | "aria-setsize">>;
33
28
  /**
34
29
  * Callback that returns menu actions for tree item.
35
30
  * Must return an array of `<TreeActionBase />` or `<Divider />` elements.
@@ -57,7 +52,17 @@ interface TreeRendererOwnProps {
57
52
  }) => ReactNode[];
58
53
  }
59
54
  /** @alpha */
60
- type StrataKitTreeRendererProps = TreeRendererProps & Pick<TreeErrorRendererProps, "onFilterClick"> & Omit<TreeNodeRendererProps, "node" | "aria-level" | "aria-posinset" | "aria-setsize" | "reloadTree" | "selected" | "error" | "getMenuActions" | "getInlineActions" | "getContextMenuActions"> & TreeRendererOwnProps & ComponentPropsWithoutRef<typeof LocalizationContextProvider>;
55
+ export interface StrataKitTreeRendererAttributes {
56
+ /**
57
+ * Opens rename mode for the first node that matches the given predicate. Node must be already loaded in the tree.
58
+ * If the node is not visible (because its parent is collapsed), all parents will be expanded to make it visible and node will be scrolled into view.
59
+ *
60
+ * Returns "node-not-found" if no node matches the predicate, "success" if rename was initiated.
61
+ */
62
+ renameNode: (predicate: (node: PresentationHierarchyNode) => boolean) => "node-not-found" | "success";
63
+ }
64
+ /** @alpha */
65
+ type StrataKitTreeRendererProps = TreeRendererProps & Pick<TreeErrorRendererProps, "onFilterClick"> & TreeRendererOwnProps & ComponentPropsWithoutRef<typeof LocalizationContextProvider>;
61
66
  /**
62
67
  * A component that renders a tree using the `Tree` component from `@itwin/itwinui-react`. The tree nodes
63
68
  * are rendered using `TreeNodeRenderer` component from this package.
@@ -65,6 +70,6 @@ type StrataKitTreeRendererProps = TreeRendererProps & Pick<TreeErrorRendererProp
65
70
  * @see https://itwinui.bentley.com/docs/tree
66
71
  * @alpha
67
72
  */
68
- export declare function StrataKitTreeRenderer({ rootNodes, selectNodes, selectionMode, expandNode, treeLabel, localizedStrings, getHierarchyLevelDetails, onFilterClick, reloadTree, isNodeSelected, errorRenderer, onNodeClick: onNodeClickOverride, onNodeKeyDown: onNodeKeyDownOverride, getEditingProps, id, getInlineActions, getMenuActions, getContextMenuActions, ...treeProps }: StrataKitTreeRendererProps): import("react/jsx-runtime").JSX.Element;
73
+ export declare const StrataKitTreeRenderer: FC<PropsWithoutRef<StrataKitTreeRendererProps> & RefAttributes<StrataKitTreeRendererAttributes>>;
69
74
  export {};
70
75
  //# sourceMappingURL=TreeRenderer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"TreeRenderer.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/stratakit/TreeRenderer.tsx"],"names":[],"mappings":"AAKA,OAAO,EAAE,wBAAwB,EAAmC,YAAY,EAAE,SAAS,EAA2C,MAAM,OAAO,CAAC;AACpJ,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAuB,MAAM,2BAA2B,CAAC;AAG/E,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AAEvE,OAAO,EAAqB,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACnF,OAAO,EAAmB,yBAAyB,EAAE,MAAM,uBAAuB,CAAC;AAEnF,aAAa;AACb,MAAM,MAAM,SAAS,GAAG,wBAAwB,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC;AAEnE,aAAa;AACb,MAAM,MAAM,qBAAqB,GAAG,wBAAwB,CAAC,OAAO,yBAAyB,CAAC,CAAC;AAE/F,aAAa;AACb,UAAU,oBAAoB;IAC5B;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,4FAA4F;IAC5F,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,YAAY,CAAC;IAChE,2DAA2D;IAC3D,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK;QACrD;;;;WAIG;QACH,cAAc,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;KAC7C,CAAC;IAEF;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,yBAAyB,CAAC;QAAC,aAAa,EAAE,yBAAyB,EAAE,CAAA;KAAE,KAAK,SAAS,EAAE,CAAC;IAC/H;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,yBAAyB,CAAC;QAAC,aAAa,EAAE,yBAAyB,EAAE,CAAA;KAAE,KAAK,SAAS,EAAE,CAAC;IACjI;;;OAGG;IACH,qBAAqB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,yBAAyB,CAAC;QAAC,aAAa,EAAE,yBAAyB,EAAE,CAAA;KAAE,KAAK,SAAS,EAAE,CAAC;CACvI;AAED,aAAa;AACb,KAAK,0BAA0B,GAAG,iBAAiB,GACjD,IAAI,CAAC,sBAAsB,EAAE,eAAe,CAAC,GAC7C,IAAI,CACF,qBAAqB,EACnB,MAAM,GACN,YAAY,GACZ,eAAe,GACf,cAAc,GACd,YAAY,GACZ,UAAU,GACV,OAAO,GACP,gBAAgB,GAChB,kBAAkB,GAClB,uBAAuB,CAC1B,GACD,oBAAoB,GACpB,wBAAwB,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAE/D;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CAAC,EACpC,SAAS,EACT,WAAW,EACX,aAAa,EACb,UAAU,EACV,SAAS,EACT,gBAAgB,EAChB,wBAAwB,EACxB,aAAa,EACb,UAAU,EACV,cAAc,EACd,aAAa,EACb,WAAW,EAAE,mBAAmB,EAChC,aAAa,EAAE,qBAAqB,EACpC,eAAe,EACf,EAAE,EACF,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EACrB,GAAG,SAAS,EACb,EAAE,0BAA0B,2CAgH5B"}
1
+ {"version":3,"file":"TreeRenderer.d.ts","sourceRoot":"","sources":["../../../../src/presentation-hierarchies-react/stratakit/TreeRenderer.tsx"],"names":[],"mappings":"AAKA,OAAO,EACL,cAAc,EACd,wBAAwB,EAExB,EAAE,EAGF,eAAe,EACf,YAAY,EACZ,SAAS,EACT,aAAa,EAMd,MAAM,OAAO,CAAC;AACf,OAAO,EAAE,IAAI,EAAE,MAAM,uBAAuB,CAAC;AAE7C,OAAO,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACpD,OAAO,EAAE,yBAAyB,EAAE,MAAM,gBAAgB,CAAC;AAC3D,OAAO,EAAE,aAAa,EAAuB,MAAM,2BAA2B,CAAC;AAG/E,OAAO,EAAE,2BAA2B,EAAE,MAAM,0BAA0B,CAAC;AACvE,OAAO,EAAqB,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACnF,OAAO,EAAE,oBAAoB,EAAgE,MAAM,2BAA2B,CAAC;AAC/H,OAAO,EAAmB,sBAAsB,EAAoD,MAAM,uBAAuB,CAAC;AAElI,aAAa;AACb,UAAU,oBAAoB;IAC5B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,sEAAsE;IACtE,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,4FAA4F;IAC5F,aAAa,CAAC,EAAE,CAAC,KAAK,EAAE,sBAAsB,KAAK,YAAY,CAAC;IAChE,2DAA2D;IAC3D,eAAe,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,oBAAoB,GAAG,SAAS,CAAC;IAExF,gDAAgD;IAChD,aAAa,CAAC,EAAE,OAAO,CAAC,IAAI,CAAC,cAAc,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;IAEzE,iEAAiE;IACjE,gBAAgB,CAAC,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,OAAO,CAAC,IAAI,CAAC,sBAAsB,EAAE,UAAU,GAAG,YAAY,GAAG,eAAe,GAAG,cAAc,CAAC,CAAC,CAAC;IAE5J;;;OAGG;IACH,cAAc,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,yBAAyB,CAAC;QAAC,aAAa,EAAE,yBAAyB,EAAE,CAAA;KAAE,KAAK,SAAS,EAAE,CAAC;IAC/H;;;;OAIG;IACH,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,yBAAyB,CAAC;QAAC,aAAa,EAAE,yBAAyB,EAAE,CAAA;KAAE,KAAK,SAAS,EAAE,CAAC;IACjI;;;OAGG;IACH,qBAAqB,CAAC,EAAE,CAAC,KAAK,EAAE;QAAE,UAAU,EAAE,yBAAyB,CAAC;QAAC,aAAa,EAAE,yBAAyB,EAAE,CAAA;KAAE,KAAK,SAAS,EAAE,CAAC;CACvI;AAED,aAAa;AACb,MAAM,WAAW,+BAA+B;IAC9C;;;;;OAKG;IACH,UAAU,EAAE,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,yBAAyB,KAAK,OAAO,KAAK,gBAAgB,GAAG,SAAS,CAAC;CACvG;AAED,aAAa;AACb,KAAK,0BAA0B,GAAG,iBAAiB,GACjD,IAAI,CAAC,sBAAsB,EAAE,eAAe,CAAC,GAC7C,oBAAoB,GACpB,wBAAwB,CAAC,OAAO,2BAA2B,CAAC,CAAC;AAE/D;;;;;;GAMG;AACH,eAAO,MAAM,qBAAqB,EAAE,EAAE,CAAC,eAAe,CAAC,0BAA0B,CAAC,GAAG,aAAa,CAAC,+BAA+B,CAAC,CA+KjI,CAAC"}