@babylonjs/shared-ui-components 8.28.1 → 8.28.3

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.
@@ -56,6 +56,10 @@ const usePropertyLineStyles = makeStyles({
56
56
  expandedContent: {
57
57
  paddingLeft: "20px",
58
58
  },
59
+ infoPopup: {
60
+ whiteSpace: "normal",
61
+ wordBreak: "break-word",
62
+ },
59
63
  });
60
64
  /**
61
65
  * A reusable component that renders a property line with a label and child content, and an optional description, copy button, and expandable section.
@@ -70,7 +74,7 @@ export const PropertyLine = forwardRef((props, ref) => {
70
74
  const [expanded, setExpanded] = useState("expandByDefault" in props ? props.expandByDefault : false);
71
75
  const cachedVal = useRef(nullable ? props.value : null);
72
76
  const { disableCopy } = useContext(ToolContext);
73
- const description = props.description ?? (props.docLink ? _jsx(Link, { href: props.docLink, children: props.description ?? "Docs" }) : props.description);
77
+ const description = props.docLink ? _jsx(Link, { href: props.docLink, children: props.description ?? "Docs" }) : props.description;
74
78
  // Process children to handle nullable state -- creating component in disabled state with default value in lieu of null value
75
79
  const processedChildren = (nullable || ignoreNullable) && isValidElement(children)
76
80
  ? cloneElement(children, {
@@ -80,7 +84,7 @@ export const PropertyLine = forwardRef((props, ref) => {
80
84
  defaultValue: undefined, // Don't pass defaultValue to children as there is no guarantee how this will be used and we can't mix controlled + uncontrolled state
81
85
  })
82
86
  : children;
83
- return (_jsxs(LineContainer, { ref: ref, children: [_jsxs("div", { className: classes.line, children: [_jsx(InfoLabel, { className: classes.label, info: description, title: label, children: _jsx(Body1Strong, { className: classes.labelText, children: label }) }), _jsxs("div", { className: classes.rightContent, children: [nullable && !ignoreNullable && (
87
+ return (_jsxs(LineContainer, { ref: ref, children: [_jsxs("div", { className: classes.line, children: [_jsx(InfoLabel, { className: classes.label, info: description ? _jsx("div", { className: classes.infoPopup, children: description }) : undefined, title: label, children: _jsx(Body1Strong, { className: classes.labelText, children: label }) }), _jsxs("div", { className: classes.rightContent, children: [nullable && !ignoreNullable && (
84
88
  // If this is a nullableProperty and ignoreNullable was not sent, display a checkbox used to toggle null ('checked' means 'non null')
85
89
  _jsx(Checkbox, { checked: !(props.value == null), onChange: (_, data) => {
86
90
  if (data.checked) {
@@ -1 +1 @@
1
- {"version":3,"file":"propertyLine.js","sourceRoot":"","sources":["../../../../../../dev/sharedUiComponents/src/fluent/hoc/propertyLines/propertyLine.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Body1, Body1Strong, Button, InfoLabel, Link, ToggleButton, Checkbox, makeStyles, tokens } from \"@fluentui/react-components\";\r\nimport { AddFilled, CopyRegular, SubtractFilled } from \"@fluentui/react-icons\";\r\nimport type { FunctionComponent, HTMLProps, PropsWithChildren } from \"react\";\r\nimport { useContext, useState, forwardRef, cloneElement, isValidElement, useRef } from \"react\";\r\nimport { Collapse } from \"../../primitives/collapse\";\r\nimport { copyCommandToClipboard } from \"../../../copyCommandToClipboard\";\r\nimport { ToolContext } from \"../fluentToolWrapper\";\r\nimport type { PrimitiveProps } from \"../../primitives/primitive\";\r\n\r\nconst usePropertyLineStyles = makeStyles({\r\n container: {\r\n width: \"100%\",\r\n display: \"flex\",\r\n flexDirection: \"column\", // Stack line + expanded content\r\n padding: `${tokens.spacingVerticalXS} 0px`,\r\n borderBottom: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke1}`,\r\n },\r\n line: {\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"flex-start\",\r\n width: \"100%\",\r\n },\r\n label: {\r\n flex: \"1 1 0\", // grow=1, shrink =1, basis = 0 initial size before\r\n minWidth: \"50px\",\r\n textAlign: \"left\",\r\n whiteSpace: \"nowrap\",\r\n overflow: \"hidden\",\r\n textOverflow: \"ellipsis\",\r\n },\r\n labelText: {\r\n whiteSpace: \"nowrap\",\r\n },\r\n rightContent: {\r\n flex: \"0 1 auto\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"flex-end\",\r\n gap: tokens.spacingHorizontalS,\r\n },\r\n button: {\r\n marginLeft: tokens.spacingHorizontalXXS,\r\n margin: 0,\r\n padding: 0,\r\n border: 0,\r\n minWidth: 0,\r\n },\r\n fillRestOfRightContentWidth: {\r\n flex: 1,\r\n display: \"flex\",\r\n justifyContent: \"flex-end\",\r\n alignItems: \"center\",\r\n },\r\n expandButton: {\r\n margin: 0,\r\n },\r\n expandedContent: {\r\n paddingLeft: \"20px\",\r\n },\r\n});\r\n\r\ntype BasePropertyLineProps = {\r\n /**\r\n * The name of the property to display in the property line.\r\n */\r\n label: string;\r\n /**\r\n * Optional description for the property, shown on hover of the info icon\r\n */\r\n description?: string;\r\n /**\r\n * Optional function returning a string to copy to clipboard.\r\n */\r\n onCopy?: () => string;\r\n /**\r\n * Link to the documentation for this property, available from the info icon either linked from the description (if provided) or default 'docs' text\r\n */\r\n docLink?: string;\r\n};\r\n\r\n// Only require value/onChange/defaultValue props if nullable is true\r\ntype NullableProperty<ValueT> = {\r\n nullable: true;\r\n ignoreNullable: false;\r\n value: ValueT;\r\n onChange: (value: ValueT) => void;\r\n defaultValue?: ValueT;\r\n};\r\n\r\ntype IgnoreNullable<ValueT> = {\r\n ignoreNullable: true;\r\n nullable: false;\r\n value: ValueT;\r\n onChange: (value: ValueT) => void;\r\n defaultValue: ValueT;\r\n};\r\n\r\ntype NonNullableProperty = {\r\n nullable?: false;\r\n ignoreNullable?: false;\r\n};\r\n\r\n// Only expect optional expandByDefault prop if expandedContent is defined\r\ntype ExpandableProperty = {\r\n /**\r\n * If supplied, an 'expand' icon will be shown which, when clicked, renders this component within the property line.\r\n */\r\n expandedContent: JSX.Element;\r\n\r\n /**\r\n * If true, the expanded content will be shown by default.\r\n */\r\n expandByDefault?: boolean;\r\n};\r\n\r\n// If expanded content is undefined, don't expect expandByDefault prop\r\ntype NonExpandableProperty = {\r\n expandedContent?: undefined;\r\n};\r\n\r\nexport type PropertyLineProps<ValueT> = BasePropertyLineProps &\r\n (NullableProperty<ValueT> | NonNullableProperty | IgnoreNullable<ValueT>) &\r\n (ExpandableProperty | NonExpandableProperty);\r\n\r\n/**\r\n * A reusable component that renders a property line with a label and child content, and an optional description, copy button, and expandable section.\r\n *\r\n * @param props - The properties for the PropertyLine component.\r\n * @returns A React element representing the property line.\r\n *\r\n */\r\nexport const PropertyLine = forwardRef<HTMLDivElement, PropsWithChildren<PropertyLineProps<any>>>((props, ref) => {\r\n const classes = usePropertyLineStyles();\r\n const { label, onCopy, expandedContent, children, nullable, ignoreNullable } = props;\r\n\r\n const [expanded, setExpanded] = useState(\"expandByDefault\" in props ? props.expandByDefault : false);\r\n const cachedVal = useRef(nullable ? props.value : null);\r\n\r\n const { disableCopy } = useContext(ToolContext);\r\n\r\n const description = props.description ?? (props.docLink ? <Link href={props.docLink}>{props.description ?? \"Docs\"}</Link> : props.description);\r\n\r\n // Process children to handle nullable state -- creating component in disabled state with default value in lieu of null value\r\n const processedChildren =\r\n (nullable || ignoreNullable) && isValidElement(children)\r\n ? cloneElement(children, {\r\n ...children.props,\r\n disabled: children.props.disabled || (nullable && props.value == null),\r\n value: props.value ?? props.defaultValue,\r\n defaultValue: undefined, // Don't pass defaultValue to children as there is no guarantee how this will be used and we can't mix controlled + uncontrolled state\r\n })\r\n : children;\r\n\r\n return (\r\n <LineContainer ref={ref}>\r\n <div className={classes.line}>\r\n <InfoLabel className={classes.label} info={description} title={label}>\r\n <Body1Strong className={classes.labelText}>{label}</Body1Strong>\r\n </InfoLabel>\r\n <div className={classes.rightContent}>\r\n {nullable && !ignoreNullable && (\r\n // If this is a nullableProperty and ignoreNullable was not sent, display a checkbox used to toggle null ('checked' means 'non null')\r\n <Checkbox\r\n checked={!(props.value == null)}\r\n onChange={(_, data) => {\r\n if (data.checked) {\r\n // if checked this means we are returning to non-null, use cached value if exists. If no cached value, use default value\r\n cachedVal.current != null ? props.onChange(cachedVal.current) : props.onChange(props.defaultValue);\r\n } else {\r\n // if moving to un-checked state, this means moving to null value. Cache the old value and tell props.onChange(null)\r\n cachedVal.current = props.value;\r\n props.onChange(null);\r\n }\r\n }}\r\n title=\"Toggle null state\"\r\n />\r\n )}\r\n <div className={classes.fillRestOfRightContentWidth}>{processedChildren}</div>\r\n\r\n {expandedContent && (\r\n <ToggleButton\r\n appearance=\"transparent\"\r\n icon={expanded ? <SubtractFilled /> : <AddFilled />}\r\n className={classes.button}\r\n checked={expanded}\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n setExpanded((expanded) => !expanded);\r\n }}\r\n />\r\n )}\r\n\r\n {onCopy && !disableCopy && (\r\n <Button className={classes.button} id=\"copyProperty\" icon={<CopyRegular />} onClick={() => copyCommandToClipboard(onCopy())} title=\"Copy to clipboard\" />\r\n )}\r\n </div>\r\n </div>\r\n {expandedContent && (\r\n <Collapse visible={!!expanded}>\r\n <div className={classes.expandedContent}>{expandedContent}</div>\r\n </Collapse>\r\n )}\r\n </LineContainer>\r\n );\r\n});\r\n\r\nexport const LineContainer = forwardRef<HTMLDivElement, PropsWithChildren<HTMLProps<HTMLDivElement>>>((props, ref) => {\r\n const classes = usePropertyLineStyles();\r\n return (\r\n <div ref={ref} className={classes.container} {...props}>\r\n {props.children}\r\n </div>\r\n );\r\n});\r\n\r\nexport const PlaceholderPropertyLine: FunctionComponent<PrimitiveProps<any> & PropertyLineProps<any>> = (props) => {\r\n return (\r\n <PropertyLine {...props}>\r\n <Body1>{props.value}</Body1>\r\n </PropertyLine>\r\n );\r\n};\r\n"]}
1
+ {"version":3,"file":"propertyLine.js","sourceRoot":"","sources":["../../../../../../dev/sharedUiComponents/src/fluent/hoc/propertyLines/propertyLine.tsx"],"names":[],"mappings":"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","sourcesContent":["import { Body1, Body1Strong, Button, InfoLabel, Link, ToggleButton, Checkbox, makeStyles, tokens } from \"@fluentui/react-components\";\r\nimport { AddFilled, CopyRegular, SubtractFilled } from \"@fluentui/react-icons\";\r\nimport type { FunctionComponent, HTMLProps, PropsWithChildren } from \"react\";\r\nimport { useContext, useState, forwardRef, cloneElement, isValidElement, useRef } from \"react\";\r\nimport { Collapse } from \"../../primitives/collapse\";\r\nimport { copyCommandToClipboard } from \"../../../copyCommandToClipboard\";\r\nimport { ToolContext } from \"../fluentToolWrapper\";\r\nimport type { PrimitiveProps } from \"../../primitives/primitive\";\r\n\r\nconst usePropertyLineStyles = makeStyles({\r\n container: {\r\n width: \"100%\",\r\n display: \"flex\",\r\n flexDirection: \"column\", // Stack line + expanded content\r\n padding: `${tokens.spacingVerticalXS} 0px`,\r\n borderBottom: `${tokens.strokeWidthThin} solid ${tokens.colorNeutralStroke1}`,\r\n },\r\n line: {\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"flex-start\",\r\n width: \"100%\",\r\n },\r\n label: {\r\n flex: \"1 1 0\", // grow=1, shrink =1, basis = 0 initial size before\r\n minWidth: \"50px\",\r\n textAlign: \"left\",\r\n whiteSpace: \"nowrap\",\r\n overflow: \"hidden\",\r\n textOverflow: \"ellipsis\",\r\n },\r\n labelText: {\r\n whiteSpace: \"nowrap\",\r\n },\r\n rightContent: {\r\n flex: \"0 1 auto\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n justifyContent: \"flex-end\",\r\n gap: tokens.spacingHorizontalS,\r\n },\r\n button: {\r\n marginLeft: tokens.spacingHorizontalXXS,\r\n margin: 0,\r\n padding: 0,\r\n border: 0,\r\n minWidth: 0,\r\n },\r\n fillRestOfRightContentWidth: {\r\n flex: 1,\r\n display: \"flex\",\r\n justifyContent: \"flex-end\",\r\n alignItems: \"center\",\r\n },\r\n expandButton: {\r\n margin: 0,\r\n },\r\n expandedContent: {\r\n paddingLeft: \"20px\",\r\n },\r\n infoPopup: {\r\n whiteSpace: \"normal\",\r\n wordBreak: \"break-word\",\r\n },\r\n});\r\n\r\ntype BasePropertyLineProps = {\r\n /**\r\n * The name of the property to display in the property line.\r\n */\r\n label: string;\r\n /**\r\n * Optional description for the property, shown on hover of the info icon\r\n */\r\n description?: string;\r\n /**\r\n * Optional function returning a string to copy to clipboard.\r\n */\r\n onCopy?: () => string;\r\n /**\r\n * Link to the documentation for this property, available from the info icon either linked from the description (if provided) or default 'docs' text\r\n */\r\n docLink?: string;\r\n};\r\n\r\n// Only require value/onChange/defaultValue props if nullable is true\r\ntype NullableProperty<ValueT> = {\r\n nullable: true;\r\n ignoreNullable: false;\r\n value: ValueT;\r\n onChange: (value: ValueT) => void;\r\n defaultValue?: ValueT;\r\n};\r\n\r\ntype IgnoreNullable<ValueT> = {\r\n ignoreNullable: true;\r\n nullable: false;\r\n value: ValueT;\r\n onChange: (value: ValueT) => void;\r\n defaultValue: ValueT;\r\n};\r\n\r\ntype NonNullableProperty = {\r\n nullable?: false;\r\n ignoreNullable?: false;\r\n};\r\n\r\n// Only expect optional expandByDefault prop if expandedContent is defined\r\ntype ExpandableProperty = {\r\n /**\r\n * If supplied, an 'expand' icon will be shown which, when clicked, renders this component within the property line.\r\n */\r\n expandedContent: JSX.Element;\r\n\r\n /**\r\n * If true, the expanded content will be shown by default.\r\n */\r\n expandByDefault?: boolean;\r\n};\r\n\r\n// If expanded content is undefined, don't expect expandByDefault prop\r\ntype NonExpandableProperty = {\r\n expandedContent?: undefined;\r\n};\r\n\r\nexport type PropertyLineProps<ValueT> = BasePropertyLineProps &\r\n (NullableProperty<ValueT> | NonNullableProperty | IgnoreNullable<ValueT>) &\r\n (ExpandableProperty | NonExpandableProperty);\r\n\r\n/**\r\n * A reusable component that renders a property line with a label and child content, and an optional description, copy button, and expandable section.\r\n *\r\n * @param props - The properties for the PropertyLine component.\r\n * @returns A React element representing the property line.\r\n *\r\n */\r\nexport const PropertyLine = forwardRef<HTMLDivElement, PropsWithChildren<PropertyLineProps<any>>>((props, ref) => {\r\n const classes = usePropertyLineStyles();\r\n const { label, onCopy, expandedContent, children, nullable, ignoreNullable } = props;\r\n\r\n const [expanded, setExpanded] = useState(\"expandByDefault\" in props ? props.expandByDefault : false);\r\n const cachedVal = useRef(nullable ? props.value : null);\r\n\r\n const { disableCopy } = useContext(ToolContext);\r\n\r\n const description = props.docLink ? <Link href={props.docLink}>{props.description ?? \"Docs\"}</Link> : props.description;\r\n\r\n // Process children to handle nullable state -- creating component in disabled state with default value in lieu of null value\r\n const processedChildren =\r\n (nullable || ignoreNullable) && isValidElement(children)\r\n ? cloneElement(children, {\r\n ...children.props,\r\n disabled: children.props.disabled || (nullable && props.value == null),\r\n value: props.value ?? props.defaultValue,\r\n defaultValue: undefined, // Don't pass defaultValue to children as there is no guarantee how this will be used and we can't mix controlled + uncontrolled state\r\n })\r\n : children;\r\n\r\n return (\r\n <LineContainer ref={ref}>\r\n <div className={classes.line}>\r\n <InfoLabel className={classes.label} info={description ? <div className={classes.infoPopup}>{description}</div> : undefined} title={label}>\r\n <Body1Strong className={classes.labelText}>{label}</Body1Strong>\r\n </InfoLabel>\r\n <div className={classes.rightContent}>\r\n {nullable && !ignoreNullable && (\r\n // If this is a nullableProperty and ignoreNullable was not sent, display a checkbox used to toggle null ('checked' means 'non null')\r\n <Checkbox\r\n checked={!(props.value == null)}\r\n onChange={(_, data) => {\r\n if (data.checked) {\r\n // if checked this means we are returning to non-null, use cached value if exists. If no cached value, use default value\r\n cachedVal.current != null ? props.onChange(cachedVal.current) : props.onChange(props.defaultValue);\r\n } else {\r\n // if moving to un-checked state, this means moving to null value. Cache the old value and tell props.onChange(null)\r\n cachedVal.current = props.value;\r\n props.onChange(null);\r\n }\r\n }}\r\n title=\"Toggle null state\"\r\n />\r\n )}\r\n <div className={classes.fillRestOfRightContentWidth}>{processedChildren}</div>\r\n\r\n {expandedContent && (\r\n <ToggleButton\r\n appearance=\"transparent\"\r\n icon={expanded ? <SubtractFilled /> : <AddFilled />}\r\n className={classes.button}\r\n checked={expanded}\r\n onClick={(e) => {\r\n e.stopPropagation();\r\n setExpanded((expanded) => !expanded);\r\n }}\r\n />\r\n )}\r\n\r\n {onCopy && !disableCopy && (\r\n <Button className={classes.button} id=\"copyProperty\" icon={<CopyRegular />} onClick={() => copyCommandToClipboard(onCopy())} title=\"Copy to clipboard\" />\r\n )}\r\n </div>\r\n </div>\r\n {expandedContent && (\r\n <Collapse visible={!!expanded}>\r\n <div className={classes.expandedContent}>{expandedContent}</div>\r\n </Collapse>\r\n )}\r\n </LineContainer>\r\n );\r\n});\r\n\r\nexport const LineContainer = forwardRef<HTMLDivElement, PropsWithChildren<HTMLProps<HTMLDivElement>>>((props, ref) => {\r\n const classes = usePropertyLineStyles();\r\n return (\r\n <div ref={ref} className={classes.container} {...props}>\r\n {props.children}\r\n </div>\r\n );\r\n});\r\n\r\nexport const PlaceholderPropertyLine: FunctionComponent<PrimitiveProps<any> & PropertyLineProps<any>> = (props) => {\r\n return (\r\n <PropertyLine {...props}>\r\n <Body1>{props.value}</Body1>\r\n </PropertyLine>\r\n );\r\n};\r\n"]}
@@ -16,6 +16,10 @@ export type TensorPropertyLineProps<V extends Vector2 | Vector3 | Vector4 | Quat
16
16
  * Will be displayed in the input UI to indicate the unit of measurement
