@onerjs/shared-ui-components 8.42.7 → 8.42.9

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.
@@ -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 type { ChangeEvent, FocusEvent, KeyboardEvent, PointerEvent } from \"react\";\r\n\r\nimport type { PrimitiveProps } from \"./primitive\";\r\n\r\nimport { Input, makeStyles, mergeClasses, tokens, useId, useMergedRefs } from \"@fluentui/react-components\";\r\nimport { ArrowBidirectionalUpDownFilled } from \"@fluentui/react-icons\";\r\n\r\nimport { Clamp } from \"core/Maths/math.scalar.functions\";\r\nimport { forwardRef, useCallback, useContext, useEffect, useRef, useState } from \"react\";\r\nimport { ToolContext } from \"../hoc/fluentToolWrapper\";\r\nimport { useKeyState } from \"../hooks/keyboardHooks\";\r\nimport { InfoLabel } from \"./infoLabel\";\r\nimport { CalculatePrecision, HandleKeyDown, HandleOnBlur, useInputStyles } from \"./utils\";\r\n\r\nfunction CoerceStepValue(step: number, isFineKeyPressed: boolean, isCourseKeyPressed: boolean): number {\r\n // When the fine key is pressed, decrease step by a factor of 10.\r\n if (isFineKeyPressed) {\r\n return step * 0.1;\r\n }\r\n\r\n // When the course key is pressed, increase step by a factor of 10.\r\n if (isCourseKeyPressed) {\r\n return step * 10;\r\n }\r\n\r\n return step;\r\n}\r\n\r\n// Allow arbitrary expressions, primarily for math operations (e.g. 10*60 for 10 minutes in seconds).\r\n// Use Function constructor to safely evaluate the expression without allowing access to scope.\r\n// If the expression is invalid, fallback to NaN which will be caught by validateValue and prevent committing.\r\nfunction EvaluateExpression(rawValue: string): number {\r\n const val = rawValue.trim();\r\n try {\r\n return Number(Function(`\"use strict\";return (${val})`)());\r\n } catch {\r\n return NaN;\r\n }\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 /** Optional fixed precision (number of decimal digits). Overrides the automatically computed display precision. */\r\n precision?: number;\r\n /** Optional className for the input element */\r\n inputClassName?: string;\r\n /** When true, hides the drag-to-scrub button */\r\n disableDragButton?: boolean;\r\n};\r\n\r\nconst useStyles = makeStyles({\r\n icon: {\r\n \"&:hover\": {\r\n color: tokens.colorBrandForeground1,\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * A numeric input with a vertical drag-to-scrub icon (ArrowsBidirectionalRegular rotated 90°).\r\n * Click-and-drag up/down on the icon to increment/decrement the value.\r\n */\r\nexport const SpinButton = forwardRef<HTMLInputElement, SpinButtonProps>((props, ref) => {\r\n SpinButton.displayName = \"SpinButton2\";\r\n const inputClasses = useInputStyles();\r\n const classes = useStyles();\r\n const { size } = useContext(ToolContext);\r\n\r\n const { min, max } = props;\r\n const baseStep = props.step ?? 1;\r\n\r\n // Local ref for the input element so we can blur it programmatically (e.g. when a drag starts while editing).\r\n const inputRef = useRef<HTMLInputElement | null>(null);\r\n const mergedRef = useMergedRefs(ref, inputRef);\r\n\r\n // Modifier keys for step coercion.\r\n const isAltKeyPressed = useKeyState(\"Alt\", { preventDefault: true });\r\n const isShiftKeyPressed = useKeyState(\"Shift\");\r\n\r\n const step = CoerceStepValue(baseStep, isAltKeyPressed, isShiftKeyPressed);\r\n const stepPrecision = Math.max(0, CalculatePrecision(step));\r\n\r\n const [value, setValue] = useState<number>(props.value ?? 0);\r\n const lastCommittedValue = useRef(props.value);\r\n const [isDragging, setIsDragging] = useState(false);\r\n const scrubStartYRef = useRef(0);\r\n const scrubStartValueRef = useRef(0);\r\n const lastPointerYRef = useRef(0);\r\n const [isHovered, setIsHovered] = useState(false);\r\n\r\n // Editing state: when the user is typing, we show their raw text rather than the formatted value.\r\n const [isEditing, setIsEditing] = useState(false);\r\n const [editText, setEditText] = useState(\"\");\r\n\r\n const valuePrecision = Math.max(0, CalculatePrecision(value));\r\n // Display precision: controls how many decimals are shown in the formatted displayValue. Cap at 4 to avoid wild numbers.\r\n // If a fixed precision prop is provided, use it instead.\r\n const displayPrecision = props.precision ?? Math.min(4, Math.max(stepPrecision, valuePrecision));\r\n\r\n // Format a number for display: toFixed, then trim trailing zeros and period unless a fixed precision is specified.\r\n const formatValue = useCallback(\r\n (v: number) => {\r\n const fixed = v.toFixed(displayPrecision);\r\n if (props.precision !== undefined) {\r\n return fixed;\r\n }\r\n return fixed.replace(/(\\.\\d*?)0+$/, \"$1\").replace(/\\.$/, \"\");\r\n },\r\n [displayPrecision, props.precision]\r\n );\r\n\r\n useEffect(() => {\r\n if (!isDragging && props.value !== lastCommittedValue.current) {\r\n lastCommittedValue.current = props.value;\r\n setValue(props.value ?? 0);\r\n }\r\n }, [props.value, isDragging]);\r\n\r\n const validateValue = useCallback(\r\n (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 [min, max, props.validator, props.forceInt]\r\n );\r\n\r\n // Constrain a value to the valid range by clamping to [min, max].\r\n const constrainValue = useCallback((v: number) => Clamp(v, min ?? -Infinity, max ?? Infinity), [min, max]);\r\n\r\n const tryCommitValue = useCallback(\r\n (currVal: number) => {\r\n if (validateValue(currVal) && currVal !== lastCommittedValue.current) {\r\n lastCommittedValue.current = currVal;\r\n props.onChange(currVal);\r\n }\r\n },\r\n [validateValue, props.onChange]\r\n );\r\n\r\n const handleInputChange = useCallback((_: ChangeEvent, data: { value: string }) => {\r\n // Just update the raw text — no evaluation or commit until Enter/blur.\r\n setEditText(data.value);\r\n }, []);\r\n\r\n // Evaluate the current edit text and commit the value. Returns the clamped value if valid, or undefined.\r\n const commitEditText = useCallback(\r\n (text: string): number | undefined => {\r\n const numericValue = EvaluateExpression(text);\r\n if (!isNaN(numericValue) && validateValue(numericValue)) {\r\n const constrained = constrainValue(numericValue);\r\n setValue(constrained);\r\n tryCommitValue(constrained);\r\n return constrained;\r\n }\r\n return undefined;\r\n },\r\n [validateValue, constrainValue, tryCommitValue]\r\n );\r\n\r\n const handleIconPointerDown = useCallback(\r\n (e: PointerEvent<Element>) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n // If the input was being edited, commit the current text and blur the input\r\n // so the focus state stays consistent after the drag ends.\r\n let startValue = value;\r\n if (isEditing) {\r\n const committed = commitEditText(editText);\r\n if (committed !== undefined) {\r\n startValue = committed;\r\n }\r\n setIsEditing(false);\r\n }\r\n // Blur the active element to ensure we can observe document level modifier keys.\r\n (inputRef.current?.ownerDocument.activeElement as Partial<HTMLElement>)?.blur?.();\r\n setIsDragging(true);\r\n scrubStartYRef.current = e.clientY;\r\n scrubStartValueRef.current = startValue;\r\n e.currentTarget.setPointerCapture(e.pointerId);\r\n },\r\n [value, isEditing, editText, commitEditText]\r\n );\r\n\r\n // When the step size changes during a drag (e.g. Shift/Alt pressed or released), reset the scrub reference point\r\n // to the current value and pointer position so only future movement uses the new step.\r\n useEffect(() => {\r\n if (isDragging) {\r\n scrubStartValueRef.current = value;\r\n scrubStartYRef.current = lastPointerYRef.current;\r\n }\r\n }, [step]);\r\n\r\n const handleIconPointerMove = useCallback(\r\n (e: PointerEvent) => {\r\n if (!isDragging) {\r\n return;\r\n }\r\n lastPointerYRef.current = e.clientY;\r\n // Dragging up (negative dy) should increment, dragging down should decrement.\r\n // Scale delta by step but round to display precision (not step) for smooth fine-grained control.\r\n const dy = scrubStartYRef.current - e.clientY;\r\n // 5 is just a number that \"feels right\" for the drag sensitivity — it determines how far the user needs to drag to change the value by 1 step.\r\n const delta = (dy * step) / 5;\r\n const raw = scrubStartValueRef.current + delta;\r\n const precisionFactor = Math.pow(10, displayPrecision);\r\n const rounded = Math.round(raw * precisionFactor) / precisionFactor;\r\n const constrained = constrainValue(rounded);\r\n setValue(constrained);\r\n tryCommitValue(constrained);\r\n },\r\n [isDragging, step, displayPrecision, constrainValue, tryCommitValue]\r\n );\r\n\r\n const handleIconPointerUp = useCallback((e: PointerEvent<Element>) => {\r\n setIsDragging(false);\r\n e.currentTarget.releasePointerCapture(e.pointerId);\r\n }, []);\r\n\r\n const handleKeyDown = useCallback(\r\n (event: KeyboardEvent<HTMLInputElement>) => {\r\n // Commit on Enter and blur the input if the value is valid.\r\n if (event.key === \"Enter\") {\r\n const committed = commitEditText(event.currentTarget.value);\r\n if (committed !== undefined) {\r\n inputRef.current?.blur();\r\n }\r\n }\r\n\r\n if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\r\n event.preventDefault();\r\n const direction = event.key === \"ArrowUp\" ? 1 : -1;\r\n const newValue = constrainValue(Math.round((value + direction * step) / step) * step);\r\n setValue(newValue);\r\n tryCommitValue(newValue);\r\n // Update edit text to reflect the new value so the user sees the change\r\n setEditText(formatValue(newValue));\r\n }\r\n\r\n HandleKeyDown(event);\r\n },\r\n [value, step, constrainValue, tryCommitValue, commitEditText, formatValue]\r\n );\r\n\r\n const id = useId(\"spin-button2\");\r\n\r\n // Real-time validation: when editing, validate the expression; otherwise validate the committed value.\r\n // (validateValue already handles NaN, so no separate isNaN check needed.)\r\n const isInputInvalid = !validateValue(isEditing ? EvaluateExpression(editText) : value);\r\n\r\n const mergedClassName = mergeClasses(inputClasses.input, isInputInvalid ? inputClasses.invalid : \"\", props.className);\r\n const inputSlotClassName = mergeClasses(inputClasses.inputSlot, props.inputClassName);\r\n\r\n const formattedValue = formatValue(value);\r\n\r\n const handleFocus = useCallback(() => {\r\n setIsEditing(true);\r\n setEditText(formattedValue);\r\n }, [formattedValue]);\r\n\r\n const handleBlur = useCallback(\r\n (event: FocusEvent<HTMLInputElement>) => {\r\n // Skip blur handling if a drag just started (icon pointerDown already committed).\r\n if (isDragging) {\r\n return;\r\n }\r\n commitEditText(event.target.value);\r\n setIsEditing(false);\r\n HandleOnBlur(event);\r\n },\r\n [commitEditText, isDragging]\r\n );\r\n\r\n const contentBefore =\r\n !props.disableDragButton && (isHovered || isDragging) && !isInputInvalid ? (\r\n <ArrowBidirectionalUpDownFilled\r\n className={classes.icon}\r\n style={{ cursor: isDragging ? \"ns-resize\" : \"pointer\" }}\r\n onPointerDown={handleIconPointerDown}\r\n onPointerMove={handleIconPointerMove}\r\n onPointerUp={handleIconPointerUp}\r\n />\r\n ) : undefined;\r\n\r\n const input = (\r\n <div\r\n onMouseEnter={() => setIsHovered(true)}\r\n onMouseLeave={() => {\r\n if (!isDragging) {\r\n setIsHovered(false);\r\n }\r\n }}\r\n >\r\n <Input\r\n ref={mergedRef}\r\n id={id}\r\n appearance=\"outline\"\r\n size={size}\r\n className={mergedClassName}\r\n input={{ className: inputSlotClassName }}\r\n value={isEditing ? editText : formattedValue}\r\n onChange={handleInputChange}\r\n onFocus={handleFocus}\r\n onKeyDown={handleKeyDown}\r\n onBlur={handleBlur}\r\n contentBefore={contentBefore}\r\n contentAfter={props.unit}\r\n />\r\n </div>\r\n );\r\n\r\n return props.infoLabel ? (\r\n <div className={inputClasses.container}>\r\n <InfoLabel {...props.infoLabel} htmlFor={id} />\r\n {input}\r\n </div>\r\n ) : (\r\n input\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 type { ChangeEvent, FocusEvent, KeyboardEvent, PointerEvent } from \"react\";\r\n\r\nimport type { PrimitiveProps } from \"./primitive\";\r\n\r\nimport { Input, makeStyles, mergeClasses, tokens, useId, useMergedRefs } from \"@fluentui/react-components\";\r\nimport { ArrowBidirectionalUpDownFilled } from \"@fluentui/react-icons\";\r\n\r\nimport { Clamp } from \"core/Maths/math.scalar.functions\";\r\nimport { forwardRef, useCallback, useContext, useEffect, useRef, useState } from \"react\";\r\nimport { ToolContext } from \"../hoc/fluentToolWrapper\";\r\nimport { useKeyState } from \"../hooks/keyboardHooks\";\r\nimport { InfoLabel } from \"./infoLabel\";\r\nimport { CalculatePrecision, HandleKeyDown, HandleOnBlur, useInputStyles } from \"./utils\";\r\n\r\nfunction CoerceStepValue(step: number, isFineKeyPressed: boolean, isCourseKeyPressed: boolean): number {\r\n // When the fine key is pressed, decrease step by a factor of 10.\r\n if (isFineKeyPressed) {\r\n return step * 0.1;\r\n }\r\n\r\n // When the course key is pressed, increase step by a factor of 10.\r\n if (isCourseKeyPressed) {\r\n return step * 10;\r\n }\r\n\r\n return step;\r\n}\r\n\r\n// Allow arbitrary expressions, primarily for math operations (e.g. 10*60 for 10 minutes in seconds).\r\n// Use Function constructor to safely evaluate the expression without allowing access to scope.\r\n// If the expression is invalid, fallback to NaN which will be caught by validateValue and prevent committing.\r\nfunction EvaluateExpression(rawValue: string): number {\r\n const val = rawValue.trim();\r\n try {\r\n return Number(Function(`\"use strict\";return (${val})`)());\r\n } catch {\r\n return NaN;\r\n }\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 /** Optional fixed precision (number of decimal digits). Overrides the automatically computed display precision. */\r\n precision?: number;\r\n /** Optional className for the input element */\r\n inputClassName?: string;\r\n /** When true, hides the drag-to-scrub button */\r\n disableDragButton?: boolean;\r\n};\r\n\r\nconst useStyles = makeStyles({\r\n icon: {\r\n \"&:hover\": {\r\n color: tokens.colorBrandForeground1,\r\n },\r\n },\r\n});\r\n\r\n/**\r\n * A numeric input with a vertical drag-to-scrub icon (ArrowsBidirectionalRegular rotated 90°).\r\n * Click-and-drag up/down on the icon to increment/decrement the value.\r\n */\r\nexport const SpinButton = forwardRef<HTMLInputElement, SpinButtonProps>((props, ref) => {\r\n SpinButton.displayName = \"SpinButton2\";\r\n const inputClasses = useInputStyles();\r\n const classes = useStyles();\r\n const { size } = useContext(ToolContext);\r\n\r\n const { min, max } = props;\r\n const baseStep = props.step ?? 1;\r\n\r\n // Local ref for the input element so we can blur it programmatically (e.g. when a drag starts while editing).\r\n const inputRef = useRef<HTMLInputElement | null>(null);\r\n const mergedRef = useMergedRefs(ref, inputRef);\r\n\r\n // Modifier keys for step coercion.\r\n const isAltKeyPressed = useKeyState(\"Alt\", { preventDefault: true });\r\n const isShiftKeyPressed = useKeyState(\"Shift\");\r\n\r\n const step = CoerceStepValue(baseStep, isAltKeyPressed, isShiftKeyPressed);\r\n const stepPrecision = Math.max(0, CalculatePrecision(step));\r\n\r\n const [value, setValue] = useState<number>(props.value ?? 0);\r\n const lastCommittedValue = useRef(props.value);\r\n const [isDragging, setIsDragging] = useState(false);\r\n const scrubStartYRef = useRef(0);\r\n const scrubStartValueRef = useRef(0);\r\n const lastPointerYRef = useRef(0);\r\n const [isHovered, setIsHovered] = useState(false);\r\n\r\n // Editing state: when the user is typing, we show their raw text rather than the formatted value.\r\n const [isEditing, setIsEditing] = useState(false);\r\n const [editText, setEditText] = useState(\"\");\r\n\r\n const valuePrecision = Math.max(0, CalculatePrecision(value));\r\n // Display precision: controls how many decimals are shown in the formatted displayValue. Cap at 4 to avoid wild numbers.\r\n // If a fixed precision prop is provided, use it instead.\r\n const displayPrecision = props.precision ?? Math.min(4, Math.max(stepPrecision, valuePrecision));\r\n\r\n // Format a number for display: toFixed, then trim trailing zeros and period unless a fixed precision is specified.\r\n const formatValue = useCallback(\r\n (v: number) => {\r\n const fixed = v.toFixed(displayPrecision);\r\n if (props.precision !== undefined) {\r\n return fixed;\r\n }\r\n return fixed.replace(/(\\.\\d*?)0+$/, \"$1\").replace(/\\.$/, \"\");\r\n },\r\n [displayPrecision, props.precision]\r\n );\r\n\r\n useEffect(() => {\r\n if (!isDragging && props.value !== lastCommittedValue.current) {\r\n lastCommittedValue.current = props.value;\r\n setValue(props.value ?? 0);\r\n }\r\n }, [props.value, isDragging]);\r\n\r\n const validateValue = useCallback(\r\n (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 [min, max, props.validator, props.forceInt]\r\n );\r\n\r\n // Constrain a value to the valid range by clamping to [min, max].\r\n const constrainValue = useCallback((v: number) => Clamp(v, min ?? -Infinity, max ?? Infinity), [min, max]);\r\n\r\n const tryCommitValue = useCallback(\r\n (currVal: number) => {\r\n if (validateValue(currVal) && currVal !== lastCommittedValue.current) {\r\n lastCommittedValue.current = currVal;\r\n props.onChange(currVal);\r\n }\r\n },\r\n [validateValue, props.onChange]\r\n );\r\n\r\n const handleInputChange = useCallback((_: ChangeEvent, data: { value: string }) => {\r\n // Just update the raw text — no evaluation or commit until Enter/blur.\r\n setEditText(data.value);\r\n }, []);\r\n\r\n // Evaluate the current edit text and commit the value. Returns the clamped value if valid, or undefined.\r\n const commitEditText = useCallback(\r\n (text: string): number | undefined => {\r\n const numericValue = EvaluateExpression(text);\r\n if (!isNaN(numericValue) && validateValue(numericValue)) {\r\n const constrained = constrainValue(numericValue);\r\n setValue(constrained);\r\n tryCommitValue(constrained);\r\n return constrained;\r\n }\r\n return undefined;\r\n },\r\n [validateValue, constrainValue, tryCommitValue]\r\n );\r\n\r\n const handleIconPointerDown = useCallback(\r\n (e: PointerEvent<Element>) => {\r\n e.preventDefault();\r\n e.stopPropagation();\r\n // If the input was being edited, commit the current text and blur the input\r\n // so the focus state stays consistent after the drag ends.\r\n let startValue = value;\r\n if (isEditing) {\r\n const committed = commitEditText(editText);\r\n if (committed !== undefined) {\r\n startValue = committed;\r\n }\r\n setIsEditing(false);\r\n }\r\n // Blur the active element to ensure we can observe document level modifier keys.\r\n (inputRef.current?.ownerDocument.activeElement as Partial<HTMLElement>)?.blur?.();\r\n setIsDragging(true);\r\n scrubStartYRef.current = e.clientY;\r\n scrubStartValueRef.current = startValue;\r\n e.currentTarget.setPointerCapture(e.pointerId);\r\n },\r\n [value, isEditing, editText, commitEditText]\r\n );\r\n\r\n // When the step size changes during a drag (e.g. Shift/Alt pressed or released), reset the scrub reference point\r\n // to the current value and pointer position so only future movement uses the new step.\r\n useEffect(() => {\r\n if (isDragging) {\r\n scrubStartValueRef.current = value;\r\n scrubStartYRef.current = lastPointerYRef.current;\r\n }\r\n }, [step]);\r\n\r\n const handleIconPointerMove = useCallback(\r\n (e: PointerEvent) => {\r\n if (!isDragging) {\r\n return;\r\n }\r\n lastPointerYRef.current = e.clientY;\r\n // Dragging up (negative dy) should increment, dragging down should decrement.\r\n // Scale delta by step but round to display precision (not step) for smooth fine-grained control.\r\n const dy = scrubStartYRef.current - e.clientY;\r\n // 5 is just a number that \"feels right\" for the drag sensitivity — it determines how far the user needs to drag to change the value by 1 step.\r\n const delta = (dy * step) / 5;\r\n const raw = scrubStartValueRef.current + delta;\r\n const precisionFactor = Math.pow(10, displayPrecision);\r\n const rounded = Math.round(raw * precisionFactor) / precisionFactor;\r\n const constrained = constrainValue(rounded);\r\n setValue(constrained);\r\n tryCommitValue(constrained);\r\n },\r\n [isDragging, step, displayPrecision, constrainValue, tryCommitValue]\r\n );\r\n\r\n const handleIconPointerUp = useCallback((e: PointerEvent<Element>) => {\r\n setIsDragging(false);\r\n e.currentTarget.releasePointerCapture(e.pointerId);\r\n }, []);\r\n\r\n const handleKeyDown = useCallback(\r\n (event: KeyboardEvent<HTMLInputElement>) => {\r\n // Commit on Enter and blur the input if the value is valid.\r\n if (event.key === \"Enter\") {\r\n const committed = commitEditText(event.currentTarget.value);\r\n if (committed !== undefined) {\r\n inputRef.current?.blur();\r\n }\r\n }\r\n\r\n if (event.key === \"ArrowUp\" || event.key === \"ArrowDown\") {\r\n event.preventDefault();\r\n const direction = event.key === \"ArrowUp\" ? 1 : -1;\r\n const newValue = constrainValue(Math.round((value + direction * step) / step) * step);\r\n setValue(newValue);\r\n tryCommitValue(newValue);\r\n // Update edit text to reflect the new value so the user sees the change\r\n setEditText(formatValue(newValue));\r\n }\r\n\r\n HandleKeyDown(event);\r\n },\r\n [value, step, constrainValue, tryCommitValue, commitEditText, formatValue]\r\n );\r\n\r\n const id = useId(\"spin-button2\");\r\n\r\n // Real-time validation: when editing, validate the expression; otherwise validate the committed value.\r\n // (validateValue already handles NaN, so no separate isNaN check needed.)\r\n const isInputInvalid = !validateValue(isEditing ? EvaluateExpression(editText) : value);\r\n\r\n const mergedClassName = mergeClasses(inputClasses.inputFill, isInputInvalid ? inputClasses.invalid : \"\");\r\n const inputSlotClassName = mergeClasses(inputClasses.inputSlot, props.inputClassName);\r\n\r\n const formattedValue = formatValue(value);\r\n\r\n const handleFocus = useCallback(() => {\r\n setIsEditing(true);\r\n setEditText(formattedValue);\r\n }, [formattedValue]);\r\n\r\n const handleBlur = useCallback(\r\n (event: FocusEvent<HTMLInputElement>) => {\r\n // Skip blur handling if a drag just started (icon pointerDown already committed).\r\n if (isDragging) {\r\n return;\r\n }\r\n commitEditText(event.target.value);\r\n setIsEditing(false);\r\n HandleOnBlur(event);\r\n },\r\n [commitEditText, isDragging]\r\n );\r\n\r\n const contentBefore =\r\n !props.disableDragButton && !props.disabled && (isHovered || isDragging) && !isInputInvalid ? (\r\n <ArrowBidirectionalUpDownFilled\r\n className={classes.icon}\r\n style={{ cursor: isDragging ? \"ns-resize\" : \"pointer\" }}\r\n onPointerDown={handleIconPointerDown}\r\n onPointerMove={handleIconPointerMove}\r\n onPointerUp={handleIconPointerUp}\r\n />\r\n ) : undefined;\r\n\r\n const input = (\r\n <div\r\n className={props.infoLabel ? undefined : props.className}\r\n onPointerEnter={(e) => e.pointerType === \"mouse\" && setIsHovered(true)}\r\n onPointerLeave={() => {\r\n if (!isDragging) {\r\n setIsHovered(false);\r\n }\r\n }}\r\n >\r\n <Input\r\n ref={mergedRef}\r\n id={id}\r\n appearance=\"outline\"\r\n size={size}\r\n className={mergedClassName}\r\n input={{ className: inputSlotClassName }}\r\n value={isEditing ? editText : formattedValue}\r\n disabled={props.disabled}\r\n onChange={handleInputChange}\r\n onFocus={handleFocus}\r\n onKeyDown={handleKeyDown}\r\n onBlur={handleBlur}\r\n contentBefore={contentBefore}\r\n contentAfter={props.unit}\r\n />\r\n </div>\r\n );\r\n\r\n return props.infoLabel ? (\r\n <div className={mergeClasses(inputClasses.container, props.className)}>\r\n <InfoLabel {...props.infoLabel} htmlFor={id} />\r\n {input}\r\n </div>\r\n ) : (\r\n input\r\n );\r\n});\r\n"]}
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
- import { makeStyles } from "@fluentui/react-components";
2
+ import { makeStyles, mergeClasses } from "@fluentui/react-components";
3
3
  import { SpinButton } from "./spinButton.js";
