@babylonjs/shared-ui-components 8.17.1 → 8.18.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,12 @@
1
+ import type { FunctionComponent } from "react";
2
+ export type ComboBoxProps = {
3
+ label: string;
4
+ value: string[];
5
+ onChange: (value: string) => void;
6
+ };
7
+ /**
8
+ * Wrapper around a Fluent ComboBox that allows for filtering options
9
+ * @param props
10
+ * @returns
11
+ */
12
+ export declare const ComboBox: FunctionComponent<ComboBoxProps>;
@@ -0,0 +1,32 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { Combobox as FluentComboBox, makeStyles, useComboboxFilter, useId } from "@fluentui/react-components";
4
+ const useStyles = makeStyles({
5
+ root: {
6
+ // Stack the label above the field with a gap
7
+ display: "grid",
8
+ gridTemplateRows: "repeat(1fr)",
9
+ justifyItems: "start",
10
+ gap: "2px",
11
+ maxWidth: "400px",
12
+ },
13
+ });
14
+ /**
15
+ * Wrapper around a Fluent ComboBox that allows for filtering options
16
+ * @param props
17
+ * @returns
18
+ */
19
+ export const ComboBox = (props) => {
20
+ const comboId = useId();
21
+ const styles = useStyles();
22
+ const [query, setQuery] = useState("");
23
+ const children = useComboboxFilter(query, props.value, {
24
+ noOptionsMessage: "No items match your search.",
25
+ });
26
+ const onOptionSelect = (_e, data) => {
27
+ setQuery(data.optionText ?? "");
28
+ data.optionText && props.onChange(data.optionText);
29
+ };
30
+ return (_jsxs("div", { className: styles.root, children: [_jsx("label", { id: comboId, children: props.label }), _jsx(FluentComboBox, { onOptionSelect: onOptionSelect, "aria-labelledby": comboId, placeholder: "Search..", onChange: (ev) => setQuery(ev.target.value), value: query, children: children })] }));
31
+ };
32
+ //# sourceMappingURL=comboBox.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"comboBox.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/comboBox.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjC,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,UAAU,EAAE,iBAAiB,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAE9G,MAAM,SAAS,GAAG,UAAU,CAAC;IACzB,IAAI,EAAE;QACF,6CAA6C;QAC7C,OAAO,EAAE,MAAM;QACf,gBAAgB,EAAE,aAAa;QAC/B,YAAY,EAAE,OAAO;QACrB,GAAG,EAAE,KAAK;QACV,QAAQ,EAAE,OAAO;KACpB;CACJ,CAAC,CAAC;AAOH;;;;GAIG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAqC,CAAC,KAAK,EAAE,EAAE;IAChE,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;IACxB,MAAM,MAAM,GAAG,SAAS,EAAE,CAAC;IAE3B,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,iBAAiB,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE;QACnD,gBAAgB,EAAE,6BAA6B;KAClD,CAAC,CAAC;IACH,MAAM,cAAc,GAAG,CAAC,EAAmB,EAAE,IAAwB,EAAE,EAAE;QACrE,QAAQ,CAAC,IAAI,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC;QAChC,IAAI,CAAC,UAAU,IAAI,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvD,CAAC,CAAC;IAEF,OAAO,CACH,eAAK,SAAS,EAAE,MAAM,CAAC,IAAI,aACvB,gBAAO,EAAE,EAAE,OAAO,YAAG,KAAK,CAAC,KAAK,GAAS,EACzC,KAAC,cAAc,IAAC,cAAc,EAAE,cAAc,qBAAmB,OAAO,EAAE,WAAW,EAAC,UAAU,EAAC,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,YACrJ,QAAQ,GACI,IACf,CACT,CAAC;AACN,CAAC,CAAC","sourcesContent":["import type { FunctionComponent } from \"react\";\r\nimport { useState } from \"react\";\r\nimport { Combobox as FluentComboBox, makeStyles, useComboboxFilter, useId } from \"@fluentui/react-components\";\r\nimport type { OptionOnSelectData, SelectionEvents } from \"@fluentui/react-components\";\r\nconst useStyles = makeStyles({\r\n root: {\r\n // Stack the label above the field with a gap\r\n display: \"grid\",\r\n gridTemplateRows: \"repeat(1fr)\",\r\n justifyItems: \"start\",\r\n gap: \"2px\",\r\n maxWidth: \"400px\",\r\n },\r\n});\r\n\r\nexport type ComboBoxProps = {\r\n label: string;\r\n value: string[];\r\n onChange: (value: string) => void;\r\n};\r\n/**\r\n * Wrapper around a Fluent ComboBox that allows for filtering options\r\n * @param props\r\n * @returns\r\n */\r\nexport const ComboBox: FunctionComponent<ComboBoxProps> = (props) => {\r\n const comboId = useId();\r\n const styles = useStyles();\r\n\r\n const [query, setQuery] = useState(\"\");\r\n const children = useComboboxFilter(query, props.value, {\r\n noOptionsMessage: \"No items match your search.\",\r\n });\r\n const onOptionSelect = (_e: SelectionEvents, data: OptionOnSelectData) => {\r\n setQuery(data.optionText ?? \"\");\r\n data.optionText && props.onChange(data.optionText);\r\n };\r\n\r\n return (\r\n <div className={styles.root}>\r\n <label id={comboId}>{props.label}</label>\r\n <FluentComboBox onOptionSelect={onOptionSelect} aria-labelledby={comboId} placeholder=\"Search..\" onChange={(ev) => setQuery(ev.target.value)} value={query}>\r\n {children}\r\n </FluentComboBox>\r\n </div>\r\n );\r\n};\r\n"]}
@@ -1,33 +1,56 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { makeStyles, tokens } from "@fluentui/react-components";
3
3
  import { DeleteFilled } from "@fluentui/react-icons";