17
17
  */
18
18
  unit?: string;
19
+ /**
20
+ * Internal spinbutton's step
21
+ */
22
+ step?: number;
19
23
  /**
20
24
  * If passed, the UX will use the conversion functions to display/update values
21
25
  */
@@ -5,6 +5,7 @@ import { PropertyLine } from "./propertyLine.js";
5
5
  import { SyncedSliderPropertyLine } from "./syncedSliderPropertyLine.js";
6
6
  import { Quaternion, Vector2, Vector4 } from "@babylonjs/core/Maths/math.vector.js";
7
7
  import { Tools } from "@babylonjs/core/Misc/tools.js";
8
+ import { CalculatePrecision } from "../../primitives/spinButton.js";
8
9
  const HasZ = (vector) => !(vector instanceof Vector2);
9
10
  const HasW = (vector) => vector instanceof Vector4 || vector instanceof Quaternion;
10
11
  /**
@@ -15,7 +16,7 @@ const HasW = (vector) => vector instanceof Vector4 || vector instanceof Quaterni
15
16
  */
16
17
  const TensorPropertyLine = (props) => {
17
18
  const converted = (val) => (props.valueConverter ? props.valueConverter.from(val) : val);
18
- const formatted = (val) => converted(val).toFixed(2);
19
+ const formatted = (val) => converted(val).toFixed(props.step !== undefined ? CalculatePrecision(props.step) : 2);
19
20
  const [vector, setVector] = useState(props.value);
20
21
  const { min, max } = props;
21
22
  const onChange = (val, key) => {
@@ -25,13 +26,13 @@ const TensorPropertyLine = (props) => {
25
26
  setVector(newVector);
26
27
  props.onChange(newVector);
27
28
  };
28
- return (_jsx(PropertyLine, { ...props, expandedContent: _jsxs(_Fragment, { children: [_jsx(SyncedSliderPropertyLine, { label: "X", value: converted(vector.x), min: min, max: max, onChange: (val) => onChange(val, "x"), unit: props.unit }), _jsx(SyncedSliderPropertyLine, { label: "Y", value: converted(vector.y), min: min, max: max, onChange: (val) => onChange(val, "y"), unit: props.unit }), HasZ(vector) && (_jsx(SyncedSliderPropertyLine, { label: "Z", value: converted(vector.z), min: min, max: max, onChange: (val) => onChange(val, "z"), unit: props.unit })), HasW(vector) && (_jsx(SyncedSliderPropertyLine, { label: "W", value: converted(vector.w), min: min, max: max, onChange: (val) => onChange(val, "w"), unit: props.unit }))] }), children: _jsx(Body1, { children: `X: ${formatted(props.value.x)} | Y: ${formatted(props.value.y)}${HasZ(props.value) ? ` | Z: ${formatted(props.value.z)}` : ""}${HasW(props.value) ? ` | W: ${formatted(props.value.w)}` : ""}` }) }));
29
+ return (_jsx(PropertyLine, { ...props, onCopy: () => `(${vector.x}, ${vector.y} ${HasZ(vector) ? `, ${vector.z}` : ""}${HasW(vector) ? `, ${vector.w}` : ""})`, expandedContent: _jsxs(_Fragment, { children: [_jsx(SyncedSliderPropertyLine, { label: "X", value: converted(vector.x), min: min, max: max, onChange: (val) => onChange(val, "x"), unit: props.unit, step: props.step }), _jsx(SyncedSliderPropertyLine, { label: "Y", value: converted(vector.y), min: min, max: max, onChange: (val) => onChange(val, "y"), unit: props.unit, step: props.step }), HasZ(vector) && (_jsx(SyncedSliderPropertyLine, { label: "Z", value: converted(vector.z), min: min, max: max, onChange: (val) => onChange(val, "z"), unit: props.unit, step: props.step })), HasW(vector) && (_jsx(SyncedSliderPropertyLine, { label: "W", value: converted(vector.w), min: min, max: max, onChange: (val) => onChange(val, "w"), unit: props.unit, step: props.step }))] }), children: _jsx(Body1, { children: `X: ${formatted(props.value.x)} | Y: ${formatted(props.value.y)}${HasZ(props.value) ? ` | Z: ${formatted(props.value.z)}` : ""}${HasW(props.value) ? ` | W: ${formatted(props.value.w)}` : ""}` }) }));
29
30
  };
30
31
  const ToDegreesConverter = { from: Tools.ToDegrees, to: Tools.ToRadians };
31
32
  export const RotationVectorPropertyLine = (props) => {
32
33
  const min = props.useDegrees ? 0 : undefined;
33
34
  const max = props.useDegrees ? 360 : undefined;
34
- return _jsx(Vector3PropertyLine, { ...props, unit: props.useDegrees ? "deg" : "rad", valueConverter: props.useDegrees ? ToDegreesConverter : undefined, min: min, max: max });
35
+ return (_jsx(Vector3PropertyLine, { ...props, unit: props.useDegrees ? "deg" : "rad", valueConverter: props.useDegrees ? ToDegreesConverter : undefined, min: min, max: max, step: 0.001 }));
35
36
  };
36
37
  const QuaternionPropertyLineInternal = TensorPropertyLine;
37
38
  export const QuaternionPropertyLine = (props) => {
@@ -1 +1 @@
1
- {"version":3,"file":"vectorPropertyLine.js","sourceRoot":"","sources":["../../../../../../dev/sharedUiComponents/src/fluent/hoc/propertyLines/vectorPropertyLine.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from \"react\";\r\nimport type { FunctionComponent } from \"react\";\r\n\r\nimport { Body1 } from \"@fluentui/react-components\";\r\nimport { PropertyLine } from \"./propertyLine\";\r\nimport type { PrimitiveProps } from \"../../primitives/primitive\";\r\nimport type { PropertyLineProps } from \"./propertyLine\";\r\n\r\nimport { SyncedSliderPropertyLine } from \"./syncedSliderPropertyLine\";\r\nimport type { Vector3 } from \"core/Maths/math.vector\";\r\nimport { Quaternion, Vector2, Vector4 } from \"core/Maths/math.vector\";\r\nimport { Tools } from \"core/Misc/tools\";\r\n\r\nexport type TensorPropertyLineProps<V extends Vector2 | Vector3 | Vector4 | Quaternion> = PropertyLineProps<V> &\r\n PrimitiveProps<V> & {\r\n /**\r\n * If passed, all sliders will use this for the min value\r\n */\r\n min?: number;\r\n /**\r\n * If passed, all sliders will use this for the max value\r\n */\r\n max?: number;\r\n /**\r\n * Will be displayed in the input UI to indicate the unit of measurement\r\n */\r\n unit?: string;\r\n /**\r\n * If passed, the UX will use the conversion functions to display/update values\r\n */\r\n valueConverter?: {\r\n /**\r\n * Will call from(val) before displaying in the UX\r\n */\r\n from: (val: number) => number;\r\n /**\r\n * Will call to(val) before calling onChange\r\n */\r\n to: (val: number) => number;\r\n };\r\n };\r\n\r\nconst HasZ = (vector: Vector2 | Vector3 | Vector4 | Quaternion): vector is Vector3 => !(vector instanceof Vector2);\r\nconst HasW = (vector: Vector2 | Vector3 | Vector4 | Quaternion): vector is Vector4 => vector instanceof Vector4 || vector instanceof Quaternion;\r\n\r\n/**\r\n * Reusable component which renders a vector property line containing a label, vector value, and expandable XYZW values\r\n * The expanded section contains a slider/input box for each component of the vector (x, y, z, w)\r\n * @param props\r\n * @returns\r\n */\r\nconst TensorPropertyLine: FunctionComponent<TensorPropertyLineProps<Vector2 | Vector3 | Vector4 | Quaternion>> = (props) => {\r\n const converted = (val: number) => (props.valueConverter ? props.valueConverter.from(val) : val);\r\n const formatted = (val: number) => converted(val).toFixed(2);\r\n\r\n const [vector, setVector] = useState(props.value);\r\n const { min, max } = props;\r\n\r\n const onChange = (val: number, key: \"x\" | \"y\" | \"z\" | \"w\") => {\r\n const value = props.valueConverter ? props.valueConverter.to(val) : val;\r\n const newVector = vector.clone();\r\n (newVector as Vector4)[key] = value; // The syncedSlider for 'w' is only rendered when vector is a Vector4, so this is safe\r\n\r\n setVector(newVector);\r\n props.onChange(newVector);\r\n };\r\n\r\n return (\r\n <PropertyLine\r\n {...props}\r\n expandedContent={\r\n <>\r\n <SyncedSliderPropertyLine label=\"X\" value={converted(vector.x)} min={min} max={max} onChange={(val) => onChange(val, \"x\")} unit={props.unit} />\r\n <SyncedSliderPropertyLine label=\"Y\" value={converted(vector.y)} min={min} max={max} onChange={(val) => onChange(val, \"y\")} unit={props.unit} />\r\n {HasZ(vector) && (\r\n <SyncedSliderPropertyLine label=\"Z\" value={converted(vector.z)} min={min} max={max} onChange={(val) => onChange(val, \"z\")} unit={props.unit} />\r\n )}\r\n {HasW(vector) && (\r\n <SyncedSliderPropertyLine label=\"W\" value={converted(vector.w)} min={min} max={max} onChange={(val) => onChange(val, \"w\")} unit={props.unit} />\r\n )}\r\n </>\r\n }\r\n >\r\n <Body1>{`X: ${formatted(props.value.x)} | Y: ${formatted(props.value.y)}${HasZ(props.value) ? ` | Z: ${formatted(props.value.z)}` : \"\"}${HasW(props.value) ? ` | W: ${formatted(props.value.w)}` : \"\"}`}</Body1>\r\n </PropertyLine>\r\n );\r\n};\r\n\r\ntype RotationVectorPropertyLineProps = TensorPropertyLineProps<Vector3> & {\r\n /**\r\n * Display angles as degrees instead of radians\r\n */\r\n useDegrees?: boolean;\r\n};\r\n\r\nconst ToDegreesConverter = { from: Tools.ToDegrees, to: Tools.ToRadians };\r\nexport const RotationVectorPropertyLine: FunctionComponent<RotationVectorPropertyLineProps> = (props) => {\r\n const min = props.useDegrees ? 0 : undefined;\r\n const max = props.useDegrees ? 360 : undefined;\r\n return <Vector3PropertyLine {...props} unit={props.useDegrees ? \"deg\" : \"rad\"} valueConverter={props.useDegrees ? ToDegreesConverter : undefined} min={min} max={max} />;\r\n};\r\n\r\ntype QuaternionPropertyLineProps = TensorPropertyLineProps<Quaternion> & {\r\n /**\r\n * Display angles as degrees instead of radians\r\n */\r\n useDegrees?: boolean;\r\n};\r\nconst QuaternionPropertyLineInternal = TensorPropertyLine as FunctionComponent<TensorPropertyLineProps<Quaternion>>;\r\nexport const QuaternionPropertyLine: FunctionComponent<QuaternionPropertyLineProps> = (props) => {\r\n const min = props.useDegrees ? 0 : undefined;\r\n const max = props.useDegrees ? 360 : undefined;\r\n const [quat, setQuat] = useState(props.value);\r\n\r\n // Extract only the properties that exist on QuaternionPropertyLineProps\r\n const { useDegrees, ...restProps } = props;\r\n\r\n const onQuatChange = (val: Quaternion) => {\r\n setQuat(val);\r\n props.onChange(val);\r\n };\r\n\r\n const onEulerChange = (val: Vector3) => {\r\n const quat = Quaternion.FromEulerAngles(val.x, val.y, val.z);\r\n setQuat(quat);\r\n props.onChange(quat);\r\n };\r\n\r\n return useDegrees ? (\r\n <Vector3PropertyLine\r\n {...restProps}\r\n nullable={false}\r\n ignoreNullable={false}\r\n value={quat.toEulerAngles()}\r\n valueConverter={ToDegreesConverter}\r\n min={min}\r\n max={max}\r\n onChange={onEulerChange}\r\n unit=\"deg\"\r\n />\r\n ) : (\r\n <QuaternionPropertyLineInternal {...props} unit={\"rad\"} nullable={false} value={quat} min={min} max={max} onChange={onQuatChange} />\r\n );\r\n};\r\nexport const Vector2PropertyLine = TensorPropertyLine as FunctionComponent<TensorPropertyLineProps<Vector2>>;\r\nexport const Vector3PropertyLine = TensorPropertyLine as FunctionComponent<TensorPropertyLineProps<Vector3>>;\r\nexport const Vector4PropertyLine = TensorPropertyLine as FunctionComponent<TensorPropertyLineProps<Vector4>>;\r\n"]}
1
+ {"version":3,"file":"vectorPropertyLine.js","sourceRoot":"","sources":["../../../../../../dev/sharedUiComponents/src/fluent/hoc/propertyLines/vectorPropertyLine.tsx"],"names":[],"mappings":"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","sourcesContent":["import { useState } from \"react\";\r\nimport type { FunctionComponent } from \"react\";\r\n\r\nimport { Body1 } from \"@fluentui/react-components\";\r\nimport { PropertyLine } from \"./propertyLine\";\r\nimport type { PrimitiveProps } from \"../../primitives/primitive\";\r\nimport type { PropertyLineProps } from \"./propertyLine\";\r\n\r\nimport { SyncedSliderPropertyLine } from \"./syncedSliderPropertyLine\";\r\nimport type { Vector3 } from \"core/Maths/math.vector\";\r\nimport { Quaternion, Vector2, Vector4 } from \"core/Maths/math.vector\";\r\nimport { Tools } from \"core/Misc/tools\";\r\nimport { CalculatePrecision } from \"../../primitives/spinButton\";\r\n\r\nexport type TensorPropertyLineProps<V extends Vector2 | Vector3 | Vector4 | Quaternion> = PropertyLineProps<V> &\r\n PrimitiveProps<V> & {\r\n /**\r\n * If passed, all sliders will use this for the min value\r\n */\r\n min?: number;\r\n /**\r\n * If passed, all sliders will use this for the max value\r\n */\r\n max?: number;\r\n /**\r\n * Will be displayed in the input UI to indicate the unit of measurement\r\n */\r\n unit?: string;\r\n\r\n /**\r\n * Internal spinbutton's step\r\n */\r\n step?: number;\r\n /**\r\n * If passed, the UX will use the conversion functions to display/update values\r\n */\r\n valueConverter?: {\r\n /**\r\n * Will call from(val) before displaying in the UX\r\n */\r\n from: (val: number) => number;\r\n /**\r\n * Will call to(val) before calling onChange\r\n */\r\n to: (val: number) => number;\r\n };\r\n };\r\n\r\nconst HasZ = (vector: Vector2 | Vector3 | Vector4 | Quaternion): vector is Vector3 => !(vector instanceof Vector2);\r\nconst HasW = (vector: Vector2 | Vector3 | Vector4 | Quaternion): vector is Vector4 => vector instanceof Vector4 || vector instanceof Quaternion;\r\n\r\n/**\r\n * Reusable component which renders a vector property line containing a label, vector value, and expandable XYZW values\r\n * The expanded section contains a slider/input box for each component of the vector (x, y, z, w)\r\n * @param props\r\n * @returns\r\n */\r\nconst TensorPropertyLine: FunctionComponent<TensorPropertyLineProps<Vector2 | Vector3 | Vector4 | Quaternion>> = (props) => {\r\n const converted = (val: number) => (props.valueConverter ? props.valueConverter.from(val) : val);\r\n const formatted = (val: number) => converted(val).toFixed(props.step !== undefined ? CalculatePrecision(props.step) : 2);\r\n\r\n const [vector, setVector] = useState(props.value);\r\n const { min, max } = props;\r\n\r\n const onChange = (val: number, key: \"x\" | \"y\" | \"z\" | \"w\") => {\r\n const value = props.valueConverter ? props.valueConverter.to(val) : val;\r\n const newVector = vector.clone();\r\n (newVector as Vector4)[key] = value; // The syncedSlider for 'w' is only rendered when vector is a Vector4, so this is safe\r\n\r\n setVector(newVector);\r\n props.onChange(newVector);\r\n };\r\n\r\n return (\r\n <PropertyLine\r\n {...props}\r\n onCopy={() => `(${vector.x}, ${vector.y} ${HasZ(vector) ? `, ${vector.z}` : \"\"}${HasW(vector) ? `, ${vector.w}` : \"\"})`}\r\n expandedContent={\r\n <>\r\n <SyncedSliderPropertyLine\r\n label=\"X\"\r\n value={converted(vector.x)}\r\n min={min}\r\n max={max}\r\n onChange={(val) => onChange(val, \"x\")}\r\n unit={props.unit}\r\n step={props.step}\r\n />\r\n <SyncedSliderPropertyLine\r\n label=\"Y\"\r\n value={converted(vector.y)}\r\n min={min}\r\n max={max}\r\n onChange={(val) => onChange(val, \"y\")}\r\n unit={props.unit}\r\n step={props.step}\r\n />\r\n {HasZ(vector) && (\r\n <SyncedSliderPropertyLine\r\n label=\"Z\"\r\n value={converted(vector.z)}\r\n min={min}\r\n max={max}\r\n onChange={(val) => onChange(val, \"z\")}\r\n unit={props.unit}\r\n step={props.step}\r\n />\r\n )}\r\n {HasW(vector) && (\r\n <SyncedSliderPropertyLine\r\n label=\"W\"\r\n value={converted(vector.w)}\r\n min={min}\r\n max={max}\r\n onChange={(val) => onChange(val, \"w\")}\r\n unit={props.unit}\r\n step={props.step}\r\n />\r\n )}\r\n </>\r\n }\r\n >\r\n <Body1>{`X: ${formatted(props.value.x)} | Y: ${formatted(props.value.y)}${HasZ(props.value) ? ` | Z: ${formatted(props.value.z)}` : \"\"}${HasW(props.value) ? ` | W: ${formatted(props.value.w)}` : \"\"}`}</Body1>\r\n </PropertyLine>\r\n );\r\n};\r\n\r\ntype RotationVectorPropertyLineProps = TensorPropertyLineProps<Vector3> & {\r\n /**\r\n * Display angles as degrees instead of radians\r\n */\r\n useDegrees?: boolean;\r\n};\r\n\r\nconst ToDegreesConverter = { from: Tools.ToDegrees, to: Tools.ToRadians };\r\nexport const RotationVectorPropertyLine: FunctionComponent<RotationVectorPropertyLineProps> = (props) => {\r\n const min = props.useDegrees ? 0 : undefined;\r\n const max = props.useDegrees ? 360 : undefined;\r\n return (\r\n <Vector3PropertyLine\r\n {...props}\r\n unit={props.useDegrees ? \"deg\" : \"rad\"}\r\n valueConverter={props.useDegrees ? ToDegreesConverter : undefined}\r\n min={min}\r\n max={max}\r\n step={0.001}\r\n />\r\n );\r\n};\r\n\r\ntype QuaternionPropertyLineProps = TensorPropertyLineProps<Quaternion> & {\r\n /**\r\n * Display angles as degrees instead of radians\r\n */\r\n useDegrees?: boolean;\r\n};\r\nconst QuaternionPropertyLineInternal = TensorPropertyLine as FunctionComponent<TensorPropertyLineProps<Quaternion>>;\r\nexport const QuaternionPropertyLine: FunctionComponent<QuaternionPropertyLineProps> = (props) => {\r\n const min = props.useDegrees ? 0 : undefined;\r\n const max = props.useDegrees ? 360 : undefined;\r\n const [quat, setQuat] = useState(props.value);\r\n\r\n // Extract only the properties that exist on QuaternionPropertyLineProps\r\n const { useDegrees, ...restProps } = props;\r\n\r\n const onQuatChange = (val: Quaternion) => {\r\n setQuat(val);\r\n props.onChange(val);\r\n };\r\n\r\n const onEulerChange = (val: Vector3) => {\r\n const quat = Quaternion.FromEulerAngles(val.x, val.y, val.z);\r\n setQuat(quat);\r\n props.onChange(quat);\r\n };\r\n\r\n return useDegrees ? (\r\n <Vector3PropertyLine\r\n {...restProps}\r\n nullable={false}\r\n ignoreNullable={false}\r\n value={quat.toEulerAngles()}\r\n valueConverter={ToDegreesConverter}\r\n min={min}\r\n max={max}\r\n onChange={onEulerChange}\r\n unit=\"deg\"\r\n />\r\n ) : (\r\n <QuaternionPropertyLineInternal {...props} unit={\"rad\"} nullable={false} value={quat} min={min} max={max} onChange={onQuatChange} />\r\n );\r\n};\r\nexport const Vector2PropertyLine = TensorPropertyLine as FunctionComponent<TensorPropertyLineProps<Vector2>>;\r\nexport const Vector3PropertyLine = TensorPropertyLine as FunctionComponent<TensorPropertyLineProps<Vector3>>;\r\nexport const Vector4PropertyLine = TensorPropertyLine as FunctionComponent<TensorPropertyLineProps<Vector4>>;\r\n"]}
@@ -64,7 +64,7 @@ export const Accordion = (props) => {
64
64
  }
65
65
  }, []);