4
4
  import { Slider } from "./slider.js";
5
5
  import { useEffect, useState, useRef } from "react";
@@ -13,20 +13,27 @@ const useSyncedSliderStyles = makeStyles({
13
13
  alignItems: "center",
14
14
  minWidth: 0,
15
15
  },
16
+ // Default: 50/50 split between slider and spinbutton
16
17
  slider: {
17
- flex: "1 1 auto",
18
- minWidth: "75px",
19
- maxWidth: "75px",
18
+ flex: "1 1 0",
19
+ minWidth: 0,
20
+ },
21
+ spinButton: {
22
+ flex: "1 1 0",
23
+ minWidth: 0,
20
24
  },
25
+ spinButtonInput: {
26
+ minWidth: "0",
27
+ },
28
+ // compact/growSlider overrides for standalone (non-PropertyLine) usage
21
29
  compactSlider: {
22
30
  flex: "1 1 auto",
23
- minWidth: "50px", // Allow shrinking for compact mode
31
+ minWidth: "50px",
24
32
  maxWidth: "75px",
25
33
  },
26
34
  growSlider: {
27
35
  flex: "1 1 auto",
28
36
  minWidth: "50px",
29
- // No maxWidth - slider grows to fill available space
30
37
  },
31
38
  compactSpinButton: {
32
39
  width: "65px",
@@ -78,7 +85,7 @@ export const SyncedSliderInput = (props) => {
78
85
  props.onChange(value); // Input always updates immediately
79
86
  };
80
87
  const hasSlider = props.min !== undefined && props.max !== undefined;
81
- // Determine Slider className based on props
88
+ const useCompactSizing = props.compact || props.growSlider;
82
89
  const getSliderClassName = () => {
83
90
  if (props.growSlider) {
84
91
  return classes.growSlider;
@@ -88,6 +95,6 @@ export const SyncedSliderInput = (props) => {
88
95
  }
89
96
  return classes.slider;
90
97
  };
91
- return (_jsxs("div", { className: classes.container, children: [infoLabel && _jsx(InfoLabel, { ...infoLabel, htmlFor: "syncedSlider" }), _jsxs("div", { id: "syncedSlider", className: classes.syncedSlider, children: [hasSlider && (_jsx(Slider, { className: getSliderClassName(), value: value, onChange: handleSliderChange, min: props.min, max: props.max, step: props.step, disabled: props.disabled, onPointerDown: handleSliderPointerDown, onPointerUp: handleSliderPointerUp })), _jsx(SpinButton, { ...passthroughProps, className: hasSlider || props.compact ? classes.compactSpinButton : undefined, inputClassName: hasSlider || props.compact ? classes.compactSpinButtonInput : undefined, value: value, onChange: handleInputChange, step: props.step, disableDragButton: true })] })] }));
98
+ return (_jsxs("div", { className: mergeClasses(classes.container, props.className), children: [infoLabel && _jsx(InfoLabel, { ...infoLabel, htmlFor: "syncedSlider" }), _jsxs("div", { id: "syncedSlider", className: classes.syncedSlider, children: [hasSlider && (_jsx(Slider, { className: getSliderClassName(), value: value, onChange: handleSliderChange, min: props.min, max: props.max, step: props.step, disabled: props.disabled, onPointerDown: handleSliderPointerDown, onPointerUp: handleSliderPointerUp })), _jsx(SpinButton, { ...passthroughProps, className: useCompactSizing ? classes.compactSpinButton : classes.spinButton, inputClassName: useCompactSizing ? classes.compactSpinButtonInput : classes.spinButtonInput, value: value, onChange: handleInputChange, step: props.step, disabled: props.disabled, disableDragButton: true })] })] }));
92
99
  };
93
100
  //# sourceMappingURL=syncedSlider.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"syncedSlider.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/syncedSlider.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { FunctionComponent } from \"react\";\r\nimport { makeStyles } from \"@fluentui/react-components\";\r\nimport { SpinButton } from \"./spinButton\";\r\nimport { Slider } from \"./slider\";\r\nimport { useEffect, useState, useRef } from \"react\";\r\nimport type { PrimitiveProps } from \"./primitive\";\r\nimport { InfoLabel } from \"./infoLabel\";\r\n\r\nconst useSyncedSliderStyles = makeStyles({\r\n container: { display: \"flex\", minWidth: 0 },\r\n syncedSlider: {\r\n flex: \"1 1 0\",\r\n flexDirection: \"row\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n minWidth: 0,\r\n },\r\n slider: {\r\n flex: \"1 1 auto\",\r\n minWidth: \"75px\",\r\n maxWidth: \"75px\",\r\n },\r\n compactSlider: {\r\n flex: \"1 1 auto\",\r\n minWidth: \"50px\", // Allow shrinking for compact mode\r\n maxWidth: \"75px\",\r\n },\r\n growSlider: {\r\n flex: \"1 1 auto\",\r\n minWidth: \"50px\",\r\n // No maxWidth - slider grows to fill available space\r\n },\r\n compactSpinButton: {\r\n width: \"65px\",\r\n minWidth: \"65px\",\r\n maxWidth: \"65px\",\r\n },\r\n compactSpinButtonInput: {\r\n minWidth: \"0\",\r\n },\r\n});\r\n\r\nexport type SyncedSliderProps = PrimitiveProps<number> & {\r\n /** Minimum value for the slider */\r\n min?: number;\r\n /** Maximum value for the slider */\r\n max?: number;\r\n /** Step size for the slider */\r\n step?: number;\r\n /** Optional fixed precision (number of decimal digits). Overrides the automatically computed display precision. */\r\n precision?: number;\r\n /** Displayed in the ux to indicate unit of measurement */\r\n unit?: string;\r\n /** When true, onChange is only called when the user releases the slider, not during drag */\r\n notifyOnlyOnRelease?: boolean;\r\n /** When true, slider grows to fill space and SpinButton is fixed at 65px */\r\n compact?: boolean;\r\n /** When true, slider grows to fill all available space (no maxWidth constraint) */\r\n growSlider?: boolean;\r\n};\r\n\r\n/**\r\n * Component which synchronizes a slider and an input field, allowing the user to change the value using either control\r\n * @param props\r\n * @returns SyncedSlider component\r\n */\r\nexport const SyncedSliderInput: FunctionComponent<SyncedSliderProps> = (props) => {\r\n SyncedSliderInput.displayName = \"SyncedSliderInput\";\r\n const { infoLabel, ...passthroughProps } = props;\r\n const classes = useSyncedSliderStyles();\r\n const [value, setValue] = useState<number>(props.value ?? 0);\r\n const pendingValueRef = useRef<number>(undefined);\r\n const isDraggingRef = useRef(false);\r\n\r\n useEffect(() => {\r\n !isDraggingRef.current && setValue(props.value ?? 0); // Update local state when props.value changes as long as user is not actively dragging\r\n }, [props.value]);\r\n\r\n const handleSliderChange = (newValue: number) => {\r\n setValue(newValue);\r\n\r\n if (props.notifyOnlyOnRelease) {\r\n // Store the value but don't notify parent yet\r\n pendingValueRef.current = newValue;\r\n } else {\r\n // Notify parent as slider changes\r\n props.onChange(newValue);\r\n }\r\n };\r\n\r\n const handleSliderPointerDown = () => {\r\n isDraggingRef.current = true;\r\n };\r\n\r\n const handleSliderPointerUp = () => {\r\n if (props.notifyOnlyOnRelease && isDraggingRef.current && pendingValueRef.current !== undefined) {\r\n props.onChange(pendingValueRef.current);\r\n pendingValueRef.current = undefined;\r\n }\r\n isDraggingRef.current = false;\r\n };\r\n\r\n const handleInputChange = (value: number) => {\r\n setValue(value);\r\n props.onChange(value); // Input always updates immediately\r\n };\r\n\r\n const hasSlider = props.min !== undefined && props.max !== undefined;\r\n\r\n // Determine Slider className based on props\r\n const getSliderClassName = () => {\r\n if (props.growSlider) {\r\n return classes.growSlider;\r\n }\r\n if (props.compact) {\r\n return classes.compactSlider;\r\n }\r\n return classes.slider;\r\n };\r\n\r\n return (\r\n <div className={classes.container}>\r\n {infoLabel && <InfoLabel {...infoLabel} htmlFor={\"syncedSlider\"} />}\r\n <div id=\"syncedSlider\" className={classes.syncedSlider}>\r\n {hasSlider && (\r\n <Slider\r\n className={getSliderClassName()}\r\n value={value}\r\n onChange={handleSliderChange}\r\n min={props.min}\r\n max={props.max}\r\n step={props.step}\r\n disabled={props.disabled}\r\n onPointerDown={handleSliderPointerDown}\r\n onPointerUp={handleSliderPointerUp}\r\n />\r\n )}\r\n <SpinButton\r\n {...passthroughProps}\r\n className={hasSlider || props.compact ? classes.compactSpinButton : undefined}\r\n inputClassName={hasSlider || props.compact ? classes.compactSpinButtonInput : undefined}\r\n value={value}\r\n onChange={handleInputChange}\r\n step={props.step}\r\n disableDragButton\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n"]}
1
+ {"version":3,"file":"syncedSlider.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/syncedSlider.tsx"],"names":[],"mappings":"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","sourcesContent":["import type { FunctionComponent } from \"react\";\r\nimport { makeStyles, mergeClasses } from \"@fluentui/react-components\";\r\nimport { SpinButton } from \"./spinButton\";\r\nimport { Slider } from \"./slider\";\r\nimport { useEffect, useState, useRef } from \"react\";\r\nimport type { PrimitiveProps } from \"./primitive\";\r\nimport { InfoLabel } from \"./infoLabel\";\r\n\r\nconst useSyncedSliderStyles = makeStyles({\r\n container: { display: \"flex\", minWidth: 0 },\r\n syncedSlider: {\r\n flex: \"1 1 0\",\r\n flexDirection: \"row\",\r\n display: \"flex\",\r\n alignItems: \"center\",\r\n minWidth: 0,\r\n },\r\n // Default: 50/50 split between slider and spinbutton\r\n slider: {\r\n flex: \"1 1 0\",\r\n minWidth: 0,\r\n },\r\n spinButton: {\r\n flex: \"1 1 0\",\r\n minWidth: 0,\r\n },\r\n spinButtonInput: {\r\n minWidth: \"0\",\r\n },\r\n // compact/growSlider overrides for standalone (non-PropertyLine) usage\r\n compactSlider: {\r\n flex: \"1 1 auto\",\r\n minWidth: \"50px\",\r\n maxWidth: \"75px\",\r\n },\r\n growSlider: {\r\n flex: \"1 1 auto\",\r\n minWidth: \"50px\",\r\n },\r\n compactSpinButton: {\r\n width: \"65px\",\r\n minWidth: \"65px\",\r\n maxWidth: \"65px\",\r\n },\r\n compactSpinButtonInput: {\r\n minWidth: \"0\",\r\n },\r\n});\r\n\r\nexport type SyncedSliderProps = PrimitiveProps<number> & {\r\n /** Minimum value for the slider */\r\n min?: number;\r\n /** Maximum value for the slider */\r\n max?: number;\r\n /** Step size for the slider */\r\n step?: number;\r\n /** Optional fixed precision (number of decimal digits). Overrides the automatically computed display precision. */\r\n precision?: number;\r\n /** Displayed in the ux to indicate unit of measurement */\r\n unit?: string;\r\n /** When true, onChange is only called when the user releases the slider, not during drag */\r\n notifyOnlyOnRelease?: boolean;\r\n /** When true, slider grows to fill space and SpinButton is fixed at 65px */\r\n compact?: boolean;\r\n /** When true, slider grows to fill all available space (no maxWidth constraint) */\r\n growSlider?: boolean;\r\n};\r\n\r\n/**\r\n * Component which synchronizes a slider and an input field, allowing the user to change the value using either control\r\n * @param props\r\n * @returns SyncedSlider component\r\n */\r\nexport const SyncedSliderInput: FunctionComponent<SyncedSliderProps> = (props) => {\r\n SyncedSliderInput.displayName = \"SyncedSliderInput\";\r\n const { infoLabel, ...passthroughProps } = props;\r\n const classes = useSyncedSliderStyles();\r\n const [value, setValue] = useState<number>(props.value ?? 0);\r\n const pendingValueRef = useRef<number>(undefined);\r\n const isDraggingRef = useRef(false);\r\n\r\n useEffect(() => {\r\n !isDraggingRef.current && setValue(props.value ?? 0); // Update local state when props.value changes as long as user is not actively dragging\r\n }, [props.value]);\r\n\r\n const handleSliderChange = (newValue: number) => {\r\n setValue(newValue);\r\n\r\n if (props.notifyOnlyOnRelease) {\r\n // Store the value but don't notify parent yet\r\n pendingValueRef.current = newValue;\r\n } else {\r\n // Notify parent as slider changes\r\n props.onChange(newValue);\r\n }\r\n };\r\n\r\n const handleSliderPointerDown = () => {\r\n isDraggingRef.current = true;\r\n };\r\n\r\n const handleSliderPointerUp = () => {\r\n if (props.notifyOnlyOnRelease && isDraggingRef.current && pendingValueRef.current !== undefined) {\r\n props.onChange(pendingValueRef.current);\r\n pendingValueRef.current = undefined;\r\n }\r\n isDraggingRef.current = false;\r\n };\r\n\r\n const handleInputChange = (value: number) => {\r\n setValue(value);\r\n props.onChange(value); // Input always updates immediately\r\n };\r\n\r\n const hasSlider = props.min !== undefined && props.max !== undefined;\r\n const useCompactSizing = props.compact || props.growSlider;\r\n\r\n const getSliderClassName = () => {\r\n if (props.growSlider) {\r\n return classes.growSlider;\r\n }\r\n if (props.compact) {\r\n return classes.compactSlider;\r\n }\r\n return classes.slider;\r\n };\r\n\r\n return (\r\n <div className={mergeClasses(classes.container, props.className)}>\r\n {infoLabel && <InfoLabel {...infoLabel} htmlFor={\"syncedSlider\"} />}\r\n <div id=\"syncedSlider\" className={classes.syncedSlider}>\r\n {hasSlider && (\r\n <Slider\r\n className={getSliderClassName()}\r\n value={value}\r\n onChange={handleSliderChange}\r\n min={props.min}\r\n max={props.max}\r\n step={props.step}\r\n disabled={props.disabled}\r\n onPointerDown={handleSliderPointerDown}\r\n onPointerUp={handleSliderPointerUp}\r\n />\r\n )}\r\n <SpinButton\r\n {...passthroughProps}\r\n className={useCompactSizing ? classes.compactSpinButton : classes.spinButton}\r\n inputClassName={useCompactSizing ? classes.compactSpinButtonInput : classes.spinButtonInput}\r\n value={value}\r\n onChange={handleInputChange}\r\n step={props.step}\r\n disabled={props.disabled}\r\n disableDragButton\r\n />\r\n </div>\r\n </div>\r\n );\r\n};\r\n"]}
@@ -46,8 +46,8 @@ export const TextInput = (props) => {
46
46
  tryCommitValue(event.currentTarget.value);
47
47
  }
48
48
  };
