@andreyfedkovich/cozy-ui 0.3.0 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -31,7 +31,7 @@ npm i @andreyfedkovich/cozy-ui
31
31
  - [Design tokens](#design-tokens)
32
32
  - [Component API](#component-api)
33
33
  - [Layout & content](#layout--content) — `BaseBlock`, `Card`, `CollapsableBlock`, `Collapse`, `Carousel`, `EmptyComponent`, `Spinner`
34
- - [Inputs & forms](#inputs--forms) — `Button`, `RadioGroupButton`, `Select`, `DialogSelect`, `TreeDialogSelect`, `InputCaption`, `Label`
34
+ - [Inputs & forms](#inputs--forms) — `Button`, `RadioGroupButton`, `Input`, `Calendar`, `Checkbox`, `Select`, `DialogSelect`, `TreeDialogSelect`, `InputCaption`, `Label`
35
35
  - [Navigation](#navigation) — `Tabs`, `TabsRounded`, `Stepper`
36
36
  - [Overlays](#overlays) — `Popover`, `TooltipDark`, `TooltipLight`
37
37
  - [Utility](#utility) — `Tag`, `CopyTextTrigger`
@@ -312,6 +312,121 @@ const [view, setView] = useState<"grid" | "list">("grid");
312
312
  />;
313
313
  ```
314
314
 
315
+ #### `Input`
316
+
317
+ Accessible text field with optional label and validation message for product forms.
318
+
319
+ | Prop | Type | Default | Description |
320
+ | ---------------- | --------------------------------------- | ------- | ------------------------------------ |
321
+ | `label` | `ReactNode` | — | Field label above the input. |
322
+ | `tooltipContent` | `ReactNode` | — | Help tooltip on the «?» icon next to the label. |
323
+ | `tooltipPopperClassName` | `string` | — | Extra class for the tooltip popper. |
324
+ | `error` | `string \| null` | — | Validation message under the input. |
325
+ | `disabled` | `boolean` | `false` | Disabled state. |
326
+ | `className` | `string` | — | Wrapper class. |
327
+ | `inputClassName` | `string` | — | Native `<input>` class. |
328
+ | `...rest` | `InputHTMLAttributes<HTMLInputElement>` | — | All native input props. |
329
+
330
+ ```tsx
331
+ import { Input } from "@andreyfedkovich/cozy-ui";
332
+ import { useState } from "react";
333
+
334
+ const [email, setEmail] = useState("");
335
+
336
+ <Input
337
+ label="Email"
338
+ placeholder="you@company.com"
339
+ value={email}
340
+ onChange={(e) => setEmail(e.target.value)}
341
+ />;
342
+
343
+ <Input
344
+ label="Password"
345
+ type="password"
346
+ error="Minimum 8 characters."
347
+ />;
348
+ ```
349
+
350
+ #### `Calendar`
351
+
352
+ Date picker field for forms. Value is stored as `yyyy-MM-dd` (or `null`); the trigger shows `dd.MM.yyyy`. Includes helpers for parsing and serializing local calendar days.
353
+
354
+ | Prop | Type | Default | Description |
355
+ | ------------------------- | --------------------------------- | ------- | -------------------------------------------------------- |
356
+ | `label` | `string` | — | Field label. |
357
+ | `required` | `boolean` | `false` | Appends ` *` to the label. |
358
+ | `value` | `string \| null` | — | Selected date as `yyyy-MM-dd`. |
359
+ | `onChange` | `(value: string \| null) => void` | — | Called when the user picks or clears a date. |
360
+ | `minDate` | `Date` | — | Earliest selectable day (inclusive, local calendar). |
361
+ | `error` | `string \| null` | — | Validation message under the field. |
362
+ | `disabled` | `boolean` | `false` | Disables the trigger. |
363
+ | `tooltipContent` | `ReactNode` | — | Help tooltip on the «i» icon next to the label. |
364
+ | `tooltipPopperClassName` | `string` | — | Extra class for the tooltip popper. |
365
+ | `className` | `string` | — | Wrapper class. |
366
+
367
+ Exported utilities: `startOfLocalDay`, `todayLocalDay`, `toYmdString`, `parseYmdToLocalDay`.
368
+
369
+ ```tsx
370
+ import {
371
+ Calendar,
372
+ todayLocalDay,
373
+ } from "@andreyfedkovich/cozy-ui";
374
+ import { useState } from "react";
375
+
376
+ const [startDate, setStartDate] = useState<string | null>(null);
377
+
378
+ <Calendar
379
+ label="Дата начала"
380
+ required
381
+ value={startDate}
382
+ onChange={setStartDate}
383
+ minDate={todayLocalDay()}
384
+ />;
385
+
386
+ <Calendar
387
+ label="Дедлайн"
388
+ value={startDate}
389
+ onChange={setStartDate}
390
+ error="Укажите дату."
391
+ tooltipContent="Дата должна быть не раньше сегодня."
392
+ />;
393
+ ```
394
+
395
+ #### `Checkbox`
396
+
397
+ Accessible checkbox with a custom premium box, optional inline label, and validation message.
398
+
399
+ | Prop | Type | Default | Description |
400
+ | ------------------- | -------------------------------------------- | ------- | ---------------------------------------- |
401
+ | `label` | `ReactNode` | — | Label text to the right of the checkbox. |
402
+ | `error` | `string \| null` | — | Validation message under the control. |
403
+ | `disabled` | `boolean` | `false` | Disabled state. |
404
+ | `className` | `string` | — | Wrapper class. |
405
+ | `checkboxClassName` | `string` | — | Class on the visual checkbox box. |
406
+ | `...rest` | `Omit<InputHTMLAttributes<HTMLInputElement>, "type">` | — | All native checkbox props (`checked`, `onChange`, `name`, etc.). |
407
+
408
+ ```tsx
409
+ import { Checkbox } from "@andreyfedkovich/cozy-ui";
410
+ import { useState } from "react";
411
+
412
+ const [agreed, setAgreed] = useState(false);
413
+
414
+ <Checkbox
415
+ label="Согласен с условиями обработки данных"
416
+ checked={agreed}
417
+ onChange={(e) => setAgreed(e.target.checked)}
418
+ />;
419
+
420
+ <Checkbox label="Уведомления по email" defaultChecked disabled />;
421
+
422
+ <Checkbox
423
+ label="Обязательное согласие"
424
+ checked={agreed}
425
+ onChange={(e) => setAgreed(e.target.checked)}
426
+ error={agreed ? null : "Необходимо принять условия."}
427
+ />;
428
+ ```
429
+
315
430
  #### `Select`
316
431
 
317
432
  Powerful, virtualized-friendly select with `single` and `multiple` modes, search, custom rendering, and table layout.
@@ -327,7 +442,9 @@ Powerful, virtualized-friendly select with `single` and `multiple` modes, search
327
442
  | `columns` | `SelectColumn[]` | — | Required when `template="table"`. |
328
443
  | `isLoading` | `boolean` | `false` | Show loading state in dropdown. |
329
444
  | `error` | `string \| null` | — | Validation message. |
330
- | `label` | `ReactNode` | — | Field label. |
445
+ | `label` | `ReactNode` | — | Field label. |
446
+ | `tooltipContent` | `ReactNode` | — | Help tooltip on the «?» icon next to the label. |
447
+ | `tooltipPopperClassName` | `string` | — | Extra class for the tooltip popper. |
331
448
 
332
449
  ```tsx
333
450
  import { Select, type CustomOption } from "@andreyfedkovich/cozy-ui";
@@ -354,6 +471,12 @@ const [value, setValue] = useState<CustomOption<unknown, string> | null>(null);
354
471
 
355
472
  Dialog-based picker for large datasets — search + paginated loading + multi-select.
356
473
 
474
+ | Prop | Type | Description |
475
+ | ------------------------ | ----------- | ----------------------------------------------- |
476
+ | `label` | `ReactNode` | Field label above the trigger. |
477
+ | `tooltipContent` | `ReactNode` | Help tooltip on the «?» icon next to the label. |
478
+ | `tooltipPopperClassName` | `string` | Extra class for the tooltip popper. |
479
+
357
480
  ```tsx
358
481
  import { DialogSelect } from "@andreyfedkovich/cozy-ui";
359
482
 
@@ -373,6 +496,12 @@ import { DialogSelect } from "@andreyfedkovich/cozy-ui";
373
496
 
374
497
  Hierarchical picker with lazy-loaded branches and search.
375
498
 
499
+ | Prop | Type | Description |
500
+ | ------------------------ | ----------- | ----------------------------------------------- |
501
+ | `label` | `ReactNode` | Field label above the trigger. |
502
+ | `tooltipContent` | `ReactNode` | Help tooltip on the «?» icon next to the label. |
503
+ | `tooltipPopperClassName` | `string` | Extra class for the tooltip popper. |
504
+
376
505
  ```tsx
377
506
  import { TreeDialogSelect } from "@andreyfedkovich/cozy-ui";
378
507
 
@@ -25,6 +25,7 @@ import { default as FileReloadIcon } from './fileReload.svg?react';
25
25
  import { default as FileSync } from './fileSync.svg?react';
26
26
  import { default as FilterIcon } from './filter.svg?react';
27
27
  import { default as FolderEditIcon } from './folderEdit.svg?react';
28
+ import { ForwardRefExoticComponent } from 'react';
28
29
  import { default as GraduateIcon } from './graduate.svg?react';
29
30
  import { default as GridIcon } from './grid.svg?react';
30
31
  import { default as HeartIcon } from './heart.svg?react';
@@ -33,6 +34,7 @@ import { default as HistoryBlue } from './historyBlue.svg?react';
33
34
  import { default as HomeIcon } from './home.svg?react';
34
35
  import { HTMLAttributes } from 'react';
35
36
  import { default as InfoIcon } from './info.svg?react';
37
+ import { InputHTMLAttributes } from 'react';
36
38
  import { default as IslandIcon } from './island.svg?react';
37
39
  import { JSX } from 'react/jsx-runtime';
38
40
  import { default as ListIcon } from './list.svg?react';
@@ -48,6 +50,7 @@ import { default as ProfileSearchIcon } from './profileSearch.svg?react';
48
50
  import { PropsWithChildren } from 'react';
49
51
  import * as React_2 from 'react';
50
52
  import { ReactNode } from 'react';
53
+ import { RefAttributes } from 'react';
51
54
  import { RefObject } from 'react';
52
55
  import { default as ReloadIcon } from './reload.svg?react';
53
56
  import { default as SchoolIcon } from './school.svg?react';
@@ -131,6 +134,23 @@ declare type ButtonSize = "small" | "medium" | "large";
131
134
 
132
135
  declare type ButtonVariant = "default" | "primary" | "secondary" | "text" | "link" | "danger";
133
136
 
137
+ export declare const Calendar: ({ label, required, value, onChange, minDate, error, disabled, tooltipContent, tooltipPopperClassName, className, }: CalendarProps) => JSX.Element;
138
+
139
+ export declare interface CalendarProps {
140
+ label: string;
141
+ required?: boolean;
142
+ value?: string | null;
143
+ onChange: (value: string | null) => void;
144
+ /** Нижняя граница выбора (включительно), локальный календарный день */
145
+ minDate?: Date;
146
+ error?: string | null;
147
+ disabled?: boolean;
148
+ /** Подсказка по наведению на иконку «?» справа от подписи */
149
+ tooltipContent?: ReactNode;
150
+ tooltipPopperClassName?: string;
151
+ className?: string;
152
+ }
153
+
134
154
  export { CameraIcon }
135
155
 
136
156
  export { CancelIcon }
@@ -178,6 +198,14 @@ export { ChartIcon }
178
198
 
179
199
  export { ChatIcon }
180
200
 
201
+ export declare const Checkbox: ForwardRefExoticComponent<CheckboxProps & RefAttributes<HTMLInputElement>>;
202
+
203
+ export declare interface CheckboxProps extends Omit<InputHTMLAttributes<HTMLInputElement>, "type"> {
204
+ label?: ReactNode;
205
+ error?: string | null;
206
+ checkboxClassName?: string;
207
+ }
208
+
181
209
  export { CheckGreen }
182
210
 
183
211
  export { ClockFilledIcon }
@@ -228,6 +256,100 @@ export declare enum Colors {
228
256
  YELLOW_02 = "#FFA300"
229
257
  }
230
258
 
259
+ declare type Comment_2 = {
260
+ id: string;
261
+ parentId: string | null;
262
+ author: CommentAuthor;
263
+ text: string;
264
+ createdAt: string;
265
+ editedAt?: string;
266
+ attachments?: CommentAttachment[];
267
+ recipients?: CommentAuthor[];
268
+ repliesCount: number;
269
+ deleted?: boolean;
270
+ permissions?: CommentPermissions;
271
+ };
272
+ export { Comment_2 as Comment }
273
+
274
+ export declare type CommentAttachment = {
275
+ id: string;
276
+ name: string;
277
+ size: number;
278
+ url?: string;
279
+ mimeType?: string;
280
+ };
281
+
282
+ export declare type CommentAuthor = {
283
+ id: string;
284
+ name: string;
285
+ avatarUrl?: string;
286
+ };
287
+
288
+ export declare type CommentEditInput = {
289
+ id: string;
290
+ text: string;
291
+ attachments: CommentAttachment[];
292
+ recipients: CommentAuthor[];
293
+ };
294
+
295
+ export declare const CommentFeed: default_2.ForwardRefExoticComponent<CommentFeedProps & default_2.RefAttributes<CommentFeedHandle>>;
296
+
297
+ export declare interface CommentFeedHandle {
298
+ refresh: (parentId?: string | null) => void;
299
+ }
300
+
301
+ export declare interface CommentFeedProps {
302
+ loadComments: (p: CommentLoadParams) => Promise<CommentLoadResult>;
303
+ currentUser: CommentAuthor;
304
+ recipientsSource?: (params: {
305
+ search: string;
306
+ page: number;
307
+ pageSize: number;
308
+ }) => Promise<{
309
+ options: CustomOption<CommentAuthor, string>[];
310
+ total?: number;
311
+ }>;
312
+ onCreate?: (input: CommentMutationInput) => Promise<Comment_2>;
313
+ onEdit?: (input: CommentEditInput) => Promise<Comment_2>;
314
+ onDelete?: (id: string) => Promise<void>;
315
+ onUploadAttachment?: (file: File) => Promise<CommentAttachment>;
316
+ onDownloadAttachment?: (a: CommentAttachment) => void;
317
+ onDeleteAttachment?: (a: CommentAttachment) => Promise<void>;
318
+ permissions?: {
319
+ canCreate?: boolean;
320
+ canReply?: boolean;
321
+ };
322
+ editWindowMs?: number;
323
+ pageSize?: number;
324
+ title?: string;
325
+ eyebrow?: string;
326
+ className?: string;
327
+ }
328
+
329
+ export declare type CommentLoadParams = {
330
+ parentId: string | null;
331
+ skip: number;
332
+ take: number;
333
+ };
334
+
335
+ export declare type CommentLoadResult = {
336
+ items: Comment_2[];
337
+ total: number;
338
+ };
339
+
340
+ export declare type CommentMutationInput = {
341
+ parentId: string | null;
342
+ text: string;
343
+ attachments: CommentAttachment[];
344
+ recipients: CommentAuthor[];
345
+ };
346
+
347
+ export declare type CommentPermissions = {
348
+ canEdit?: boolean;
349
+ canDelete?: boolean;
350
+ canReply?: boolean;
351
+ };
352
+
231
353
  export { CopyIcon }
232
354
 
233
355
  export declare const CopyTextTrigger: MemoExoticComponent<({ children, onClick, copied, tooltipText, ariaLabel, showIcon, iconOnly, className, }: CopyTextTriggerProps) => JSX.Element>;
@@ -273,6 +395,9 @@ declare type CustomSelectProps<T, S> = {
273
395
  onClear?: () => void;
274
396
  icon?: ReactNode;
275
397
  label?: ReactNode;
398
+ /** Подсказка по наведению на иконку «?» справа от подписи */
399
+ tooltipContent?: ReactNode;
400
+ tooltipPopperClassName?: string;
276
401
  onSearch?: (value: string) => void;
277
402
  isLoading?: boolean;
278
403
  disabled?: boolean;
@@ -346,7 +471,7 @@ export declare interface DetailViewProps {
346
471
  id?: string;
347
472
  }
348
473
 
349
- export declare const DialogSelect: <T, S extends string | number>({ value, placeholder, loadOptions, onChange, onClear, columns, label, title, searchPlaceholder, selectButtonText, closeButtonText, manualButtonText, onManualAdd, pageSize, debounceMs, disabled, error, className, inputClassName, selectedOptionRender, }: DialogSelectProps<T, S>) => JSX.Element;
474
+ export declare const DialogSelect: <T, S extends string | number>({ value, placeholder, loadOptions, onChange, onClear, columns, label, tooltipContent, tooltipPopperClassName, title, searchPlaceholder, selectButtonText, closeButtonText, manualButtonText, onManualAdd, pageSize, debounceMs, disabled, error, className, inputClassName, selectedOptionRender, }: DialogSelectProps<T, S>) => JSX.Element;
350
475
 
351
476
  export declare type DialogSelectColumn<T, S extends string | number> = {
352
477
  key: string;
@@ -363,6 +488,9 @@ export declare interface DialogSelectProps<T, S extends string | number> {
363
488
  onClear?: () => void;
364
489
  columns?: DialogSelectColumn<T, S>[];
365
490
  label?: ReactNode;
491
+ /** Подсказка по наведению на иконку «?» справа от подписи */
492
+ tooltipContent?: ReactNode;
493
+ tooltipPopperClassName?: string;
366
494
  title?: ReactNode;
367
495
  searchPlaceholder?: string;
368
496
  selectButtonText?: string;
@@ -438,6 +566,8 @@ export { HomeIcon }
438
566
 
439
567
  export { InfoIcon }
440
568
 
569
+ export declare const Input: ForwardRefExoticComponent<InputProps & RefAttributes<HTMLInputElement>>;
570
+
441
571
  export declare const InputCaption: React_2.FC<PropsWithChildren<InputCaptionProps>>;
442
572
 
443
573
  declare interface InputCaptionProps {
@@ -450,6 +580,15 @@ declare interface InputCaptionProps {
450
580
 
451
581
  export declare type InputCaptionVariant = "neutral" | "error" | "success";
452
582
 
583
+ export declare interface InputProps extends InputHTMLAttributes<HTMLInputElement> {
584
+ label?: ReactNode;
585
+ error?: string | null;
586
+ inputClassName?: string;
587
+ /** Подсказка по наведению на иконку «?» справа от подписи */
588
+ tooltipContent?: ReactNode;
589
+ tooltipPopperClassName?: string;
590
+ }
591
+
453
592
  export { IslandIcon }
454
593
 
455
594
  export declare const Label: ({ htmlFor, children, className }: LabelProps) => JSX.Element;
@@ -501,6 +640,8 @@ declare type ModeProps<T, S> = {
501
640
 
502
641
  export { NotebookIcon }
503
642
 
643
+ export declare const parseYmdToLocalDay: (value: string | null | undefined) => Date | undefined;
644
+
504
645
  export { PhoneIcon }
505
646
 
506
647
  export { PlaneIcon }
@@ -603,7 +744,7 @@ declare interface SectionComponentProps extends Omit<DetailSection, "fields"> {
603
744
  children?: ReactNode;
604
745
  }
605
746
 
606
- export declare const Select: <T, S extends string | number>({ options, value, mode, placeholder, onChange, dropdownRender, optionRender, selectedOptionRender, dropdownIcon, tagRender, dropDownClassName, optionClassName, inputClassName, deleteIconClassName, onDelete, onClear, label, onSearch, searchClassName, searchPlaceholder, isLoading, disabled, onClose, portalTarget, error, fixedHeight, template, columns, total, }: CustomSelectProps<T, S>) => JSX.Element;
747
+ export declare const Select: <T, S extends string | number>({ options, value, mode, placeholder, onChange, dropdownRender, optionRender, selectedOptionRender, dropdownIcon, tagRender, dropDownClassName, optionClassName, inputClassName, deleteIconClassName, onDelete, onClear, label, tooltipContent, tooltipPopperClassName, onSearch, searchClassName, searchPlaceholder, isLoading, disabled, onClose, portalTarget, error, fixedHeight, template, columns, total, }: CustomSelectProps<T, S>) => JSX.Element;
607
748
 
608
749
  export declare type SelectColumn<T, S> = {
609
750
  key: string;
@@ -618,6 +759,8 @@ export declare const Spinner: React_2.FC<Props>;
618
759
 
619
760
  declare type SpinnerSize = "big" | "small" | "extraSmall" | "medium" | "large";
620
761
 
762
+ export declare const startOfLocalDay: (d: Date) => Date;
763
+
621
764
  export declare const Stepper: default_2.FC<StepperProps>;
622
765
 
623
766
  export declare type StepperItem = {
@@ -688,6 +831,8 @@ export { TaskListIcon }
688
831
 
689
832
  export { TimesheetIcon }
690
833
 
834
+ export declare const todayLocalDay: () => Date;
835
+
691
836
  export declare const TooltipDark: MemoExoticComponent<({ title, content, open: openProp, defaultOpen, trigger, mouseEnterDelay, mouseLeaveDelay, onOpenChange, placement, arrow, children, overlayClassName, getPopupContainer, }: TooltipProps) => JSX.Element>;
692
837
 
693
838
  export declare const TooltipLight: FC<TooltipLightProps>;
@@ -731,7 +876,10 @@ declare type TooltipTarget = string | HTMLElement | RefObject<HTMLElement | null
731
876
 
732
877
  export declare type TooltipTrigger = "hover" | "click";
733
878
 
734
- export declare const TreeDialogSelect: <T, S extends string | number>({ value, placeholder, loadChildren: loadChildrenProp, loadNodes, searchNodes, onChange, onClear, label, title, searchPlaceholder, selectButtonText, closeButtonText, confirmButtonText, debounceMs, disabled, error, className, inputClassName, selectedOptionRender, nodeRender, leafConfirmOnly, }: TreeDialogSelectProps<T, S>) => JSX.Element;
879
+ /** `yyyy-MM-dd` for API / form state */
880
+ export declare const toYmdString: (d: Date) => string;
881
+
882
+ export declare const TreeDialogSelect: <T, S extends string | number>({ value, placeholder, loadChildren: loadChildrenProp, loadNodes, searchNodes, onChange, onClear, label, tooltipContent, tooltipPopperClassName, title, searchPlaceholder, selectButtonText, closeButtonText, confirmButtonText, debounceMs, disabled, error, className, inputClassName, selectedOptionRender, nodeRender, leafConfirmOnly, }: TreeDialogSelectProps<T, S>) => JSX.Element;
735
883
 
736
884
  /** Pass either {@link loadNodes} or {@link loadChildren} (deprecated alias). */
737
885
  export declare type TreeDialogSelectProps<T, S extends string | number> = TreeDialogSelectShared<T, S> & ({
@@ -749,6 +897,9 @@ declare interface TreeDialogSelectShared<T, S extends string | number> {
749
897
  onChange?: (node: TreeNode<T, S>) => void;
750
898
  onClear?: () => void;
751
899
  label?: ReactNode;
900
+ /** Подсказка по наведению на иконку «?» справа от подписи */
901
+ tooltipContent?: ReactNode;
902
+ tooltipPopperClassName?: string;
752
903
  title?: ReactNode;
753
904
  searchPlaceholder?: string;
754
905
  selectButtonText?: string;