66
66
  return (_jsx(FluentAccordion, { className: classes.accordion, collapsible: true, multiple: true, onToggle: onToggle, openItems: openItems, ...rest, children: validChildren.map((child) => {
67
- return (_jsxs(AccordionItem, { value: child.title, children: [_jsx(AccordionHeader, { expandIconPosition: "end", children: _jsx(Subtitle1, { children: child.title }) }), _jsx(AccordionPanel, { children: _jsx("div", { className: classes.panelDiv, children: child.content }) })] }, child.title));
67
+ return (_jsxs(AccordionItem, { value: child.title, children: [_jsx(AccordionHeader, { expandIconPosition: "end", children: _jsx(Subtitle1, { children: child.title }) }), _jsx(AccordionPanel, { children: _jsx("div", { className: classes.panelDiv, children: child.content }) })] }, child.content.key));
68
68
  }) }));
69
69
  };
70
70
  //# sourceMappingURL=accordion.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"accordion.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/accordion.tsx"],"names":[],"mappings":";AAGA,OAAO,EAAE,QAAQ,EAAE,cAAc,EAAE,WAAW,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAE5F,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,cAAc,EAAE,SAAS,IAAI,eAAe,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAEzJ,MAAM,SAAS,GAAG,UAAU,CAAC;IACzB,SAAS,EAAE;QACP,SAAS,EAAE,QAAQ;QACnB,SAAS,EAAE,MAAM;QACjB,aAAa,EAAE,MAAM,CAAC,gBAAgB;QACtC,OAAO,EAAE,MAAM;QACf,aAAa,EAAE,QAAQ;QACvB,MAAM,EAAE,MAAM,CAAC,gBAAgB;QAC/B,MAAM,EAAE,MAAM;KACjB;IACD,QAAQ,EAAE;QACN,OAAO,EAAE,MAAM;QACf,aAAa,EAAE,QAAQ;QACvB,QAAQ,EAAE,QAAQ;KACrB;CACJ,CAAC,CAAC;AAOH,MAAM,CAAC,MAAM,gBAAgB,GAAgE,CAAC,KAAK,EAAE,EAAE;IACnG,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAE5B,OAAO,cAAK,SAAS,EAAE,OAAO,CAAC,QAAQ,YAAG,KAAK,CAAC,QAAQ,GAAO,CAAC;AACpE,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,SAAS,GAAyC,CAAC,KAAK,EAAE,EAAE;IACrE,MAAM,OAAO,GAAG,SAAS,EAAE,CAAC;IAE5B,MAAM,EAAE,QAAQ,EAAE,GAAG,IAAI,EAAE,GAAG,KAAK,CAAC;IACpC,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE;QAC/B,OAAO,CACH,QAAQ,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,EAAE;YAC7B,IAAI,cAAc,CAAC,KAAK,CAAC,EAAE,CAAC;gBACxB,MAAM,UAAU,GAAG,KAAK,CAAC,KAAuC,CAAC;gBACjE,IAAI,UAAU,CAAC,KAAK,EAAE,CAAC;oBACnB,OAAO;wBACH,KAAK,EAAE,UAAU,CAAC,KAAK;wBACvB,iBAAiB,EAAE,UAAU,CAAC,iBAAiB;wBAC/C,OAAO,EAAE,KAAK;qBACjB,CAAC;gBACN,CAAC;YACL,CAAC;YACD,OAAO,IAAI,CAAC;QAChB,CAAC,CAAC,EAAE,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,CAC5B,CAAC;IACN,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAEf,uFAAuF;IACvF,MAAM,CAAC,SAAS,EAAE,YAAY,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAElI,8GAA8G;IAC9G,sGAAsG;IACtG,MAAM,CAAC,WAAW,EAAE,cAAc,CAAC,GAAG,QAAQ,CAAC,aAAa,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAErI,SAAS,CAAC,GAAG,EAAE;QACX,KAAK,MAAM,eAAe,IAAI,aAAa,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,EAAE,CAAC;YAClH,0FAA0F;YAC1F,gGAAgG;YAChG,IAAI,CAAC,WAAW,CAAC,QAAQ,CAAC,eAAe,CAAC,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,eAAe,CAAC,EAAE,CAAC;gBACjF,YAAY,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC;YACvD,CAAC;QACL,CAAC;IACL,CAAC,EAAE,CAAC,aAAa,CAAC,CAAC,CAAC;IAEpB,MAAM,QAAQ,GAAG,WAAW,CAAC,CAAC,KAA2B,EAAE,IAAiC,EAAE,EAAE;QAC5F,IAAI,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;YACtC,YAAY,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAC9C,cAAc,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACzE,CAAC;aAAM,CAAC;YACJ,cAAc,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;YAChD,YAAY,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QACvE,CAAC;IACL,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,CACH,KAAC,eAAe,IAAC,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,WAAW,QAAC,QAAQ,QAAC,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,KAAM,IAAI,YACjH,aAAa,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE;YACzB,OAAO,CACH,MAAC,aAAa,IAAmB,KAAK,EAAE,KAAK,CAAC,KAAK,aAC/C,KAAC,eAAe,IAAC,kBAAkB,EAAC,KAAK,YACrC,KAAC,SAAS,cAAE,KAAK,CAAC,KAAK,GAAa,GACtB,EAClB,KAAC,cAAc,cACX,cAAK,SAAS,EAAE,OAAO,CAAC,QAAQ,YAAG,KAAK,CAAC,OAAO,GAAO,GAC1C,KAND,KAAK,CAAC,KAAK,CAOf,CACnB,CAAC;QACN,CAAC,CAAC,GACY,CACrB,CAAC;AACN,CAAC,CAAC","sourcesContent":["import type { AccordionToggleData, AccordionToggleEvent } from \"@fluentui/react-components\";\r\nimport type { FunctionComponent, PropsWithChildren } from \"react\";\r\n\r\nimport { Children, isValidElement, useCallback, useEffect, useMemo, useState } from \"react\";\r\n\r\nimport { AccordionHeader, AccordionItem, AccordionPanel, Accordion as FluentAccordion, Subtitle1, makeStyles, tokens } from \"@fluentui/react-components\";\r\n\r\nconst useStyles = makeStyles({\r\n accordion: {\r\n overflowX: \"hidden\",\r\n overflowY: \"auto\",\r\n paddingBottom: tokens.spacingVerticalM,\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n rowGap: tokens.spacingVerticalM,\r\n height: \"100%\",\r\n },\r\n panelDiv: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n overflow: \"hidden\",\r\n },\r\n});\r\n\r\nexport type AccordionSectionProps = {\r\n title: string;\r\n collapseByDefault?: boolean;\r\n};\r\n\r\nexport const AccordionSection: FunctionComponent<PropsWithChildren<AccordionSectionProps>> = (props) => {\r\n const classes = useStyles();\r\n\r\n return <div className={classes.panelDiv}>{props.children}</div>;\r\n};\r\n\r\nexport const Accordion: FunctionComponent<PropsWithChildren> = (props) => {\r\n const classes = useStyles();\r\n\r\n const { children, ...rest } = props;\r\n const validChildren = useMemo(() => {\r\n return (\r\n Children.map(children, (child) => {\r\n if (isValidElement(child)) {\r\n const childProps = child.props as Partial<AccordionSectionProps>;\r\n if (childProps.title) {\r\n return {\r\n title: childProps.title,\r\n collapseByDefault: childProps.collapseByDefault,\r\n content: child,\r\n };\r\n }\r\n }\r\n return null;\r\n })?.filter(Boolean) ?? []\r\n );\r\n }, [children]);\r\n\r\n // Tracks open items, and used to tell the Accordion which sections should be expanded.\r\n const [openItems, setOpenItems] = useState(validChildren.filter((child) => !child.collapseByDefault).map((child) => child.title));\r\n\r\n // Tracks closed items, which is needed so that when the children change, we only update the open/closed state\r\n // (depending on the collapseByDefault prop) for items that have not been explicitly opened or closed.\r\n const [closedItems, setClosedItems] = useState(validChildren.filter((child) => child.collapseByDefault).map((child) => child.title));\r\n\r\n useEffect(() => {\r\n for (const defaultOpenItem of validChildren.filter((child) => !child.collapseByDefault).map((child) => child.title)) {\r\n // If a child is not marked as collapseByDefault, then it should be opened by default, and\r\n // it is only \"default\" if it hasn't already been explicitly added to the opened or closed list.\r\n if (!closedItems.includes(defaultOpenItem) && !openItems.includes(defaultOpenItem)) {\r\n setOpenItems((prev) => [...prev, defaultOpenItem]);\r\n }\r\n }\r\n }, [validChildren]);\r\n\r\n const onToggle = useCallback((event: AccordionToggleEvent, data: AccordionToggleData<string>) => {\r\n if (data.openItems.includes(data.value)) {\r\n setOpenItems((prev) => [...prev, data.value]);\r\n setClosedItems((prev) => prev.filter((item) => item !== data.value));\r\n } else {\r\n setClosedItems((prev) => [...prev, data.value]);\r\n setOpenItems((prev) => prev.filter((item) => item !== data.value));\r\n }\r\n }, []);\r\n\r\n return (\r\n <FluentAccordion className={classes.accordion} collapsible multiple onToggle={onToggle} openItems={openItems} {...rest}>\r\n {validChildren.map((child) => {\r\n return (\r\n <AccordionItem key={child.title} value={child.title}>\r\n <AccordionHeader expandIconPosition=\"end\">\r\n <Subtitle1>{child.title}</Subtitle1>\r\n </AccordionHeader>\r\n <AccordionPanel>\r\n <div className={classes.panelDiv}>{child.content}</div>\r\n </AccordionPanel>\r\n </AccordionItem>\r\n );\r\n })}\r\n </FluentAccordion>\r\n );\r\n};\r\n"]}
