@trackunit/react-form-components 2.6.23-alpha-3e7014314a8.0 → 2.6.26
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,42 @@ 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.
|
|
4884
|
+
//
|
|
4885
|
+
// Only picks are bridged. A value arriving from the `value` prop is something the parent already
|
|
4886
|
+
// holds, so reporting it back would be an echo - and through `register(...).onChange` that echo
|
|
4887
|
+
// is indistinguishable from typing, marking the consumer's form dirty with no user interaction.
|
|
4888
|
+
const lastNotifiedValueRef = react.useRef(innerValue);
|
|
4889
|
+
// A box, not a bare value: `null` then unambiguously means "no pick pending", so the origin gate
|
|
4890
|
+
// below cannot be satisfied by a parent-driven change that merely matches the ref's empty state.
|
|
4891
|
+
const pendingUserPickRef = react.useRef(null);
|
|
4883
4892
|
react.useEffect(() => {
|
|
4884
|
-
if (
|
|
4893
|
+
if (lastNotifiedValueRef.current === innerValue) {
|
|
4885
4894
|
return;
|
|
4886
4895
|
}
|
|
4887
|
-
|
|
4896
|
+
lastNotifiedValueRef.current = innerValue;
|
|
4897
|
+
// Keep the hidden select in sync whatever the origin - this is state, not notification.
|
|
4888
4898
|
if (innerValue === "" && innerRef.current) {
|
|
4889
4899
|
innerRef.current.value = ""; // Set the desired option value
|
|
4890
4900
|
}
|
|
4901
|
+
// Keyed to the value the pick expected, not a boolean: react-select reports a re-pick of the
|
|
4902
|
+
// current option, which leaves `innerValue` untouched and so never runs this effect. A boolean
|
|
4903
|
+
// would still be set when the parent's next value arrives, and that value would be reported
|
|
4904
|
+
// back as a user edit.
|
|
4905
|
+
const pendingUserPick = pendingUserPickRef.current;
|
|
4906
|
+
pendingUserPickRef.current = null;
|
|
4907
|
+
const isUserChange = pendingUserPick !== null && pendingUserPick.value === innerValue;
|
|
4908
|
+
// No `undefined` guard needed: a pick is always a string or number (react-select's clear maps
|
|
4909
|
+
// to ""), so matching one narrows `innerValue` away from `undefined`. Only the parent can put
|
|
4910
|
+
// `undefined` there, and the gate above already rejects parent-driven values.
|
|
4911
|
+
if (!isUserChange) {
|
|
4912
|
+
return;
|
|
4913
|
+
}
|
|
4914
|
+
const event = new Event("change");
|
|
4891
4915
|
innerRef.current?.dispatchEvent(event);
|
|
4892
4916
|
onChangeRef.current?.(event);
|
|
4893
|
-
}, [innerValue
|
|
4917
|
+
}, [innerValue]);
|
|
4894
4918
|
const optionsWithCurrentSelectionBackupOption = [
|
|
4895
4919
|
// Add the current selection in case there's no options loaded yet (in CreatableSelect)
|
|
4896
4920
|
// Also _don't_ add it if it's a duplicate
|
|
@@ -4926,7 +4950,9 @@ const FormFieldSelectAdapter = ({ className, "data-testid": dataTestId, helpText
|
|
|
4926
4950
|
// If theres no value, set the inner value to an empty string
|
|
4927
4951
|
// A native select can not have a null value
|
|
4928
4952
|
// So even if react-select sends a null value, we need to convert it to an empty string
|
|
4929
|
-
|
|
4953
|
+
const nextValue = !e ? "" : e.value;
|
|
4954
|
+
pendingUserPickRef.current = { value: nextValue };
|
|
4955
|
+
setInnerValue(nextValue);
|
|
4930
4956
|
},
|
|
4931
4957
|
"data-testid": dataTestId,
|
|
4932
4958
|
value: selectedOption,
|
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
|
|
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,42 @@ 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.
|
|
4883
|
+
//
|
|
4884
|
+
// Only picks are bridged. A value arriving from the `value` prop is something the parent already
|
|
4885
|
+
// holds, so reporting it back would be an echo - and through `register(...).onChange` that echo
|
|
4886
|
+
// is indistinguishable from typing, marking the consumer's form dirty with no user interaction.
|
|
4887
|
+
const lastNotifiedValueRef = useRef(innerValue);
|
|
4888
|
+
// A box, not a bare value: `null` then unambiguously means "no pick pending", so the origin gate
|
|
4889
|
+
// below cannot be satisfied by a parent-driven change that merely matches the ref's empty state.
|
|
4890
|
+
const pendingUserPickRef = useRef(null);
|
|
4882
4891
|
useEffect(() => {
|
|
4883
|
-
if (
|
|
4892
|
+
if (lastNotifiedValueRef.current === innerValue) {
|
|
4884
4893
|
return;
|
|
4885
4894
|
}
|
|
4886
|
-
|
|
4895
|
+
lastNotifiedValueRef.current = innerValue;
|
|
4896
|
+
// Keep the hidden select in sync whatever the origin - this is state, not notification.
|
|
4887
4897
|
if (innerValue === "" && innerRef.current) {
|
|
4888
4898
|
innerRef.current.value = ""; // Set the desired option value
|
|
4889
4899
|
}
|
|
4900
|
+
// Keyed to the value the pick expected, not a boolean: react-select reports a re-pick of the
|
|
4901
|
+
// current option, which leaves `innerValue` untouched and so never runs this effect. A boolean
|
|
4902
|
+
// would still be set when the parent's next value arrives, and that value would be reported
|
|
4903
|
+
// back as a user edit.
|
|
4904
|
+
const pendingUserPick = pendingUserPickRef.current;
|
|
4905
|
+
pendingUserPickRef.current = null;
|
|
4906
|
+
const isUserChange = pendingUserPick !== null && pendingUserPick.value === innerValue;
|
|
4907
|
+
// No `undefined` guard needed: a pick is always a string or number (react-select's clear maps
|
|
4908
|
+
// to ""), so matching one narrows `innerValue` away from `undefined`. Only the parent can put
|
|
4909
|
+
// `undefined` there, and the gate above already rejects parent-driven values.
|
|
4910
|
+
if (!isUserChange) {
|
|
4911
|
+
return;
|
|
4912
|
+
}
|
|
4913
|
+
const event = new Event("change");
|
|
4890
4914
|
innerRef.current?.dispatchEvent(event);
|
|
4891
4915
|
onChangeRef.current?.(event);
|
|
4892
|
-
}, [innerValue
|
|
4916
|
+
}, [innerValue]);
|
|
4893
4917
|
const optionsWithCurrentSelectionBackupOption = [
|
|
4894
4918
|
// Add the current selection in case there's no options loaded yet (in CreatableSelect)
|
|
4895
4919
|
// Also _don't_ add it if it's a duplicate
|
|
@@ -4925,7 +4949,9 @@ const FormFieldSelectAdapter = ({ className, "data-testid": dataTestId, helpText
|
|
|
4925
4949
|
// If theres no value, set the inner value to an empty string
|
|
4926
4950
|
// A native select can not have a null value
|
|
4927
4951
|
// So even if react-select sends a null value, we need to convert it to an empty string
|
|
4928
|
-
|
|
4952
|
+
const nextValue = !e ? "" : e.value;
|
|
4953
|
+
pendingUserPickRef.current = { value: nextValue };
|
|
4954
|
+
setInnerValue(nextValue);
|
|
4929
4955
|
},
|
|
4930
4956
|
"data-testid": dataTestId,
|
|
4931
4957
|
value: selectedOption,
|
|
@@ -1,11 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.insertAttributeIntoOpeningTag = exports.logSummary = exports.
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
36
|
+
exports.insertAttributeIntoOpeningTag = exports.logSummary = exports.parseTsx = exports.hasSpreadAttribute = exports.findJsxAttribute = exports.findJsxElements = exports.getLocalAliasFor = exports.getImportedAliases = exports.visitTsFiles = exports.visitTsxFiles = void 0;
|
|
5
37
|
const devkit_1 = require("@nx/devkit");
|
|
6
|
-
const
|
|
7
|
-
Object.defineProperty(exports, "tsquery", { enumerable: true, get: function () { return tsquery_1.tsquery; } });
|
|
8
|
-
const ts = tslib_1.__importStar(require("typescript"));
|
|
38
|
+
const ts = __importStar(require("typescript"));
|
|
9
39
|
const TSX_EXTENSIONS = [".tsx", ".jsx"];
|
|
10
40
|
const TS_EXTENSIONS = [".ts", ".tsx", ".jsx"];
|
|
11
41
|
const isTsxFile = (filePath) => TSX_EXTENSIONS.some(ext => filePath.endsWith(ext));
|
|
@@ -1,9 +1,41 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
2
35
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
36
|
exports.actionButtonAddTitle = void 0;
|
|
4
|
-
const tslib_1 = require("tslib");
|
|
5
37
|
const devkit_1 = require("@nx/devkit");
|
|
6
|
-
const ts =
|
|
38
|
+
const ts = __importStar(require("typescript"));
|
|
7
39
|
const jsx_utils_1 = require("../utils/jsx-utils");
|
|
8
40
|
const PACKAGE_NAME = "@trackunit/react-form-components";
|
|
9
41
|
const COMPONENT_NAME = "ActionButton";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@trackunit/react-form-components",
|
|
3
|
-
"version": "2.6.
|
|
3
|
+
"version": "2.6.26",
|
|
4
4
|
"repository": "https://github.com/Trackunit/manager",
|
|
5
5
|
"license": "SEE LICENSE IN LICENSE.txt",
|
|
6
6
|
"migrations": "./migrations.json",
|
|
@@ -10,17 +10,17 @@
|
|
|
10
10
|
"dependencies": {
|
|
11
11
|
"react-calendar": "^6.0.0",
|
|
12
12
|
"react-select": "^5.10.2",
|
|
13
|
-
"@trackunit/date-and-time-utils": "1.14.
|
|
13
|
+
"@trackunit/date-and-time-utils": "1.14.20",
|
|
14
14
|
"usehooks-ts": "^3.1.0",
|
|
15
15
|
"libphonenumber-js": "^1.13.6",
|
|
16
16
|
"zod": "^3.25.76",
|
|
17
17
|
"tailwind-merge": "^2.0.0",
|
|
18
|
-
"@trackunit/css-class-variance-utilities": "1.14.
|
|
19
|
-
"@trackunit/react-components": "2.10.
|
|
20
|
-
"@trackunit/ui-icons": "1.14.
|
|
21
|
-
"@trackunit/shared-utils": "1.16.
|
|
22
|
-
"@trackunit/ui-design-tokens": "1.15.
|
|
23
|
-
"@trackunit/i18n-library-translation": "2.4.
|
|
18
|
+
"@trackunit/css-class-variance-utilities": "1.14.19",
|
|
19
|
+
"@trackunit/react-components": "2.10.19",
|
|
20
|
+
"@trackunit/ui-icons": "1.14.18",
|
|
21
|
+
"@trackunit/shared-utils": "1.16.22",
|
|
22
|
+
"@trackunit/ui-design-tokens": "1.15.9",
|
|
23
|
+
"@trackunit/i18n-library-translation": "2.4.25",
|
|
24
24
|
"string-ts": "^2.0.0",
|
|
25
25
|
"es-toolkit": "^1.39.10"
|
|
26
26
|
},
|
|
@@ -32,6 +32,11 @@ export interface SelectFieldProps<TOption extends BaseOptionType = BaseOptionTyp
|
|
|
32
32
|
/**
|
|
33
33
|
* The onChange handler for the SelectField.
|
|
34
34
|
*
|
|
35
|
+
* Called when the user picks a different option. It is not called when the `value` prop changes,
|
|
36
|
+
* since that value is one the parent already holds, and not when the user re-picks the option that
|
|
37
|
+
* is already selected. It is also forwarded to the hidden native `<select>`, so a change event
|
|
38
|
+
* dispatched on that node invokes it too.
|
|
39
|
+
*
|
|
35
40
|
* @important
|
|
36
41
|
*/
|
|
37
42
|
onChange?: (event: {
|