@trackunit/react-form-components 2.6.14 → 2.6.16

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.cjs.js CHANGED
@@ -4860,7 +4860,6 @@ Search.displayName = "Search";
4860
4860
  *
4861
4861
  */
4862
4862
  const FormFieldSelectAdapter = ({ className, "data-testid": dataTestId, helpText, helpAddon, tip, label, isInvalid = false, errorMessage, name, onBlur, options, value, defaultValue, id, htmlFor: htmlForProp, onChange, children, style, ref, required = false, ...rest }) => {
4863
- const isFirstRender = reactComponents.useIsFirstRender();
4864
4863
  const [innerValue, setInnerValue] = react.useState(value ?? defaultValue);
4865
4864
  const onChangeRef = react.useRef(onChange);
4866
4865
  react.useEffect(() => {
@@ -4880,17 +4879,23 @@ const FormFieldSelectAdapter = ({ className, "data-testid": dataTestId, helpText
4880
4879
  const innerRef = react.useRef(null);
4881
4880
  // eslint-disable-next-line @trackunit/no-typescript-assertion, @typescript-eslint/no-non-null-assertion
4882
4881
  react.useImperativeHandle(ref, () => innerRef.current, []);
4882
+ // Bridges a react-select pick back to the hidden native <select> so `register`/native form
4883
+ // consumers see a real change event. It must fire only when the value actually changes: seeding
4884
+ // the ref with the initial value means mounting with a value is not reported as a change, which
4885
+ // would otherwise write to the consumer's form and mark it dirty with no user interaction.
4886
+ const lastNotifiedValueRef = react.useRef(innerValue);
4883
4887
  react.useEffect(() => {
4884
- if (isFirstRender || innerValue === undefined) {
4888
+ if (innerValue === undefined || lastNotifiedValueRef.current === innerValue) {
4885
4889
  return;
4886
4890
  }
4891
+ lastNotifiedValueRef.current = innerValue;
4887
4892
  const event = new Event("change");
4888
4893
  if (innerValue === "" && innerRef.current) {
4889
4894
  innerRef.current.value = ""; // Set the desired option value
4890
4895
  }
4891
4896
  innerRef.current?.dispatchEvent(event);
4892
4897
  onChangeRef.current?.(event);
4893
- }, [innerValue, isFirstRender]);
4898
+ }, [innerValue]);
4894
4899
  const optionsWithCurrentSelectionBackupOption = [
4895
4900
  // Add the current selection in case there's no options loaded yet (in CreatableSelect)
4896
4901
  // Also _don't_ add it if it's a duplicate
package/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
2
2
  import { registerTranslations, useNamespaceTranslation, NamespaceTrans } from '@trackunit/i18n-library-translation';
3
- import { IconButton, Icon, Tooltip, Button, Popover, PopoverTrigger, PopoverContent, cvaMenu, cvaMenuList, Tag, useIsTextTruncated, ZStack, MenuItem, useMeasure, useDebounce, useMergeRefs, Spinner, useScrollBlock, Text, Heading, useIsFirstRender } from '@trackunit/react-components';
3
+ import { IconButton, Icon, Tooltip, Button, Popover, PopoverTrigger, PopoverContent, cvaMenu, cvaMenuList, Tag, useIsTextTruncated, ZStack, MenuItem, useMeasure, useDebounce, useMergeRefs, Spinner, useScrollBlock, Text, Heading } from '@trackunit/react-components';
4
4
  import { useMemo, useRef, useEffect, useImperativeHandle, useState, useCallback, useLayoutEffect, isValidElement, cloneElement, useReducer, createContext, useContext, useId } from 'react';
5
5
  import { twMerge } from 'tailwind-merge';
6
6
  import { cvaMerge } from '@trackunit/css-class-variance-utilities';
@@ -4859,7 +4859,6 @@ Search.displayName = "Search";
4859
4859
  *
4860
4860
  */
4861
4861
  const FormFieldSelectAdapter = ({ className, "data-testid": dataTestId, helpText, helpAddon, tip, label, isInvalid = false, errorMessage, name, onBlur, options, value, defaultValue, id, htmlFor: htmlForProp, onChange, children, style, ref, required = false, ...rest }) => {
4862
- const isFirstRender = useIsFirstRender();
4863
4862
  const [innerValue, setInnerValue] = useState(value ?? defaultValue);
4864
4863
  const onChangeRef = useRef(onChange);
4865
4864
  useEffect(() => {
@@ -4879,17 +4878,23 @@ const FormFieldSelectAdapter = ({ className, "data-testid": dataTestId, helpText
4879
4878
  const innerRef = useRef(null);
4880
4879
  // eslint-disable-next-line @trackunit/no-typescript-assertion, @typescript-eslint/no-non-null-assertion
4881
4880
  useImperativeHandle(ref, () => innerRef.current, []);
4881
+ // Bridges a react-select pick back to the hidden native <select> so `register`/native form
4882
+ // consumers see a real change event. It must fire only when the value actually changes: seeding
4883
+ // the ref with the initial value means mounting with a value is not reported as a change, which
4884
+ // would otherwise write to the consumer's form and mark it dirty with no user interaction.
4885
+ const lastNotifiedValueRef = useRef(innerValue);
4882
4886
  useEffect(() => {
4883
- if (isFirstRender || innerValue === undefined) {
4887
+ if (innerValue === undefined || lastNotifiedValueRef.current === innerValue) {
4884
4888
  return;
4885
4889
  }
4890
+ lastNotifiedValueRef.current = innerValue;
4886
4891
  const event = new Event("change");
4887
4892
  if (innerValue === "" && innerRef.current) {
4888
4893
  innerRef.current.value = ""; // Set the desired option value
4889
4894
  }
4890
4895
  innerRef.current?.dispatchEvent(event);
4891
4896
  onChangeRef.current?.(event);
4892
- }, [innerValue, isFirstRender]);
4897
+ }, [innerValue]);
4893
4898
  const optionsWithCurrentSelectionBackupOption = [
4894
4899
  // Add the current selection in case there's no options loaded yet (in CreatableSelect)
4895
4900
  // Also _don't_ add it if it's a duplicate
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@trackunit/react-form-components",
3
- "version": "2.6.14",
3
+ "version": "2.6.16",
4
4
  "repository": "https://github.com/Trackunit/manager",
5
5
  "license": "SEE LICENSE IN LICENSE.txt",
6
6
  "migrations": "./migrations.json",
@@ -16,7 +16,7 @@
16
16
  "zod": "^3.25.76",
17
17
  "tailwind-merge": "^2.0.0",
18
18
  "@trackunit/css-class-variance-utilities": "1.14.17",
19
- "@trackunit/react-components": "2.10.9",
19
+ "@trackunit/react-components": "2.10.10",
20
20
  "@trackunit/ui-icons": "1.14.16",
21
21
  "@trackunit/shared-utils": "1.16.20",
22
22
  "@trackunit/ui-design-tokens": "1.15.7",