1
+ {"version":3,"file":"accordion.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/accordion.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { AccordionToggleData, AccordionToggleEvent } from \"@fluentui/react-components\";\r\nimport type { FunctionComponent, PropsWithChildren } from \"react\";\r\n\r\nimport { Children, isValidElement, useCallback, useEffect, useMemo, useState } from \"react\";\r\n\r\nimport { AccordionHeader, AccordionItem, AccordionPanel, Accordion as FluentAccordion, Subtitle1, makeStyles, tokens } from \"@fluentui/react-components\";\r\n\r\nconst useStyles = makeStyles({\r\n accordion: {\r\n overflowX: \"hidden\",\r\n overflowY: \"auto\",\r\n paddingBottom: tokens.spacingVerticalM,\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n rowGap: tokens.spacingVerticalM,\r\n height: \"100%\",\r\n },\r\n panelDiv: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n overflow: \"hidden\",\r\n },\r\n});\r\n\r\nexport type AccordionSectionProps = {\r\n title: string;\r\n collapseByDefault?: boolean;\r\n};\r\n\r\nexport const AccordionSection: FunctionComponent<PropsWithChildren<AccordionSectionProps>> = (props) => {\r\n const classes = useStyles();\r\n\r\n return <div className={classes.panelDiv}>{props.children}</div>;\r\n};\r\n\r\nexport const Accordion: FunctionComponent<PropsWithChildren> = (props) => {\r\n const classes = useStyles();\r\n\r\n const { children, ...rest } = props;\r\n const validChildren = useMemo(() => {\r\n return (\r\n Children.map(children, (child) => {\r\n if (isValidElement(child)) {\r\n const childProps = child.props as Partial<AccordionSectionProps>;\r\n if (childProps.title) {\r\n return {\r\n title: childProps.title,\r\n collapseByDefault: childProps.collapseByDefault,\r\n content: child,\r\n };\r\n }\r\n }\r\n return null;\r\n })?.filter(Boolean) ?? []\r\n );\r\n }, [children]);\r\n\r\n // Tracks open items, and used to tell the Accordion which sections should be expanded.\r\n const [openItems, setOpenItems] = useState(validChildren.filter((child) => !child.collapseByDefault).map((child) => child.title));\r\n\r\n // Tracks closed items, which is needed so that when the children change, we only update the open/closed state\r\n // (depending on the collapseByDefault prop) for items that have not been explicitly opened or closed.\r\n const [closedItems, setClosedItems] = useState(validChildren.filter((child) => child.collapseByDefault).map((child) => child.title));\r\n\r\n useEffect(() => {\r\n for (const defaultOpenItem of validChildren.filter((child) => !child.collapseByDefault).map((child) => child.title)) {\r\n // If a child is not marked as collapseByDefault, then it should be opened by default, and\r\n // it is only \"default\" if it hasn't already been explicitly added to the opened or closed list.\r\n if (!closedItems.includes(defaultOpenItem) && !openItems.includes(defaultOpenItem)) {\r\n setOpenItems((prev) => [...prev, defaultOpenItem]);\r\n }\r\n }\r\n }, [validChildren]);\r\n\r\n const onToggle = useCallback((event: AccordionToggleEvent, data: AccordionToggleData<string>) => {\r\n if (data.openItems.includes(data.value)) {\r\n setOpenItems((prev) => [...prev, data.value]);\r\n setClosedItems((prev) => prev.filter((item) => item !== data.value));\r\n } else {\r\n setClosedItems((prev) => [...prev, data.value]);\r\n setOpenItems((prev) => prev.filter((item) => item !== data.value));\r\n }\r\n }, []);\r\n\r\n return (\r\n <FluentAccordion className={classes.accordion} collapsible multiple onToggle={onToggle} openItems={openItems} {...rest}>\r\n {validChildren.map((child) => {\r\n return (\r\n <AccordionItem key={child.content.key} value={child.title}>\r\n <AccordionHeader expandIconPosition=\"end\">\r\n <Subtitle1>{child.title}</Subtitle1>\r\n </AccordionHeader>\r\n <AccordionPanel>\r\n <div className={classes.panelDiv}>{child.content}</div>\r\n </AccordionPanel>\r\n </AccordionItem>\r\n );\r\n })}\r\n </FluentAccordion>\r\n );\r\n};\r\n"]}
@@ -6,6 +6,12 @@ const useCollapseStyles = makeStyles({
6
6
  overflow: "hidden",
7
7
  display: "flex",
8
8
  },
9
+ horizontal: {
10
+ flexDirection: "row",
11
+ },
12
+ vertical: {
13
+ flexDirection: "column",
14
+ },
9
15
  });