4
- import { LineContainer } from "../hoc/propertyLines/propertyLine.js";
5
4
  const useDraggableStyles = makeStyles({
6
5
  draggable: {
7
- display: "inline-flex",
6
+ display: "flex",
8
7
  alignItems: "center",
8
+ justifyContent: "center",
9
+ position: "relative",
9
10
  columnGap: tokens.spacingHorizontalS,
10
11
  cursor: "grab",
11
12
  textAlign: "center",
12
13
  boxSizing: "border-box",
13
- borderBottom: "black",
14
14
  margin: `${tokens.spacingVerticalXS} 0px`,
15
+ padding: `${tokens.spacingVerticalSNudge} ${tokens.spacingHorizontalMNudge}`,
16
+ // Button-like styling
17
+ backgroundColor: tokens.colorNeutralBackground1,
15
18
  border: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke1}`,
19
+ borderRadius: tokens.borderRadiusMedium,
20
+ color: tokens.colorNeutralForeground1,
21
+ fontSize: tokens.fontSizeBase300,
22
+ fontFamily: tokens.fontFamilyBase,
23
+ fontWeight: tokens.fontWeightRegular,
24
+ lineHeight: tokens.lineHeightBase300,
25
+ minHeight: "32px",
16
26
  // eslint-disable-next-line @typescript-eslint/naming-convention
17
27
  ":hover": {
18
- backgroundColor: tokens.colorBrandBackground2Hover,
28
+ backgroundColor: tokens.colorNeutralBackground1Hover,
29
+ },
30
+ // eslint-disable-next-line @typescript-eslint/naming-convention
31
+ ":active": {
32
+ backgroundColor: tokens.colorNeutralBackground1Pressed,
19
33
  },
20
34
  },
21
35
  icon: {
22
36
  pointerEvents: "auto", // re‑enable interaction
23
37
  display: "flex",
24
38
  alignItems: "center",
39
+ position: "absolute",
40
+ right: tokens.spacingHorizontalSNudge,
41
+ color: tokens.colorNeutralForeground2,
42
+ cursor: "pointer",
43
+ fontSize: tokens.fontSizeBase400,
44
+ // eslint-disable-next-line @typescript-eslint/naming-convention
45
+ ":hover": {
46
+ color: tokens.colorNeutralForeground2Hover,
47
+ },
25
48
  },
26
49
  });
27
50
  export const DraggableLine = (props) => {
28
51
  const classes = useDraggableStyles();
29
- return (_jsx("div", { className: classes.draggable, title: props.tooltip, draggable: true, onDragStart: (event) => {
52
+ return (_jsxs("div", { className: classes.draggable, title: props.tooltip, draggable: true, onDragStart: (event) => {
30
53
  event.dataTransfer.setData(props.format, props.data);
31
- }, children: _jsxs(LineContainer, { children: [props.label, props.onDelete && _jsx(DeleteFilled, { className: classes.icon, onClick: props.onDelete })] }) }));
54
+ }, children: [props.label, props.onDelete && _jsx(DeleteFilled, { className: classes.icon, onClick: props.onDelete })] }));
32
55
  };
33
56
  //# sourceMappingURL=draggable.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"draggable.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/draggable.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAUlE,MAAM,kBAAkB,GAAG,UAAU,CAAC;IAClC,SAAS,EAAE;QACP,OAAO,EAAE,aAAa;QACtB,UAAU,EAAE,QAAQ;QACpB,SAAS,EAAE,MAAM,CAAC,kBAAkB;QACpC,MAAM,EAAE,MAAM;QACd,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,YAAY;QACvB,YAAY,EAAE,OAAO;QACrB,MAAM,EAAE,GAAG,MAAM,CAAC,iBAAiB,MAAM;QACzC,MAAM,EAAE,GAAG,MAAM,CAAC,eAAe,UAAU,MAAM,CAAC,mBAAmB,EAAE;QAEvE,gEAAgE;QAChE,QAAQ,EAAE;YACN,eAAe,EAAE,MAAM,CAAC,0BAA0B;SACrD;KACJ;IACD,IAAI,EAAE;QACF,aAAa,EAAE,MAAM,EAAE,wBAAwB;QAC/C,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;KACvB;CACJ,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAgD,CAAC,KAAK,EAAE,EAAE;IAChF,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACrC,OAAO,CACH,cACI,SAAS,EAAE,OAAO,CAAC,SAAS,EAC5B,KAAK,EAAE,KAAK,CAAC,OAAO,EACpB,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE;YACnB,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACzD,CAAC,YAED,MAAC,aAAa,eACT,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,QAAQ,IAAI,KAAC,YAAY,IAAC,SAAS,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,GAAI,IACzE,GACd,CACT,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { makeStyles, tokens } from \"@fluentui/react-components\";\r\nimport { DeleteFilled } from \"@fluentui/react-icons\";\r\nimport { LineContainer } from \"../hoc/propertyLines/propertyLine\";\r\n\r\nexport type DraggableLineProps = {\r\n format: string;\r\n data: string;\r\n tooltip: string;\r\n label: string;\r\n onDelete?: () => void;\r\n};\r\n\r\nconst useDraggableStyles = makeStyles({\r\n draggable: {\r\n display: \"inline-flex\",\r\n alignItems: \"center\",\r\n columnGap: tokens.spacingHorizontalS,\r\n cursor: \"grab\",\r\n textAlign: \"center\",\r\n boxSizing: \"border-box\",\r\n borderBottom: \"black\",\r\n margin: `${tokens.spacingVerticalXS} 0px`,\r\n border: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke1}`,\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \":hover\": {\r\n backgroundColor: tokens.colorBrandBackground2Hover,\r\n },\r\n },\r\n icon: {\r\n pointerEvents: \"auto\", // re‑enable interaction\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n },\r\n});\r\n\r\nexport const DraggableLine: React.FunctionComponent<DraggableLineProps> = (props) => {\r\n const classes = useDraggableStyles();\r\n return (\r\n <div\r\n className={classes.draggable}\r\n title={props.tooltip}\r\n draggable={true}\r\n onDragStart={(event) => {\r\n event.dataTransfer.setData(props.format, props.data);\r\n }}\r\n >\r\n <LineContainer>\r\n {props.label}\r\n {props.onDelete && <DeleteFilled className={classes.icon} onClick={props.onDelete} />}\r\n </LineContainer>\r\n </div>\r\n );\r\n};\r\n"]}
