@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 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 as CopyClipboardButtonProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps as EmailInputProps, Hooks, type Language, LocalizationProvider, type MyAvatarComponentProps as MyAvatarProps, type NumberInputComponentProps as NumberInputProps, Providers, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps as TextFieldProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps as TranslatableTooltipProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps as UserAvatarProps, type UserGroupedSessions, type UserPopoverComponentProps as UserPopoverProps, type UserRoleChipComponentProps as UserRoleChipProps, type UserSessionItem, UserSettingsProvider, type UserStatusChipComponentProps as UserStatusChipProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
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 as CopyClipboardButtonProps, type DialogSeverity, type DisplayState, type EmailInputComponentProps as EmailInputProps, Hooks, type Language, LocalizationProvider, type MyAvatarComponentProps as MyAvatarProps, type NumberInputComponentProps as NumberInputProps, Providers, Services, type SupabaseConfig, SupabaseProvider, type SupabaseProviderProps, type TextFieldComponentProps as TextFieldProps, type ThemeColors, type ThemeConfig, type ThemeMode, ThemeProvider, ToastProvider, type ToastType, type TranslatableTooltipComponentProps as TranslatableTooltipProps, TranslateProvider, TranslateText, TranslationEditProvider, type TypographyConfig, UI, type UrlComponentProps as UrlProps, type UserAvatarComponentProps as UserAvatarProps, type UserGroupedSessions, type UserPopoverComponentProps as UserPopoverProps, type UserRoleChipComponentProps as UserRoleChipProps, type UserSessionItem, UserSettingsProvider, type UserStatusChipComponentProps as UserStatusChipProps, useAI, useAppSettings, useAppTheme, useAuth, useBreadcrumb, useConfirmation, useLocalization, useSupabase, useToast, useTranslationEdit, useTranslationNamespace, useUserSettings };
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
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@serhii.olishevskyi/docs",
3
- "version": "1.1.6",
3
+ "version": "1.1.8",
4
4
  "description": "DOCS.UA react packages",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",