49
- const mergedClassName = mergeClasses(classes.input, !validateValue(value) ? classes.invalid : "", props.className);
49
+ const mergedClassName = mergeClasses(classes.inputFill, !validateValue(value) ? classes.invalid : "");
50
50
  const id = useId("input-button");
51
- return (_jsxs("div", { className: classes.container, children: [props.infoLabel && _jsx(InfoLabel, { ...props.infoLabel, htmlFor: id }), _jsx(FluentInput, { ...props, input: { className: classes.inputSlot }, id: id, size: size, value: value, onChange: handleChange, onKeyUp: handleKeyUp, onKeyDown: HandleKeyDown, onBlur: handleBlur, className: mergedClassName })] }));
51
+ return (_jsxs("div", { className: mergeClasses(classes.container, props.className), children: [props.infoLabel && _jsx(InfoLabel, { ...props.infoLabel, htmlFor: id }), _jsx(FluentInput, { ...props, input: { className: classes.inputSlot }, id: id, size: size, value: value, onChange: handleChange, onKeyUp: handleKeyUp, onKeyDown: HandleKeyDown, onBlur: handleBlur, className: mergedClassName })] }));
52
52
  };
53
53
  //# sourceMappingURL=textInput.js.map
@@ -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, FocusEvent } from \"react\";\r\nimport { useContext, useEffect, useRef, useState } from \"react\";\r\nimport type { InputOnChangeData } from \"@fluentui/react-components\";\r\nimport { Input as FluentInput, mergeClasses, useId } from \"@fluentui/react-components\";\r\nimport type { PrimitiveProps } from \"./primitive\";\r\nimport { InfoLabel } from \"./infoLabel\";\r\nimport { HandleKeyDown, HandleOnBlur, useInputStyles } from \"./utils\";\r\nimport { ToolContext } from \"../hoc/fluentToolWrapper\";\r\n\r\nexport type TextInputProps = PrimitiveProps<string> & {\r\n validator?: (value: string) => boolean;\r\n validateOnlyOnBlur?: boolean;\r\n};\r\n\r\nexport const TextInput: FunctionComponent<TextInputProps> = (props) => {\r\n TextInput.displayName = \"TextInput\";\r\n const classes = useInputStyles();\r\n const [value, setValue] = useState(props.value);\r\n const lastCommittedValue = useRef(props.value);\r\n const { size } = useContext(ToolContext);\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 if (!props.validateOnlyOnBlur) {\r\n tryCommitValue(data.value);\r\n }\r\n };\r\n\r\n const handleKeyUp = (event: KeyboardEvent<HTMLInputElement>) => {\r\n event.stopPropagation();\r\n if (!props.validateOnlyOnBlur) {\r\n tryCommitValue(event.currentTarget.value);\r\n }\r\n };\r\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\r\n HandleOnBlur(event);\r\n if (props.validateOnlyOnBlur) {\r\n tryCommitValue(event.currentTarget.value);\r\n }\r\n };\r\n\r\n const mergedClassName = mergeClasses(classes.input, !validateValue(value) ? classes.invalid : \"\", props.className);\r\n\r\n const id = useId(\"input-button\");\r\n return (\r\n <div className={classes.container}>\r\n {props.infoLabel && <InfoLabel {...props.infoLabel} htmlFor={id} />}\r\n <FluentInput\r\n {...props}\r\n input={{ className: classes.inputSlot }}\r\n id={id}\r\n size={size}\r\n value={value}\r\n onChange={handleChange}\r\n onKeyUp={handleKeyUp}\r\n onKeyDown={HandleKeyDown}\r\n onBlur={handleBlur}\r\n className={mergedClassName}\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":";AACA,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAEhE,OAAO,EAAE,KAAK,IAAI,WAAW,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAEvF,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,aAAa,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AACtE,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAOvD,MAAM,CAAC,MAAM,SAAS,GAAsC,CAAC,KAAK,EAAE,EAAE;IAClE,SAAS,CAAC,WAAW,GAAG,WAAW,CAAC;IACpC,MAAM,OAAO,GAAG,cAAc,EAAE,CAAC;IACjC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAChD,MAAM,kBAAkB,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,EAAE,IAAI,EAAE,GAAG,UAAU,CAAC,WAAW,CAAC,CAAC;IACzC,SAAS,CAAC,GAAG,EAAE;QACX,IAAI,KAAK,CAAC,KAAK,KAAK,kBAAkB,CAAC,OAAO,EAAE,CAAC;YAC7C,QAAQ,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,8CAA8C;YACrE,kBAAkB,CAAC,OAAO,GAAG,KAAK,CAAC,KAAK,CAAC;QAC7C,CAAC;IACL,CAAC,EAAE,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;IAElB,MAAM,aAAa,GAAG,CAAC,GAAW,EAAW,EAAE;QAC3C,MAAM,cAAc,GAAG,KAAK,CAAC,SAAS,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC;QAChE,OAAO,CAAC,cAAc,CAAC;IAC3B,CAAC,CAAC;IAEF,MAAM,cAAc,GAAG,CAAC,OAAe,EAAE,EAAE;QACvC,+DAA+D;QAC/D,IAAI,aAAa,CAAC,OAAO,CAAC,IAAI,OAAO,KAAK,kBAAkB,CAAC,OAAO,EAAE,CAAC;YACnE,kBAAkB,CAAC,OAAO,GAAG,OAAO,CAAC;YACrC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QAC5B,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,YAAY,GAAG,CAAC,KAAoC,EAAE,IAAuB,EAAE,EAAE;QACnF,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC;YAC5B,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC/B,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,WAAW,GAAG,CAAC,KAAsC,EAAE,EAAE;QAC3D,KAAK,CAAC,eAAe,EAAE,CAAC;QACxB,IAAI,CAAC,KAAK,CAAC,kBAAkB,EAAE,CAAC;YAC5B,cAAc,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9C,CAAC;IACL,CAAC,CAAC;IACF,MAAM,UAAU,GAAG,CAAC,KAAmC,EAAE,EAAE;QACvD,YAAY,CAAC,KAAK,CAAC,CAAC;QACpB,IAAI,KAAK,CAAC,kBAAkB,EAAE,CAAC;YAC3B,cAAc,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;QAC9C,CAAC;IACL,CAAC,CAAC;IAEF,MAAM,eAAe,GAAG,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IAEtG,MAAM,EAAE,GAAG,KAAK,CAAC,cAAc,CAAC,CAAC;IACjC,OAAO,CACH,eAAK,SAAS,EAAE,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,CAAC,aAC3D,KAAK,CAAC,SAAS,IAAI,KAAC,SAAS,OAAK,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,EAAE,GAAI,EACnE,KAAC,WAAW,OACJ,KAAK,EACT,KAAK,EAAE,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,EACvC,EAAE,EAAE,EAAE,EACN,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,KAAK,EACZ,QAAQ,EAAE,YAAY,EACtB,OAAO,EAAE,WAAW,EACpB,SAAS,EAAE,aAAa,EACxB,MAAM,EAAE,UAAU,EAClB,SAAS,EAAE,eAAe,GAC5B,IACA,CACT,CAAC;AACN,CAAC,CAAC","sourcesContent":["import type { FunctionComponent, KeyboardEvent, ChangeEvent, FocusEvent } from \"react\";\r\nimport { useContext, useEffect, useRef, useState } from \"react\";\r\nimport type { InputOnChangeData } from \"@fluentui/react-components\";\r\nimport { Input as FluentInput, mergeClasses, useId } from \"@fluentui/react-components\";\r\nimport type { PrimitiveProps } from \"./primitive\";\r\nimport { InfoLabel } from \"./infoLabel\";\r\nimport { HandleKeyDown, HandleOnBlur, useInputStyles } from \"./utils\";\r\nimport { ToolContext } from \"../hoc/fluentToolWrapper\";\r\n\r\nexport type TextInputProps = PrimitiveProps<string> & {\r\n validator?: (value: string) => boolean;\r\n validateOnlyOnBlur?: boolean;\r\n};\r\n\r\nexport const TextInput: FunctionComponent<TextInputProps> = (props) => {\r\n TextInput.displayName = \"TextInput\";\r\n const classes = useInputStyles();\r\n const [value, setValue] = useState(props.value);\r\n const lastCommittedValue = useRef(props.value);\r\n const { size } = useContext(ToolContext);\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 if (!props.validateOnlyOnBlur) {\r\n tryCommitValue(data.value);\r\n }\r\n };\r\n\r\n const handleKeyUp = (event: KeyboardEvent<HTMLInputElement>) => {\r\n event.stopPropagation();\r\n if (!props.validateOnlyOnBlur) {\r\n tryCommitValue(event.currentTarget.value);\r\n }\r\n };\r\n const handleBlur = (event: FocusEvent<HTMLInputElement>) => {\r\n HandleOnBlur(event);\r\n if (props.validateOnlyOnBlur) {\r\n tryCommitValue(event.currentTarget.value);\r\n }\r\n };\r\n\r\n const mergedClassName = mergeClasses(classes.inputFill, !validateValue(value) ? classes.invalid : \"\");\r\n\r\n const id = useId(\"input-button\");\r\n return (\r\n <div className={mergeClasses(classes.container, props.className)}>\r\n {props.infoLabel && <InfoLabel {...props.infoLabel} htmlFor={id} />}\r\n <FluentInput\r\n {...props}\r\n input={{ className: classes.inputSlot }}\r\n id={id}\r\n size={size}\r\n value={value}\r\n onChange={handleChange}\r\n onKeyUp={handleKeyUp}\r\n onKeyDown={HandleKeyDown}\r\n onBlur={handleBlur}\r\n className={mergedClassName}\r\n />\r\n </div>\r\n );\r\n};\r\n"]}
@@ -17,7 +17,7 @@ export declare const TokenMap: {
17
17
  px40: string;
18
18
  };
