@companix/uikit 0.0.2 → 0.0.3

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.
Files changed (254) hide show
  1. package/dist/bundle.es.js +61 -0
  2. package/dist/bundle.es10.js +87 -0
  3. package/dist/bundle.es11.js +75 -0
  4. package/dist/bundle.es12.js +38 -0
  5. package/dist/bundle.es13.js +33 -0
  6. package/dist/bundle.es14.js +18 -0
  7. package/dist/bundle.es15.js +11 -0
  8. package/dist/bundle.es16.js +35 -0
  9. package/dist/bundle.es17.js +27 -0
  10. package/dist/bundle.es18.js +23 -0
  11. package/dist/bundle.es19.js +24 -0
  12. package/dist/bundle.es20.js +15 -0
  13. package/dist/bundle.es21.js +41 -0
  14. package/dist/bundle.es22.js +18 -0
  15. package/dist/bundle.es23.js +36 -0
  16. package/dist/bundle.es24.js +23 -0
  17. package/dist/bundle.es25.js +42 -0
  18. package/dist/bundle.es26.js +114 -0
  19. package/dist/bundle.es27.js +115 -0
  20. package/dist/bundle.es28.js +38 -0
  21. package/dist/bundle.es29.js +13 -0
  22. package/dist/bundle.es3.js +45 -0
  23. package/dist/bundle.es30.js +27 -0
  24. package/dist/bundle.es31.js +38 -0
  25. package/dist/bundle.es35.js +43 -0
  26. package/dist/bundle.es36.js +442 -0
  27. package/dist/bundle.es37.js +24 -0
  28. package/dist/bundle.es38.js +26 -0
  29. package/dist/bundle.es39.js +83 -0
  30. package/dist/bundle.es4.js +14 -0
  31. package/dist/bundle.es40.js +20 -0
  32. package/dist/bundle.es41.js +16 -0
  33. package/dist/bundle.es43.js +7 -0
  34. package/dist/bundle.es44.js +23 -0
  35. package/dist/bundle.es45.js +16 -0
  36. package/dist/bundle.es46.js +72 -0
  37. package/dist/bundle.es47.js +70 -0
  38. package/dist/bundle.es48.js +34 -0
  39. package/dist/bundle.es49.js +70 -0
  40. package/dist/bundle.es5.js +88 -0
  41. package/dist/bundle.es50.js +33 -0
  42. package/dist/bundle.es51.js +78 -0
  43. package/dist/bundle.es52.js +51 -0
  44. package/dist/bundle.es53.js +45 -0
  45. package/dist/bundle.es54.js +40 -0
  46. package/dist/bundle.es55.js +36 -0
  47. package/dist/bundle.es56.js +9 -0
  48. package/dist/bundle.es57.js +9 -0
  49. package/dist/bundle.es58.js +7 -0
  50. package/dist/bundle.es59.js +9 -0
  51. package/dist/bundle.es6.js +87 -0
  52. package/dist/bundle.es60.js +8 -0
  53. package/dist/bundle.es61.js +19 -0
  54. package/dist/bundle.es62.js +15 -0
  55. package/dist/bundle.es63.js +22 -0
  56. package/dist/bundle.es64.js +45 -0
  57. package/dist/bundle.es65.js +28 -0
  58. package/dist/bundle.es66.js +34 -0
  59. package/dist/bundle.es67.js +6 -0
  60. package/dist/bundle.es68.js +12 -0
  61. package/dist/bundle.es69.js +47 -0
  62. package/dist/bundle.es7.js +80 -0
  63. package/dist/bundle.es70.js +11 -0
  64. package/dist/bundle.es71.js +18 -0
  65. package/dist/bundle.es72.js +32 -0
  66. package/dist/bundle.es73.js +35 -0
  67. package/dist/bundle.es74.js +6 -0
  68. package/dist/bundle.es75.js +7 -0
  69. package/dist/bundle.es76.js +7 -0
  70. package/dist/bundle.es77.js +11 -0
  71. package/dist/bundle.es78.js +17 -0
  72. package/dist/bundle.es79.js +7 -0
  73. package/dist/bundle.es8.js +29 -0
  74. package/dist/bundle.es80.js +17 -0
  75. package/dist/bundle.es81.js +25 -0
  76. package/dist/bundle.es9.js +47 -0
  77. package/dist/types/Button/index.d.ts +20 -0
  78. package/dist/types/ButtonGroup/index.d.ts +7 -0
  79. package/dist/types/Checkbox/index.d.ts +10 -0
  80. package/dist/types/Countdown/index.d.ts +7 -0
  81. package/dist/types/DateInput/index.d.ts +13 -0
  82. package/dist/types/DatePicker/Calendar.d.ts +14 -0
  83. package/dist/types/DatePicker/CalendarHeader.d.ts +10 -0
  84. package/dist/types/DatePicker/index.d.ts +12 -0
  85. package/dist/types/Dialog/index.d.ts +12 -0
  86. package/dist/types/DialogAlert/Alert.d.ts +19 -0
  87. package/dist/types/DialogAlert/Viewport.d.ts +8 -0
  88. package/dist/types/DialogAlert/index.d.ts +11 -0
  89. package/dist/types/Drawer/index.d.ts +13 -0
  90. package/dist/types/File/index.d.ts +10 -0
  91. package/dist/types/Form/index.d.ts +17 -0
  92. package/dist/types/Icon/index.d.ts +7 -0
  93. package/dist/types/LoadButton/index.d.ts +5 -0
  94. package/dist/types/NumberInput/index.d.ts +6 -0
  95. package/dist/types/OptionItem/OptionItem.d.ts +7 -0
  96. package/dist/types/OptionItem/OptionsList.d.ts +8 -0
  97. package/dist/types/Popover/index.d.ts +26 -0
  98. package/dist/types/Radio/index.d.ts +20 -0
  99. package/dist/types/Scrollable/ImitateScroll.d.ts +10 -0
  100. package/dist/types/Scrollable/index.d.ts +33 -0
  101. package/dist/types/Select/SelectInput.d.ts +14 -0
  102. package/dist/types/Select/index.d.ts +15 -0
  103. package/dist/types/SelectTags/index.d.ts +15 -0
  104. package/dist/types/Spinner/index.d.ts +8 -0
  105. package/dist/types/Stepper/index.d.ts +8 -0
  106. package/dist/types/Switch/index.d.ts +10 -0
  107. package/dist/types/Tabs/index.d.ts +13 -0
  108. package/dist/types/TextArea/index.d.ts +7 -0
  109. package/dist/types/Toaster/RemoveListener.d.ts +3 -0
  110. package/dist/types/Toaster/Toast.d.ts +9 -0
  111. package/dist/types/Toaster/Viewport.d.ts +13 -0
  112. package/dist/types/Toaster/index.d.ts +15 -0
  113. package/dist/types/Tooltip/index.d.ts +8 -0
  114. package/dist/types/__hooks/use-frooze-closing.d.ts +5 -0
  115. package/dist/types/__hooks/use-loading.d.ts +8 -0
  116. package/dist/types/__hooks/use-local-storage.d.ts +1 -0
  117. package/dist/types/__hooks/use-popover-position.d.ts +8 -0
  118. package/dist/types/__hooks/use-previos.d.ts +2 -0
  119. package/dist/types/__hooks/use-resize.d.ts +3 -0
  120. package/dist/types/__hooks/use-scrollbox.d.ts +7 -0
  121. package/dist/types/__hooks/use-stepper-input.d.ts +13 -0
  122. package/dist/types/__hooks/use-update.d.ts +1 -0
  123. package/dist/types/__hooks/useCalendar.d.ts +17 -0
  124. package/dist/types/__hooks/useCalendarOptions-copy.d.ts +22 -0
  125. package/dist/types/__hooks/useCalendarOptions.d.ts +31 -0
  126. package/dist/types/__libs/calendar.d.ts +25 -0
  127. package/dist/types/__utils/utils.d.ts +25 -0
  128. package/dist/types/index.d.ts +31 -0
  129. package/dist/types/types.d.ts +13 -0
  130. package/dist/uikit.css +1 -0
  131. package/package.json +10 -6
  132. package/.eslintrc +0 -54
  133. package/declaration.d.ts +0 -4
  134. package/index.html +0 -12
  135. package/playground/App.tsx +0 -166
  136. package/playground/Example.tsx +0 -14
  137. package/playground/Test.tsx +0 -44
  138. package/playground/animation-test-1/index.scss +0 -20
  139. package/playground/animation-test-1/index.tsx +0 -17
  140. package/playground/animation-test-2/index.scss +0 -62
  141. package/playground/animation-test-2/index.tsx +0 -32
  142. package/playground/bootstrap.tsx +0 -19
  143. package/playground/buttons/index.tsx +0 -132
  144. package/playground/checkbox/index.tsx +0 -64
  145. package/playground/date-input/index.tsx +0 -45
  146. package/playground/date-picker/index.tsx +0 -41
  147. package/playground/dialog/index.tsx +0 -92
  148. package/playground/dialog-alert/index.tsx +0 -47
  149. package/playground/drawer/index.tsx +0 -55
  150. package/playground/index.css +0 -33
  151. package/playground/index.scss +0 -270
  152. package/playground/input/index.tsx +0 -112
  153. package/playground/number-inputs/index.tsx +0 -50
  154. package/playground/popovers/index.tsx +0 -70
  155. package/playground/radio-group/index.tsx +0 -69
  156. package/playground/select/index.tsx +0 -72
  157. package/playground/select-tags/index.tsx +0 -36
  158. package/playground/styles.scss +0 -2
  159. package/playground/switch/index.tsx +0 -44
  160. package/playground/tabs/index.tsx +0 -16
  161. package/playground/test.scss +0 -0
  162. package/playground/text-area/index.tsx +0 -17
  163. package/playground/text-input/index.tsx +0 -12
  164. package/playground/toaster/index.tsx +0 -156
  165. package/playground/tooltip/index.tsx +0 -26
  166. package/src/Button/Button.scss +0 -128
  167. package/src/Button/index.tsx +0 -72
  168. package/src/ButtonGroup/ButtonGroup.scss +0 -18
  169. package/src/ButtonGroup/index.tsx +0 -20
  170. package/src/Checkbox/Checkbox.scss +0 -115
  171. package/src/Checkbox/index.tsx +0 -46
  172. package/src/Countdown/index.tsx +0 -54
  173. package/src/DateInput/DateInput.scss +0 -11
  174. package/src/DateInput/index.tsx +0 -96
  175. package/src/DatePicker/Calendar.scss +0 -125
  176. package/src/DatePicker/Calendar.tsx +0 -157
  177. package/src/DatePicker/CalendarHeader.tsx +0 -139
  178. package/src/DatePicker/DatePicker.scss +0 -0
  179. package/src/DatePicker/index.tsx +0 -177
  180. package/src/Dialog/Dialog.scss +0 -25
  181. package/src/Dialog/Popup.scss +0 -55
  182. package/src/Dialog/index.tsx +0 -31
  183. package/src/DialogAlert/Alert.scss +0 -52
  184. package/src/DialogAlert/Alert.tsx +0 -78
  185. package/src/DialogAlert/Viewport.tsx +0 -52
  186. package/src/DialogAlert/index.tsx +0 -37
  187. package/src/Drawer/Drawer.scss +0 -112
  188. package/src/Drawer/index.tsx +0 -46
  189. package/src/File/index.tsx +0 -60
  190. package/src/Form/Form.scss +0 -70
  191. package/src/Form/Input.scss +0 -24
  192. package/src/Form/index.tsx +0 -131
  193. package/src/Icon/icon.scss +0 -18
  194. package/src/Icon/index.tsx +0 -43
  195. package/src/LoadButton/index.tsx +0 -17
  196. package/src/NumberInput/index.tsx +0 -74
  197. package/src/OptionItem/Option.scss +0 -89
  198. package/src/OptionItem/OptionItem.tsx +0 -49
  199. package/src/OptionItem/OptionsList.tsx +0 -26
  200. package/src/Popover/Popover.scss +0 -80
  201. package/src/Popover/index.tsx +0 -117
  202. package/src/Radio/Radio.scss +0 -148
  203. package/src/Radio/index.tsx +0 -68
  204. package/src/Scrollable/ImitateScroll.tsx +0 -141
  205. package/src/Scrollable/Scrollable.scss +0 -50
  206. package/src/Scrollable/index.tsx +0 -141
  207. package/src/Select/Select.scss +0 -80
  208. package/src/Select/SelectInput.tsx +0 -131
  209. package/src/Select/index.tsx +0 -134
  210. package/src/SelectTags/SelectTags.scss +0 -66
  211. package/src/SelectTags/index.tsx +0 -192
  212. package/src/Spinner/Spinner.scss +0 -14
  213. package/src/Spinner/index.tsx +0 -19
  214. package/src/Stepper/StepperInput.scss +0 -35
  215. package/src/Stepper/index.tsx +0 -76
  216. package/src/Switch/Switch.scss +0 -102
  217. package/src/Switch/index.tsx +0 -49
  218. package/src/Tabs/Tabs.scss +0 -58
  219. package/src/Tabs/index.tsx +0 -89
  220. package/src/TextArea/TextArea.scss +0 -34
  221. package/src/TextArea/index.tsx +0 -51
  222. package/src/Toaster/RemoveListener.tsx +0 -11
  223. package/src/Toaster/Toast.tsx +0 -69
  224. package/src/Toaster/Toaster.scss +0 -151
  225. package/src/Toaster/Viewport.tsx +0 -117
  226. package/src/Toaster/index.tsx +0 -52
  227. package/src/Tooltip/Tooltip.scss +0 -28
  228. package/src/Tooltip/index.tsx +0 -33
  229. package/src/__hooks/use-frooze-closing.ts +0 -51
  230. package/src/__hooks/use-loading.ts +0 -34
  231. package/src/__hooks/use-local-storage.ts +0 -19
  232. package/src/__hooks/use-popover-position.ts +0 -24
  233. package/src/__hooks/use-previos.ts +0 -25
  234. package/src/__hooks/use-resize.ts +0 -41
  235. package/src/__hooks/use-scrollbox.ts +0 -45
  236. package/src/__hooks/use-stepper-input.ts +0 -82
  237. package/src/__hooks/use-update.ts +0 -19
  238. package/src/__hooks/useCalendar.ts +0 -104
  239. package/src/__hooks/useCalendarOptions-copy.ts +0 -87
  240. package/src/__hooks/useCalendarOptions.ts +0 -68
  241. package/src/__libs/calendar.ts +0 -175
  242. package/src/__utils/utils.ts +0 -137
  243. package/src/css.scss +0 -120
  244. package/src/index.scss +0 -22
  245. package/src/index.ts +0 -36
  246. package/src/mixins.scss +0 -99
  247. package/src/theme.scss +0 -103
  248. package/src/types.ts +0 -14
  249. package/tailwind.config.js +0 -91
  250. package/themes/classic/animations.scss +0 -179
  251. package/themes/classic/classic.scss +0 -493
  252. package/tsconfig.json +0 -27
  253. package/vite.build.ts +0 -35
  254. package/vite.config.ts +0 -33