10
16
  /**
11
17
  * Wraps the passed in children with a fluent collapse component, handling smooth animation when visible prop changes
@@ -15,6 +21,6 @@ const useCollapseStyles = makeStyles({
15
21
  */
16
22
  export const Collapse = (props) => {
17
23
  const classes = useCollapseStyles();
18
- return (_jsx(FluentCollapse, { visible: props.visible, orientation: props.orientation, children: _jsx("div", { className: classes.collapseContent, children: props.children }) }));
24
+ return (_jsx(FluentCollapse, { visible: props.visible, orientation: props.orientation, children: _jsx("div", { className: `${classes.collapseContent} ${props.orientation === "horizontal" ? classes.horizontal : classes.vertical}`, children: props.children }) }));
19
25
  };
20
26
  //# sourceMappingURL=collapse.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"collapse.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/collapse.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAQvF,MAAM,iBAAiB,GAAG,UAAU,CAAC;IACjC,eAAe,EAAE;QACb,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,MAAM;KAClB;CACJ,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAwD,CAAC,KAAK,EAAE,EAAE;IACnF,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC;IACpC,OAAO,CACH,KAAC,cAAc,IAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,YAClE,cAAK,SAAS,EAAE,OAAO,CAAC,eAAe,YAAG,KAAK,CAAC,QAAQ,GAAO,GAClD,CACpB,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { makeStyles } from \"@fluentui/react-components\";\r\nimport { Collapse as FluentCollapse } from \"@fluentui/react-motion-components-preview\";\r\nimport type { FunctionComponent, PropsWithChildren } from \"react\";\r\n\r\ntype CollapseProps = {\r\n visible: boolean;\r\n orientation?: \"horizontal\" | \"vertical\";\r\n};\r\n\r\nconst useCollapseStyles = makeStyles({\r\n collapseContent: {\r\n overflow: \"hidden\",\r\n display: \"flex\",\r\n },\r\n});\r\n\r\n/**\r\n * Wraps the passed in children with a fluent collapse component, handling smooth animation when visible prop changes\r\n * NOTE: When passing in children, prefer react fragment over empty div to avoid bloating the react tree with an unnecessary div\r\n * @param props\r\n * @returns\r\n */\r\nexport const Collapse: FunctionComponent<PropsWithChildren<CollapseProps>> = (props) => {\r\n const classes = useCollapseStyles();\r\n return (\r\n <FluentCollapse visible={props.visible} orientation={props.orientation}>\r\n <div className={classes.collapseContent}>{props.children}</div>\r\n </FluentCollapse>\r\n );\r\n};\r\n"]}