19
19
  export declare const CustomTokens: {
20
- inputWidth: string;
20
+ valueWidth: string;
21
21
  lineHeight: string;
22
22
  lineHeightSmall: string;
23
23
  dividerGap: string;
@@ -28,7 +28,7 @@ export declare const CustomTokens: {
28
28
  rightAlignOffset: string;
29
29
  };
30
30
  export declare const UniformWidthStyling: GriffelStyle;
31
- export declare const useInputStyles: () => Record<"input" | "container" | "invalid" | "inputSlot", string>;
31
+ export declare const useInputStyles: () => Record<"container" | "invalid" | "inputSlot" | "inputFill", string>;
32
32
  export declare function HandleOnBlur(event: FocusEvent<HTMLInputElement>): void;
33
33
  export declare function HandleKeyDown(event: KeyboardEvent<HTMLInputElement>): void;
34
34
  /**
@@ -16,7 +16,7 @@ export const TokenMap = {
16
16
  px40: tokens.lineHeightHero800,
17
17
  };
18
18
  export const CustomTokens = {
19
- inputWidth: "150px",
19
+ valueWidth: "150px",
20
20
  lineHeight: TokenMap.px36,
21
21
  lineHeightSmall: TokenMap.px28,
22
22
  dividerGap: TokenMap.px10,
@@ -26,9 +26,8 @@ export const CustomTokens = {
26
26
  sliderMaxWidth: "80px",
27
27
  rightAlignOffset: `-${TokenMap.px8}`,
28
28
  };
29
- export const UniformWidthStyling = { width: CustomTokens.inputWidth, boxSizing: "border-box" };
29
+ export const UniformWidthStyling = { width: CustomTokens.valueWidth, boxSizing: "border-box" };
30
30
  export const useInputStyles = makeStyles({
31
- input: UniformWidthStyling,
32
31
  inputSlot: { textAlign: "right" },
33
32
  invalid: { backgroundColor: tokens.colorPaletteRedBackground2 },
34
33
  container: {
@@ -37,6 +36,10 @@ export const useInputStyles = makeStyles({
37
36
  justifyContent: "center", // align items vertically
38
37
  minWidth: 0, // Allow shrinking
39
38
  },
39
+ inputFill: {
40
+ width: "100%",
41
+ minWidth: 0,
42
+ },
40
43
  });
41
44
  export function HandleOnBlur(event) {
42
45
  event.stopPropagation();
@@ -1 +1 @@
1
- {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/utils.ts"],"names":[],"mappings":"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","sourcesContent":["import { makeStyles, tokens } from \"@fluentui/react-components\";\r\nimport type { GriffelStyle } from \"@fluentui/react-components\";\r\n\r\nimport type { KeyboardEvent, FocusEvent } from \"react\";\r\n\r\nexport const TokenMap = {\r\n px2: tokens.borderRadiusSmall,\r\n px4: tokens.borderRadiusMedium,\r\n px6: tokens.borderRadiusLarge,\r\n px8: tokens.borderRadiusXLarge,\r\n px10: tokens.fontSizeBase100,\r\n px12: tokens.fontSizeBase200,\r\n px14: tokens.fontSizeBase300,\r\n px16: tokens.fontSizeBase400,\r\n px20: tokens.fontSizeBase500,\r\n px24: tokens.fontSizeBase600,\r\n px28: tokens.lineHeightBase500,\r\n px32: tokens.lineHeightBase600,\r\n px36: tokens.lineHeightHero700,\r\n px40: tokens.lineHeightHero800,\r\n};\r\n\r\nexport const CustomTokens = {\r\n inputWidth: \"150px\",\r\n lineHeight: TokenMap.px36,\r\n lineHeightSmall: TokenMap.px28,\r\n dividerGap: TokenMap.px10,\r\n dividerGapSmall: TokenMap.px4,\r\n labelMinWidth: \"50px\",\r\n sliderMinWidth: \"30px\",\r\n sliderMaxWidth: \"80px\",\r\n rightAlignOffset: `-${TokenMap.px8}`,\r\n};\r\n\r\nexport const UniformWidthStyling: GriffelStyle = { width: CustomTokens.inputWidth, boxSizing: \"border-box\" };\r\nexport const useInputStyles = makeStyles({\r\n input: UniformWidthStyling,\r\n inputSlot: { textAlign: \"right\" },\r\n invalid: { backgroundColor: tokens.colorPaletteRedBackground2 },\r\n container: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n justifyContent: \"center\", // align items vertically\r\n minWidth: 0, // Allow shrinking\r\n },\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\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\nconst HEX_REGEX = RegExp(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/);\r\nexport function ValidateColorHex(val: string) {\r\n return val != \"\" && HEX_REGEX.test(val);\r\n}\r\n"]}
1
+ {"version":3,"file":"utils.js","sourceRoot":"","sources":["../../../../../dev/sharedUiComponents/src/fluent/primitives/utils.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,4BAA4B,CAAC;AAKhE,MAAM,CAAC,MAAM,QAAQ,GAAG;IACpB,GAAG,EAAE,MAAM,CAAC,iBAAiB;IAC7B,GAAG,EAAE,MAAM,CAAC,kBAAkB;IAC9B,GAAG,EAAE,MAAM,CAAC,iBAAiB;IAC7B,GAAG,EAAE,MAAM,CAAC,kBAAkB;IAC9B,IAAI,EAAE,MAAM,CAAC,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAC,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAC,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAC,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAC,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAC,eAAe;IAC5B,IAAI,EAAE,MAAM,CAAC,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC,iBAAiB;IAC9B,IAAI,EAAE,MAAM,CAAC,iBAAiB;CACjC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG;IACxB,UAAU,EAAE,OAAO;IACnB,UAAU,EAAE,QAAQ,CAAC,IAAI;IACzB,eAAe,EAAE,QAAQ,CAAC,IAAI;IAC9B,UAAU,EAAE,QAAQ,CAAC,IAAI;IACzB,eAAe,EAAE,QAAQ,CAAC,GAAG;IAC7B,aAAa,EAAE,MAAM;IACrB,cAAc,EAAE,MAAM;IACtB,cAAc,EAAE,MAAM;IACtB,gBAAgB,EAAE,IAAI,QAAQ,CAAC,GAAG,EAAE;CACvC,CAAC;AAEF,MAAM,CAAC,MAAM,mBAAmB,GAAiB,EAAE,KAAK,EAAE,YAAY,CAAC,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,CAAC;AAC7G,MAAM,CAAC,MAAM,cAAc,GAAG,UAAU,CAAC;IACrC,SAAS,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE;IACjC,OAAO,EAAE,EAAE,eAAe,EAAE,MAAM,CAAC,0BAA0B,EAAE;IAC/D,SAAS,EAAE;QACP,OAAO,EAAE,MAAM;QACf,aAAa,EAAE,QAAQ;QACvB,cAAc,EAAE,QAAQ,EAAE,yBAAyB;QACnD,QAAQ,EAAE,CAAC,EAAE,kBAAkB;KAClC;IACD,SAAS,EAAE;QACP,KAAK,EAAE,MAAM;QACb,QAAQ,EAAE,CAAC;KACd;CACJ,CAAC,CAAC;AAEH,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;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,kBAAkB,CAAC,KAAa;IAC5C;;;;;OAKG,CAAC,MAAM,MAAM,GAAG,yBAAyB,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,IAAI,CAAC,MAAM,EAAE,CAAC;QACV,OAAO,CAAC,CAAC;IACb,CAAC;IACD,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACZ,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC7B,CAAC;IACD,IAAI,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC;QACZ,OAAO,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IAC5B,CAAC;IACD,OAAO,CAAC,CAAC;AACb,CAAC;AAED,MAAM,SAAS,GAAG,MAAM,CAAC,mDAAmD,CAAC,CAAC;AAC9E,MAAM,UAAU,gBAAgB,CAAC,GAAW;IACxC,OAAO,GAAG,IAAI,EAAE,IAAI,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5C,CAAC","sourcesContent":["import { makeStyles, tokens } from \"@fluentui/react-components\";\r\nimport type { GriffelStyle } from \"@fluentui/react-components\";\r\n\r\nimport type { KeyboardEvent, FocusEvent } from \"react\";\r\n\r\nexport const TokenMap = {\r\n px2: tokens.borderRadiusSmall,\r\n px4: tokens.borderRadiusMedium,\r\n px6: tokens.borderRadiusLarge,\r\n px8: tokens.borderRadiusXLarge,\r\n px10: tokens.fontSizeBase100,\r\n px12: tokens.fontSizeBase200,\r\n px14: tokens.fontSizeBase300,\r\n px16: tokens.fontSizeBase400,\r\n px20: tokens.fontSizeBase500,\r\n px24: tokens.fontSizeBase600,\r\n px28: tokens.lineHeightBase500,\r\n px32: tokens.lineHeightBase600,\r\n px36: tokens.lineHeightHero700,\r\n px40: tokens.lineHeightHero800,\r\n};\r\n\r\nexport const CustomTokens = {\r\n valueWidth: \"150px\",\r\n lineHeight: TokenMap.px36,\r\n lineHeightSmall: TokenMap.px28,\r\n dividerGap: TokenMap.px10,\r\n dividerGapSmall: TokenMap.px4,\r\n labelMinWidth: \"50px\",\r\n sliderMinWidth: \"30px\",\r\n sliderMaxWidth: \"80px\",\r\n rightAlignOffset: `-${TokenMap.px8}`,\r\n};\r\n\r\nexport const UniformWidthStyling: GriffelStyle = { width: CustomTokens.valueWidth, boxSizing: \"border-box\" };\r\nexport const useInputStyles = makeStyles({\r\n inputSlot: { textAlign: \"right\" },\r\n invalid: { backgroundColor: tokens.colorPaletteRedBackground2 },\r\n container: {\r\n display: \"flex\",\r\n flexDirection: \"column\",\r\n justifyContent: \"center\", // align items vertically\r\n minWidth: 0, // Allow shrinking\r\n },\r\n inputFill: {\r\n width: \"100%\",\r\n minWidth: 0,\r\n },\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\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\nconst HEX_REGEX = RegExp(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3}|[A-Fa-f0-9]{8})$/);\r\nexport function ValidateColorHex(val: string) {\r\n return val != \"\" && HEX_REGEX.test(val);\r\n}\r\n"]}
@@ -479,8 +479,8 @@ export class GraphCanvasComponent extends React.Component {
479
479
  if (!newNode) {
480
480
  continue;
481
481
  }
482
- let x = 0;
483
- let y = 0;
482
+ let x;
483
+ let y;
484
484
  if (originalNode) {
485
485
  x = currentX + node.x - originalNode.x;
486
486
  y = currentY + node.y - originalNode.y;