@serhii.olishevskyi/docs 1.1.5 → 1.1.7
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 +43 -2
- package/dist/index.d.ts +43 -2
- package/dist/index.js +341 -0
- package/dist/index.mjs +346 -0
- 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 } 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
|
/** Текст, який буде скопійовано в буфер обміну */
|
|
@@ -196,6 +229,8 @@ declare const UI: {
|
|
|
196
229
|
TextField: React$1.FC<TextFieldComponentProps>;
|
|
197
230
|
NumberField: React$1.FC<NumberInputComponentProps>;
|
|
198
231
|
EmailField: React$1.FC<EmailInputComponentProps>;
|
|
232
|
+
Search: React$1.FC<SearchComponentProps>;
|
|
233
|
+
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
234
|
Url: typeof UrlComponent;
|
|
200
235
|
};
|
|
201
236
|
Buttons: {
|
|
@@ -528,4 +563,10 @@ declare const Services: {
|
|
|
528
563
|
};
|
|
529
564
|
};
|
|
530
565
|
|
|
531
|
-
|
|
566
|
+
declare function useDebounce<T>(value: T, delay?: number): T;
|
|
567
|
+
|
|
568
|
+
declare const Hooks: {
|
|
569
|
+
readonly useDebounce: typeof useDebounce;
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
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, Hooks, type Language, LocalizationProvider, type MyAvatarComponentProps, type NumberInputComponentProps, Providers, type SearchComponentProps, type SelectComponentProps, 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 } 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
|
/** Текст, який буде скопійовано в буфер обміну */
|
|
@@ -196,6 +229,8 @@ declare const UI: {
|
|
|
196
229
|
TextField: React$1.FC<TextFieldComponentProps>;
|
|
197
230
|
NumberField: React$1.FC<NumberInputComponentProps>;
|
|
198
231
|
EmailField: React$1.FC<EmailInputComponentProps>;
|
|
232
|
+
Search: React$1.FC<SearchComponentProps>;
|
|
233
|
+
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
234
|
Url: typeof UrlComponent;
|
|
200
235
|
};
|
|
201
236
|
Buttons: {
|
|
@@ -528,4 +563,10 @@ declare const Services: {
|
|
|
528
563
|
};
|
|
529
564
|
};
|
|
530
565
|
|
|
531
|
-
|
|
566
|
+
declare function useDebounce<T>(value: T, delay?: number): T;
|
|
567
|
+
|
|
568
|
+
declare const Hooks: {
|
|
569
|
+
readonly useDebounce: typeof useDebounce;
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
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, Hooks, type Language, LocalizationProvider, type MyAvatarComponentProps, type NumberInputComponentProps, Providers, type SearchComponentProps, type SelectComponentProps, 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
|
@@ -2748,6 +2748,7 @@ __export(index_exports, {
|
|
|
2748
2748
|
AuthProvider: () => AuthProvider,
|
|
2749
2749
|
BreadcrumbProvider: () => BreadcrumbProvider,
|
|
2750
2750
|
ConfirmationProvider: () => ConfirmationProvider,
|
|
2751
|
+
Hooks: () => Hooks,
|
|
2751
2752
|
LocalizationProvider: () => LocalizationProvider,
|
|
2752
2753
|
Providers: () => Providers,
|
|
2753
2754
|
Services: () => Services,
|
|
@@ -3978,12 +3979,346 @@ var PublicLanguageSelector = () => {
|
|
|
3978
3979
|
] });
|
|
3979
3980
|
};
|
|
3980
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
|
+
|
|
3981
4314
|
// src/UI/index.ts
|
|
3982
4315
|
var UI = {
|
|
3983
4316
|
Inputs: {
|
|
3984
4317
|
TextField: TextFieldComponent,
|
|
3985
4318
|
NumberField: NumberInputComponent,
|
|
3986
4319
|
EmailField: EmailInputComponent,
|
|
4320
|
+
Search: SearchComponent,
|
|
4321
|
+
Select: SelectComponent,
|
|
3987
4322
|
Url: UrlComponent
|
|
3988
4323
|
},
|
|
3989
4324
|
Buttons: {
|
|
@@ -4024,6 +4359,11 @@ var Services = {
|
|
|
4024
4359
|
getUsersLastSeenMap
|
|
4025
4360
|
}
|
|
4026
4361
|
};
|
|
4362
|
+
|
|
4363
|
+
// src/hooks/index.ts
|
|
4364
|
+
var Hooks = {
|
|
4365
|
+
useDebounce
|
|
4366
|
+
};
|
|
4027
4367
|
// Annotate the CommonJS export names for ESM import in node:
|
|
4028
4368
|
0 && (module.exports = {
|
|
4029
4369
|
AIProvider,
|
|
@@ -4031,6 +4371,7 @@ var Services = {
|
|
|
4031
4371
|
AuthProvider,
|
|
4032
4372
|
BreadcrumbProvider,
|
|
4033
4373
|
ConfirmationProvider,
|
|
4374
|
+
Hooks,
|
|
4034
4375
|
LocalizationProvider,
|
|
4035
4376
|
Providers,
|
|
4036
4377
|
Services,
|
package/dist/index.mjs
CHANGED
|
@@ -1247,12 +1247,352 @@ 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
|
+
|
|
1250
1588
|
// src/UI/index.ts
|
|
1251
1589
|
var UI = {
|
|
1252
1590
|
Inputs: {
|
|
1253
1591
|
TextField: TextFieldComponent,
|
|
1254
1592
|
NumberField: NumberInputComponent,
|
|
1255
1593
|
EmailField: EmailInputComponent,
|
|
1594
|
+
Search: SearchComponent,
|
|
1595
|
+
Select: SelectComponent,
|
|
1256
1596
|
Url: UrlComponent
|
|
1257
1597
|
},
|
|
1258
1598
|
Buttons: {
|
|
@@ -1288,12 +1628,18 @@ var Services = {
|
|
|
1288
1628
|
getUsersLastSeenMap
|
|
1289
1629
|
}
|
|
1290
1630
|
};
|
|
1631
|
+
|
|
1632
|
+
// src/hooks/index.ts
|
|
1633
|
+
var Hooks = {
|
|
1634
|
+
useDebounce
|
|
1635
|
+
};
|
|
1291
1636
|
export {
|
|
1292
1637
|
AIProvider,
|
|
1293
1638
|
AppSettingsProvider,
|
|
1294
1639
|
AuthProvider,
|
|
1295
1640
|
BreadcrumbProvider,
|
|
1296
1641
|
ConfirmationProvider,
|
|
1642
|
+
Hooks,
|
|
1297
1643
|
LocalizationProvider,
|
|
1298
1644
|
Providers,
|
|
1299
1645
|
Services,
|