@opengeoweb/form-fields 14.0.1 → 14.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/index.esm.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
2
2
|
import { FormControl, FormHelperText, InputLabel, Select, RadioGroup, TextField, InputAdornment } from '@mui/material';
|
|
3
|
-
import { useFormContext, useController, useForm, FormProvider } from 'react-hook-form';
|
|
3
|
+
import { useFormContext, useController, useForm, FormProvider, Controller } from 'react-hook-form';
|
|
4
4
|
import { isEqual } from 'lodash';
|
|
5
5
|
import { dateUtils } from '@opengeoweb/shared';
|
|
6
6
|
import 'i18next';
|
|
7
7
|
import { useTranslation } from 'react-i18next';
|
|
8
|
-
import React from 'react';
|
|
8
|
+
import React, { useState } from 'react';
|
|
9
9
|
import { DateTimePicker } from '@mui/x-date-pickers';
|
|
10
10
|
import { CalendarToday } from '@opengeoweb/theme';
|
|
11
11
|
import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns';
|
|
@@ -940,6 +940,131 @@ var ReactHookFormHiddenInput = function ReactHookFormHiddenInput(_ref) {
|
|
|
940
940
|
}, props)) : null;
|
|
941
941
|
};
|
|
942
942
|
|
|
943
|
+
function decimalToDegreesMinutes(value) {
|
|
944
|
+
var sign = value < 0 ? '-' : '';
|
|
945
|
+
var abs = Math.abs(value);
|
|
946
|
+
var degrees = Math.floor(abs);
|
|
947
|
+
var minutes = Math.round((abs - degrees) * 60);
|
|
948
|
+
// normalize rounding overflow (e.g. 59.9 min → +1 degree)
|
|
949
|
+
if (minutes === 60) {
|
|
950
|
+
abs += 1;
|
|
951
|
+
return decimalToDegreesMinutes(sign === '-' ? -abs : abs);
|
|
952
|
+
}
|
|
953
|
+
return "" + sign + degrees + "\xB0" + minutes.toString().padStart(2, '0') + "\u2032";
|
|
954
|
+
}
|
|
955
|
+
function degreesMinutesToDecimal(input) {
|
|
956
|
+
var raw = input.toString().trim();
|
|
957
|
+
var negative = raw.startsWith('-');
|
|
958
|
+
var digits = raw.replace(/[^0-9]/g, '');
|
|
959
|
+
var sign = negative ? -1 : 1;
|
|
960
|
+
if (digits.length <= 2) {
|
|
961
|
+
var _deg = parseInt(digits || '0', 10);
|
|
962
|
+
return sign * _deg;
|
|
963
|
+
}
|
|
964
|
+
// split into degrees + minutes
|
|
965
|
+
var deg = parseInt(digits.slice(0, digits.length - 2), 10);
|
|
966
|
+
var min = parseInt(digits.slice(-2), 10);
|
|
967
|
+
// normalize minutes overflow (e.g. 65 → 1°05′)
|
|
968
|
+
var extraDeg = Math.floor(min / 60);
|
|
969
|
+
min %= 60;
|
|
970
|
+
return sign * (deg + extraDeg + min / 60);
|
|
971
|
+
}
|
|
972
|
+
var DegreesMinutesField = function DegreesMinutesField(_ref) {
|
|
973
|
+
var name = _ref.name,
|
|
974
|
+
label = _ref.label,
|
|
975
|
+
_ref$disabled = _ref.disabled,
|
|
976
|
+
disabled = _ref$disabled === void 0 ? false : _ref$disabled,
|
|
977
|
+
_ref$isReadOnly = _ref.isReadOnly,
|
|
978
|
+
isReadOnly = _ref$isReadOnly === void 0 ? false : _ref$isReadOnly,
|
|
979
|
+
_ref$size = _ref.size,
|
|
980
|
+
size = _ref$size === void 0 ? 'small' : _ref$size,
|
|
981
|
+
_ref$isLongitude = _ref.isLongitude,
|
|
982
|
+
isLongitude = _ref$isLongitude === void 0 ? false : _ref$isLongitude,
|
|
983
|
+
t = _ref.t;
|
|
984
|
+
var _useFormContext = useFormContext(),
|
|
985
|
+
control = _useFormContext.control;
|
|
986
|
+
var _useState = useState(null),
|
|
987
|
+
localInput = _useState[0],
|
|
988
|
+
setLocalInput = _useState[1];
|
|
989
|
+
var _useState2 = useState(false),
|
|
990
|
+
isEditing = _useState2[0],
|
|
991
|
+
setIsEditing = _useState2[1];
|
|
992
|
+
return jsx(Controller, {
|
|
993
|
+
control: control,
|
|
994
|
+
name: name,
|
|
995
|
+
render: function render(_ref2) {
|
|
996
|
+
var _fieldState$error;
|
|
997
|
+
var field = _ref2.field,
|
|
998
|
+
fieldState = _ref2.fieldState;
|
|
999
|
+
var value = field.value,
|
|
1000
|
+
onChange = field.onChange;
|
|
1001
|
+
var handleChange = function handleChange(e) {
|
|
1002
|
+
setLocalInput(e.target.value);
|
|
1003
|
+
setIsEditing(true);
|
|
1004
|
+
};
|
|
1005
|
+
var handleBlur = function handleBlur() {
|
|
1006
|
+
if (localInput != null && localInput !== '-' && localInput !== '') {
|
|
1007
|
+
var input = localInput.replace(/[^\d-]/g, '');
|
|
1008
|
+
var negative = input.startsWith('-');
|
|
1009
|
+
var digits = input.replace(/[^0-9]/g, '');
|
|
1010
|
+
// Latitude: 4 digits (DDMM), Longitude: 5 (DDDMM)
|
|
1011
|
+
var maxLen = isLongitude ? 5 : 4;
|
|
1012
|
+
if (digits.length > maxLen) {
|
|
1013
|
+
digits = digits.slice(0, maxLen);
|
|
1014
|
+
}
|
|
1015
|
+
var normalized = negative ? "-" + digits : digits;
|
|
1016
|
+
try {
|
|
1017
|
+
var decimal = degreesMinutesToDecimal(normalized);
|
|
1018
|
+
onChange(decimal);
|
|
1019
|
+
} catch (_unused) {
|
|
1020
|
+
// Invalid, do not update form value
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
setIsEditing(false);
|
|
1024
|
+
setLocalInput(null);
|
|
1025
|
+
};
|
|
1026
|
+
var displayValue;
|
|
1027
|
+
if (isEditing) {
|
|
1028
|
+
displayValue = localInput != null ? localInput : '';
|
|
1029
|
+
} else if (value != null) {
|
|
1030
|
+
displayValue = decimalToDegreesMinutes(value);
|
|
1031
|
+
} else {
|
|
1032
|
+
displayValue = '';
|
|
1033
|
+
}
|
|
1034
|
+
return jsx(TextField, {
|
|
1035
|
+
disabled: disabled,
|
|
1036
|
+
error: !!fieldState.error,
|
|
1037
|
+
helperText: (_fieldState$error = fieldState.error) == null ? void 0 : _fieldState$error.message,
|
|
1038
|
+
label: label,
|
|
1039
|
+
onBlur: handleBlur,
|
|
1040
|
+
onChange: handleChange,
|
|
1041
|
+
placeholder: isLongitude ? 'DDD°MM′' : 'DD°MM′',
|
|
1042
|
+
size: size,
|
|
1043
|
+
slotProps: {
|
|
1044
|
+
input: {
|
|
1045
|
+
readOnly: isReadOnly
|
|
1046
|
+
}
|
|
1047
|
+
},
|
|
1048
|
+
value: displayValue
|
|
1049
|
+
});
|
|
1050
|
+
},
|
|
1051
|
+
rules: {
|
|
1052
|
+
validate: function validate(value) {
|
|
1053
|
+
if (value == null || isNaN(value)) {
|
|
1054
|
+
return true;
|
|
1055
|
+
} // let empty pass
|
|
1056
|
+
if (!isLongitude && (value < -90 || value > 90)) {
|
|
1057
|
+
return t('form-fields-error-latitude-minutes');
|
|
1058
|
+
}
|
|
1059
|
+
if (isLongitude && (value < -180 || value > 180)) {
|
|
1060
|
+
return t('form-fields-error-longitude-minutes');
|
|
1061
|
+
}
|
|
1062
|
+
return true;
|
|
1063
|
+
}
|
|
1064
|
+
}
|
|
1065
|
+
});
|
|
1066
|
+
};
|
|
1067
|
+
|
|
943
1068
|
// hidden input helpers, should not be part of send formdata
|
|
944
1069
|
var HIDDEN_INPUT_HELPER_IS_DRAFT = 'IS_DRAFT';
|
|
945
1070
|
var useDraftFormHelpers = function useDraftFormHelpers(isDefaultDraft) {
|
|
@@ -983,4 +1108,4 @@ var useDraftFormHelpers = function useDraftFormHelpers(isDefaultDraft) {
|
|
|
983
1108
|
};
|
|
984
1109
|
};
|
|
985
1110
|
|
|
986
|
-
export { FORM_FIELDS_NAMESPACE, HIDDEN_INPUT_HELPER_IS_DRAFT, ReactHookKeyboardDateTimePicker as ReactHookFormDateTime, ReactHookFormFormControl, ReactHookFormHiddenInput, ReactHookFormNumberField, ReactHookFormProviderWrapper as ReactHookFormProvider, ReactHookFormRadioGroup, ReactHookFormSelect, ReactHookFormTextField, countIntersectionPoints, defaultFormOptions, errorMessages, formFieldsTranslations, getDateValue, getDeepProperty, getFormattedValueForDatePicker, hasIntersectionWithFIR, hasMulitpleIntersections, hasValidGeometry, isEmpty, isGeometryDirty, isInteger, isLatitude, isLongitude, isMaximumOneDrawing, isNonOrBothCoordinates, isValidGeoJsonCoordinates, isValidMax, isValidMin, isXHoursAfter, isXHoursBefore, useDraftFormHelpers };
|
|
1111
|
+
export { DegreesMinutesField, FORM_FIELDS_NAMESPACE, HIDDEN_INPUT_HELPER_IS_DRAFT, ReactHookKeyboardDateTimePicker as ReactHookFormDateTime, ReactHookFormFormControl, ReactHookFormHiddenInput, ReactHookFormNumberField, ReactHookFormProviderWrapper as ReactHookFormProvider, ReactHookFormRadioGroup, ReactHookFormSelect, ReactHookFormTextField, countIntersectionPoints, defaultFormOptions, errorMessages, formFieldsTranslations, getDateValue, getDeepProperty, getFormattedValueForDatePicker, hasIntersectionWithFIR, hasMulitpleIntersections, hasValidGeometry, isEmpty, isGeometryDirty, isInteger, isLatitude, isLongitude, isMaximumOneDrawing, isNonOrBothCoordinates, isValidGeoJsonCoordinates, isValidMax, isValidMin, isXHoursAfter, isXHoursBefore, useDraftFormHelpers };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@opengeoweb/form-fields",
|
|
3
|
-
"version": "14.0
|
|
3
|
+
"version": "14.1.0",
|
|
4
4
|
"description": "GeoWeb form-fields library for the opengeoweb project",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"repository": {
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
"url": "git@gitlab.com:opengeoweb/opengeoweb.git"
|
|
9
9
|
},
|
|
10
10
|
"dependencies": {
|
|
11
|
-
"@opengeoweb/theme": "14.0
|
|
11
|
+
"@opengeoweb/theme": "14.1.0",
|
|
12
12
|
"react-hook-form": "^7.50.1",
|
|
13
13
|
"@mui/x-date-pickers": "^8.11.2",
|
|
14
14
|
"lodash": "^4.17.21",
|
|
15
|
-
"@opengeoweb/shared": "14.0
|
|
15
|
+
"@opengeoweb/shared": "14.1.0",
|
|
16
16
|
"react-i18next": "^15.1.1",
|
|
17
17
|
"@mui/material": "^7.0.1",
|
|
18
18
|
"i18next": "^25.0.1",
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { TFunction } from 'i18next';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export declare function decimalToDegreesMinutes(value: number): string;
|
|
4
|
+
export declare function degreesMinutesToDecimal(input: string | number): number;
|
|
5
|
+
interface Props {
|
|
6
|
+
name: string;
|
|
7
|
+
label: string;
|
|
8
|
+
disabled?: boolean;
|
|
9
|
+
isReadOnly?: boolean;
|
|
10
|
+
size?: 'small' | 'medium';
|
|
11
|
+
isLongitude?: boolean;
|
|
12
|
+
t: TFunction;
|
|
13
|
+
}
|
|
14
|
+
export declare const DegreesMinutesField: React.FC<Props>;
|
|
15
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -7,6 +7,7 @@ export { default as ReactHookFormDateTime } from './ReactHookFormDateTime';
|
|
|
7
7
|
export * from './ReactHookFormDateTime';
|
|
8
8
|
export { default as ReactHookFormProvider } from './ReactHookFormProvider';
|
|
9
9
|
export { default as ReactHookFormHiddenInput } from './ReactHookFormHiddenInput';
|
|
10
|
+
export { DegreesMinutesField } from './DegreesMinutesField';
|
|
10
11
|
export { defaultFormOptions } from './ReactHookFormProvider';
|
|
11
12
|
export { errorMessages, isMaximumOneDrawing, hasValidGeometry, isGeometryDirty, isValidGeoJsonCoordinates, hasIntersectionWithFIR, countIntersectionPoints, isValidMax, isValidMin, isInteger, hasMulitpleIntersections, isLatitude, isLongitude, isNonOrBothCoordinates, isEmpty, isXHoursAfter, isXHoursBefore, } from './utils';
|
|
12
13
|
export { getDeepProperty } from './formUtils';
|