@serhii.olishevskyi/docs 1.1.6 → 1.1.8
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/dist/index.d.mts +45 -2
- package/dist/index.d.ts +45 -2
- package/dist/index.js +402 -16
- package/dist/index.mjs +407 -16
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React$1 from 'react';
|
|
2
2
|
import React__default, { ReactNode } from 'react';
|
|
3
|
-
import { TextFieldProps, IconButtonProps, TooltipProps, SxProps, Theme } from '@mui/material';
|
|
3
|
+
import { TextFieldProps, SelectProps, SelectChangeEvent, IconButtonProps, TooltipProps, SxProps, Theme, TypographyProps } from '@mui/material';
|
|
4
4
|
import * as _supabase_supabase_js from '@supabase/supabase-js';
|
|
5
5
|
import { SupabaseClient, User, Session } from '@supabase/supabase-js';
|
|
6
6
|
|
|
@@ -70,6 +70,39 @@ type EmailInputComponentProps = Omit<TextFieldComponentProps, 'type'> & {
|
|
|
70
70
|
onValidationChange?: (isValid: boolean) => void;
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
+
interface SearchComponentProps extends Omit<TextFieldProps, 'placeholder'> {
|
|
74
|
+
overrideNamespace?: string;
|
|
75
|
+
label?: ReactNode;
|
|
76
|
+
placeholderKey?: string;
|
|
77
|
+
clearTooltip?: string;
|
|
78
|
+
onClear?: () => void;
|
|
79
|
+
debounceDelay?: number;
|
|
80
|
+
onDebounceChange?: (value: string) => void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface SelectOption<T = string> {
|
|
84
|
+
value: T;
|
|
85
|
+
label: React__default.ReactNode;
|
|
86
|
+
isItalic?: boolean;
|
|
87
|
+
}
|
|
88
|
+
interface SelectComponentProps<T = string> extends Omit<SelectProps<T | T[]>, 'onChange' | 'value'> {
|
|
89
|
+
overrideNamespace?: string;
|
|
90
|
+
label: React__default.ReactNode;
|
|
91
|
+
value: T | T[];
|
|
92
|
+
options: SelectOption<T>[];
|
|
93
|
+
onChange?: (event: SelectChangeEvent<T | T[]>, child: React__default.ReactNode) => void;
|
|
94
|
+
id?: string;
|
|
95
|
+
fullWidth?: boolean;
|
|
96
|
+
size?: 'small' | 'medium';
|
|
97
|
+
multiple?: boolean;
|
|
98
|
+
withCheckboxes?: boolean;
|
|
99
|
+
clearable?: boolean;
|
|
100
|
+
maxSelect?: number;
|
|
101
|
+
maxDisplayedTags?: number;
|
|
102
|
+
helperText?: ReactNode;
|
|
103
|
+
defaultValueOnClear?: T;
|
|
104
|
+
}
|
|
105
|
+
|
|
73
106
|
interface CopyClipboardButtonComponentProps extends Omit<IconButtonProps, 'onClick'> {
|
|
74
107
|
overrideNamespace?: string;
|
|
75
108
|
/** Текст, який буде скопійовано в буфер обміну */
|
|
@@ -191,11 +224,20 @@ interface MyAvatarComponentProps {
|
|
|
191
224
|
sx?: SxProps<Theme>;
|
|
192
225
|
}
|
|
193
226
|
|
|
227
|
+
interface ExpandableNoteComponentProps extends Omit<TypographyProps, 'children'> {
|
|
228
|
+
overrideNamespace?: string;
|
|
229
|
+
text?: string;
|
|
230
|
+
maxLength?: number;
|
|
231
|
+
label?: React__default.ReactNode;
|
|
232
|
+
}
|
|
233
|
+
|
|
194
234
|
declare const UI: {
|
|
195
235
|
Inputs: {
|
|
196
236
|
TextField: React$1.FC<TextFieldComponentProps>;
|
|
197
237
|
NumberField: React$1.FC<NumberInputComponentProps>;
|
|
198
238
|
EmailField: React$1.FC<EmailInputComponentProps>;
|
|
239
|
+
Search: React$1.FC<SearchComponentProps>;
|
|
240
|
+
Select: <T extends string | number>({ overrideNamespace, label, value, options, onChange, id, fullWidth, size, multiple, withCheckboxes, clearable, maxSelect, disabled, maxDisplayedTags, helperText, defaultValueOnClear, sx, ...restProps }: SelectComponentProps<T>) => React$1.JSX.Element;
|
|
199
241
|
Url: typeof UrlComponent;
|
|
200
242
|
};
|
|
201
243
|
Buttons: {
|
|
@@ -208,6 +250,7 @@ declare const UI: {
|
|
|
208
250
|
UserRoleChip: React$1.FC<UserRoleChipComponentProps>;
|
|
209
251
|
UserStatusChip: React$1.FC<UserStatusChipComponentProps>;
|
|
210
252
|
MyAvatar: React$1.FC<MyAvatarComponentProps>;
|
|
253
|
+
ExpandableNote: React$1.FC<ExpandableNoteComponentProps>;
|
|
211
254
|
};
|
|
212
255
|
Widgets: {
|
|
213
256
|
ProtectedLanguageSelector: React$1.FC<{}>;
|
|
@@ -534,4 +577,4 @@ declare const Hooks: {
|
|
|
534
577
|
readonly useDebounce: typeof useDebounce;
|
|
535
578
|
};
|
|
536
579
|
|
|
537
|
-
export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps
|
|
580
|
+
export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, type ExpandableNoteComponentProps, Hooks, type Language, LocalizationProvider, type MyAvatarComponentProps, type NumberInputComponentProps, Providers, type SearchComponentProps, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserRoleChipComponentProps, type UserSessionItem, UserSettingsProvider, type UserStatusChipComponentProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as React$1 from 'react';
|
|
2
2
|
import React__default, { ReactNode } from 'react';
|
|
3
|
-
import { TextFieldProps, IconButtonProps, TooltipProps, SxProps, Theme } from '@mui/material';
|
|
3
|
+
import { TextFieldProps, SelectProps, SelectChangeEvent, IconButtonProps, TooltipProps, SxProps, Theme, TypographyProps } from '@mui/material';
|
|
4
4
|
import * as _supabase_supabase_js from '@supabase/supabase-js';
|
|
5
5
|
import { SupabaseClient, User, Session } from '@supabase/supabase-js';
|
|
6
6
|
|
|
@@ -70,6 +70,39 @@ type EmailInputComponentProps = Omit<TextFieldComponentProps, 'type'> & {
|
|
|
70
70
|
onValidationChange?: (isValid: boolean) => void;
|
|
71
71
|
};
|
|
72
72
|
|
|
73
|
+
interface SearchComponentProps extends Omit<TextFieldProps, 'placeholder'> {
|
|
74
|
+
overrideNamespace?: string;
|
|
75
|
+
label?: ReactNode;
|
|
76
|
+
placeholderKey?: string;
|
|
77
|
+
clearTooltip?: string;
|
|
78
|
+
onClear?: () => void;
|
|
79
|
+
debounceDelay?: number;
|
|
80
|
+
onDebounceChange?: (value: string) => void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
interface SelectOption<T = string> {
|
|
84
|
+
value: T;
|
|
85
|
+
label: React__default.ReactNode;
|
|
86
|
+
isItalic?: boolean;
|
|
87
|
+
}
|
|
88
|
+
interface SelectComponentProps<T = string> extends Omit<SelectProps<T | T[]>, 'onChange' | 'value'> {
|
|
89
|
+
overrideNamespace?: string;
|
|
90
|
+
label: React__default.ReactNode;
|
|
91
|
+
value: T | T[];
|
|
92
|
+
options: SelectOption<T>[];
|
|
93
|
+
onChange?: (event: SelectChangeEvent<T | T[]>, child: React__default.ReactNode) => void;
|
|
94
|
+
id?: string;
|
|
95
|
+
fullWidth?: boolean;
|
|
96
|
+
size?: 'small' | 'medium';
|
|
97
|
+
multiple?: boolean;
|
|
98
|
+
withCheckboxes?: boolean;
|
|
99
|
+
clearable?: boolean;
|
|
100
|
+
maxSelect?: number;
|
|
101
|
+
maxDisplayedTags?: number;
|
|
102
|
+
helperText?: ReactNode;
|
|
103
|
+
defaultValueOnClear?: T;
|
|
104
|
+
}
|
|
105
|
+
|
|
73
106
|
interface CopyClipboardButtonComponentProps extends Omit<IconButtonProps, 'onClick'> {
|
|
74
107
|
overrideNamespace?: string;
|
|
75
108
|
/** Текст, який буде скопійовано в буфер обміну */
|
|
@@ -191,11 +224,20 @@ interface MyAvatarComponentProps {
|
|
|
191
224
|
sx?: SxProps<Theme>;
|
|
192
225
|
}
|
|
193
226
|
|
|
227
|
+
interface ExpandableNoteComponentProps extends Omit<TypographyProps, 'children'> {
|
|
228
|
+
overrideNamespace?: string;
|
|
229
|
+
text?: string;
|
|
230
|
+
maxLength?: number;
|
|
231
|
+
label?: React__default.ReactNode;
|
|
232
|
+
}
|
|
233
|
+
|
|
194
234
|
declare const UI: {
|
|
195
235
|
Inputs: {
|
|
196
236
|
TextField: React$1.FC<TextFieldComponentProps>;
|
|
197
237
|
NumberField: React$1.FC<NumberInputComponentProps>;
|
|
198
238
|
EmailField: React$1.FC<EmailInputComponentProps>;
|
|
239
|
+
Search: React$1.FC<SearchComponentProps>;
|
|
240
|
+
Select: <T extends string | number>({ overrideNamespace, label, value, options, onChange, id, fullWidth, size, multiple, withCheckboxes, clearable, maxSelect, disabled, maxDisplayedTags, helperText, defaultValueOnClear, sx, ...restProps }: SelectComponentProps<T>) => React$1.JSX.Element;
|
|
199
241
|
Url: typeof UrlComponent;
|
|
200
242
|
};
|
|
201
243
|
Buttons: {
|
|
@@ -208,6 +250,7 @@ declare const UI: {
|
|
|
208
250
|
UserRoleChip: React$1.FC<UserRoleChipComponentProps>;
|
|
209
251
|
UserStatusChip: React$1.FC<UserStatusChipComponentProps>;
|
|
210
252
|
MyAvatar: React$1.FC<MyAvatarComponentProps>;
|
|
253
|
+
ExpandableNote: React$1.FC<ExpandableNoteComponentProps>;
|
|
211
254
|
};
|
|
212
255
|
Widgets: {
|
|
213
256
|
ProtectedLanguageSelector: React$1.FC<{}>;
|
|
@@ -534,4 +577,4 @@ declare const Hooks: {
|
|
|
534
577
|
readonly useDebounce: typeof useDebounce;
|
|
535
578
|
};
|
|
536
579
|
|
|
537
|
-
export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps
|
|
580
|
+
export { type AIConfig, type AIGenerateOptions, AIProvider, type AIProviderProps, type AIProviderType, AppSettingsProvider, AuthProvider, BreadcrumbProvider, type ConfirmOptions, type ConfirmResult, ConfirmationProvider, type ConfirmationProviderProps, type CopyClipboardButtonComponentProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps, type ExpandableNoteComponentProps, Hooks, type Language, LocalizationProvider, type MyAvatarComponentProps, type NumberInputComponentProps, Providers, type SearchComponentProps, type SelectComponentProps, type SelectOption, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps, type UserGroupedSessions, type UserPopoverComponentProps, type UserRoleChipComponentProps, type UserSessionItem, UserSettingsProvider, type UserStatusChipComponentProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
|
package/dist/index.js
CHANGED
|
@@ -3979,12 +3979,412 @@ var PublicLanguageSelector = () => {
|
|
|
3979
3979
|
] });
|
|
3980
3980
|
};
|
|
3981
3981
|
|
|
3982
|
+
// src/UI/components/inputs/SearchComponent.tsx
|
|
3983
|
+
var import_react26 = require("react");
|
|
3984
|
+
var import_react_i18next6 = require("react-i18next");
|
|
3985
|
+
var import_material18 = require("@mui/material");
|
|
3986
|
+
var import_Translate4 = __toESM(require("@mui/icons-material/Translate"));
|
|
3987
|
+
var import_Clear2 = __toESM(require("@mui/icons-material/Clear"));
|
|
3988
|
+
init_context();
|
|
3989
|
+
init_translation_service();
|
|
3990
|
+
init_TranslationDialog();
|
|
3991
|
+
init_TranslatableTooltipComponent();
|
|
3992
|
+
|
|
3993
|
+
// src/hooks/useDebounce.ts
|
|
3994
|
+
var import_react25 = require("react");
|
|
3995
|
+
function useDebounce(value, delay = 500) {
|
|
3996
|
+
const [debouncedValue, setDebouncedValue] = (0, import_react25.useState)(value);
|
|
3997
|
+
(0, import_react25.useEffect)(() => {
|
|
3998
|
+
const timer = setTimeout(() => {
|
|
3999
|
+
setDebouncedValue(value);
|
|
4000
|
+
}, delay);
|
|
4001
|
+
return () => {
|
|
4002
|
+
clearTimeout(timer);
|
|
4003
|
+
};
|
|
4004
|
+
}, [value, delay]);
|
|
4005
|
+
return debouncedValue;
|
|
4006
|
+
}
|
|
4007
|
+
|
|
4008
|
+
// src/UI/components/inputs/SearchComponent.tsx
|
|
4009
|
+
var import_jsx_runtime28 = require("react/jsx-runtime");
|
|
4010
|
+
var SearchComponent = ({
|
|
4011
|
+
overrideNamespace,
|
|
4012
|
+
label = "",
|
|
4013
|
+
value = "",
|
|
4014
|
+
onChange,
|
|
4015
|
+
onClear,
|
|
4016
|
+
placeholderKey,
|
|
4017
|
+
clearTooltip = "Clear",
|
|
4018
|
+
debounceDelay = 500,
|
|
4019
|
+
onDebounceChange,
|
|
4020
|
+
slotProps,
|
|
4021
|
+
...restProps
|
|
4022
|
+
}) => {
|
|
4023
|
+
const supabase = useSupabase();
|
|
4024
|
+
const namespace = useTranslationNamespace();
|
|
4025
|
+
const { t, i18n: i18n2 } = (0, import_react_i18next6.useTranslation)(namespace);
|
|
4026
|
+
const { isTranslationMode } = useTranslationEdit();
|
|
4027
|
+
const [isDialogOpen, setIsDialogOpen] = (0, import_react26.useState)(false);
|
|
4028
|
+
const [localValue, setLocalValue] = (0, import_react26.useState)(String(value ?? ""));
|
|
4029
|
+
const debouncedValue = useDebounce(localValue, debounceDelay);
|
|
4030
|
+
(0, import_react26.useEffect)(() => {
|
|
4031
|
+
setLocalValue(String(value ?? ""));
|
|
4032
|
+
}, [value]);
|
|
4033
|
+
(0, import_react26.useEffect)(() => {
|
|
4034
|
+
if (onDebounceChange) {
|
|
4035
|
+
onDebounceChange(debouncedValue);
|
|
4036
|
+
}
|
|
4037
|
+
if (onChange && debouncedValue !== String(value ?? "")) {
|
|
4038
|
+
const syntheticEvent = {
|
|
4039
|
+
target: { value: debouncedValue },
|
|
4040
|
+
currentTarget: { value: debouncedValue }
|
|
4041
|
+
};
|
|
4042
|
+
onChange(syntheticEvent);
|
|
4043
|
+
}
|
|
4044
|
+
}, [debouncedValue]);
|
|
4045
|
+
const hasValue = localValue.length > 0;
|
|
4046
|
+
const handleChange = (e) => {
|
|
4047
|
+
setLocalValue(e.target.value);
|
|
4048
|
+
};
|
|
4049
|
+
const handleClear = (e) => {
|
|
4050
|
+
e.stopPropagation();
|
|
4051
|
+
setLocalValue("");
|
|
4052
|
+
if (onClear) {
|
|
4053
|
+
onClear();
|
|
4054
|
+
}
|
|
4055
|
+
if (onChange) {
|
|
4056
|
+
const syntheticEvent = {
|
|
4057
|
+
...e,
|
|
4058
|
+
target: { ...e.target, value: "" },
|
|
4059
|
+
currentTarget: { ...e.currentTarget, value: "" }
|
|
4060
|
+
};
|
|
4061
|
+
onChange(syntheticEvent);
|
|
4062
|
+
}
|
|
4063
|
+
};
|
|
4064
|
+
const translatedPlaceholder = placeholderKey ? t(placeholderKey) : void 0;
|
|
4065
|
+
const handleSaveTranslations = async (newValues, contextHint) => {
|
|
4066
|
+
if (!placeholderKey) return;
|
|
4067
|
+
const upsertData = Object.entries(newValues).map(([langCode, text]) => ({
|
|
4068
|
+
lang_code: langCode,
|
|
4069
|
+
namespace,
|
|
4070
|
+
key: placeholderKey,
|
|
4071
|
+
value: text,
|
|
4072
|
+
context_hint: contextHint
|
|
4073
|
+
}));
|
|
4074
|
+
const { error } = await supabase.from("translations").upsert(upsertData, { onConflict: "lang_code,namespace,key" });
|
|
4075
|
+
if (error) {
|
|
4076
|
+
alert("\u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u043F\u0456\u0434 \u0447\u0430\u0441 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043D\u043D\u044F \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043D\u0438\u0445");
|
|
4077
|
+
throw error;
|
|
4078
|
+
}
|
|
4079
|
+
await translationService.incrementVersion(supabase, namespace, Object.keys(newValues));
|
|
4080
|
+
Object.entries(newValues).forEach(([langCode, text]) => {
|
|
4081
|
+
i18n2.addResource(langCode, namespace, placeholderKey, text);
|
|
4082
|
+
});
|
|
4083
|
+
};
|
|
4084
|
+
const renderEndAdornment = () => {
|
|
4085
|
+
const rawInputProps = slotProps?.input;
|
|
4086
|
+
const isInputObject = typeof rawInputProps === "object" && rawInputProps !== null;
|
|
4087
|
+
const existingEndAdornment = isInputObject && "endAdornment" in rawInputProps ? rawInputProps.endAdornment : void 0;
|
|
4088
|
+
if (!hasValue && (!isTranslationMode || !placeholderKey)) {
|
|
4089
|
+
return existingEndAdornment;
|
|
4090
|
+
}
|
|
4091
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
4092
|
+
existingEndAdornment,
|
|
4093
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_material18.InputAdornment, { position: "end", children: [
|
|
4094
|
+
hasValue && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TranslatableTooltipComponent, { title: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TranslateText, { overrideNamespace, children: clearTooltip }), children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4095
|
+
import_material18.IconButton,
|
|
4096
|
+
{
|
|
4097
|
+
size: "small",
|
|
4098
|
+
onClick: handleClear,
|
|
4099
|
+
edge: "end",
|
|
4100
|
+
"aria-label": "clear input",
|
|
4101
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_Clear2.default, { fontSize: "small" })
|
|
4102
|
+
}
|
|
4103
|
+
) }),
|
|
4104
|
+
isTranslationMode && placeholderKey && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_material18.Tooltip, { title: `Translate placeholder: "${placeholderKey}"`, children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4105
|
+
import_material18.IconButton,
|
|
4106
|
+
{
|
|
4107
|
+
size: "small",
|
|
4108
|
+
onClick: (e) => {
|
|
4109
|
+
e.preventDefault();
|
|
4110
|
+
e.stopPropagation();
|
|
4111
|
+
setIsDialogOpen(true);
|
|
4112
|
+
},
|
|
4113
|
+
sx: {
|
|
4114
|
+
color: "#d97706",
|
|
4115
|
+
backgroundColor: "rgba(254, 243, 199, 0.6)",
|
|
4116
|
+
border: "1px dashed #f59e0b",
|
|
4117
|
+
p: "3px",
|
|
4118
|
+
ml: 0.5,
|
|
4119
|
+
"&:hover": {
|
|
4120
|
+
backgroundColor: "#fef08a"
|
|
4121
|
+
}
|
|
4122
|
+
},
|
|
4123
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(import_Translate4.default, { fontSize: "small" })
|
|
4124
|
+
}
|
|
4125
|
+
) })
|
|
4126
|
+
] })
|
|
4127
|
+
] });
|
|
4128
|
+
};
|
|
4129
|
+
return /* @__PURE__ */ (0, import_jsx_runtime28.jsxs)(import_jsx_runtime28.Fragment, { children: [
|
|
4130
|
+
/* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4131
|
+
import_material18.TextField,
|
|
4132
|
+
{
|
|
4133
|
+
...restProps,
|
|
4134
|
+
label: typeof label === "string" ? /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(TranslateText, { overrideNamespace, children: label }) : label,
|
|
4135
|
+
value: localValue,
|
|
4136
|
+
onChange: handleChange,
|
|
4137
|
+
placeholder: translatedPlaceholder,
|
|
4138
|
+
slotProps: {
|
|
4139
|
+
...slotProps,
|
|
4140
|
+
input: {
|
|
4141
|
+
...slotProps?.input,
|
|
4142
|
+
endAdornment: renderEndAdornment()
|
|
4143
|
+
}
|
|
4144
|
+
}
|
|
4145
|
+
}
|
|
4146
|
+
),
|
|
4147
|
+
placeholderKey && /* @__PURE__ */ (0, import_jsx_runtime28.jsx)(
|
|
4148
|
+
TranslationDialog,
|
|
4149
|
+
{
|
|
4150
|
+
open: isDialogOpen,
|
|
4151
|
+
onClose: () => setIsDialogOpen(false),
|
|
4152
|
+
translationKey: placeholderKey,
|
|
4153
|
+
namespace,
|
|
4154
|
+
onSave: handleSaveTranslations
|
|
4155
|
+
}
|
|
4156
|
+
)
|
|
4157
|
+
] });
|
|
4158
|
+
};
|
|
4159
|
+
|
|
4160
|
+
// src/UI/components/inputs/SelectComponent.tsx
|
|
4161
|
+
var import_material19 = require("@mui/material");
|
|
4162
|
+
var import_Close = __toESM(require("@mui/icons-material/Close"));
|
|
4163
|
+
init_context();
|
|
4164
|
+
var import_jsx_runtime29 = require("react/jsx-runtime");
|
|
4165
|
+
var SelectComponent = ({
|
|
4166
|
+
overrideNamespace,
|
|
4167
|
+
label,
|
|
4168
|
+
value,
|
|
4169
|
+
options,
|
|
4170
|
+
onChange,
|
|
4171
|
+
id = "translated-select",
|
|
4172
|
+
fullWidth,
|
|
4173
|
+
size = "medium",
|
|
4174
|
+
multiple = false,
|
|
4175
|
+
withCheckboxes = false,
|
|
4176
|
+
clearable = true,
|
|
4177
|
+
maxSelect,
|
|
4178
|
+
disabled,
|
|
4179
|
+
maxDisplayedTags = 2,
|
|
4180
|
+
helperText,
|
|
4181
|
+
defaultValueOnClear,
|
|
4182
|
+
sx,
|
|
4183
|
+
...restProps
|
|
4184
|
+
}) => {
|
|
4185
|
+
const labelId = `${id}-label`;
|
|
4186
|
+
const safeValue = multiple ? Array.isArray(value) ? value : [] : value ?? "";
|
|
4187
|
+
const selectedArray = multiple ? safeValue : [];
|
|
4188
|
+
const isLimitReached = Boolean(multiple && maxSelect && selectedArray.length >= maxSelect);
|
|
4189
|
+
const hasValue = multiple ? selectedArray.length > 0 : safeValue !== "" && safeValue !== null && safeValue !== void 0;
|
|
4190
|
+
const handleChange = (event, child) => {
|
|
4191
|
+
if (multiple && maxSelect) {
|
|
4192
|
+
const newValue = event.target.value;
|
|
4193
|
+
if (newValue.length > maxSelect) {
|
|
4194
|
+
return;
|
|
4195
|
+
}
|
|
4196
|
+
}
|
|
4197
|
+
onChange?.(event, child);
|
|
4198
|
+
};
|
|
4199
|
+
const handleClear = (e) => {
|
|
4200
|
+
e.stopPropagation();
|
|
4201
|
+
if (!onChange) return;
|
|
4202
|
+
const emptyValue = multiple ? [] : "";
|
|
4203
|
+
const targetValue = defaultValueOnClear !== void 0 ? defaultValueOnClear : emptyValue;
|
|
4204
|
+
const syntheticEvent = {
|
|
4205
|
+
target: {
|
|
4206
|
+
value: targetValue,
|
|
4207
|
+
name: restProps.name
|
|
4208
|
+
}
|
|
4209
|
+
};
|
|
4210
|
+
onChange(syntheticEvent, null);
|
|
4211
|
+
};
|
|
4212
|
+
const renderValueHandler = (selected) => {
|
|
4213
|
+
if (!multiple) return void 0;
|
|
4214
|
+
const currentSelected = selected;
|
|
4215
|
+
if (currentSelected.length === 0) return null;
|
|
4216
|
+
const selectedOptions = options.filter((opt) => currentSelected.includes(opt.value));
|
|
4217
|
+
const visibleLabels = selectedOptions.slice(0, maxDisplayedTags).map((opt) => typeof opt.label === "string" ? opt.label : String(opt.value));
|
|
4218
|
+
const hiddenCount = selectedOptions.length - maxDisplayedTags;
|
|
4219
|
+
if (hiddenCount > 0) {
|
|
4220
|
+
return `${visibleLabels.join(", ")} (+${hiddenCount})`;
|
|
4221
|
+
}
|
|
4222
|
+
return visibleLabels.join(", ");
|
|
4223
|
+
};
|
|
4224
|
+
const isSmall = size === "small";
|
|
4225
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4226
|
+
import_material19.Tooltip,
|
|
4227
|
+
{
|
|
4228
|
+
title: multiple ? Array.isArray(value) ? options.filter((opt) => value.includes(opt.value)).map((opt) => typeof opt.label === "string" ? opt.label : String(opt.value)).join(", ") : "" : options.find((opt) => opt.value === value)?.label ?? String(value ?? ""),
|
|
4229
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(import_material19.FormControl, { fullWidth, size, sx: { mt: 1 }, children: [
|
|
4230
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_material19.InputLabel, { id: labelId, size: isSmall ? "small" : "medium", children: typeof label === "string" ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TranslateText, { overrideNamespace, children: label }) : label }),
|
|
4231
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4232
|
+
import_material19.Select,
|
|
4233
|
+
{
|
|
4234
|
+
labelId,
|
|
4235
|
+
id,
|
|
4236
|
+
value: safeValue,
|
|
4237
|
+
label: typeof label === "string" ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(TranslateText, { overrideNamespace, children: label }) : label,
|
|
4238
|
+
size,
|
|
4239
|
+
multiple,
|
|
4240
|
+
disabled,
|
|
4241
|
+
onChange: handleChange,
|
|
4242
|
+
renderValue: multiple ? renderValueHandler : void 0,
|
|
4243
|
+
...restProps,
|
|
4244
|
+
endAdornment: clearable && hasValue && !disabled ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_material19.InputAdornment, { position: "end", sx: { mr: 1 }, children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4245
|
+
import_material19.IconButton,
|
|
4246
|
+
{
|
|
4247
|
+
size: "small",
|
|
4248
|
+
onClick: handleClear,
|
|
4249
|
+
"aria-label": "clear selection",
|
|
4250
|
+
edge: "end",
|
|
4251
|
+
sx: { p: 0.5 },
|
|
4252
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_Close.default, { fontSize: "small" })
|
|
4253
|
+
}
|
|
4254
|
+
) }) : null,
|
|
4255
|
+
sx: {
|
|
4256
|
+
// 1. Задаем фиксированную высоту для всего контейнера инпута
|
|
4257
|
+
height: isSmall ? "40px" : "56px",
|
|
4258
|
+
minHeight: isSmall ? "40px" : "56px",
|
|
4259
|
+
// 2. Выравниваем внутренний класс текстового поля
|
|
4260
|
+
"& .MuiSelect-select": {
|
|
4261
|
+
display: "flex",
|
|
4262
|
+
alignItems: "center",
|
|
4263
|
+
boxSizing: "border-box",
|
|
4264
|
+
height: "100%",
|
|
4265
|
+
minHeight: "100% !important",
|
|
4266
|
+
py: 0,
|
|
4267
|
+
lineHeight: "normal",
|
|
4268
|
+
overflow: "hidden",
|
|
4269
|
+
textOverflow: "ellipsis",
|
|
4270
|
+
whiteSpace: "nowrap",
|
|
4271
|
+
paddingRight: clearable && hasValue ? "64px !important" : "32px !important"
|
|
4272
|
+
},
|
|
4273
|
+
// 3. Корректируем иконку стрелки выпадающего списка
|
|
4274
|
+
"& .MuiSelect-icon": {
|
|
4275
|
+
top: "calc(50% - 12px)"
|
|
4276
|
+
},
|
|
4277
|
+
// 4. Корректируем расположение иконки очистки
|
|
4278
|
+
"& .MuiInputAdornment-root": {
|
|
4279
|
+
maxHeight: "100%",
|
|
4280
|
+
height: "100%",
|
|
4281
|
+
alignItems: "center"
|
|
4282
|
+
},
|
|
4283
|
+
...sx
|
|
4284
|
+
},
|
|
4285
|
+
children: options.map((option) => {
|
|
4286
|
+
const isSelected = multiple && selectedArray.includes(option.value);
|
|
4287
|
+
const isDisabled = Boolean(isLimitReached && !isSelected);
|
|
4288
|
+
return /* @__PURE__ */ (0, import_jsx_runtime29.jsxs)(
|
|
4289
|
+
import_material19.MenuItem,
|
|
4290
|
+
{
|
|
4291
|
+
value: option.value,
|
|
4292
|
+
disabled: isDisabled,
|
|
4293
|
+
children: [
|
|
4294
|
+
multiple && withCheckboxes && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_material19.Checkbox, { checked: isSelected, size, disabled: isDisabled }),
|
|
4295
|
+
/* @__PURE__ */ (0, import_jsx_runtime29.jsx)(
|
|
4296
|
+
import_material19.ListItemText,
|
|
4297
|
+
{
|
|
4298
|
+
primary: option.isItalic ? /* @__PURE__ */ (0, import_jsx_runtime29.jsx)("em", { children: option.label }) : option.label
|
|
4299
|
+
}
|
|
4300
|
+
)
|
|
4301
|
+
]
|
|
4302
|
+
},
|
|
4303
|
+
String(option.value)
|
|
4304
|
+
);
|
|
4305
|
+
})
|
|
4306
|
+
}
|
|
4307
|
+
),
|
|
4308
|
+
helperText && /* @__PURE__ */ (0, import_jsx_runtime29.jsx)(import_material19.FormHelperText, { children: helperText })
|
|
4309
|
+
] })
|
|
4310
|
+
}
|
|
4311
|
+
);
|
|
4312
|
+
};
|
|
4313
|
+
|
|
4314
|
+
// src/UI/components/data.display/ExpandableNoteComponent.tsx
|
|
4315
|
+
var import_react27 = require("react");
|
|
4316
|
+
var import_material20 = require("@mui/material");
|
|
4317
|
+
init_context();
|
|
4318
|
+
var import_jsx_runtime30 = require("react/jsx-runtime");
|
|
4319
|
+
var ExpandableNoteComponent = ({
|
|
4320
|
+
overrideNamespace,
|
|
4321
|
+
text,
|
|
4322
|
+
maxLength = 100,
|
|
4323
|
+
label,
|
|
4324
|
+
sx,
|
|
4325
|
+
...restProps
|
|
4326
|
+
}) => {
|
|
4327
|
+
const [isExpanded, setIsExpanded] = (0, import_react27.useState)(false);
|
|
4328
|
+
if (!text) return null;
|
|
4329
|
+
const isLong = text.length > maxLength;
|
|
4330
|
+
const displayedText = isExpanded || !isLong ? text : `${text.slice(0, maxLength).trim()}...`;
|
|
4331
|
+
const toggleExpand = (e) => {
|
|
4332
|
+
e.stopPropagation();
|
|
4333
|
+
setIsExpanded((prev) => !prev);
|
|
4334
|
+
};
|
|
4335
|
+
return /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(
|
|
4336
|
+
import_material20.Typography,
|
|
4337
|
+
{
|
|
4338
|
+
variant: "caption",
|
|
4339
|
+
sx: {
|
|
4340
|
+
color: "text.secondary",
|
|
4341
|
+
fontStyle: "italic",
|
|
4342
|
+
display: "inline-block",
|
|
4343
|
+
...sx
|
|
4344
|
+
},
|
|
4345
|
+
...restProps,
|
|
4346
|
+
children: [
|
|
4347
|
+
label !== void 0 ? label : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
4348
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "Note" }),
|
|
4349
|
+
": "
|
|
4350
|
+
] }),
|
|
4351
|
+
" ",
|
|
4352
|
+
displayedText,
|
|
4353
|
+
" ",
|
|
4354
|
+
isLong && /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(
|
|
4355
|
+
import_material20.Link,
|
|
4356
|
+
{
|
|
4357
|
+
component: "button",
|
|
4358
|
+
type: "button",
|
|
4359
|
+
variant: "caption",
|
|
4360
|
+
underline: "hover",
|
|
4361
|
+
onClick: toggleExpand,
|
|
4362
|
+
sx: {
|
|
4363
|
+
fontStyle: "normal",
|
|
4364
|
+
fontWeight: "bold",
|
|
4365
|
+
ml: 0.5,
|
|
4366
|
+
cursor: "pointer",
|
|
4367
|
+
verticalAlign: "baseline"
|
|
4368
|
+
},
|
|
4369
|
+
children: isExpanded ? /* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "less" }) : /* @__PURE__ */ (0, import_jsx_runtime30.jsxs)(import_jsx_runtime30.Fragment, { children: [
|
|
4370
|
+
/* @__PURE__ */ (0, import_jsx_runtime30.jsx)(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "more" }),
|
|
4371
|
+
"..."
|
|
4372
|
+
] })
|
|
4373
|
+
}
|
|
4374
|
+
)
|
|
4375
|
+
]
|
|
4376
|
+
}
|
|
4377
|
+
);
|
|
4378
|
+
};
|
|
4379
|
+
|
|
3982
4380
|
// src/UI/index.ts
|
|
3983
4381
|
var UI = {
|
|
3984
4382
|
Inputs: {
|
|
3985
4383
|
TextField: TextFieldComponent,
|
|
3986
4384
|
NumberField: NumberInputComponent,
|
|
3987
4385
|
EmailField: EmailInputComponent,
|
|
4386
|
+
Search: SearchComponent,
|
|
4387
|
+
Select: SelectComponent,
|
|
3988
4388
|
Url: UrlComponent
|
|
3989
4389
|
},
|
|
3990
4390
|
Buttons: {
|
|
@@ -3996,7 +4396,8 @@ var UI = {
|
|
|
3996
4396
|
UserPopover: UserPopoverComponent_default,
|
|
3997
4397
|
UserRoleChip: UserRoleChipComponent,
|
|
3998
4398
|
UserStatusChip: UserStatusChipComponent,
|
|
3999
|
-
MyAvatar: MyAvatarComponent
|
|
4399
|
+
MyAvatar: MyAvatarComponent,
|
|
4400
|
+
ExpandableNote: ExpandableNoteComponent
|
|
4000
4401
|
},
|
|
4001
4402
|
/*Layout: {
|
|
4002
4403
|
Row: FormRow,
|
|
@@ -4026,21 +4427,6 @@ var Services = {
|
|
|
4026
4427
|
}
|
|
4027
4428
|
};
|
|
4028
4429
|
|
|
4029
|
-
// src/hooks/useDebounce.ts
|
|
4030
|
-
var import_react25 = require("react");
|
|
4031
|
-
function useDebounce(value, delay = 500) {
|
|
4032
|
-
const [debouncedValue, setDebouncedValue] = (0, import_react25.useState)(value);
|
|
4033
|
-
(0, import_react25.useEffect)(() => {
|
|
4034
|
-
const timer = setTimeout(() => {
|
|
4035
|
-
setDebouncedValue(value);
|
|
4036
|
-
}, delay);
|
|
4037
|
-
return () => {
|
|
4038
|
-
clearTimeout(timer);
|
|
4039
|
-
};
|
|
4040
|
-
}, [value, delay]);
|
|
4041
|
-
return debouncedValue;
|
|
4042
|
-
}
|
|
4043
|
-
|
|
4044
4430
|
// src/hooks/index.ts
|
|
4045
4431
|
var Hooks = {
|
|
4046
4432
|
useDebounce
|
package/dist/index.mjs
CHANGED
|
@@ -1247,12 +1247,417 @@ var PublicLanguageSelector = () => {
|
|
|
1247
1247
|
] });
|
|
1248
1248
|
};
|
|
1249
1249
|
|
|
1250
|
+
// src/UI/components/inputs/SearchComponent.tsx
|
|
1251
|
+
import { useState as useState9, useEffect as useEffect5 } from "react";
|
|
1252
|
+
import { useTranslation as useTranslation3 } from "react-i18next";
|
|
1253
|
+
import { TextField as TextField3, InputAdornment as InputAdornment4, IconButton as IconButton5, Tooltip as Tooltip5 } from "@mui/material";
|
|
1254
|
+
import TranslateIcon2 from "@mui/icons-material/Translate";
|
|
1255
|
+
import ClearIcon2 from "@mui/icons-material/Clear";
|
|
1256
|
+
|
|
1257
|
+
// src/hooks/useDebounce.ts
|
|
1258
|
+
import { useEffect as useEffect4, useState as useState8 } from "react";
|
|
1259
|
+
function useDebounce(value, delay = 500) {
|
|
1260
|
+
const [debouncedValue, setDebouncedValue] = useState8(value);
|
|
1261
|
+
useEffect4(() => {
|
|
1262
|
+
const timer = setTimeout(() => {
|
|
1263
|
+
setDebouncedValue(value);
|
|
1264
|
+
}, delay);
|
|
1265
|
+
return () => {
|
|
1266
|
+
clearTimeout(timer);
|
|
1267
|
+
};
|
|
1268
|
+
}, [value, delay]);
|
|
1269
|
+
return debouncedValue;
|
|
1270
|
+
}
|
|
1271
|
+
|
|
1272
|
+
// src/UI/components/inputs/SearchComponent.tsx
|
|
1273
|
+
import { Fragment as Fragment7, jsx as jsx8, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
1274
|
+
var SearchComponent = ({
|
|
1275
|
+
overrideNamespace,
|
|
1276
|
+
label = "",
|
|
1277
|
+
value = "",
|
|
1278
|
+
onChange,
|
|
1279
|
+
onClear,
|
|
1280
|
+
placeholderKey,
|
|
1281
|
+
clearTooltip = "Clear",
|
|
1282
|
+
debounceDelay = 500,
|
|
1283
|
+
onDebounceChange,
|
|
1284
|
+
slotProps,
|
|
1285
|
+
...restProps
|
|
1286
|
+
}) => {
|
|
1287
|
+
const supabase = useSupabase();
|
|
1288
|
+
const namespace = useTranslationNamespace();
|
|
1289
|
+
const { t, i18n } = useTranslation3(namespace);
|
|
1290
|
+
const { isTranslationMode } = useTranslationEdit();
|
|
1291
|
+
const [isDialogOpen, setIsDialogOpen] = useState9(false);
|
|
1292
|
+
const [localValue, setLocalValue] = useState9(String(value ?? ""));
|
|
1293
|
+
const debouncedValue = useDebounce(localValue, debounceDelay);
|
|
1294
|
+
useEffect5(() => {
|
|
1295
|
+
setLocalValue(String(value ?? ""));
|
|
1296
|
+
}, [value]);
|
|
1297
|
+
useEffect5(() => {
|
|
1298
|
+
if (onDebounceChange) {
|
|
1299
|
+
onDebounceChange(debouncedValue);
|
|
1300
|
+
}
|
|
1301
|
+
if (onChange && debouncedValue !== String(value ?? "")) {
|
|
1302
|
+
const syntheticEvent = {
|
|
1303
|
+
target: { value: debouncedValue },
|
|
1304
|
+
currentTarget: { value: debouncedValue }
|
|
1305
|
+
};
|
|
1306
|
+
onChange(syntheticEvent);
|
|
1307
|
+
}
|
|
1308
|
+
}, [debouncedValue]);
|
|
1309
|
+
const hasValue = localValue.length > 0;
|
|
1310
|
+
const handleChange = (e) => {
|
|
1311
|
+
setLocalValue(e.target.value);
|
|
1312
|
+
};
|
|
1313
|
+
const handleClear = (e) => {
|
|
1314
|
+
e.stopPropagation();
|
|
1315
|
+
setLocalValue("");
|
|
1316
|
+
if (onClear) {
|
|
1317
|
+
onClear();
|
|
1318
|
+
}
|
|
1319
|
+
if (onChange) {
|
|
1320
|
+
const syntheticEvent = {
|
|
1321
|
+
...e,
|
|
1322
|
+
target: { ...e.target, value: "" },
|
|
1323
|
+
currentTarget: { ...e.currentTarget, value: "" }
|
|
1324
|
+
};
|
|
1325
|
+
onChange(syntheticEvent);
|
|
1326
|
+
}
|
|
1327
|
+
};
|
|
1328
|
+
const translatedPlaceholder = placeholderKey ? t(placeholderKey) : void 0;
|
|
1329
|
+
const handleSaveTranslations = async (newValues, contextHint) => {
|
|
1330
|
+
if (!placeholderKey) return;
|
|
1331
|
+
const upsertData = Object.entries(newValues).map(([langCode, text]) => ({
|
|
1332
|
+
lang_code: langCode,
|
|
1333
|
+
namespace,
|
|
1334
|
+
key: placeholderKey,
|
|
1335
|
+
value: text,
|
|
1336
|
+
context_hint: contextHint
|
|
1337
|
+
}));
|
|
1338
|
+
const { error } = await supabase.from("translations").upsert(upsertData, { onConflict: "lang_code,namespace,key" });
|
|
1339
|
+
if (error) {
|
|
1340
|
+
alert("\u041F\u043E\u043C\u0438\u043B\u043A\u0430 \u043F\u0456\u0434 \u0447\u0430\u0441 \u0437\u0431\u0435\u0440\u0435\u0436\u0435\u043D\u043D\u044F \u0432 \u0431\u0430\u0437\u0443 \u0434\u0430\u043D\u0438\u0445");
|
|
1341
|
+
throw error;
|
|
1342
|
+
}
|
|
1343
|
+
await translationService.incrementVersion(supabase, namespace, Object.keys(newValues));
|
|
1344
|
+
Object.entries(newValues).forEach(([langCode, text]) => {
|
|
1345
|
+
i18n.addResource(langCode, namespace, placeholderKey, text);
|
|
1346
|
+
});
|
|
1347
|
+
};
|
|
1348
|
+
const renderEndAdornment = () => {
|
|
1349
|
+
const rawInputProps = slotProps?.input;
|
|
1350
|
+
const isInputObject = typeof rawInputProps === "object" && rawInputProps !== null;
|
|
1351
|
+
const existingEndAdornment = isInputObject && "endAdornment" in rawInputProps ? rawInputProps.endAdornment : void 0;
|
|
1352
|
+
if (!hasValue && (!isTranslationMode || !placeholderKey)) {
|
|
1353
|
+
return existingEndAdornment;
|
|
1354
|
+
}
|
|
1355
|
+
return /* @__PURE__ */ jsxs7(Fragment7, { children: [
|
|
1356
|
+
existingEndAdornment,
|
|
1357
|
+
/* @__PURE__ */ jsxs7(InputAdornment4, { position: "end", children: [
|
|
1358
|
+
hasValue && /* @__PURE__ */ jsx8(TranslatableTooltipComponent, { title: /* @__PURE__ */ jsx8(TranslateText, { overrideNamespace, children: clearTooltip }), children: /* @__PURE__ */ jsx8(
|
|
1359
|
+
IconButton5,
|
|
1360
|
+
{
|
|
1361
|
+
size: "small",
|
|
1362
|
+
onClick: handleClear,
|
|
1363
|
+
edge: "end",
|
|
1364
|
+
"aria-label": "clear input",
|
|
1365
|
+
children: /* @__PURE__ */ jsx8(ClearIcon2, { fontSize: "small" })
|
|
1366
|
+
}
|
|
1367
|
+
) }),
|
|
1368
|
+
isTranslationMode && placeholderKey && /* @__PURE__ */ jsx8(Tooltip5, { title: `Translate placeholder: "${placeholderKey}"`, children: /* @__PURE__ */ jsx8(
|
|
1369
|
+
IconButton5,
|
|
1370
|
+
{
|
|
1371
|
+
size: "small",
|
|
1372
|
+
onClick: (e) => {
|
|
1373
|
+
e.preventDefault();
|
|
1374
|
+
e.stopPropagation();
|
|
1375
|
+
setIsDialogOpen(true);
|
|
1376
|
+
},
|
|
1377
|
+
sx: {
|
|
1378
|
+
color: "#d97706",
|
|
1379
|
+
backgroundColor: "rgba(254, 243, 199, 0.6)",
|
|
1380
|
+
border: "1px dashed #f59e0b",
|
|
1381
|
+
p: "3px",
|
|
1382
|
+
ml: 0.5,
|
|
1383
|
+
"&:hover": {
|
|
1384
|
+
backgroundColor: "#fef08a"
|
|
1385
|
+
}
|
|
1386
|
+
},
|
|
1387
|
+
children: /* @__PURE__ */ jsx8(TranslateIcon2, { fontSize: "small" })
|
|
1388
|
+
}
|
|
1389
|
+
) })
|
|
1390
|
+
] })
|
|
1391
|
+
] });
|
|
1392
|
+
};
|
|
1393
|
+
return /* @__PURE__ */ jsxs7(Fragment7, { children: [
|
|
1394
|
+
/* @__PURE__ */ jsx8(
|
|
1395
|
+
TextField3,
|
|
1396
|
+
{
|
|
1397
|
+
...restProps,
|
|
1398
|
+
label: typeof label === "string" ? /* @__PURE__ */ jsx8(TranslateText, { overrideNamespace, children: label }) : label,
|
|
1399
|
+
value: localValue,
|
|
1400
|
+
onChange: handleChange,
|
|
1401
|
+
placeholder: translatedPlaceholder,
|
|
1402
|
+
slotProps: {
|
|
1403
|
+
...slotProps,
|
|
1404
|
+
input: {
|
|
1405
|
+
...slotProps?.input,
|
|
1406
|
+
endAdornment: renderEndAdornment()
|
|
1407
|
+
}
|
|
1408
|
+
}
|
|
1409
|
+
}
|
|
1410
|
+
),
|
|
1411
|
+
placeholderKey && /* @__PURE__ */ jsx8(
|
|
1412
|
+
TranslationDialog,
|
|
1413
|
+
{
|
|
1414
|
+
open: isDialogOpen,
|
|
1415
|
+
onClose: () => setIsDialogOpen(false),
|
|
1416
|
+
translationKey: placeholderKey,
|
|
1417
|
+
namespace,
|
|
1418
|
+
onSave: handleSaveTranslations
|
|
1419
|
+
}
|
|
1420
|
+
)
|
|
1421
|
+
] });
|
|
1422
|
+
};
|
|
1423
|
+
|
|
1424
|
+
// src/UI/components/inputs/SelectComponent.tsx
|
|
1425
|
+
import {
|
|
1426
|
+
FormControl,
|
|
1427
|
+
InputLabel,
|
|
1428
|
+
Select,
|
|
1429
|
+
MenuItem as MenuItem2,
|
|
1430
|
+
Checkbox,
|
|
1431
|
+
ListItemText,
|
|
1432
|
+
IconButton as IconButton6,
|
|
1433
|
+
InputAdornment as InputAdornment5,
|
|
1434
|
+
Tooltip as Tooltip6,
|
|
1435
|
+
FormHelperText
|
|
1436
|
+
} from "@mui/material";
|
|
1437
|
+
import CloseIcon from "@mui/icons-material/Close";
|
|
1438
|
+
import { jsx as jsx9, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
1439
|
+
var SelectComponent = ({
|
|
1440
|
+
overrideNamespace,
|
|
1441
|
+
label,
|
|
1442
|
+
value,
|
|
1443
|
+
options,
|
|
1444
|
+
onChange,
|
|
1445
|
+
id = "translated-select",
|
|
1446
|
+
fullWidth,
|
|
1447
|
+
size = "medium",
|
|
1448
|
+
multiple = false,
|
|
1449
|
+
withCheckboxes = false,
|
|
1450
|
+
clearable = true,
|
|
1451
|
+
maxSelect,
|
|
1452
|
+
disabled,
|
|
1453
|
+
maxDisplayedTags = 2,
|
|
1454
|
+
helperText,
|
|
1455
|
+
defaultValueOnClear,
|
|
1456
|
+
sx,
|
|
1457
|
+
...restProps
|
|
1458
|
+
}) => {
|
|
1459
|
+
const labelId = `${id}-label`;
|
|
1460
|
+
const safeValue = multiple ? Array.isArray(value) ? value : [] : value ?? "";
|
|
1461
|
+
const selectedArray = multiple ? safeValue : [];
|
|
1462
|
+
const isLimitReached = Boolean(multiple && maxSelect && selectedArray.length >= maxSelect);
|
|
1463
|
+
const hasValue = multiple ? selectedArray.length > 0 : safeValue !== "" && safeValue !== null && safeValue !== void 0;
|
|
1464
|
+
const handleChange = (event, child) => {
|
|
1465
|
+
if (multiple && maxSelect) {
|
|
1466
|
+
const newValue = event.target.value;
|
|
1467
|
+
if (newValue.length > maxSelect) {
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1470
|
+
}
|
|
1471
|
+
onChange?.(event, child);
|
|
1472
|
+
};
|
|
1473
|
+
const handleClear = (e) => {
|
|
1474
|
+
e.stopPropagation();
|
|
1475
|
+
if (!onChange) return;
|
|
1476
|
+
const emptyValue = multiple ? [] : "";
|
|
1477
|
+
const targetValue = defaultValueOnClear !== void 0 ? defaultValueOnClear : emptyValue;
|
|
1478
|
+
const syntheticEvent = {
|
|
1479
|
+
target: {
|
|
1480
|
+
value: targetValue,
|
|
1481
|
+
name: restProps.name
|
|
1482
|
+
}
|
|
1483
|
+
};
|
|
1484
|
+
onChange(syntheticEvent, null);
|
|
1485
|
+
};
|
|
1486
|
+
const renderValueHandler = (selected) => {
|
|
1487
|
+
if (!multiple) return void 0;
|
|
1488
|
+
const currentSelected = selected;
|
|
1489
|
+
if (currentSelected.length === 0) return null;
|
|
1490
|
+
const selectedOptions = options.filter((opt) => currentSelected.includes(opt.value));
|
|
1491
|
+
const visibleLabels = selectedOptions.slice(0, maxDisplayedTags).map((opt) => typeof opt.label === "string" ? opt.label : String(opt.value));
|
|
1492
|
+
const hiddenCount = selectedOptions.length - maxDisplayedTags;
|
|
1493
|
+
if (hiddenCount > 0) {
|
|
1494
|
+
return `${visibleLabels.join(", ")} (+${hiddenCount})`;
|
|
1495
|
+
}
|
|
1496
|
+
return visibleLabels.join(", ");
|
|
1497
|
+
};
|
|
1498
|
+
const isSmall = size === "small";
|
|
1499
|
+
return /* @__PURE__ */ jsx9(
|
|
1500
|
+
Tooltip6,
|
|
1501
|
+
{
|
|
1502
|
+
title: multiple ? Array.isArray(value) ? options.filter((opt) => value.includes(opt.value)).map((opt) => typeof opt.label === "string" ? opt.label : String(opt.value)).join(", ") : "" : options.find((opt) => opt.value === value)?.label ?? String(value ?? ""),
|
|
1503
|
+
children: /* @__PURE__ */ jsxs8(FormControl, { fullWidth, size, sx: { mt: 1 }, children: [
|
|
1504
|
+
/* @__PURE__ */ jsx9(InputLabel, { id: labelId, size: isSmall ? "small" : "medium", children: typeof label === "string" ? /* @__PURE__ */ jsx9(TranslateText, { overrideNamespace, children: label }) : label }),
|
|
1505
|
+
/* @__PURE__ */ jsx9(
|
|
1506
|
+
Select,
|
|
1507
|
+
{
|
|
1508
|
+
labelId,
|
|
1509
|
+
id,
|
|
1510
|
+
value: safeValue,
|
|
1511
|
+
label: typeof label === "string" ? /* @__PURE__ */ jsx9(TranslateText, { overrideNamespace, children: label }) : label,
|
|
1512
|
+
size,
|
|
1513
|
+
multiple,
|
|
1514
|
+
disabled,
|
|
1515
|
+
onChange: handleChange,
|
|
1516
|
+
renderValue: multiple ? renderValueHandler : void 0,
|
|
1517
|
+
...restProps,
|
|
1518
|
+
endAdornment: clearable && hasValue && !disabled ? /* @__PURE__ */ jsx9(InputAdornment5, { position: "end", sx: { mr: 1 }, children: /* @__PURE__ */ jsx9(
|
|
1519
|
+
IconButton6,
|
|
1520
|
+
{
|
|
1521
|
+
size: "small",
|
|
1522
|
+
onClick: handleClear,
|
|
1523
|
+
"aria-label": "clear selection",
|
|
1524
|
+
edge: "end",
|
|
1525
|
+
sx: { p: 0.5 },
|
|
1526
|
+
children: /* @__PURE__ */ jsx9(CloseIcon, { fontSize: "small" })
|
|
1527
|
+
}
|
|
1528
|
+
) }) : null,
|
|
1529
|
+
sx: {
|
|
1530
|
+
// 1. Задаем фиксированную высоту для всего контейнера инпута
|
|
1531
|
+
height: isSmall ? "40px" : "56px",
|
|
1532
|
+
minHeight: isSmall ? "40px" : "56px",
|
|
1533
|
+
// 2. Выравниваем внутренний класс текстового поля
|
|
1534
|
+
"& .MuiSelect-select": {
|
|
1535
|
+
display: "flex",
|
|
1536
|
+
alignItems: "center",
|
|
1537
|
+
boxSizing: "border-box",
|
|
1538
|
+
height: "100%",
|
|
1539
|
+
minHeight: "100% !important",
|
|
1540
|
+
py: 0,
|
|
1541
|
+
lineHeight: "normal",
|
|
1542
|
+
overflow: "hidden",
|
|
1543
|
+
textOverflow: "ellipsis",
|
|
1544
|
+
whiteSpace: "nowrap",
|
|
1545
|
+
paddingRight: clearable && hasValue ? "64px !important" : "32px !important"
|
|
1546
|
+
},
|
|
1547
|
+
// 3. Корректируем иконку стрелки выпадающего списка
|
|
1548
|
+
"& .MuiSelect-icon": {
|
|
1549
|
+
top: "calc(50% - 12px)"
|
|
1550
|
+
},
|
|
1551
|
+
// 4. Корректируем расположение иконки очистки
|
|
1552
|
+
"& .MuiInputAdornment-root": {
|
|
1553
|
+
maxHeight: "100%",
|
|
1554
|
+
height: "100%",
|
|
1555
|
+
alignItems: "center"
|
|
1556
|
+
},
|
|
1557
|
+
...sx
|
|
1558
|
+
},
|
|
1559
|
+
children: options.map((option) => {
|
|
1560
|
+
const isSelected = multiple && selectedArray.includes(option.value);
|
|
1561
|
+
const isDisabled = Boolean(isLimitReached && !isSelected);
|
|
1562
|
+
return /* @__PURE__ */ jsxs8(
|
|
1563
|
+
MenuItem2,
|
|
1564
|
+
{
|
|
1565
|
+
value: option.value,
|
|
1566
|
+
disabled: isDisabled,
|
|
1567
|
+
children: [
|
|
1568
|
+
multiple && withCheckboxes && /* @__PURE__ */ jsx9(Checkbox, { checked: isSelected, size, disabled: isDisabled }),
|
|
1569
|
+
/* @__PURE__ */ jsx9(
|
|
1570
|
+
ListItemText,
|
|
1571
|
+
{
|
|
1572
|
+
primary: option.isItalic ? /* @__PURE__ */ jsx9("em", { children: option.label }) : option.label
|
|
1573
|
+
}
|
|
1574
|
+
)
|
|
1575
|
+
]
|
|
1576
|
+
},
|
|
1577
|
+
String(option.value)
|
|
1578
|
+
);
|
|
1579
|
+
})
|
|
1580
|
+
}
|
|
1581
|
+
),
|
|
1582
|
+
helperText && /* @__PURE__ */ jsx9(FormHelperText, { children: helperText })
|
|
1583
|
+
] })
|
|
1584
|
+
}
|
|
1585
|
+
);
|
|
1586
|
+
};
|
|
1587
|
+
|
|
1588
|
+
// src/UI/components/data.display/ExpandableNoteComponent.tsx
|
|
1589
|
+
import { useState as useState10 } from "react";
|
|
1590
|
+
import { Typography as Typography5, Link } from "@mui/material";
|
|
1591
|
+
import { Fragment as Fragment8, jsx as jsx10, jsxs as jsxs9 } from "react/jsx-runtime";
|
|
1592
|
+
var ExpandableNoteComponent = ({
|
|
1593
|
+
overrideNamespace,
|
|
1594
|
+
text,
|
|
1595
|
+
maxLength = 100,
|
|
1596
|
+
label,
|
|
1597
|
+
sx,
|
|
1598
|
+
...restProps
|
|
1599
|
+
}) => {
|
|
1600
|
+
const [isExpanded, setIsExpanded] = useState10(false);
|
|
1601
|
+
if (!text) return null;
|
|
1602
|
+
const isLong = text.length > maxLength;
|
|
1603
|
+
const displayedText = isExpanded || !isLong ? text : `${text.slice(0, maxLength).trim()}...`;
|
|
1604
|
+
const toggleExpand = (e) => {
|
|
1605
|
+
e.stopPropagation();
|
|
1606
|
+
setIsExpanded((prev) => !prev);
|
|
1607
|
+
};
|
|
1608
|
+
return /* @__PURE__ */ jsxs9(
|
|
1609
|
+
Typography5,
|
|
1610
|
+
{
|
|
1611
|
+
variant: "caption",
|
|
1612
|
+
sx: {
|
|
1613
|
+
color: "text.secondary",
|
|
1614
|
+
fontStyle: "italic",
|
|
1615
|
+
display: "inline-block",
|
|
1616
|
+
...sx
|
|
1617
|
+
},
|
|
1618
|
+
...restProps,
|
|
1619
|
+
children: [
|
|
1620
|
+
label !== void 0 ? label : /* @__PURE__ */ jsxs9(Fragment8, { children: [
|
|
1621
|
+
/* @__PURE__ */ jsx10(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "Note" }),
|
|
1622
|
+
": "
|
|
1623
|
+
] }),
|
|
1624
|
+
" ",
|
|
1625
|
+
displayedText,
|
|
1626
|
+
" ",
|
|
1627
|
+
isLong && /* @__PURE__ */ jsx10(
|
|
1628
|
+
Link,
|
|
1629
|
+
{
|
|
1630
|
+
component: "button",
|
|
1631
|
+
type: "button",
|
|
1632
|
+
variant: "caption",
|
|
1633
|
+
underline: "hover",
|
|
1634
|
+
onClick: toggleExpand,
|
|
1635
|
+
sx: {
|
|
1636
|
+
fontStyle: "normal",
|
|
1637
|
+
fontWeight: "bold",
|
|
1638
|
+
ml: 0.5,
|
|
1639
|
+
cursor: "pointer",
|
|
1640
|
+
verticalAlign: "baseline"
|
|
1641
|
+
},
|
|
1642
|
+
children: isExpanded ? /* @__PURE__ */ jsx10(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "less" }) : /* @__PURE__ */ jsxs9(Fragment8, { children: [
|
|
1643
|
+
/* @__PURE__ */ jsx10(TranslateText, { overrideNamespace: overrideNamespace || "form_components", children: "more" }),
|
|
1644
|
+
"..."
|
|
1645
|
+
] })
|
|
1646
|
+
}
|
|
1647
|
+
)
|
|
1648
|
+
]
|
|
1649
|
+
}
|
|
1650
|
+
);
|
|
1651
|
+
};
|
|
1652
|
+
|
|
1250
1653
|
// src/UI/index.ts
|
|
1251
1654
|
var UI = {
|
|
1252
1655
|
Inputs: {
|
|
1253
1656
|
TextField: TextFieldComponent,
|
|
1254
1657
|
NumberField: NumberInputComponent,
|
|
1255
1658
|
EmailField: EmailInputComponent,
|
|
1659
|
+
Search: SearchComponent,
|
|
1660
|
+
Select: SelectComponent,
|
|
1256
1661
|
Url: UrlComponent
|
|
1257
1662
|
},
|
|
1258
1663
|
Buttons: {
|
|
@@ -1264,7 +1669,8 @@ var UI = {
|
|
|
1264
1669
|
UserPopover: UserPopoverComponent_default,
|
|
1265
1670
|
UserRoleChip: UserRoleChipComponent,
|
|
1266
1671
|
UserStatusChip: UserStatusChipComponent,
|
|
1267
|
-
MyAvatar: MyAvatarComponent
|
|
1672
|
+
MyAvatar: MyAvatarComponent,
|
|
1673
|
+
ExpandableNote: ExpandableNoteComponent
|
|
1268
1674
|
},
|
|
1269
1675
|
/*Layout: {
|
|
1270
1676
|
Row: FormRow,
|
|
@@ -1289,21 +1695,6 @@ var Services = {
|
|
|
1289
1695
|
}
|
|
1290
1696
|
};
|
|
1291
1697
|
|
|
1292
|
-
// src/hooks/useDebounce.ts
|
|
1293
|
-
import { useEffect as useEffect4, useState as useState8 } from "react";
|
|
1294
|
-
function useDebounce(value, delay = 500) {
|
|
1295
|
-
const [debouncedValue, setDebouncedValue] = useState8(value);
|
|
1296
|
-
useEffect4(() => {
|
|
1297
|
-
const timer = setTimeout(() => {
|
|
1298
|
-
setDebouncedValue(value);
|
|
1299
|
-
}, delay);
|
|
1300
|
-
return () => {
|
|
1301
|
-
clearTimeout(timer);
|
|
1302
|
-
};
|
|
1303
|
-
}, [value, delay]);
|
|
1304
|
-
return debouncedValue;
|
|
1305
|
-
}
|
|
1306
|
-
|
|
1307
1698
|
// src/hooks/index.ts
|
|
1308
1699
|
var Hooks = {
|
|
1309
1700
|
useDebounce
|