@@ -1,80 +0,0 @@
1
- @use '../mixins.scss';
2
-
3
- .select {
4
- cursor: pointer;
5
- max-width: 100%;
6
-
7
- &-layout {
8
- display: flex;
9
- align-items: center;
10
- width: 100%;
11
- min-height: inherit;
12
- }
13
-
14
- &-placeholder {
15
- user-select: none;
16
-
17
- @include mixins.use-styles(form, placeholder);
18
- }
19
-
20
- &-content {
21
- position: relative;
22
- display: flex;
23
- flex: 1;
24
- align-items: center;
25
- align-self: stretch;
26
- overflow: hidden;
27
-
28
- &:first-child {
29
- padding-left: var(--form_space, 0);
30
- }
31
-
32
- &-text {
33
- overflow: hidden;
34
- text-overflow: ellipsis;
35
- white-space: nowrap;
36
- }
37
- }
38
-
39
- &-element {
40
- height: 100%;
41
- display: flex;
42
- align-items: center;
43
- }
44
-
45
- &-close-button {
46
- pointer-events: auto;
47
- cursor: pointer;
48
- padding: 0px var(--form_space, 0);
49
- height: 100%;
50
- outline: none;
51
- color: var(--select_clean_color);
52
-
53
- &:hover {
54
- color: var(--select_clean_hover_color);
55
- }
56
- }
57
-
58
- &-expand {
59
- margin-right: var(--form_space, 0);
60
-
61
- &:first-child {
62
- margin-left: var(--form_space, 0);
63
- }
64
- }
65
- }
66
-
67
- // expand icon
68
-
69
- .expand-icon {
70
- color: var(--select_expand_color);
71
- transition: transform 0.2s;
72
- }
73
-
74
- .form {
75
- &[data-state='open'] {
76
- .expand-icon {
77
- transform: rotate(180deg);
78
- }
79
- }
80
- }
@@ -1,131 +0,0 @@
1
- import cn from 'classnames'
2
-
3
- import { attr } from '@companix/utils-browser'
4
- import { forwardRef, useCallback, useRef } from 'react'
5
- import { Icon } from '../Icon'
6
- import { faChevronDown, faClose } from '@fortawesome/free-solid-svg-icons'
7
- import { VisuallyHidden } from '@radix-ui/react-visually-hidden'
8
-
9
- export interface SelectFormProps extends React.HTMLAttributes<HTMLDivElement> {
10
- required?: boolean
11
- disabled?: boolean
12
- className?: string
13
- leftElement?: React.ReactNode
14
- placeholder?: string
15
- value?: string | number
16
- size?: 'sm' | 'md' | 'lg'
17
- fill?: boolean
18
- clearButton?: boolean
19
- clearButtonIcon?: boolean
20
- onClear?: (event: React.MouseEvent<HTMLButtonElement>) => void
21
- }
22
-
23
- export const SelectInput = forwardRef<HTMLDivElement, SelectFormProps>(
24
- (
25
- {
26
- required,
27
- size,
28
- fill,
29
- leftElement,
30
- className,
31
- value,
32
- clearButton,
33
- placeholder,
34
- clearButtonIcon,
35
- disabled,
36
- onClear,
37
- ...containerProps
38
- },
39
- ref
40
- ) => {
41
- const selectInputRef = useRef<HTMLInputElement>(null)
42
-
43
- // https://vkui.io/components/custom-select/
44
- const passClickAndFocusToInputOnClick = useCallback(
45
- (e: React.MouseEvent<HTMLDivElement>) => {
46
- if (!selectInputRef.current || !document) {
47
- return
48
- }
49
-
50
- const clickTargetIsNotAnInput = e.target !== selectInputRef.current
51
- if (clickTargetIsNotAnInput) {
52
- selectInputRef.current.click()
53
-
54
- const inputIsNotFocused = document.activeElement !== selectInputRef.current
55
- if (inputIsNotFocused) {
56
- selectInputRef.current.focus()
57
- }
58
- }
59
- },
60
- [selectInputRef]
61
- )
62
-
63
- const preventInputBlurWhenClickInsideFocusedSelectArea = (e: React.MouseEvent<HTMLDivElement>) => {
64
- // Так как инпут больше не оборачивается пустым лэйблом, то клик внутри обертки,
65
- // но вне инпута (например по иконке дропдауна), будет убирать фокус с инпута.
66
- // Чтобы в такой ситуации отключить blur инпута мы превентим mousedown событие обёртки
67
- const isInputFocused = document && document.activeElement === selectInputRef.current
68
- if (isInputFocused) {
69
- e.preventDefault()
70
- }
71
- }
72
-
73
- const onClick = (event: React.MouseEvent<HTMLDivElement>) => {
74
- if (disabled) return
75
- passClickAndFocusToInputOnClick(event)
76
- }
77
-
78
- const onMouseDown = (event: React.MouseEvent<HTMLDivElement>) => {
79
- preventInputBlurWhenClickInsideFocusedSelectArea(event)
80
- }
81
-
82
- const handleClear = (event: React.MouseEvent<HTMLButtonElement>) => {
83
- selectInputRef.current && selectInputRef.current.focus()
84
- onClear?.(event)
85
- }
86
-
87
- return (
88
- <div
89
- ref={ref}
90
- className={cn('form select', className)}
91
- data-size={size ?? 'md'}
92
- data-fill={attr(fill)}
93
- data-required={attr(required)}
94
- data-disabled={attr(disabled)}
95
- onMouseDown={onMouseDown}
96
- {...containerProps}
97
- onClick={onClick}
98
- >
99
- <div className="select-layout form-input">
100
- {leftElement && <div className="select-element">{leftElement}</div>}
101
- <div className="select-content">
102
- <div className="select-content-text" aria-disabled={disabled}>
103
- {!value && <span className="select-placeholder">{placeholder}</span>}
104
- {value}
105
- </div>
106
- </div>
107
- <div className="select-element">
108
- {clearButton && value && (
109
- <button className="select-close-button" onClick={handleClear}>
110
- {clearButtonIcon ?? <Icon className="select-close-icon" icon={faClose} size="xxxs" />}
111
- </button>
112
- )}
113
- <Icon className="expand-icon select-expand" icon={faChevronDown} size="xxxs" />
114
- </div>
115
- </div>
116
- <VisuallyHidden asChild>
117
- <input
118
- ref={selectInputRef}
119
- autoComplete="off"
120
- autoCapitalize="none"
121
- autoCorrect="off"
122
- spellCheck="false"
123
- aria-autocomplete="none"
124
- onClick={containerProps.onClick}
125
- readOnly
126
- />
127
- </VisuallyHidden>
128
- </div>
129
- )
130
- }
131
- )
@@ -1,134 +0,0 @@
1
- import { useEffect, useMemo } from 'react'
2
- import { OptionsList } from '../OptionItem/OptionsList'
3
- import { OptionItem } from '../OptionItem/OptionItem'
4
- import { Popover } from '../Popover'
5
- import { useFroozeClosing } from '../__hooks/use-frooze-closing'
6
- import { FormProps } from '../Form'
7
- import type { Option } from '../types'
8
- import { SelectInput } from './SelectInput'
9
- import { useScrollListController } from '../__hooks/use-scrollbox'
10
-
11
- interface SelectProps<T> extends Omit<FormProps, 'value' | 'onChange' | 'rightElement'> {
12
- options: Option<T>[]
13
- onChange: (event: T | null) => void
14
- placeholder?: string
15
- clearButton?: boolean
16
- clearButtonIcon?: boolean
17
- value: T | null
18
- children?: React.ReactNode
19
- minimalOptions?: boolean
20
- matchTarget?: 'width' | 'min-width'
21
- }
22
-
23
- export const Select = <T,>(props: SelectProps<T>) => {
24
- const {
25
- options,
26
- onChange,
27
- minimalOptions,
28
- clearButton,
29
- clearButtonIcon,
30
- matchTarget = 'width',
31
- value,
32
- children,
33
- disabled,
34
- ...inputProps
35
- } = props
36
-
37
- const currentOption = useMemo(() => {
38
- const index = options.findIndex((o) => o.value === value)
39
-
40
- return {
41
- index,
42
- option: options[index] as Option<T> | undefined
43
- }
44
- }, [options, value])
45
-
46
- const active = currentOption.option?.value ?? null
47
-
48
- const { popoverRef, froozePopoverPosition, handleAnimationEnd } = useFroozeClosing()
49
- const { scrollToElement, optionsWrapperRef, scrollBoxRef } = useScrollListController()
50
-
51
- const handleChange = (value: T, close: () => void) => {
52
- froozePopoverPosition()
53
- onChange(value)
54
- close()
55
- }
56
-
57
- const handleClear = (e: React.MouseEvent) => {
58
- e.stopPropagation()
59
- onChange(null)
60
- }
61
-
62
- const onOpened = () => {
63
- if (currentOption.index !== -1) {
64
- scrollToElement(currentOption.index, true)
65
- }
66
- }
67
-
68
- return (
69
- <Popover
70
- minimal
71
- ref={popoverRef}
72
- sideOffset={0}
73
- matchTarget={matchTarget}
74
- onAnimationEnd={handleAnimationEnd}
75
- onOpenAutoFocus={(e) => e.preventDefault()}
76
- onCloseAutoFocus={(e) => e.preventDefault()}
77
- disabled={disabled}
78
- content={({ close }) => (
79
- <SelectPopover<T>
80
- options={options}
81
- active={active}
82
- scrollboxRef={scrollBoxRef}
83
- optionsWrapperRef={optionsWrapperRef}
84
- minimalOptions={minimalOptions}
85
- onOpened={onOpened}
86
- onSelect={(value) => handleChange(value, close)}
87
- />
88
- )}
89
- >
90
- {children ?? (
91
- <SelectInput
92
- {...inputProps}
93
- disabled={disabled}
94
- value={currentOption.option?.title ?? ''}
95
- onClear={handleClear}
96
- clearButton={clearButton}
97
- clearButtonIcon={clearButtonIcon}
98
- />
99
- )}
100
- </Popover>
101
- )
102
- }
103
-
104
- interface SelectPopoverProps<T> {
105
- scrollboxRef?: React.Ref<HTMLDivElement>
106
- optionsWrapperRef?: React.RefObject<HTMLDivElement>
107
- options: Option<T>[]
108
- minimalOptions?: boolean
109
- active?: T | null
110
- onSelect?: (value: T) => void
111
- onOpened?: () => void
112
- }
113
-
114
- const SelectPopover = <T,>(props: SelectPopoverProps<T>) => {
115
- const { active, onOpened, scrollboxRef, optionsWrapperRef, options, onSelect, minimalOptions } = props
116
-
117
- useEffect(() => {
118
- onOpened?.()
119
- }, [])
120
-
121
- return (
122
- <OptionsList scrollboxRef={scrollboxRef} optionsWrapperRef={optionsWrapperRef} maxHeight={300}>
123
- {options.map((option, i) => (
124
- <OptionItem
125
- key={`option-item-${option.value}-${i}`}
126
- active={active === option.value}
127
- onClick={() => onSelect?.(option.value)}
128
- minimal={minimalOptions}
129
- {...option}
130
- />
131
- ))}
132
- </OptionsList>
133
- )
134
- }
@@ -1,66 +0,0 @@
1
- @use '../mixins.scss';
2
-
3
- .select-tags {
4
- display: flex;
5
- flex-direction: column;
6
-
7
- .form-input {
8
- padding-left: var(--form_space, 0);
9
- }
10
-
11
- &-empty {
12
- @include mixins.use-styles(tag, empty);
13
- }
14
-
15
- &-container {
16
- display: flex;
17
- align-items: center;
18
- cursor: text;
19
-
20
- .expand-icon {
21
- margin: 0px var(--form_space, 0);
22
- }
23
- }
24
- }
25
-
26
- .tag {
27
- display: flex;
28
- align-items: center;
29
- cursor: default;
30
- user-select: none;
31
-
32
- @include mixins.use-styles(tag);
33
-
34
- &-name {
35
- @include mixins.use-styles(tag, name);
36
- }
37
-
38
- &-close-button {
39
- cursor: pointer;
40
- @include mixins.use-styles(tag, close);
41
-
42
- &:hover {
43
- @include mixins.use-styles(tag, close, hover);
44
- }
45
- }
46
-
47
- &-close-icon {
48
- @include mixins.use-size(tag, close, size);
49
- }
50
-
51
- &-container {
52
- display: flex;
53
- flex-direction: row;
54
- align-items: center;
55
- align-self: stretch;
56
- flex-wrap: wrap;
57
- min-width: 0;
58
- position: relative;
59
-
60
- @include mixins.use-styles(tag, container);
61
-
62
- &:not([data-readonly]) {
63
- padding-bottom: 0;
64
- }
65
- }
66
- }
@@ -1,192 +0,0 @@
1
- import { useFroozeClosing } from '../__hooks/use-frooze-closing'
2
- import type { Option } from '../types'
3
- import { OptionItem, OptionsList, Popover } from '..'
4
- import { useMemo, useRef, useState } from 'react'
5
- import { Icon } from '../Icon'
6
- import { faChevronDown, faClose } from '@fortawesome/free-solid-svg-icons'
7
- import { attr, contains, getActiveElementByAnotherElement } from '@companix/utils-browser'
8
-
9
- export interface SelectTagsProps<T> {
10
- options: Option<T>[]
11
- onChange: (event: T[]) => void
12
- placeholder?: string
13
- value: T[]
14
- children?: React.ReactNode
15
- disabled?: boolean
16
- readOnly?: boolean
17
- closeAfterSelect?: boolean
18
- emptyText?: string
19
- size?: 'sm' | 'md' | 'lg'
20
- fill?: boolean
21
- }
22
-
23
- export const SelectTags = <T extends string | number>(props: SelectTagsProps<T>) => {
24
- const {
25
- options: optionsProp,
26
- closeAfterSelect,
27
- placeholder,
28
- onChange,
29
- emptyText = 'Ничего не найдено',
30
- readOnly,
31
- size = 'md',
32
- value: values,
33
- disabled
34
- } = props
35
-
36
- const [inputValue, setInputValue] = useState('')
37
- const inputRef = useRef<HTMLInputElement>(null)
38
- const listboxRef = useRef<HTMLDivElement>(null)
39
- const { popoverRef, froozePopoverPosition, handleAnimationEnd } = useFroozeClosing()
40
-
41
- const store = useMemo(() => {
42
- const store = {} as { [value in T]: Option<T> }
43
-
44
- optionsProp.forEach((option) => {
45
- store[option.value] = option
46
- })
47
-
48
- return store
49
- }, [optionsProp])
50
-
51
- const add = (value: T) => {
52
- if (values.includes(value)) {
53
- return [...values]
54
- }
55
-
56
- return [...values, value]
57
- }
58
-
59
- const remove = (value: T) => {
60
- return values.filter((item) => value !== item)
61
- }
62
-
63
- const handleSelect = (value: T[], close: () => void) => {
64
- if (closeAfterSelect) {
65
- froozePopoverPosition()
66
- onChange(value)
67
- close()
68
- } else {
69
- onChange(value)
70
- }
71
- }
72
-
73
- const options = useMemo(() => {
74
- if (!inputValue.trim()) {
75
- return optionsProp
76
- }
77
-
78
- return optionsProp.filter(({ title }) => {
79
- const normalizedTitle = title.toLowerCase()
80
- const normalizedQuery = inputValue.trim().toLowerCase()
81
-
82
- return normalizedTitle.indexOf(normalizedQuery) >= 0
83
- })
84
- }, [inputValue, optionsProp])
85
-
86
- const handleRootClick = (event: React.MouseEvent) => {
87
- if (disabled) return
88
-
89
- // Предотвращаем закрытие Popover при клике на форму
90
- if (popoverRef.current && popoverRef.current.getAttribute('data-state') === 'open') {
91
- event.preventDefault()
92
- }
93
-
94
- const activeElement = getActiveElementByAnotherElement(event.currentTarget)
95
-
96
- if (event.defaultPrevented || contains(event.currentTarget, activeElement)) {
97
- return
98
- }
99
-
100
- if (inputRef.current) {
101
- inputRef.current.focus()
102
- }
103
- }
104
-
105
- const handleRootMouseDown = (e: React.MouseEvent<HTMLDivElement>) => {
106
- // Когда клик в сам инпут, не нужно делать preventDefault, так как не будет работать выделение текста
107
- if (e.target === inputRef.current) {
108
- return
109
- }
110
- // Делаем preventDefault
111
- e.preventDefault()
112
- }
113
-
114
- const handleRemove = (e: React.MouseEvent, value: T) => {
115
- e.stopPropagation()
116
- onChange(remove(value))
117
- }
118
-
119
- // const
120
-
121
- return (
122
- <Popover
123
- minimal
124
- ref={popoverRef}
125
- sideOffset={0}
126
- matchTarget="width"
127
- onAnimationEnd={handleAnimationEnd}
128
- onOpenAutoFocus={(e) => e.preventDefault()}
129
- onCloseAutoFocus={(e) => e.preventDefault()}
130
- content={({ close }) => (
131
- <OptionsList maxHeight={300}>
132
- {options.length === 0 && <div className="select-tags-empty">{emptyText}</div>}
133
- {options.map(({ value, title, icon }, i) => (
134
- <OptionItem
135
- key={`option-item-${value}-${i}`}
136
- active={values.includes(value)}
137
- onClick={() => handleSelect(add(value), close)}
138
- title={title}
139
- icon={icon}
140
- />
141
- ))}
142
- </OptionsList>
143
- )}
144
- >
145
- <div
146
- className="form"
147
- onClick={handleRootClick}
148
- onMouseDown={handleRootMouseDown}
149
- data-size={size}
150
- >
151
- <div className="select-tags-container">
152
- <div className="select-tags">
153
- {values.length > 0 && (
154
- <div
155
- className="tag-container"
156
- ref={listboxRef}
157
- role="listbox"
158
- data-readonly={attr(readOnly)}
159
- >
160
- {values.map((value, i) => (
161
- <div key={`tag-option-${value}-${i}`} className="tag">
162
- <span className="tag-name">{store[value].title}</span>
163
- <button className="tag-close-button" onClick={(e) => handleRemove(e, value)}>
164
- <Icon className="tag-close-icon" icon={faClose} size="xxxs" />
165
- </button>
166
- </div>
167
- ))}
168
- </div>
169
- )}
170
- {(!readOnly || values.length === 0) && (
171
- <input
172
- ref={inputRef}
173
- type="text"
174
- autoCapitalize="none"
175
- autoComplete="off"
176
- autoCorrect="off"
177
- className="form-input"
178
- spellCheck={false}
179
- value={inputValue}
180
- disabled={disabled}
181
- readOnly={readOnly}
182
- placeholder={placeholder}
183
- onChange={({ target }) => setInputValue(target.value)}
184
- />
185
- )}
186
- </div>
187
- <Icon className="expand-icon" icon={faChevronDown} size="xxxs" />
188
- </div>
189
- </div>
190
- </Popover>
191
- )
192
- }
@@ -1,14 +0,0 @@
1
- @keyframes spinner-border {
2
- to {
3
- transform: rotate(360deg);
4
- }
5
- }
6
-
7
- .spinner-border {
8
- display: inline-block;
9
- border-style: solid;
10
- border-color: currentColor;
11
- border-right-color: transparent;
12
- border-radius: 50%;
13
- animation: 0.75s linear infinite spinner-border;
14
- }
@@ -1,19 +0,0 @@
1
- import './Spinner.scss'
2
- import cn from 'classnames'
3
-
4
- interface Props {
5
- size?: number
6
- width?: number
7
- color?: string
8
- className?: string
9
- }
10
-
11
- export const Spinner = ({ size = 40, className, width = 4, color = 'inherit' }: Props) => {
12
- return (
13
- <div
14
- style={{ width: `${size}px`, height: `${size}px`, color, borderWidth: `${width}px` }}
15
- className={cn('spinner-border', className)}
16
- role="status"
17
- />
18
- )
19
- }
@@ -1,35 +0,0 @@
1
- .number-input-container {
2
- display: flex;
3
- gap: 4px;
4
- }
5
-
6
- .number-stepper {
7
- display: flex;
8
- flex-direction: column;
9
- height: 30px;
10
- min-height: 30px;
11
- line-height: 30px;
12
- border: 1px solid var(--border-color);
13
- box-shadow: 0 1px 2px rgb(0 0 0 / 47%);
14
- border-radius: 4px;
15
-
16
- &-splitter {
17
- height: 1px;
18
- background-color: var(--border-color);
19
- }
20
-
21
- &-slot {
22
- border-radius: 0px;
23
- height: 13.5px;
24
-
25
- &[data-slot='decrement'] {
26
- border-bottom-left-radius: 3px;
27
- border-bottom-right-radius: 3px;
28
- }
29
-
30
- &[data-slot='increment'] {
31
- border-top-left-radius: 3px;
32
- border-top-right-radius: 3px;
33
- }
34
- }
35
- }