1
+ {"version":3,"file":"draggable.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/draggable.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAUrD,MAAM,kBAAkB,GAAG,UAAU,CAAC;IAClC,SAAS,EAAE;QACP,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;QACpB,cAAc,EAAE,QAAQ;QACxB,QAAQ,EAAE,UAAU;QACpB,SAAS,EAAE,MAAM,CAAC,kBAAkB;QACpC,MAAM,EAAE,MAAM;QACd,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,YAAY;QACvB,MAAM,EAAE,GAAG,MAAM,CAAC,iBAAiB,MAAM;QACzC,OAAO,EAAE,GAAG,MAAM,CAAC,qBAAqB,IAAI,MAAM,CAAC,uBAAuB,EAAE;QAE5E,sBAAsB;QACtB,eAAe,EAAE,MAAM,CAAC,uBAAuB;QAC/C,MAAM,EAAE,GAAG,MAAM,CAAC,eAAe,UAAU,MAAM,CAAC,mBAAmB,EAAE;QACvE,YAAY,EAAE,MAAM,CAAC,kBAAkB;QACvC,KAAK,EAAE,MAAM,CAAC,uBAAuB;QACrC,QAAQ,EAAE,MAAM,CAAC,eAAe;QAChC,UAAU,EAAE,MAAM,CAAC,cAAc;QACjC,UAAU,EAAE,MAAM,CAAC,iBAAiB;QACpC,UAAU,EAAE,MAAM,CAAC,iBAAiB;QACpC,SAAS,EAAE,MAAM;QAEjB,gEAAgE;QAChE,QAAQ,EAAE;YACN,eAAe,EAAE,MAAM,CAAC,4BAA4B;SACvD;QAED,gEAAgE;QAChE,SAAS,EAAE;YACP,eAAe,EAAE,MAAM,CAAC,8BAA8B;SACzD;KACJ;IACD,IAAI,EAAE;QACF,aAAa,EAAE,MAAM,EAAE,wBAAwB;QAC/C,OAAO,EAAE,MAAM;QACf,UAAU,EAAE,QAAQ;QACpB,QAAQ,EAAE,UAAU;QACpB,KAAK,EAAE,MAAM,CAAC,uBAAuB;QACrC,KAAK,EAAE,MAAM,CAAC,uBAAuB;QACrC,MAAM,EAAE,SAAS;QACjB,QAAQ,EAAE,MAAM,CAAC,eAAe;QAEhC,gEAAgE;QAChE,QAAQ,EAAE;YACN,KAAK,EAAE,MAAM,CAAC,4BAA4B;SAC7C;KACJ;CACJ,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,aAAa,GAAgD,CAAC,KAAK,EAAE,EAAE;IAChF,MAAM,OAAO,GAAG,kBAAkB,EAAE,CAAC;IACrC,OAAO,CACH,eACI,SAAS,EAAE,OAAO,CAAC,SAAS,EAC5B,KAAK,EAAE,KAAK,CAAC,OAAO,EACpB,SAAS,EAAE,IAAI,EACf,WAAW,EAAE,CAAC,KAAK,EAAE,EAAE;YACnB,KAAK,CAAC,YAAY,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACzD,CAAC,aAEA,KAAK,CAAC,KAAK,EACX,KAAK,CAAC,QAAQ,IAAI,KAAC,YAAY,IAAC,SAAS,EAAE,OAAO,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,GAAI,IACnF,CACT,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { makeStyles, tokens } from \"@fluentui/react-components\";\r\nimport { DeleteFilled } from \"@fluentui/react-icons\";\r\n\r\nexport type DraggableLineProps = {\r\n format: string;\r\n data: string;\r\n tooltip: string;\r\n label: string;\r\n onDelete?: () => void;\r\n};\r\n\r\nconst useDraggableStyles = makeStyles({\r\n draggable: {\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"center\",\r\n position: \"relative\",\r\n columnGap: tokens.spacingHorizontalS,\r\n cursor: \"grab\",\r\n textAlign: \"center\",\r\n boxSizing: \"border-box\",\r\n margin: `${tokens.spacingVerticalXS} 0px`,\r\n padding: `${tokens.spacingVerticalSNudge} ${tokens.spacingHorizontalMNudge}`,\r\n\r\n // Button-like styling\r\n backgroundColor: tokens.colorNeutralBackground1,\r\n border: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke1}`,\r\n borderRadius: tokens.borderRadiusMedium,\r\n color: tokens.colorNeutralForeground1,\r\n fontSize: tokens.fontSizeBase300,\r\n fontFamily: tokens.fontFamilyBase,\r\n fontWeight: tokens.fontWeightRegular,\r\n lineHeight: tokens.lineHeightBase300,\r\n minHeight: \"32px\",\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \":hover\": {\r\n backgroundColor: tokens.colorNeutralBackground1Hover,\r\n },\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \":active\": {\r\n backgroundColor: tokens.colorNeutralBackground1Pressed,\r\n },\r\n },\r\n icon: {\r\n pointerEvents: \"auto\", // re‑enable interaction\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n position: \"absolute\",\r\n right: tokens.spacingHorizontalSNudge,\r\n color: tokens.colorNeutralForeground2,\r\n cursor: \"pointer\",\r\n fontSize: tokens.fontSizeBase400,\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \":hover\": {\r\n color: tokens.colorNeutralForeground2Hover,\r\n },\r\n },\r\n});\r\n\r\nexport const DraggableLine: React.FunctionComponent<DraggableLineProps> = (props) => {\r\n const classes = useDraggableStyles();\r\n return (\r\n <div\r\n className={classes.draggable}\r\n title={props.tooltip}\r\n draggable={true}\r\n onDragStart={(event) => {\r\n event.dataTransfer.setData(props.format, props.data);\r\n }}\r\n >\r\n {props.label}\r\n {props.onDelete && <DeleteFilled className={classes.icon} onClick={props.onDelete} />}\r\n </div>\r\n );\r\n};\r\n"]}
@@ -0,0 +1,14 @@
1
+ import type { FunctionComponent, PropsWithChildren } from "react";
2
+ type PositionedPopoverProps = {
3
+ x: number;
4
+ y: number;
5
+ visible: boolean;
6
+ hide: () => void;
7
+ };
8
+ /**
9
+ * PositionedPopover component that shows a popover at specific coordinates
10
+ * @param props - The component props
11
+ * @returns The positioned popover component
12
+ */
13
+ export declare const PositionedPopover: FunctionComponent<PropsWithChildren<PositionedPopoverProps>>;
14
+ export {};
@@ -0,0 +1,34 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Popover, PopoverSurface, PopoverTrigger } from "@fluentui/react-components";
3
+ import { useState, useEffect } from "react";
4
+ /**
5
+ * PositionedPopover component that shows a popover at specific coordinates
6
+ * @param props - The component props
7
+ * @returns The positioned popover component
8
+ */
9
+ export const PositionedPopover = (props) => {
10
+ const [open, setOpen] = useState(false);
11
+ useEffect(() => {
12
+ setOpen(props.visible);
13
+ }, [props.visible, props.x, props.y]);
14
+ const handleOpenChange = (_, data) => {
15
+ setOpen(data.open);
16
+ if (!data.open) {
17
+ props.hide();
18
+ }
19
+ };
20
+ return (_jsxs(Popover, { open: open, onOpenChange: handleOpenChange, positioning: {
21
+ position: "below", // Places the popover directly below the trigger element
22
+ align: "center", // Centers the popover horizontally relative to the trigger element
23
+ autoSize: "height-always", //Automatically adjusts the popover height to fit within the viewport
24
+ fallbackPositions: ["above", "after", "before"], //If the primary position doesn't fit, automatically tries these positions in order
25
+ }, withArrow: false, children: [_jsx(PopoverTrigger, { children: _jsx("div", { style: {
26
+ position: "absolute",
27
+ left: `${props.x}px`,
28
+ top: `${props.y}px`,
29
+ width: 1,
30
+ height: 1,
31
+ pointerEvents: "none", // so it's invisible to interaction
32
+ } }) }), _jsx(PopoverSurface, { children: props.children })] }));
33
+ };
34
+ //# sourceMappingURL=positionedPopover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"positionedPopover.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/positionedPopover.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAGrF,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,OAAO,CAAC;AAS5C;;;;GAIG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAiE,CAAC,KAAK,EAAE,EAAE;IACrG,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAExC,SAAS,CAAC,GAAG,EAAE;QACX,OAAO,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IAEtC,MAAM,gBAAgB,GAAG,CAAC,CAAoB,EAAE,IAAsB,EAAE,EAAE;QACtE,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEnB,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACb,KAAK,CAAC,IAAI,EAAE,CAAC;QACjB,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,CACH,MAAC,OAAO,IACJ,IAAI,EAAE,IAAI,EACV,YAAY,EAAE,gBAAgB,EAC9B,WAAW,EAAE;YACT,QAAQ,EAAE,OAAO,EAAE,wDAAwD;YAC3E,KAAK,EAAE,QAAQ,EAAE,mEAAmE;YACpF,QAAQ,EAAE,eAAe,EAAE,qEAAqE;YAChG,iBAAiB,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,mFAAmF;SACvI,EACD,SAAS,EAAE,KAAK,aAEhB,KAAC,cAAc,cAEX,cACI,KAAK,EAAE;wBACH,QAAQ,EAAE,UAAU;wBACpB,IAAI,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI;wBACpB,GAAG,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI;wBACnB,KAAK,EAAE,CAAC;wBACR,MAAM,EAAE,CAAC;wBACT,aAAa,EAAE,MAAM,EAAE,mCAAmC;qBAC7D,GACH,GACW,EACjB,KAAC,cAAc,cAAE,KAAK,CAAC,QAAQ,GAAkB,IAC3C,CACb,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { Popover, PopoverSurface, PopoverTrigger } from \"@fluentui/react-components\";\r\nimport type { OnOpenChangeData, OpenPopoverEvents } from \"@fluentui/react-components\";\r\nimport type { FunctionComponent, PropsWithChildren } from \"react\";\r\nimport { useState, useEffect } from \"react\";\r\n\r\ntype PositionedPopoverProps = {\r\n x: number;\r\n y: number;\r\n visible: boolean;\r\n hide: () => void;\r\n};\r\n\r\n/**\r\n * PositionedPopover component that shows a popover at specific coordinates\r\n * @param props - The component props\r\n * @returns The positioned popover component\r\n */\r\nexport const PositionedPopover: FunctionComponent<PropsWithChildren<PositionedPopoverProps>> = (props) => {\r\n const [open, setOpen] = useState(false);\r\n\r\n useEffect(() => {\r\n setOpen(props.visible);\r\n }, [props.visible, props.x, props.y]);\r\n\r\n const handleOpenChange = (_: OpenPopoverEvents, data: OnOpenChangeData) => {\r\n setOpen(data.open);\r\n\r\n if (!data.open) {\r\n props.hide();\r\n }\r\n };\r\n\r\n return (\r\n <Popover\r\n open={open}\r\n onOpenChange={handleOpenChange}\r\n positioning={{\r\n position: \"below\", // Places the popover directly below the trigger element\r\n align: \"center\", // Centers the popover horizontally relative to the trigger element\r\n autoSize: \"height-always\", //Automatically adjusts the popover height to fit within the viewport\r\n fallbackPositions: [\"above\", \"after\", \"before\"], //If the primary position doesn't fit, automatically tries these positions in order\r\n }}\r\n withArrow={false} // Removes arrow that points to trigger element\r\n >\r\n <PopoverTrigger>\r\n {/* Use the invisible div as the trigger location*/}\r\n <div\r\n style={{\r\n position: \"absolute\",\r\n left: `${props.x}px`,\r\n top: `${props.y}px`,\r\n width: 1,\r\n height: 1,\r\n pointerEvents: \"none\", // so it's invisible to interaction\r\n }}\r\n />\r\n </PopoverTrigger>\r\n <PopoverSurface>{props.children}</PopoverSurface>\r\n </Popover>\r\n );\r\n};\r\n"]}
@@ -0,0 +1,6 @@
1
+ type SearchProps = {
2
+ onChange: (val: string) => void;
3
+ placeholder?: string;
4
+ };
5
+ export declare const SearchBar: import("react").ForwardRefExoticComponent<SearchProps & import("react").RefAttributes<HTMLInputElement>>;
6
+ export {};
@@ -0,0 +1,16 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Field, SearchBox as FluentSearchBox, makeStyles } from "@fluentui/react-components";
3
+ import { forwardRef } from "react";
4
+ const useStyles = makeStyles({
5
+ search: {
6
+ minWidth: "50px",
7
+ },
8
+ });
9
+ export const SearchBar = forwardRef((props, ref) => {
10
+ const classes = useStyles();
11
+ const onChange = (_, data) => {
12
+ props.onChange(data.value);
13
+ };
14
+ return (_jsx(Field, { children: _jsx(FluentSearchBox, { ref: ref, className: classes.search, placeholder: props.placeholder, onChange: onChange }) }));
15
+ });
16
+ //# sourceMappingURL=searchBar.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"searchBar.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/searchBar.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,IAAI,eAAe,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAE7F,OAAO,EAAE,UAAU,EAAE,MAAM,OAAO,CAAC;AAMnC,MAAM,SAAS,GAAG,UAAU,CAAC;IACzB,MAAM,EAAE;QACJ,QAAQ,EAAE,MAAM;KACnB;CACJ,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,SAAS,GAAG,UAAU,CAAgC,CAAC,KAAK,EAAE,GAAG,EAAE,EAAE;IAC9E,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAgE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;QACtF,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,OAAO,CACH,KAAC,KAAK,cACF,KAAC,eAAe,IAAC,GAAG,EAAE,GAAG,EAAE,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,GAAI,GACxG,CACX,CAAC;AACN,CAAC,CAAC,CAAC","sourcesContent":["import { Field, SearchBox as FluentSearchBox, makeStyles } from \"@fluentui/react-components\";\r\nimport type { InputOnChangeData, SearchBoxChangeEvent } from \"@fluentui/react-components\";\r\nimport { forwardRef } from \"react\";\r\n\r\ntype SearchProps = {\r\n onChange: (val: string) => void;\r\n placeholder?: string;\r\n};\r\nconst useStyles = makeStyles({\r\n search: {\r\n minWidth: \"50px\",\r\n },\r\n});\r\n\r\nexport const SearchBar = forwardRef<HTMLInputElement, SearchProps>((props, ref) => {\r\n const classes = useStyles();\r\n const onChange: (ev: SearchBoxChangeEvent, data: InputOnChangeData) => void = (_, data) => {\r\n props.onChange(data.value);\r\n };\r\n\r\n return (\r\n <Field>\r\n <FluentSearchBox ref={ref} className={classes.search} placeholder={props.placeholder} onChange={onChange} />\r\n </Field>\r\n );\r\n});\r\n"]}
@@ -1,6 +1,13 @@
1
- type SearchProps = {
2
- onChange: (val: string) => void;
3
- placeholder?: string;
1
+ import type { FunctionComponent } from "react";
2
+ type SearchBoxProps = {
3
+ items: string[];
4
+ onItemSelected: (item: string) => void;
5
+ title?: string;
4
6
  };
5
- export declare const SearchBox: (props: SearchProps) => import("react/jsx-runtime").JSX.Element;
7
+ /**
8
+ * SearchBox component that displays a popup with search functionality
9
+ * @param props - The component props
10
+ * @returns The search box component
11
+ */
12
+ export declare const SearchBox: FunctionComponent<SearchBoxProps>;
6
13
  export {};
@@ -1,15 +1,97 @@
1
- import { jsx as _jsx } from "react/jsx-runtime";
2
- import { Field, SearchBox as FluentSearchBox, makeStyles } from "@fluentui/react-components";
3
- const useStyles = makeStyles({
4
- search: {
5
- minWidth: "50px",
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { makeStyles, tokens } from "@fluentui/react-components";
3
+ import { SearchBar } from "./searchBar.js";
4
+ import { useState, useEffect } from "react";
5
+ const useSearchBoxStyles = makeStyles({
6
+ searchBox: {
7
+ width: "300px",
8
+ height: "400px",
9
+ backgroundColor: tokens.colorNeutralBackground1,
10
+ border: `${tokens.strokeWidthThick} solid ${tokens.colorNeutralStroke1}`,
11
+ borderRadius: tokens.borderRadiusMedium,
12
+ boxShadow: tokens.shadow16,
13
+ display: "grid",
14
+ gridTemplateRows: "auto auto 1fr",
15
+ overflow: "hidden", // Prevent content overflow
16
+ },
17
+ title: {
18
+ borderBottom: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke2}`,
19
+ margin: tokens.spacingVerticalXS,
20
+ paddingBottom: tokens.spacingVerticalXS,
21
+ color: tokens.colorNeutralForeground1,
22
+ gridRow: "1",
23
+ fontSize: tokens.fontSizeBase300,
24
+ fontWeight: tokens.fontWeightSemibold,
25
+ },
26
+ filterContainer: {
27
+ margin: tokens.spacingVerticalXS,
28
+ paddingBottom: tokens.spacingVerticalXS,
29
+ gridRow: "2",
30
+ },
31
+ list: {
32
+ gridRow: "3",
33
+ overflowY: "auto",
34
+ display: "flex",
35
+ flexDirection: "column",
36
+ maxHeight: "100%",
37
+ },
38
+ listItem: {
39
+ marginLeft: tokens.spacingHorizontalXS,
40
+ marginRight: tokens.spacingHorizontalXS,
41
+ cursor: "pointer",
42
+ color: tokens.colorNeutralForeground1,
43
+ marginTop: tokens.spacingVerticalXXS,
44
+ marginBottom: tokens.spacingVerticalXXS,
45
+ padding: tokens.spacingVerticalXS,
46
+ borderRadius: tokens.borderRadiusSmall,
47
+ // eslint-disable-next-line @typescript-eslint/naming-convention
48
+ ":hover": {
49
+ backgroundColor: tokens.colorNeutralBackground2Hover,
50
+ },
51
+ },
52
+ listItemSelected: {
53
+ backgroundColor: tokens.colorBrandBackground,
54
+ color: tokens.colorNeutralForegroundOnBrand,
55
+ // eslint-disable-next-line @typescript-eslint/naming-convention
56
+ ":hover": {
57
+ backgroundColor: tokens.colorBrandBackgroundHover,
58
+ },
6
59
  },
7
60
  });
61
+ /**
62
+ * SearchBox component that displays a popup with search functionality
63
+ * @param props - The component props
64
+ * @returns The search box component
65
+ */
8
66
  export const SearchBox = (props) => {
9
- const classes = useStyles();
10
- const onChange = (_, data) => {
11
- props.onChange(data.value);
67
+ const classes = useSearchBoxStyles();
68
+ const [selectedIndex, setSelectedIndex] = useState(0);
69
+ const [items, setItems] = useState(props.items);
70
+ // In future could replace this with a fluent component like menuList or comboBox depending on desired UX
71
+ const onKeyDown = (evt) => {
72
+ if (items.length === 0) {
73
+ return;
74
+ }
75
+ if (evt.code === "Enter") {
76
+ props.onItemSelected(items[selectedIndex]);
77
+ return;
78
+ }
79
+ if (evt.code === "ArrowDown") {
80
+ setSelectedIndex((prev) => Math.min(prev + 1, items.length - 1));
81
+ return;
82
+ }
83
+ if (evt.code === "ArrowUp") {
84
+ setSelectedIndex((prev) => Math.max(prev - 1, 0));
85
+ return;
86
+ }
87
+ };
88
+ const onFilterChange = (filter) => {
89
+ const filteredItems = props.items.filter((item) => item.toLowerCase().includes(filter.toLowerCase()));
90
+ setItems(filteredItems);
12
91
  };
13
- return (_jsx(Field, { children: _jsx(FluentSearchBox, { className: classes.search, placeholder: props.placeholder, onChange: onChange }) }));
92
+ useEffect(() => {
93
+ setItems(props.items);
94
+ }, [props.items]);
95
+ return (_jsxs("div", { className: classes.searchBox, onKeyDown: onKeyDown, children: [props.title ? _jsx("div", { className: classes.title, children: props.title }) : null, _jsx("div", { className: classes.filterContainer, children: _jsx(SearchBar, { onChange: onFilterChange, placeholder: "Search..." }) }), _jsx("div", { role: "listbox", className: classes.list, children: items.map((item, index) => (_jsx("div", { role: "option", className: `${classes.listItem} ${index === selectedIndex ? classes.listItemSelected : ""}`, onClick: () => props.onItemSelected(item), children: item }, item))) })] }));
14
96
  };
15
97
  //# sourceMappingURL=searchBox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"searchBox.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/searchBox.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,SAAS,IAAI,eAAe,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AAQ7F,MAAM,SAAS,GAAG,UAAU,CAAC;IACzB,MAAM,EAAE;QACJ,QAAQ,EAAE,MAAM;KACnB;CACJ,CAAC,CAAC;AACH,MAAM,CAAC,MAAM,SAAS,GAAG,CAAC,KAAkB,EAAE,EAAE;IAC5C,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAC5B,MAAM,QAAQ,GAAgE,CAAC,CAAC,EAAE,IAAI,EAAE,EAAE;QACtF,KAAK,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAC/B,CAAC,CAAC;IAEF,OAAO,CACH,KAAC,KAAK,cACF,KAAC,eAAe,IAAC,SAAS,EAAE,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,EAAE,QAAQ,EAAE,QAAQ,GAAI,GAC9F,CACX,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { Field, SearchBox as FluentSearchBox, makeStyles } from \"@fluentui/react-components\";\r\nimport type { InputOnChangeData } from \"@fluentui/react-components\";\r\nimport type { SearchBoxChangeEvent } from \"@fluentui/react-components\";\r\n\r\ntype SearchProps = {\r\n onChange: (val: string) => void;\r\n placeholder?: string;\r\n};\r\nconst useStyles = makeStyles({\r\n search: {\r\n minWidth: \"50px\",\r\n },\r\n});\r\nexport const SearchBox = (props: SearchProps) => {\r\n const classes = useStyles();\r\n const onChange: (ev: SearchBoxChangeEvent, data: InputOnChangeData) => void = (_, data) => {\r\n props.onChange(data.value);\r\n };\r\n\r\n return (\r\n <Field>\r\n <FluentSearchBox className={classes.search} placeholder={props.placeholder} onChange={onChange} />\r\n </Field>\r\n );\r\n};\r\n"]}
1
+ {"version":3,"file":"searchBox.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/searchBox.tsx"],"names":[],"mappings":"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","sourcesContent":["import { makeStyles, tokens } from \"@fluentui/react-components\";\r\nimport { SearchBar } from \"./searchBar\";\r\nimport type { FunctionComponent } from \"react\";\r\nimport { useState, useEffect } from \"react\";\r\n\r\ntype SearchBoxProps = {\r\n items: string[];\r\n onItemSelected: (item: string) => void;\r\n title?: string;\r\n};\r\n\r\nconst useSearchBoxStyles = makeStyles({\r\n searchBox: {\r\n width: \"300px\",\r\n height: \"400px\",\r\n backgroundColor: tokens.colorNeutralBackground1,\r\n border: `${tokens.strokeWidthThick} solid ${tokens.colorNeutralStroke1}`,\r\n borderRadius: tokens.borderRadiusMedium,\r\n boxShadow: tokens.shadow16,\r\n display: \"grid\",\r\n gridTemplateRows: \"auto auto 1fr\",\r\n overflow: \"hidden\", // Prevent content overflow\r\n },\r\n title: {\r\n borderBottom: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke2}`,\r\n margin: tokens.spacingVerticalXS,\r\n paddingBottom: tokens.spacingVerticalXS,\r\n color: tokens.colorNeutralForeground1,\r\n gridRow: \"1\",\r\n fontSize: tokens.fontSizeBase300,\r\n fontWeight: tokens.fontWeightSemibold,\r\n },\r\n filterContainer: {\r\n margin: tokens.spacingVerticalXS,\r\n paddingBottom: tokens.spacingVerticalXS,\r\n gridRow: \"2\",\r\n },\r\n list: {\r\n gridRow: \"3\",\r\n overflowY: \"auto\",\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n maxHeight: \"100%\",\r\n },\r\n listItem: {\r\n marginLeft: tokens.spacingHorizontalXS,\r\n marginRight: tokens.spacingHorizontalXS,\r\n cursor: \"pointer\",\r\n color: tokens.colorNeutralForeground1,\r\n marginTop: tokens.spacingVerticalXXS,\r\n marginBottom: tokens.spacingVerticalXXS,\r\n padding: tokens.spacingVerticalXS,\r\n borderRadius: tokens.borderRadiusSmall,\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \":hover\": {\r\n backgroundColor: tokens.colorNeutralBackground2Hover,\r\n },\r\n },\r\n listItemSelected: {\r\n backgroundColor: tokens.colorBrandBackground,\r\n color: tokens.colorNeutralForegroundOnBrand,\r\n\r\n // eslint-disable-next-line @typescript-eslint/naming-convention\r\n \":hover\": {\r\n backgroundColor: tokens.colorBrandBackgroundHover,\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * SearchBox component that displays a popup with search functionality\r\n * @param props - The component props\r\n * @returns The search box component\r\n */\r\nexport const SearchBox: FunctionComponent<SearchBoxProps> = (props) => {\r\n const classes = useSearchBoxStyles();\r\n const [selectedIndex, setSelectedIndex] = useState(0);\r\n const [items, setItems] = useState(props.items);\r\n // In future could replace this with a fluent component like menuList or comboBox depending on desired UX\r\n const onKeyDown = (evt: React.KeyboardEvent) => {\r\n if (items.length === 0) {\r\n return;\r\n }\r\n if (evt.code === \"Enter\") {\r\n props.onItemSelected(items[selectedIndex]);\r\n return;\r\n }\r\n\r\n if (evt.code === \"ArrowDown\") {\r\n setSelectedIndex((prev) => Math.min(prev + 1, items.length - 1));\r\n return;\r\n }\r\n\r\n if (evt.code === \"ArrowUp\") {\r\n setSelectedIndex((prev) => Math.max(prev - 1, 0));\r\n return;\r\n }\r\n };\r\n\r\n const onFilterChange = (filter: string) => {\r\n const filteredItems = props.items.filter((item) => item.toLowerCase().includes(filter.toLowerCase()));\r\n setItems(filteredItems);\r\n };\r\n\r\n useEffect(() => {\r\n setItems(props.items);\r\n }, [props.items]);\r\n\r\n return (\r\n <div className={classes.searchBox} onKeyDown={onKeyDown}>\r\n {props.title ? <div className={classes.title}>{props.title}</div> : null}\r\n <div className={classes.filterContainer}>\r\n <SearchBar onChange={onFilterChange} placeholder=\"Search...\" />\r\n </div>\r\n <div role=\"listbox\" className={classes.list}>\r\n {items.map((item, index) => (\r\n <div\r\n role=\"option\"\r\n key={item}\r\n className={`${classes.listItem} ${index === selectedIndex ? classes.listItemSelected : \"\"}`}\r\n onClick={() => props.onItemSelected(item)}\r\n >\r\n {item}\r\n </div>\r\n ))}\r\n </div>\r\n </div>\r\n );\r\n};\r\n"]}
@@ -21,5 +21,7 @@ export declare class SearchBoxComponent extends React.Component<ISearchBoxCompon
21
21
  onFilterChange(evt: React.ChangeEvent<HTMLInputElement>): void;
22
22
  onNewNodeRequested(name: string): void;
23
23
  onKeyDown(evt: React.KeyboardEvent): void;
24
- render(): import("react/jsx-runtime").JSX.Element | null;
24
+ renderFluent(): import("react/jsx-runtime").JSX.Element;
25
+ renderOriginal(): import("react/jsx-runtime").JSX.Element | null;
26
+ render(): import("react/jsx-runtime").JSX.Element;
25
27
  }
@@ -2,6 +2,9 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import * as React from "react";
3
3
  import "./searchBox.scss";
4
4
  import { NodeLedger } from "./nodeLedger.js";
5
+ import { ToolContext } from "../fluent/hoc/fluentToolWrapper.js";
6
+ import { PositionedPopover } from "../fluent/primitives/positionedPopover.js";
7
+ import { SearchBox } from "../fluent/primitives/searchBox.js";
5
8
  /**
6
9
  * The search box component.
7
10
  */
@@ -53,7 +56,25 @@ export class SearchBoxComponent extends React.Component {
53
56
  return;
54
57
  }
55
58
  }
56
- render() {
59
+ renderFluent() {
60
+ // Note this function no longer uses other helpers from this file for easy non-fluent removal
61
+ // Sort and deduplicate the node names.
62
+ this._nodes = Array.from(new Set(NodeLedger.RegisteredNodeNames.sort()));
63
+ const formattedNodes = this._nodes.map((name) => NodeLedger.NameFormatter(name));
64
+ return (_jsx(PositionedPopover, { x: this._targetX, y: this._targetY, visible: this.state.isVisible, hide: () => {
65
+ this.props.stateManager.modalIsDisplayed = false;
66
+ }, children: _jsx(SearchBox, { items: formattedNodes, onItemSelected: (item) => {
67
+ const originalName = this._nodes[formattedNodes.indexOf(item)];
68
+ this.props.stateManager.onNewBlockRequiredObservable.notifyObservers({
69
+ type: originalName,
70
+ targetX: this._targetX,
71
+ targetY: this._targetY,
72
+ needRepositioning: true,
73
+ smartAdd: true,
74
+ });
75
+ }, title: "Add a node" }) }));
76
+ }
77
+ renderOriginal() {
57
78
  if (!this.state.isVisible) {
58
79
  return null;
59
80
  }
@@ -88,5 +109,8 @@ export class SearchBoxComponent extends React.Component {
88
109
  return (_jsx("div", { className: "graph-search-box-list-item " + (this.state.selectedIndex === i ? "selected " : ""), onClick: () => this.onNewNodeRequested(name), children: NodeLedger.NameFormatter(name) }, name));
89
110
  }) })] })] }));