1
+ {"version":3,"file":"collapse.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/collapse.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,EAAE,QAAQ,IAAI,cAAc,EAAE,MAAM,2CAA2C,CAAC;AAQvF,MAAM,iBAAiB,GAAG,UAAU,CAAC;IACjC,eAAe,EAAE;QACb,QAAQ,EAAE,QAAQ;QAClB,OAAO,EAAE,MAAM;KAClB;IACD,UAAU,EAAE;QACR,aAAa,EAAE,KAAK;KACvB;IACD,QAAQ,EAAE;QACN,aAAa,EAAE,QAAQ;KAC1B;CACJ,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,CAAC,MAAM,QAAQ,GAAwD,CAAC,KAAK,EAAE,EAAE;IACnF,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC;IACpC,OAAO,CACH,KAAC,cAAc,IAAC,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK,CAAC,WAAW,YAClE,cAAK,SAAS,EAAE,GAAG,OAAO,CAAC,eAAe,IAAI,KAAK,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,YAAG,KAAK,CAAC,QAAQ,GAAO,GACrI,CACpB,CAAC;AACN,CAAC,CAAC","sourcesContent":["import { makeStyles } from \"@fluentui/react-components\";\r\nimport { Collapse as FluentCollapse } from \"@fluentui/react-motion-components-preview\";\r\nimport type { FunctionComponent, PropsWithChildren } from \"react\";\r\n\r\ntype CollapseProps = {\r\n visible: boolean;\r\n orientation?: \"horizontal\" | \"vertical\";\r\n};\r\n\r\nconst useCollapseStyles = makeStyles({\r\n collapseContent: {\r\n overflow: \"hidden\",\r\n display: \"flex\",\r\n },\r\n horizontal: {\r\n flexDirection: \"row\",\r\n },\r\n vertical: {\r\n flexDirection: \"column\",\r\n },\r\n});\r\n\r\n/**\r\n * Wraps the passed in children with a fluent collapse component, handling smooth animation when visible prop changes\r\n * NOTE: When passing in children, prefer react fragment over empty div to avoid bloating the react tree with an unnecessary div\r\n * @param props\r\n * @returns\r\n */\r\nexport const Collapse: FunctionComponent<PropsWithChildren<CollapseProps>> = (props) => {\r\n const classes = useCollapseStyles();\r\n return (\r\n <FluentCollapse visible={props.visible} orientation={props.orientation}>\r\n <div className={`${classes.collapseContent} ${props.orientation === \"horizontal\" ? classes.horizontal : classes.vertical}`}>{props.children}</div>\r\n </FluentCollapse>\r\n );\r\n};\r\n"]}
@@ -1,4 +1,4 @@
1
- import type { FunctionComponent, KeyboardEvent, FocusEvent } from "react";
1
+ import type { FunctionComponent } from "react";
2
2
  import type { PrimitiveProps } from "./primitive.js";