90
111
  }
112
+ render() {
113
+ return _jsx(ToolContext.Consumer, { children: ({ useFluent }) => (useFluent ? this.renderFluent() : this.renderOriginal()) });
114
+ }
91
115
  }
92
116
  //# sourceMappingURL=searchBox.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"searchBox.js","sourceRoot":"","sources":["../../../../dev/sharedUiComponents/src/nodeGraphSystem/searchBox.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from \"react\";\r\nimport type { StateManager } from \"./stateManager\";\r\nimport \"./searchBox.scss\";\r\nimport { NodeLedger } from \"./nodeLedger\";\r\n\r\nexport interface ISearchBoxComponentProps {\r\n stateManager: StateManager;\r\n}\r\n\r\n/**\r\n * The search box component.\r\n */\r\nexport class SearchBoxComponent extends React.Component<ISearchBoxComponentProps, { isVisible: boolean; filter: string; selectedIndex: number }> {\r\n private _handleEscKey: (evt: KeyboardEvent) => void;\r\n private _targetX: number;\r\n private _targetY: number;\r\n private _nodes: string[];\r\n\r\n constructor(props: ISearchBoxComponentProps) {\r\n super(props);\r\n\r\n this.state = { isVisible: false, filter: \"\", selectedIndex: 0 };\r\n\r\n this._handleEscKey = (evt: KeyboardEvent) => {\r\n if (evt.key === \"Escape\") {\r\n this.hide();\r\n }\r\n };\r\n\r\n this.props.stateManager.onSearchBoxRequiredObservable.add((loc) => {\r\n this._targetX = loc.x;\r\n this._targetY = loc.y;\r\n this.setState({ isVisible: true, filter: \"\", selectedIndex: 0 });\r\n this.props.stateManager.hostDocument.addEventListener(\"keydown\", this._handleEscKey);\r\n });\r\n }\r\n\r\n hide() {\r\n this.setState({ isVisible: false });\r\n this.props.stateManager.modalIsDisplayed = false;\r\n this.props.stateManager.hostDocument.removeEventListener(\"keydown\", this._handleEscKey);\r\n }\r\n\r\n onFilterChange(evt: React.ChangeEvent<HTMLInputElement>) {\r\n this.setState({ filter: evt.target.value });\r\n }\r\n\r\n onNewNodeRequested(name: string) {\r\n this.props.stateManager.onNewBlockRequiredObservable.notifyObservers({\r\n type: name,\r\n targetX: this._targetX,\r\n targetY: this._targetY,\r\n needRepositioning: true,\r\n smartAdd: true,\r\n });\r\n\r\n this.hide();\r\n }\r\n\r\n onKeyDown(evt: React.KeyboardEvent) {\r\n if (evt.code === \"Enter\" && this._nodes.length > 0) {\r\n this.onNewNodeRequested(this._nodes[this.state.selectedIndex]);\r\n return;\r\n }\r\n\r\n if (evt.code === \"ArrowDown\" && this._nodes.length > 0) {\r\n this.setState({ selectedIndex: Math.min(this.state.selectedIndex + 1, this._nodes.length - 1) });\r\n return;\r\n }\r\n\r\n if (evt.code === \"ArrowUp\" && this._nodes.length > 0) {\r\n this.setState({ selectedIndex: Math.max(this.state.selectedIndex - 1, 0) });\r\n return;\r\n }\r\n }\r\n\r\n override render() {\r\n if (!this.state.isVisible) {\r\n return null;\r\n }\r\n\r\n const expectedWidth = 300;\r\n const expectedHeight = 400;\r\n\r\n // Sort and deduplicate the node names.\r\n this._nodes = Array.from(new Set(NodeLedger.RegisteredNodeNames.sort()));\r\n\r\n if (this.state.filter) {\r\n const filter = this.state.filter.toLowerCase().trim();\r\n this._nodes = this._nodes.filter((name) => NodeLedger.NameFormatter(name).toLowerCase().includes(filter));\r\n }\r\n\r\n const containerRect = this.props.stateManager.hostDocument.getElementById(\"graph-canvas\")!.getBoundingClientRect();\r\n const targetX = this._targetX - (expectedWidth / 2 + containerRect.x);\r\n const targetY = this._targetY - (expectedHeight / 2 + containerRect.y);\r\n const locStyle = {\r\n left: targetX + \"px\",\r\n top: targetY + \"px\",\r\n };\r\n\r\n if (targetX + expectedWidth > containerRect.width) {\r\n locStyle.left = containerRect.width - expectedWidth - 10 + \"px\";\r\n } else if (targetX < 10) {\r\n locStyle.left = \"10px\";\r\n }\r\n\r\n if (targetY + expectedHeight > containerRect.height) {\r\n locStyle.top = containerRect.height - expectedHeight - 10 + \"px\";\r\n } else if (targetY < 10) {\r\n locStyle.top = \"10px\";\r\n }\r\n\r\n return (\r\n <div id=\"graph-search-container\">\r\n <div id=\"graph-search-picking-blocker\" onClick={() => this.hide()}></div>\r\n <div id=\"graph-search-box\" style={locStyle}>\r\n <div className=\"graph-search-box-title\">Add a node</div>\r\n <input\r\n type=\"text\"\r\n placeholder=\"Search...\"\r\n onChange={(evt) => this.onFilterChange(evt)}\r\n onKeyDown={(evt) => this.onKeyDown(evt)}\r\n value={this.state.filter}\r\n className=\"graph-search-box-filter\"\r\n autoFocus={true}\r\n tabIndex={0}\r\n />\r\n <div className=\"graph-search-box-list\">\r\n {this._nodes.map((name, i) => {\r\n return (\r\n <div\r\n className={\"graph-search-box-list-item \" + (this.state.selectedIndex === i ? \"selected \" : \"\")}\r\n onClick={() => this.onNewNodeRequested(name)}\r\n key={name}\r\n >\r\n {NodeLedger.NameFormatter(name)}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"searchBox.js","sourceRoot":"","sources":["../../../../dev/sharedUiComponents/src/nodeGraphSystem/searchBox.tsx"],"names":[],"mappings":"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","sourcesContent":["import * as React from \"react\";\r\nimport type { StateManager } from \"./stateManager\";\r\nimport \"./searchBox.scss\";\r\nimport { NodeLedger } from \"./nodeLedger\";\r\nimport { ToolContext } from \"../fluent/hoc/fluentToolWrapper\";\r\nimport { PositionedPopover } from \"../fluent/primitives/positionedPopover\";\r\nimport { SearchBox } from \"../fluent/primitives/searchBox\";\r\n\r\nexport interface ISearchBoxComponentProps {\r\n stateManager: StateManager;\r\n}\r\n\r\n/**\r\n * The search box component.\r\n */\r\nexport class SearchBoxComponent extends React.Component<ISearchBoxComponentProps, { isVisible: boolean; filter: string; selectedIndex: number }> {\r\n private _handleEscKey: (evt: KeyboardEvent) => void;\r\n private _targetX: number;\r\n private _targetY: number;\r\n private _nodes: string[];\r\n\r\n constructor(props: ISearchBoxComponentProps) {\r\n super(props);\r\n\r\n this.state = { isVisible: false, filter: \"\", selectedIndex: 0 };\r\n\r\n this._handleEscKey = (evt: KeyboardEvent) => {\r\n if (evt.key === \"Escape\") {\r\n this.hide();\r\n }\r\n };\r\n\r\n this.props.stateManager.onSearchBoxRequiredObservable.add((loc) => {\r\n this._targetX = loc.x;\r\n this._targetY = loc.y;\r\n this.setState({ isVisible: true, filter: \"\", selectedIndex: 0 });\r\n this.props.stateManager.hostDocument.addEventListener(\"keydown\", this._handleEscKey);\r\n });\r\n }\r\n\r\n hide() {\r\n this.setState({ isVisible: false });\r\n this.props.stateManager.modalIsDisplayed = false;\r\n this.props.stateManager.hostDocument.removeEventListener(\"keydown\", this._handleEscKey);\r\n }\r\n\r\n onFilterChange(evt: React.ChangeEvent<HTMLInputElement>) {\r\n this.setState({ filter: evt.target.value });\r\n }\r\n\r\n onNewNodeRequested(name: string) {\r\n this.props.stateManager.onNewBlockRequiredObservable.notifyObservers({\r\n type: name,\r\n targetX: this._targetX,\r\n targetY: this._targetY,\r\n needRepositioning: true,\r\n smartAdd: true,\r\n });\r\n\r\n this.hide();\r\n }\r\n\r\n onKeyDown(evt: React.KeyboardEvent) {\r\n if (evt.code === \"Enter\" && this._nodes.length > 0) {\r\n this.onNewNodeRequested(this._nodes[this.state.selectedIndex]);\r\n return;\r\n }\r\n\r\n if (evt.code === \"ArrowDown\" && this._nodes.length > 0) {\r\n this.setState({ selectedIndex: Math.min(this.state.selectedIndex + 1, this._nodes.length - 1) });\r\n return;\r\n }\r\n\r\n if (evt.code === \"ArrowUp\" && this._nodes.length > 0) {\r\n this.setState({ selectedIndex: Math.max(this.state.selectedIndex - 1, 0) });\r\n return;\r\n }\r\n }\r\n\r\n renderFluent() {\r\n // Note this function no longer uses other helpers from this file for easy non-fluent removal\r\n\r\n // Sort and deduplicate the node names.\r\n this._nodes = Array.from(new Set(NodeLedger.RegisteredNodeNames.sort()));\r\n const formattedNodes = this._nodes.map((name) => NodeLedger.NameFormatter(name));\r\n\r\n return (\r\n <PositionedPopover\r\n x={this._targetX}\r\n y={this._targetY}\r\n visible={this.state.isVisible}\r\n hide={() => {\r\n this.props.stateManager.modalIsDisplayed = false;\r\n }}\r\n >\r\n <SearchBox\r\n items={formattedNodes}\r\n onItemSelected={(item: string) => {\r\n const originalName = this._nodes[formattedNodes.indexOf(item)];\r\n this.props.stateManager.onNewBlockRequiredObservable.notifyObservers({\r\n type: originalName,\r\n targetX: this._targetX,\r\n targetY: this._targetY,\r\n needRepositioning: true,\r\n smartAdd: true,\r\n });\r\n }}\r\n title=\"Add a node\"\r\n />\r\n </PositionedPopover>\r\n );\r\n }\r\n\r\n renderOriginal() {\r\n if (!this.state.isVisible) {\r\n return null;\r\n }\r\n\r\n const expectedWidth = 300;\r\n const expectedHeight = 400;\r\n\r\n // Sort and deduplicate the node names.\r\n this._nodes = Array.from(new Set(NodeLedger.RegisteredNodeNames.sort()));\r\n\r\n if (this.state.filter) {\r\n const filter = this.state.filter.toLowerCase().trim();\r\n this._nodes = this._nodes.filter((name) => NodeLedger.NameFormatter(name).toLowerCase().includes(filter));\r\n }\r\n\r\n const containerRect = this.props.stateManager.hostDocument.getElementById(\"graph-canvas\")!.getBoundingClientRect();\r\n const targetX = this._targetX - (expectedWidth / 2 + containerRect.x);\r\n const targetY = this._targetY - (expectedHeight / 2 + containerRect.y);\r\n const locStyle = {\r\n left: targetX + \"px\",\r\n top: targetY + \"px\",\r\n };\r\n\r\n if (targetX + expectedWidth > containerRect.width) {\r\n locStyle.left = containerRect.width - expectedWidth - 10 + \"px\";\r\n } else if (targetX < 10) {\r\n locStyle.left = \"10px\";\r\n }\r\n\r\n if (targetY + expectedHeight > containerRect.height) {\r\n locStyle.top = containerRect.height - expectedHeight - 10 + \"px\";\r\n } else if (targetY < 10) {\r\n locStyle.top = \"10px\";\r\n }\r\n\r\n return (\r\n <div id=\"graph-search-container\">\r\n <div id=\"graph-search-picking-blocker\" onClick={() => this.hide()}></div>\r\n <div id=\"graph-search-box\" style={locStyle}>\r\n <div className=\"graph-search-box-title\">Add a node</div>\r\n <input\r\n type=\"text\"\r\n placeholder=\"Search...\"\r\n onChange={(evt) => this.onFilterChange(evt)}\r\n onKeyDown={(evt) => this.onKeyDown(evt)}\r\n value={this.state.filter}\r\n className=\"graph-search-box-filter\"\r\n autoFocus={true}\r\n tabIndex={0}\r\n />\r\n <div className=\"graph-search-box-list\">\r\n {this._nodes.map((name, i) => {\r\n return (\r\n <div\r\n className={\"graph-search-box-list-item \" + (this.state.selectedIndex === i ? \"selected \" : \"\")}\r\n onClick={() => this.onNewNodeRequested(name)}\r\n key={name}\r\n >\r\n {NodeLedger.NameFormatter(name)}\r\n </div>\r\n );\r\n })}\r\n </div>\r\n </div>\r\n </div>\r\n );\r\n }\r\n\r\n override render() {\r\n return <ToolContext.Consumer>{({ useFluent }) => (useFluent ? this.renderFluent() : this.renderOriginal())}</ToolContext.Consumer>;\r\n }\r\n}\r\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@babylonjs/shared-ui-components",
3
- "version": "8.17.1",
3
+ "version": "8.18.0",
4
4
  "main": "index.js",
5
5
  "module": "index.js",
6
6
  "types": "index.d.ts",