3
3
  export type SpinButtonProps = PrimitiveProps<number> & {
4
4
  min?: number;
@@ -11,5 +11,16 @@ export type SpinButtonProps = PrimitiveProps<number> & {
11
11
  validator?: (value: number) => boolean;
12
12
  };
13
13
  export declare const SpinButton: FunctionComponent<SpinButtonProps>;
14
- export declare function HandleOnBlur(event: FocusEvent<HTMLInputElement>): void;
15
- export declare function HandleKeyDown(event: KeyboardEvent<HTMLInputElement>): void;
14
+ /**
15
+ * Fluent's CalculatePrecision function
16
+ * https://github.com/microsoft/fluentui/blob/dcbf775d37938eacffa37922fc0b43a3cdd5753f/packages/utilities/src/math.ts#L91C1
17
+ *
18
+ * Calculates a number's precision based on the number of trailing
19
+ * zeros if the number does not have a decimal indicated by a negative
20
+ * precision. Otherwise, it calculates the number of digits after
21
+ * the decimal point indicated by a positive precision.
22
+ *
23
+ * @param value - the value to determine the precision of
24
+ * @returns the calculated precision
25
+ */
26
+ export declare function CalculatePrecision(value: number): number;
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { makeStyles, SpinButton as FluentSpinButton, useId, tokens } from "@fluentui/react-components";
3
3
  import { useEffect, useState, useRef } from "react";
4
4
  import { InfoLabel } from "./infoLabel.js";
5
+ import { HandleKeyDown, HandleOnBlur } from "./utils.js";
5
6
  const useSpinStyles = makeStyles({
6
7
  base: {
7
8
  display: "flex",
@@ -67,7 +68,7 @@ export const SpinButton = (props) => {
67
68
  * @param value - the value to determine the precision of
68
69
  * @returns the calculated precision
69
70
  */
70
- function CalculatePrecision(value) {
71
+ export function CalculatePrecision(value) {
71
72
  /**
72
73
  * Group 1:
73
74
  * [1-9]([0]+$) matches trailing zeros
@@ -98,15 +99,4 @@ function PrecisionRound(value, precision) {
98
99
  const exp = Math.pow(10, precision);
99
100
  return Math.round(value * exp) / exp;
100
101
  }
101
- export function HandleOnBlur(event) {
102
- event.stopPropagation();
103
- event.preventDefault();
104
- }
105
- export function HandleKeyDown(event) {
106
- event.stopPropagation(); // Prevent event propagation
107
- // Prevent Enter key from causing form submission or value reversion
108
- if (event.key === "Enter") {
109
- event.preventDefault();
110
- }
111
- }
112
102
  //# sourceMappingURL=spinButton.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"spinButton.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/spinButton.tsx"],"names":[],"mappings":"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","sourcesContent":["import { makeStyles, SpinButton as FluentSpinButton, useId, tokens } from \"@fluentui/react-components\";\r\nimport type { SpinButtonOnChangeData, SpinButtonChangeEvent } from \"@fluentui/react-components\";\r\nimport type { FunctionComponent, KeyboardEvent, FocusEvent } from \"react\";\r\nimport { useEffect, useState, useRef } from \"react\";\r\nimport type { PrimitiveProps } from \"./primitive\";\r\nimport { InfoLabel } from \"./infoLabel\";\r\n\r\nconst useSpinStyles = makeStyles({\r\n base: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n minWidth: \"55px\",\r\n },\r\n invalid: { backgroundColor: tokens.colorPaletteRedBackground2 },\r\n});\r\n\r\nexport type SpinButtonProps = PrimitiveProps<number> & {\r\n min?: number;\r\n max?: number;\r\n /** Determines how much the spinbutton increments with the arrow keys. Note this also determines the precision value (# of decimals in display value)\r\n * i.e. if step = 1, precision = 0. step = 0.0089, precision = 4. step = 300, precision = 2. step = 23.00, precision = 2. */\r\n step?: number;\r\n unit?: string;\r\n forceInt?: boolean;\r\n validator?: (value: number) => boolean;\r\n};\r\n\r\nexport const SpinButton: FunctionComponent<SpinButtonProps> = (props) => {\r\n const classes = useSpinStyles();\r\n const { min, max } = props;\r\n\r\n const [value, setValue] = useState(props.value);\r\n const lastCommittedValue = useRef(props.value);\r\n // step and forceInt are not mutually exclusive since there could be cases where you want to forceInt but have spinButton jump >1 int per spin\r\n const step = props.step != undefined ? props.step : props.forceInt ? 1 : undefined;\r\n\r\n useEffect(() => {\r\n if (props.value !== lastCommittedValue.current) {\r\n lastCommittedValue.current = props.value;\r\n setValue(props.value); // Update local state when props.value changes\r\n }\r\n }, [props.value]);\r\n\r\n const validateValue = (numericValue: number): boolean => {\r\n const outOfBounds = (min !== undefined && numericValue < min) || (max !== undefined && numericValue > max);\r\n const failsValidator = props.validator && !props.validator(numericValue);\r\n const failsIntCheck = props.forceInt ? !Number.isInteger(numericValue) : false;\r\n const invalid = !!outOfBounds || !!failsValidator || isNaN(numericValue) || !!failsIntCheck;\r\n return !invalid;\r\n };\r\n\r\n const tryCommitValue = (currVal: number) => {\r\n // Only commit if valid and different from last committed value\r\n if (validateValue(currVal) && currVal !== lastCommittedValue.current) {\r\n lastCommittedValue.current = currVal;\r\n props.onChange(currVal);\r\n }\r\n };\r\n\r\n const handleChange = (event: SpinButtonChangeEvent, data: SpinButtonOnChangeData) => {\r\n event.stopPropagation(); // Prevent event propagation\r\n if (data.value != null && !Number.isNaN(data.value)) {\r\n setValue(data.value);\r\n tryCommitValue(data.value);\r\n }\r\n };\r\n\r\n const handleKeyUp = (event: KeyboardEvent<HTMLInputElement>) => {\r\n event.stopPropagation(); // Prevent event propagation\r\n\r\n if (event.key !== \"Enter\") {\r\n const currVal = parseFloat((event.target as any).value); // Cannot use currentTarget.value as it won't have the most recently typed value\r\n setValue(currVal);\r\n tryCommitValue(currVal);\r\n }\r\n };\r\n\r\n const id = useId(\"spin-button\");\r\n return (\r\n <div className={classes.base}>\r\n {props.infoLabel && <InfoLabel {...props.infoLabel} htmlFor={id} />}\r\n <FluentSpinButton\r\n {...props}\r\n step={step}\r\n id={id}\r\n size=\"small\"\r\n precision={CalculatePrecision(step ?? 1.01)}\r\n displayValue={props.unit ? `${PrecisionRound(value, CalculatePrecision(step ?? 1.01))} ${props.unit}` : undefined}\r\n value={value}\r\n onChange={handleChange}\r\n onKeyUp={handleKeyUp}\r\n onKeyDown={HandleKeyDown}\r\n onBlur={HandleOnBlur}\r\n className={`${!validateValue(value) ? classes.invalid : \"\"}`}\r\n />\r\n </div>\r\n );\r\n};\r\n\r\n/**\r\n * Fluent's CalculatePrecision function\r\n * https://github.com/microsoft/fluentui/blob/dcbf775d37938eacffa37922fc0b43a3cdd5753f/packages/utilities/src/math.ts#L91C1\r\n *\r\n * Calculates a number's precision based on the number of trailing\r\n * zeros if the number does not have a decimal indicated by a negative\r\n * precision. Otherwise, it calculates the number of digits after\r\n * the decimal point indicated by a positive precision.\r\n *\r\n * @param value - the value to determine the precision of\r\n * @returns the calculated precision\r\n */\r\nfunction CalculatePrecision(value: number) {\r\n /**\r\n * Group 1:\r\n * [1-9]([0]+$) matches trailing zeros\r\n * Group 2:\r\n * \\.([0-9]*) matches all digits after a decimal point.\r\n */ const groups = /[1-9]([0]+$)|\\.([0-9]*)/.exec(String(value));\r\n if (!groups) {\r\n return 0;\r\n }\r\n if (groups[1]) {\r\n return -groups[1].length;\r\n }\r\n if (groups[2]) {\r\n return groups[2].length;\r\n }\r\n return 0;\r\n}\r\n/**\r\n * Fluent's PrecisionRound function\r\n * https://github.com/microsoft/fluentui/blob/dcbf775d37938eacffa37922fc0b43a3cdd5753f/packages/utilities/src/math.ts#L116\r\n *\r\n * Rounds a number to a certain level of precision. Accepts negative precision.\r\n * @param value - The value that is being rounded.\r\n * @param precision - The number of decimal places to round the number to\r\n * @returns The rounded number.\r\n */\r\nfunction PrecisionRound(value: number, precision: number) {\r\n const exp = Math.pow(10, precision);\r\n return Math.round(value * exp) / exp;\r\n}\r\n\r\nexport function HandleOnBlur(event: FocusEvent<HTMLInputElement>) {\r\n event.stopPropagation();\r\n event.preventDefault();\r\n}\r\n\r\nexport function HandleKeyDown(event: KeyboardEvent<HTMLInputElement>) {\r\n event.stopPropagation(); // Prevent event propagation\r\n\r\n // Prevent Enter key from causing form submission or value reversion\r\n if (event.key === \"Enter\") {\r\n event.preventDefault();\r\n }\r\n}\r\n"]}
1
+ {"version":3,"file":"spinButton.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/spinButton.tsx"],"names":[],"mappings":"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","sourcesContent":["import { makeStyles, SpinButton as FluentSpinButton, useId, tokens } from \"@fluentui/react-components\";\r\nimport type { SpinButtonOnChangeData, SpinButtonChangeEvent } from \"@fluentui/react-components\";\r\nimport type { FunctionComponent, KeyboardEvent } from \"react\";\r\nimport { useEffect, useState, useRef } from \"react\";\r\nimport type { PrimitiveProps } from \"./primitive\";\r\nimport { InfoLabel } from \"./infoLabel\";\r\nimport { HandleKeyDown, HandleOnBlur } from \"./utils\";\r\n\r\nconst useSpinStyles = makeStyles({\r\n base: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n minWidth: \"55px\",\r\n },\r\n invalid: { backgroundColor: tokens.colorPaletteRedBackground2 },\r\n});\r\n\r\nexport type SpinButtonProps = PrimitiveProps<number> & {\r\n min?: number;\r\n max?: number;\r\n /** Determines how much the spinbutton increments with the arrow keys. Note this also determines the precision value (# of decimals in display value)\r\n * i.e. if step = 1, precision = 0. step = 0.0089, precision = 4. step = 300, precision = 2. step = 23.00, precision = 2. */\r\n step?: number;\r\n unit?: string;\r\n forceInt?: boolean;\r\n validator?: (value: number) => boolean;\r\n};\r\n\r\nexport const SpinButton: FunctionComponent<SpinButtonProps> = (props) => {\r\n const classes = useSpinStyles();\r\n const { min, max } = props;\r\n\r\n const [value, setValue] = useState(props.value);\r\n const lastCommittedValue = useRef(props.value);\r\n // step and forceInt are not mutually exclusive since there could be cases where you want to forceInt but have spinButton jump >1 int per spin\r\n const step = props.step != undefined ? props.step : props.forceInt ? 1 : undefined;\r\n\r\n useEffect(() => {\r\n if (props.value !== lastCommittedValue.current) {\r\n lastCommittedValue.current = props.value;\r\n setValue(props.value); // Update local state when props.value changes\r\n }\r\n }, [props.value]);\r\n\r\n const validateValue = (numericValue: number): boolean => {\r\n const outOfBounds = (min !== undefined && numericValue < min) || (max !== undefined && numericValue > max);\r\n const failsValidator = props.validator && !props.validator(numericValue);\r\n const failsIntCheck = props.forceInt ? !Number.isInteger(numericValue) : false;\r\n const invalid = !!outOfBounds || !!failsValidator || isNaN(numericValue) || !!failsIntCheck;\r\n return !invalid;\r\n };\r\n\r\n const tryCommitValue = (currVal: number) => {\r\n // Only commit if valid and different from last committed value\r\n if (validateValue(currVal) && currVal !== lastCommittedValue.current) {\r\n lastCommittedValue.current = currVal;\r\n props.onChange(currVal);\r\n }\r\n };\r\n\r\n const handleChange = (event: SpinButtonChangeEvent, data: SpinButtonOnChangeData) => {\r\n event.stopPropagation(); // Prevent event propagation\r\n if (data.value != null && !Number.isNaN(data.value)) {\r\n setValue(data.value);\r\n tryCommitValue(data.value);\r\n }\r\n };\r\n\r\n const handleKeyUp = (event: KeyboardEvent<HTMLInputElement>) => {\r\n event.stopPropagation(); // Prevent event propagation\r\n\r\n if (event.key !== \"Enter\") {\r\n const currVal = parseFloat((event.target as any).value); // Cannot use currentTarget.value as it won't have the most recently typed value\r\n setValue(currVal);\r\n tryCommitValue(currVal);\r\n }\r\n };\r\n\r\n const id = useId(\"spin-button\");\r\n return (\r\n <div className={classes.base}>\r\n {props.infoLabel && <InfoLabel {...props.infoLabel} htmlFor={id} />}\r\n <FluentSpinButton\r\n {...props}\r\n step={step}\r\n id={id}\r\n size=\"small\"\r\n precision={CalculatePrecision(step ?? 1.01)}\r\n displayValue={props.unit ? `${PrecisionRound(value, CalculatePrecision(step ?? 1.01))} ${props.unit}` : undefined}\r\n value={value}\r\n onChange={handleChange}\r\n onKeyUp={handleKeyUp}\r\n onKeyDown={HandleKeyDown}\r\n onBlur={HandleOnBlur}\r\n className={`${!validateValue(value) ? classes.invalid : \"\"}`}\r\n />\r\n </div>\r\n );\r\n};\r\n\r\n/**\r\n * Fluent's CalculatePrecision function\r\n * https://github.com/microsoft/fluentui/blob/dcbf775d37938eacffa37922fc0b43a3cdd5753f/packages/utilities/src/math.ts#L91C1\r\n *\r\n * Calculates a number's precision based on the number of trailing\r\n * zeros if the number does not have a decimal indicated by a negative\r\n * precision. Otherwise, it calculates the number of digits after\r\n * the decimal point indicated by a positive precision.\r\n *\r\n * @param value - the value to determine the precision of\r\n * @returns the calculated precision\r\n */\r\nexport function CalculatePrecision(value: number) {\r\n /**\r\n * Group 1:\r\n * [1-9]([0]+$) matches trailing zeros\r\n * Group 2:\r\n * \\.([0-9]*) matches all digits after a decimal point.\r\n */ const groups = /[1-9]([0]+$)|\\.([0-9]*)/.exec(String(value));\r\n if (!groups) {\r\n return 0;\r\n }\r\n if (groups[1]) {\r\n return -groups[1].length;\r\n }\r\n if (groups[2]) {\r\n return groups[2].length;\r\n }\r\n return 0;\r\n}\r\n/**\r\n * Fluent's PrecisionRound function\r\n * https://github.com/microsoft/fluentui/blob/dcbf775d37938eacffa37922fc0b43a3cdd5753f/packages/utilities/src/math.ts#L116\r\n *\r\n * Rounds a number to a certain level of precision. Accepts negative precision.\r\n * @param value - The value that is being rounded.\r\n * @param precision - The number of decimal places to round the number to\r\n * @returns The rounded number.\r\n */\r\nfunction PrecisionRound(value: number, precision: number) {\r\n const exp = Math.pow(10, precision);\r\n return Math.round(value * exp) / exp;\r\n}\r\n"]}
@@ -2,7 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useEffect, useRef, useState } from "react";
3
3
  import { Input as FluentInput, makeStyles, tokens, useId } from "@fluentui/react-components";
4
4
  import { InfoLabel } from "./infoLabel.js";
5
- import { HandleOnBlur, HandleKeyDown } from "./spinButton.js";
5
+ import { HandleOnBlur, HandleKeyDown } from "./utils.js";
6
6
  const useInputStyles = makeStyles({
7
7
  base: {
8
8
  display: "flex",
@@ -1 +1 @@
1
- {"version":3,"file":"textInput.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/textInput.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { FunctionComponent, KeyboardEvent, ChangeEvent } from \"react\";\r\nimport { useEffect, useRef, useState } from \"react\";\r\nimport type { InputOnChangeData } from \"@fluentui/react-components\";\r\nimport { Input as FluentInput, makeStyles, tokens, useId } from \"@fluentui/react-components\";\r\nimport type { PrimitiveProps } from \"./primitive\";\r\nimport { InfoLabel } from \"./infoLabel\";\r\nimport { HandleOnBlur, HandleKeyDown } from \"./spinButton\";\r\n\r\nconst useInputStyles = makeStyles({\r\n base: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n width: \"100px\",\r\n },\r\n invalid: { backgroundColor: tokens.colorPaletteRedBackground2 },\r\n});\r\n\r\nexport type TextInputProps = PrimitiveProps<string> & {\r\n validator?: (value: string) => boolean;\r\n};\r\n\r\nexport const TextInput: FunctionComponent<TextInputProps> = (props) => {\r\n const classes = useInputStyles();\r\n\r\n const [value, setValue] = useState(props.value);\r\n const lastCommittedValue = useRef(props.value);\r\n\r\n useEffect(() => {\r\n if (props.value !== lastCommittedValue.current) {\r\n setValue(props.value); // Update local state when props.value changes\r\n lastCommittedValue.current = props.value;\r\n }\r\n }, [props.value]);\r\n\r\n const validateValue = (val: string): boolean => {\r\n const failsValidator = props.validator && !props.validator(val);\r\n return !failsValidator;\r\n };\r\n\r\n const tryCommitValue = (currVal: string) => {\r\n // Only commit if valid and different from last committed value\r\n if (validateValue(currVal) && currVal !== lastCommittedValue.current) {\r\n lastCommittedValue.current = currVal;\r\n props.onChange(currVal);\r\n }\r\n };\r\n\r\n const handleChange = (event: ChangeEvent<HTMLInputElement>, data: InputOnChangeData) => {\r\n event.stopPropagation();\r\n setValue(data.value);\r\n tryCommitValue(data.value);\r\n };\r\n\r\n const handleKeyUp = (event: KeyboardEvent<HTMLInputElement>) => {\r\n event.stopPropagation();\r\n setValue(event.currentTarget.value);\r\n tryCommitValue(event.currentTarget.value);\r\n };\r\n\r\n const id = useId(\"input-button\");\r\n return (\r\n <div className={classes.base}>\r\n {props.infoLabel && <InfoLabel {...props.infoLabel} htmlFor={id} />}\r\n <FluentInput\r\n {...props}\r\n id={id}\r\n size=\"small\"\r\n value={value}\r\n onChange={handleChange}\r\n onKeyUp={handleKeyUp}\r\n onKeyDown={HandleKeyDown}\r\n onBlur={HandleOnBlur}\r\n className={`${!validateValue(value) ? classes.invalid : \"\"}`}\r\n />\r\n </div>\r\n );\r\n};\r\n"]}
1
+ {"version":3,"file":"textInput.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/textInput.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { FunctionComponent, KeyboardEvent, ChangeEvent } from \"react\";\r\nimport { useEffect, useRef, useState } from \"react\";\r\nimport type { InputOnChangeData } from \"@fluentui/react-components\";\r\nimport { Input as FluentInput, makeStyles, tokens, useId } from \"@fluentui/react-components\";\r\nimport type { PrimitiveProps } from \"./primitive\";\r\nimport { InfoLabel } from \"./infoLabel\";\r\nimport { HandleOnBlur, HandleKeyDown } from \"./utils\";\r\n\r\nconst useInputStyles = makeStyles({\r\n base: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n width: \"100px\",\r\n },\r\n invalid: { backgroundColor: tokens.colorPaletteRedBackground2 },\r\n});\r\n\r\nexport type TextInputProps = PrimitiveProps<string> & {\r\n validator?: (value: string) => boolean;\r\n};\r\n\r\nexport const TextInput: FunctionComponent<TextInputProps> = (props) => {\r\n const classes = useInputStyles();\r\n\r\n const [value, setValue] = useState(props.value);\r\n const lastCommittedValue = useRef(props.value);\r\n\r\n useEffect(() => {\r\n if (props.value !== lastCommittedValue.current) {\r\n setValue(props.value); // Update local state when props.value changes\r\n lastCommittedValue.current = props.value;\r\n }\r\n }, [props.value]);\r\n\r\n const validateValue = (val: string): boolean => {\r\n const failsValidator = props.validator && !props.validator(val);\r\n return !failsValidator;\r\n };\r\n\r\n const tryCommitValue = (currVal: string) => {\r\n // Only commit if valid and different from last committed value\r\n if (validateValue(currVal) && currVal !== lastCommittedValue.current) {\r\n lastCommittedValue.current = currVal;\r\n props.onChange(currVal);\r\n }\r\n };\r\n\r\n const handleChange = (event: ChangeEvent<HTMLInputElement>, data: InputOnChangeData) => {\r\n event.stopPropagation();\r\n setValue(data.value);\r\n tryCommitValue(data.value);\r\n };\r\n\r\n const handleKeyUp = (event: KeyboardEvent<HTMLInputElement>) => {\r\n event.stopPropagation();\r\n setValue(event.currentTarget.value);\r\n tryCommitValue(event.currentTarget.value);\r\n };\r\n\r\n const id = useId(\"input-button\");\r\n return (\r\n <div className={classes.base}>\r\n {props.infoLabel && <InfoLabel {...props.infoLabel} htmlFor={id} />}\r\n <FluentInput\r\n {...props}\r\n id={id}\r\n size=\"small\"\r\n value={value}\r\n onChange={handleChange}\r\n onKeyUp={handleKeyUp}\r\n onKeyDown={HandleKeyDown}\r\n onBlur={HandleOnBlur}\r\n className={`${!validateValue(value) ? classes.invalid : \"\"}`}\r\n />\r\n </div>\r\n );\r\n};\r\n"]}
@@ -0,0 +1,3 @@
1
+ import type { KeyboardEvent, FocusEvent } from "react";
2
+ export declare function HandleOnBlur(event: FocusEvent<HTMLInputElement>): void;
3
+ export declare function HandleKeyDown(event: KeyboardEvent<HTMLInputElement>): void;
@@ -0,0 +1,12 @@
1
+ export function HandleOnBlur(event) {
2
+ event.stopPropagation();
3
+ event.preventDefault();
4
+ }
5
+ export function HandleKeyDown(event) {
6
+ event.stopPropagation(); // Prevent event propagation
7
+ // Prevent Enter key from causing form submission or value reversion
8
+ if (event.key === "Enter") {
9
+ event.preventDefault();
10
+ }
11
+ }
12
+ //# sourceMappingURL=utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/utils.ts"],"names":[],"mappings":"AAEA,MAAM,UAAU,YAAY,CAAC,KAAmC;IAC5D,KAAK,CAAC,eAAe,EAAE,CAAC;IACxB,KAAK,CAAC,cAAc,EAAE,CAAC;AAC3B,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,KAAsC;IAChE,KAAK,CAAC,eAAe,EAAE,CAAC,CAAC,4BAA4B;IAErD,oEAAoE;IACpE,IAAI,KAAK,CAAC,GAAG,KAAK,OAAO,EAAE,CAAC;QACxB,KAAK,CAAC,cAAc,EAAE,CAAC;IAC3B,CAAC;AACL,CAAC","sourcesContent":["import type { KeyboardEvent, FocusEvent } from \"react\";\r\n\r\nexport function HandleOnBlur(event: FocusEvent<HTMLInputElement>) {\r\n event.stopPropagation();\r\n event.preventDefault();\r\n}\r\n\r\nexport function HandleKeyDown(event: KeyboardEvent<HTMLInputElement>) {\r\n event.stopPropagation(); // Prevent event propagation\r\n\r\n // Prevent Enter key from causing form submission or value reversion\r\n if (event.key === \"Enter\") {\r\n event.preventDefault();\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.28.1",
3
+ "version": "8.28.3",
4
4
  "main": "index.js",
5
5
  "module": "index.js",
6
6
  "types": "index.d.ts",