@kkkarsss/ui 1.0.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.
Files changed (246) hide show
  1. package/dist/.storybook/main.d.ts +3 -0
  2. package/dist/.storybook/main.js +34 -0
  3. package/dist/.storybook/preview.d.ts +4 -0
  4. package/dist/.storybook/preview.js +19 -0
  5. package/dist/index.css +238 -0
  6. package/dist/index.d.ts +4 -0
  7. package/dist/index.js +4 -0
  8. package/dist/providers/alert/alert-context.d.ts +16 -0
  9. package/dist/providers/alert/alert-context.js +2 -0
  10. package/dist/providers/alert/alert-provider.d.ts +6 -0
  11. package/dist/providers/alert/alert-provider.js +50 -0
  12. package/dist/providers/alert/use-alerts.d.ts +1 -0
  13. package/dist/providers/alert/use-alerts.js +9 -0
  14. package/dist/providers/index.d.ts +9 -0
  15. package/dist/providers/index.js +9 -0
  16. package/dist/providers/theme/index.d.ts +3 -0
  17. package/dist/providers/theme/index.js +3 -0
  18. package/dist/providers/theme/theme-context.d.ts +7 -0
  19. package/dist/providers/theme/theme-context.js +6 -0
  20. package/dist/providers/theme/theme-provider.d.ts +9 -0
  21. package/dist/providers/theme/theme-provider.js +27 -0
  22. package/dist/providers/theme/use-theme.d.ts +4 -0
  23. package/dist/providers/theme/use-theme.js +8 -0
  24. package/dist/providers/widget/index.d.ts +3 -0
  25. package/dist/providers/widget/index.js +3 -0
  26. package/dist/providers/widget/use-widgets.d.ts +4 -0
  27. package/dist/providers/widget/use-widgets.js +8 -0
  28. package/dist/providers/widget/widget-context.d.ts +12 -0
  29. package/dist/providers/widget/widget-context.js +6 -0
  30. package/dist/providers/widget/widget-provider.d.ts +6 -0
  31. package/dist/providers/widget/widget-provider.js +13 -0
  32. package/dist/src/index.d.ts +4 -0
  33. package/dist/src/index.js +4 -0
  34. package/dist/src/providers/alert/alert-context.d.ts +16 -0
  35. package/dist/src/providers/alert/alert-context.js +2 -0
  36. package/dist/src/providers/alert/alert-provider.d.ts +6 -0
  37. package/dist/src/providers/alert/alert-provider.js +50 -0
  38. package/dist/src/providers/alert/use-alerts.d.ts +1 -0
  39. package/dist/src/providers/alert/use-alerts.js +9 -0
  40. package/dist/src/providers/index.d.ts +9 -0
  41. package/dist/src/providers/index.js +9 -0
  42. package/dist/src/providers/theme/theme-context.d.ts +7 -0
  43. package/dist/src/providers/theme/theme-context.js +6 -0
  44. package/dist/src/providers/theme/theme-provider.d.ts +9 -0
  45. package/dist/src/providers/theme/theme-provider.js +27 -0
  46. package/dist/src/providers/theme/use-theme.d.ts +4 -0
  47. package/dist/src/providers/theme/use-theme.js +8 -0
  48. package/dist/src/providers/widget/use-widgets.d.ts +4 -0
  49. package/dist/src/providers/widget/use-widgets.js +8 -0
  50. package/dist/src/providers/widget/widget-context.d.ts +12 -0
  51. package/dist/src/providers/widget/widget-context.js +6 -0
  52. package/dist/src/providers/widget/widget-provider.d.ts +6 -0
  53. package/dist/src/providers/widget/widget-provider.js +15 -0
  54. package/dist/src/ui/controls/button/button.d.ts +10 -0
  55. package/dist/src/ui/controls/button/button.js +11 -0
  56. package/dist/src/ui/controls/button/button.stories.d.ts +9 -0
  57. package/dist/src/ui/controls/button/button.stories.js +38 -0
  58. package/dist/src/ui/controls/chip/chip.d.ts +12 -0
  59. package/dist/src/ui/controls/chip/chip.js +11 -0
  60. package/dist/src/ui/controls/chip/chip.stories.d.ts +9 -0
  61. package/dist/src/ui/controls/chip/chip.stories.js +42 -0
  62. package/dist/src/ui/controls/color-picker/color-picker.d.ts +8 -0
  63. package/dist/src/ui/controls/color-picker/color-picker.js +21 -0
  64. package/dist/src/ui/controls/color-picker/color-picker.stories.d.ts +7 -0
  65. package/dist/src/ui/controls/color-picker/color-picker.stories.js +21 -0
  66. package/dist/src/ui/controls/copy/copy.d.ts +6 -0
  67. package/dist/src/ui/controls/copy/copy.js +20 -0
  68. package/dist/src/ui/controls/copy/copy.stories.d.ts +7 -0
  69. package/dist/src/ui/controls/copy/copy.stories.js +20 -0
  70. package/dist/src/ui/controls/index.d.ts +7 -0
  71. package/dist/src/ui/controls/index.js +7 -0
  72. package/dist/src/ui/controls/input/input.d.ts +14 -0
  73. package/dist/src/ui/controls/input/input.js +12 -0
  74. package/dist/src/ui/controls/input/input.stories.d.ts +9 -0
  75. package/dist/src/ui/controls/input/input.stories.js +46 -0
  76. package/dist/src/ui/controls/select/select.d.ts +14 -0
  77. package/dist/src/ui/controls/select/select.js +80 -0
  78. package/dist/src/ui/controls/select/select.stories.d.ts +8 -0
  79. package/dist/src/ui/controls/select/select.stories.js +40 -0
  80. package/dist/src/ui/controls/textarea/textarea.d.ts +11 -0
  81. package/dist/src/ui/controls/textarea/textarea.js +20 -0
  82. package/dist/src/ui/controls/textarea/textarea.stories.d.ts +8 -0
  83. package/dist/src/ui/controls/textarea/textarea.stories.js +35 -0
  84. package/dist/src/ui/index.d.ts +3 -0
  85. package/dist/src/ui/index.js +3 -0
  86. package/dist/src/ui/information/block/block.d.ts +10 -0
  87. package/dist/src/ui/information/block/block.js +10 -0
  88. package/dist/src/ui/information/block/block.stories.d.ts +8 -0
  89. package/dist/src/ui/information/block/block.stories.js +38 -0
  90. package/dist/src/ui/information/cell/cell.d.ts +26 -0
  91. package/dist/src/ui/information/cell/cell.js +31 -0
  92. package/dist/src/ui/information/cell/cell.stories.d.ts +11 -0
  93. package/dist/src/ui/information/cell/cell.stories.js +62 -0
  94. package/dist/src/ui/information/cell/cells-block.d.ts +9 -0
  95. package/dist/src/ui/information/cell/cells-block.js +5 -0
  96. package/dist/src/ui/information/cell/cells-block.stories.d.ts +6 -0
  97. package/dist/src/ui/information/cell/cells-block.stories.js +20 -0
  98. package/dist/src/ui/information/index.d.ts +6 -0
  99. package/dist/src/ui/information/index.js +6 -0
  100. package/dist/src/ui/information/spinner/spinner.d.ts +2 -0
  101. package/dist/src/ui/information/spinner/spinner.js +5 -0
  102. package/dist/src/ui/information/spinner/spinner.stories.d.ts +6 -0
  103. package/dist/src/ui/information/spinner/spinner.stories.js +8 -0
  104. package/dist/src/ui/information/tag/tag.d.ts +6 -0
  105. package/dist/src/ui/information/tag/tag.js +7 -0
  106. package/dist/src/ui/information/tag/tag.stories.d.ts +8 -0
  107. package/dist/src/ui/information/tag/tag.stories.js +25 -0
  108. package/dist/src/ui/information/text/typo.d.ts +12 -0
  109. package/dist/src/ui/information/text/typo.js +41 -0
  110. package/dist/src/ui/information/text/typo.stories.d.ts +10 -0
  111. package/dist/src/ui/information/text/typo.stories.js +60 -0
  112. package/dist/src/ui/layout/dropdown/dropdown.d.ts +11 -0
  113. package/dist/src/ui/layout/dropdown/dropdown.js +59 -0
  114. package/dist/src/ui/layout/dropdown/dropdown.stories.d.ts +6 -0
  115. package/dist/src/ui/layout/dropdown/dropdown.stories.js +24 -0
  116. package/dist/src/ui/layout/flex/flex.d.ts +12 -0
  117. package/dist/src/ui/layout/flex/flex.js +36 -0
  118. package/dist/src/ui/layout/flex/flex.stories.d.ts +8 -0
  119. package/dist/src/ui/layout/flex/flex.stories.js +53 -0
  120. package/dist/src/ui/layout/icon-action/icon-action.d.ts +9 -0
  121. package/dist/src/ui/layout/icon-action/icon-action.js +11 -0
  122. package/dist/src/ui/layout/icon-action/icon-action.stories.d.ts +7 -0
  123. package/dist/src/ui/layout/icon-action/icon-action.stories.js +23 -0
  124. package/dist/src/ui/layout/index.d.ts +5 -0
  125. package/dist/src/ui/layout/index.js +5 -0
  126. package/dist/src/ui/layout/main-page-layout/main-page-layout.d.ts +7 -0
  127. package/dist/src/ui/layout/main-page-layout/main-page-layout.js +8 -0
  128. package/dist/src/ui/layout/main-page-layout/main-page-layout.stories.d.ts +6 -0
  129. package/dist/src/ui/layout/main-page-layout/main-page-layout.stories.js +19 -0
  130. package/dist/src/ui/layout/offset/offset.d.ts +6 -0
  131. package/dist/src/ui/layout/offset/offset.js +10 -0
  132. package/dist/src/ui/layout/offset/offset.stories.d.ts +8 -0
  133. package/dist/src/ui/layout/offset/offset.stories.js +33 -0
  134. package/dist/src/utils/classes.d.ts +1 -0
  135. package/dist/src/utils/classes.js +1 -0
  136. package/dist/src/utils/index.d.ts +1 -0
  137. package/dist/src/utils/index.js +1 -0
  138. package/dist/stories/Button.d.ts +15 -0
  139. package/dist/stories/Button.js +7 -0
  140. package/dist/stories/Button.stories.d.ts +23 -0
  141. package/dist/stories/Button.stories.js +44 -0
  142. package/dist/stories/Header.d.ts +12 -0
  143. package/dist/stories/Header.js +4 -0
  144. package/dist/stories/Header.stories.d.ts +18 -0
  145. package/dist/stories/Header.stories.js +26 -0
  146. package/dist/stories/Page.d.ts +3 -0
  147. package/dist/stories/Page.js +8 -0
  148. package/dist/stories/Page.stories.d.ts +12 -0
  149. package/dist/stories/Page.stories.js +24 -0
  150. package/dist/ui/controls/button/button.d.ts +10 -0
  151. package/dist/ui/controls/button/button.js +11 -0
  152. package/dist/ui/controls/button/button.stories.d.ts +9 -0
  153. package/dist/ui/controls/button/button.stories.js +38 -0
  154. package/dist/ui/controls/chip/chip.d.ts +12 -0
  155. package/dist/ui/controls/chip/chip.js +11 -0
  156. package/dist/ui/controls/chip/chip.stories.d.ts +9 -0
  157. package/dist/ui/controls/chip/chip.stories.js +42 -0
  158. package/dist/ui/controls/color-picker/color-picker.d.ts +8 -0
  159. package/dist/ui/controls/color-picker/color-picker.js +21 -0
  160. package/dist/ui/controls/color-picker/color-picker.stories.d.ts +7 -0
  161. package/dist/ui/controls/color-picker/color-picker.stories.js +21 -0
  162. package/dist/ui/controls/copy/copy.d.ts +6 -0
  163. package/dist/ui/controls/copy/copy.js +20 -0
  164. package/dist/ui/controls/copy/copy.stories.d.ts +7 -0
  165. package/dist/ui/controls/copy/copy.stories.js +20 -0
  166. package/dist/ui/controls/date-input/date-input.d.ts +10 -0
  167. package/dist/ui/controls/date-input/date-input.js +25 -0
  168. package/dist/ui/controls/date-picker/date-picker.d.ts +7 -0
  169. package/dist/ui/controls/date-picker/date-picker.js +32 -0
  170. package/dist/ui/controls/index.d.ts +9 -0
  171. package/dist/ui/controls/index.js +9 -0
  172. package/dist/ui/controls/input/input.d.ts +15 -0
  173. package/dist/ui/controls/input/input.js +12 -0
  174. package/dist/ui/controls/input/input.stories.d.ts +9 -0
  175. package/dist/ui/controls/input/input.stories.js +46 -0
  176. package/dist/ui/controls/select/select.d.ts +14 -0
  177. package/dist/ui/controls/select/select.js +80 -0
  178. package/dist/ui/controls/select/select.stories.d.ts +8 -0
  179. package/dist/ui/controls/select/select.stories.js +40 -0
  180. package/dist/ui/controls/textarea/textarea.d.ts +11 -0
  181. package/dist/ui/controls/textarea/textarea.js +20 -0
  182. package/dist/ui/controls/textarea/textarea.stories.d.ts +8 -0
  183. package/dist/ui/controls/textarea/textarea.stories.js +35 -0
  184. package/dist/ui/controls/theme-toggle/theme-toggle.d.ts +2 -0
  185. package/dist/ui/controls/theme-toggle/theme-toggle.js +10 -0
  186. package/dist/ui/index.d.ts +3 -0
  187. package/dist/ui/index.js +3 -0
  188. package/dist/ui/information/block/block.d.ts +13 -0
  189. package/dist/ui/information/block/block.js +10 -0
  190. package/dist/ui/information/block/block.stories.d.ts +9 -0
  191. package/dist/ui/information/block/block.stories.js +47 -0
  192. package/dist/ui/information/calendar-like/calendar-like.d.ts +24 -0
  193. package/dist/ui/information/calendar-like/calendar-like.js +71 -0
  194. package/dist/ui/information/cell/cell.d.ts +26 -0
  195. package/dist/ui/information/cell/cell.js +31 -0
  196. package/dist/ui/information/cell/cell.stories.d.ts +11 -0
  197. package/dist/ui/information/cell/cell.stories.js +62 -0
  198. package/dist/ui/information/cell/cells-block.d.ts +9 -0
  199. package/dist/ui/information/cell/cells-block.js +5 -0
  200. package/dist/ui/information/cell/cells-block.stories.d.ts +6 -0
  201. package/dist/ui/information/cell/cells-block.stories.js +20 -0
  202. package/dist/ui/information/index.d.ts +8 -0
  203. package/dist/ui/information/index.js +8 -0
  204. package/dist/ui/information/not-found/not-found.d.ts +2 -0
  205. package/dist/ui/information/not-found/not-found.js +6 -0
  206. package/dist/ui/information/spinner/spinner.d.ts +2 -0
  207. package/dist/ui/information/spinner/spinner.js +5 -0
  208. package/dist/ui/information/spinner/spinner.stories.d.ts +6 -0
  209. package/dist/ui/information/spinner/spinner.stories.js +8 -0
  210. package/dist/ui/information/tag/tag.d.ts +6 -0
  211. package/dist/ui/information/tag/tag.js +7 -0
  212. package/dist/ui/information/tag/tag.stories.d.ts +8 -0
  213. package/dist/ui/information/tag/tag.stories.js +25 -0
  214. package/dist/ui/information/text/typo.d.ts +13 -0
  215. package/dist/ui/information/text/typo.js +41 -0
  216. package/dist/ui/information/text/typo.stories.d.ts +10 -0
  217. package/dist/ui/information/text/typo.stories.js +60 -0
  218. package/dist/ui/information/typo.d.ts +12 -0
  219. package/dist/ui/information/typo.js +41 -0
  220. package/dist/ui/layout/dropdown/dropdown.d.ts +11 -0
  221. package/dist/ui/layout/dropdown/dropdown.js +44 -0
  222. package/dist/ui/layout/dropdown/dropdown.stories.d.ts +6 -0
  223. package/dist/ui/layout/dropdown/dropdown.stories.js +24 -0
  224. package/dist/ui/layout/flex/flex.d.ts +13 -0
  225. package/dist/ui/layout/flex/flex.js +36 -0
  226. package/dist/ui/layout/flex/flex.stories.d.ts +8 -0
  227. package/dist/ui/layout/flex/flex.stories.js +53 -0
  228. package/dist/ui/layout/icon-action/icon-action.d.ts +9 -0
  229. package/dist/ui/layout/icon-action/icon-action.js +11 -0
  230. package/dist/ui/layout/icon-action/icon-action.stories.d.ts +7 -0
  231. package/dist/ui/layout/icon-action/icon-action.stories.js +23 -0
  232. package/dist/ui/layout/index.d.ts +5 -0
  233. package/dist/ui/layout/index.js +5 -0
  234. package/dist/ui/layout/main-page-layout/main-page-layout.d.ts +7 -0
  235. package/dist/ui/layout/main-page-layout/main-page-layout.js +8 -0
  236. package/dist/ui/layout/main-page-layout/main-page-layout.stories.d.ts +6 -0
  237. package/dist/ui/layout/main-page-layout/main-page-layout.stories.js +19 -0
  238. package/dist/ui/layout/offset/offset.d.ts +7 -0
  239. package/dist/ui/layout/offset/offset.js +10 -0
  240. package/dist/ui/layout/offset/offset.stories.d.ts +8 -0
  241. package/dist/ui/layout/offset/offset.stories.js +33 -0
  242. package/dist/utils/classes.d.ts +1 -0
  243. package/dist/utils/classes.js +1 -0
  244. package/dist/utils/index.d.ts +1 -0
  245. package/dist/utils/index.js +1 -0
  246. package/package.json +67 -0
@@ -0,0 +1,80 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { ChevronDown } from 'lucide-react';
3
+ import { useMemo, useRef, useState } from 'react';
4
+ import { jc } from '../../../utils';
5
+ import { Cell, Typo } from '../../information';
6
+ import { Dropdown, Flex, Offset } from '../../layout';
7
+ import { Input } from '../input/input';
8
+ export function Select({ options, value, onChange, label, placeholder = 'Select...', disabled, }) {
9
+ const [isOpen, setIsOpen] = useState(false);
10
+ const [search, setSearch] = useState('');
11
+ const [activeIndex, setActiveIndex] = useState(-1);
12
+ const containerRef = useRef(null);
13
+ const selectedOption = useMemo(() => options.find((opt) => opt.value === value), [options, value]);
14
+ const filteredOptions = useMemo(() => {
15
+ if (!search)
16
+ return options;
17
+ return options.filter((opt) => opt.label.toLowerCase().includes(search.toLowerCase()));
18
+ }, [options, search]);
19
+ const handleSelect = (option) => {
20
+ onChange(option.value);
21
+ setIsOpen(false);
22
+ setSearch('');
23
+ setActiveIndex(-1);
24
+ };
25
+ const handleToggle = () => {
26
+ if (disabled)
27
+ return;
28
+ const nextOpen = !isOpen;
29
+ setIsOpen(nextOpen);
30
+ setActiveIndex(-1);
31
+ if (!nextOpen) {
32
+ setSearch('');
33
+ }
34
+ };
35
+ const handleKeyDown = (e) => {
36
+ if (disabled)
37
+ return;
38
+ if (!isOpen) {
39
+ if (e.key === 'ArrowDown' || e.key === 'ArrowUp' || e.key === 'Enter') {
40
+ setIsOpen(true);
41
+ setActiveIndex(-1);
42
+ e.preventDefault();
43
+ }
44
+ return;
45
+ }
46
+ switch (e.key) {
47
+ case 'ArrowDown':
48
+ e.preventDefault();
49
+ setActiveIndex((prev) => (prev < filteredOptions.length - 1 ? prev + 1 : prev));
50
+ break;
51
+ case 'ArrowUp':
52
+ e.preventDefault();
53
+ setActiveIndex((prev) => (prev > 0 ? prev - 1 : 0));
54
+ break;
55
+ case 'Enter':
56
+ e.preventDefault();
57
+ if (activeIndex >= 0 && activeIndex < filteredOptions.length) {
58
+ handleSelect(filteredOptions[activeIndex]);
59
+ }
60
+ else if (filteredOptions.length === 1) {
61
+ handleSelect(filteredOptions[0]);
62
+ }
63
+ break;
64
+ case 'Escape':
65
+ setIsOpen(false);
66
+ setActiveIndex(-1);
67
+ break;
68
+ }
69
+ };
70
+ return (_jsxs("div", { ref: containerRef, className: "relative flex w-full cursor-pointer flex-col gap-[2px] outline-none", onClick: handleToggle, onKeyDown: handleKeyDown, tabIndex: disabled ? -1 : 0, children: [label && (_jsx(Offset, { children: _jsx(Typo, { size: 's', color: 'secondary', weight: '500', children: label }) })), _jsxs("div", { className: "relative w-full", children: [_jsxs("div", { className: jc('flex min-h-[36px] w-full items-center justify-between rounded bg-background-accent pb-1 transition-all duration-200'), children: [isOpen ? (_jsx(Input, { size: 'l', autoFocus: true, placeholder: selectedOption?.label || placeholder, value: search, onChange: (e) => {
71
+ setSearch(e.target.value);
72
+ setActiveIndex(-1);
73
+ }, onClick: (e) => e.stopPropagation() })) : (_jsx(Offset, { children: _jsx(Typo, { size: 'l', color: selectedOption?.label ? 'default' : 'secondary', weight: '500', children: selectedOption?.label || placeholder }) })), _jsx(ChevronDown, { size: 16, className: jc('opacity-50 transition-transform duration-200 mr-l', isOpen ? 'rotate-180' : undefined) })] }), _jsx(Dropdown, { isOpen: isOpen, onClose: () => {
74
+ setIsOpen(false);
75
+ setActiveIndex(-1);
76
+ }, anchorRef: containerRef, children: filteredOptions.length > 0 ? (_jsx(Flex, { direction: 'column', gap: '4px', children: filteredOptions.map((option, index) => (_jsx(Cell, { active: index === activeIndex, onClick: (e) => {
77
+ e.stopPropagation();
78
+ handleSelect(option);
79
+ }, title: _jsx(Typo, { size: 'l', color: 'secondary', children: option.label }) }, option.label))) })) : (_jsx("div", { className: "px-4 py-2 text-[12px] text-secondary-foreground", children: "No options found" })) })] })] }));
80
+ }
@@ -0,0 +1,8 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Select } from './select';
3
+ declare const meta: Meta<typeof Select>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Default: Story;
7
+ export declare const WithoutLabel: Story;
8
+ export declare const Disabled: Story;
@@ -0,0 +1,40 @@
1
+ import { Select } from './select';
2
+ const meta = {
3
+ title: 'Controls/Select',
4
+ component: Select,
5
+ tags: ['autodocs'],
6
+ argTypes: {
7
+ onChange: { action: 'changed' },
8
+ },
9
+ };
10
+ export default meta;
11
+ const options = [
12
+ { value: '1', label: 'Option 1' },
13
+ { value: '2', label: 'Option 2' },
14
+ { value: '3', label: 'Option 3' },
15
+ { value: '4', label: 'Option 4' },
16
+ { value: '5', label: 'Option 5' },
17
+ ];
18
+ export const Default = {
19
+ args: {
20
+ label: 'Choose an option',
21
+ options,
22
+ value: '1',
23
+ placeholder: 'Select...',
24
+ },
25
+ };
26
+ export const WithoutLabel = {
27
+ args: {
28
+ options,
29
+ value: '',
30
+ placeholder: 'Pick something',
31
+ },
32
+ };
33
+ export const Disabled = {
34
+ args: {
35
+ label: 'Disabled Select',
36
+ options,
37
+ value: '1',
38
+ disabled: true,
39
+ },
40
+ };
@@ -0,0 +1,11 @@
1
+ import { type ChangeEvent, type FC } from 'react';
2
+ export type TTextAreaProps = {
3
+ value: string;
4
+ onChange: (e: ChangeEvent<HTMLTextAreaElement>) => void;
5
+ label?: string;
6
+ placeholder?: string;
7
+ required?: boolean;
8
+ disabled?: boolean;
9
+ size?: 's' | 'm' | 'l';
10
+ };
11
+ export declare const TextArea: FC<TTextAreaProps>;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useEffect, useRef } from 'react';
3
+ import { jc } from '../../../utils';
4
+ import { Typo } from '../../information';
5
+ import { Offset } from '../../layout';
6
+ const sizeMap = {
7
+ s: 'text-[12px] font-normal placeholder:text-[12px] placeholder:font-normal',
8
+ m: 'text-[14px] font-medium placeholder:text-[14px] placeholder:font-medium',
9
+ l: 'text-[16px] font-medium placeholder:text-[16px] placeholder:font-medium',
10
+ };
11
+ export const TextArea = ({ onChange, label, value, required, disabled, placeholder, size = 'm', }) => {
12
+ const textareaRef = useRef(null);
13
+ useEffect(() => {
14
+ if (textareaRef.current) {
15
+ textareaRef.current.style.height = 'auto';
16
+ textareaRef.current.style.height = `${textareaRef.current.scrollHeight}px`;
17
+ }
18
+ }, [value]);
19
+ return (_jsxs("label", { className: "flex w-full cursor-pointer flex-col gap-[2px]", children: [_jsx(Offset, { children: _jsx(Typo, { size: 's', color: 'secondary', weight: '500', children: label }) }), _jsx("textarea", { ref: textareaRef, className: jc('w-full cursor-text resize-none overflow-hidden rounded-sm border-none bg-inherit px-4 pb-2 pt-1 outline-none transition-all duration-200 placeholder:text-secondary-foreground', sizeMap[size]), placeholder: placeholder, value: value, onChange: onChange, disabled: disabled, required: required, rows: 1 })] }));
20
+ };
@@ -0,0 +1,8 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { TextArea } from './textarea';
3
+ declare const meta: Meta<typeof TextArea>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Default: Story;
7
+ export declare const WithValue: Story;
8
+ export declare const Disabled: Story;
@@ -0,0 +1,35 @@
1
+ import { TextArea } from './textarea';
2
+ const meta = {
3
+ title: 'Controls/TextArea',
4
+ component: TextArea,
5
+ tags: ['autodocs'],
6
+ argTypes: {
7
+ onChange: { action: 'changed' },
8
+ size: {
9
+ control: 'select',
10
+ options: ['s', 'm', 'l'],
11
+ },
12
+ },
13
+ };
14
+ export default meta;
15
+ export const Default = {
16
+ args: {
17
+ label: 'Description',
18
+ value: '',
19
+ placeholder: 'Type something...',
20
+ },
21
+ };
22
+ export const WithValue = {
23
+ args: {
24
+ label: 'Bio',
25
+ value: 'This is a long text that should automatically resize the textarea as it gets longer and longer...',
26
+ placeholder: 'Tell us about yourself',
27
+ },
28
+ };
29
+ export const Disabled = {
30
+ args: {
31
+ label: 'Disabled TextArea',
32
+ value: 'ReadOnly content',
33
+ disabled: true,
34
+ },
35
+ };
@@ -0,0 +1,3 @@
1
+ export * from './information';
2
+ export * from './controls';
3
+ export * from './layout';
@@ -0,0 +1,3 @@
1
+ export * from './information';
2
+ export * from './controls';
3
+ export * from './layout';
@@ -0,0 +1,10 @@
1
+ import type { FC, PropsWithChildren, ReactElement, ReactNode } from 'react';
2
+ import type { TTypoProps } from '../text/typo';
3
+ export type TBlockProps = PropsWithChildren<{
4
+ title?: ReactElement<TTypoProps>;
5
+ type?: 'fill' | 'hug';
6
+ topAcc?: ReactNode;
7
+ maxWidth?: number | string;
8
+ maxHeight?: number | string;
9
+ }>;
10
+ export declare const Block: FC<TBlockProps>;
@@ -0,0 +1,10 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { jc } from '../../../utils';
3
+ import { Flex, Offset } from '../../layout';
4
+ const typeMap = {
5
+ fill: 'h-full',
6
+ hug: 'h-auto',
7
+ };
8
+ export const Block = ({ children, title, topAcc, type = 'fill', maxWidth, maxHeight, }) => {
9
+ return (_jsx("div", { className: jc('w-full', 'relative rounded-2xl', 'bg-background-accent', 'shadow-[0_0_8px_var(--shadow)]', 'scrollbar-none', 'overflow-hidden', 'overflow-y-auto', typeMap[type]), style: { maxWidth, maxHeight }, children: _jsxs(Flex, { direction: 'column', type: 'fill', children: [_jsx("div", { className: jc('sticky', 'top-0', 'z-20', 'bg-background-accent', 'w-full'), children: _jsxs(Flex, { justify: 'space-between', align: 'center', children: [title && _jsx(Offset, { type: 'both', children: title }), _jsx("div", { className: 'mx-m', children: _jsx(Flex, { align: 'center', gap: '4px', children: topAcc }) })] }) }), children] }) }));
10
+ };
@@ -0,0 +1,8 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Block } from './block';
3
+ declare const meta: Meta<typeof Block>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Default: Story;
7
+ export declare const WithTopAcc: Story;
8
+ export declare const Fill: Story;
@@ -0,0 +1,38 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Block } from './block';
3
+ import { Typo } from '../text/typo';
4
+ const meta = {
5
+ title: 'Information/Block',
6
+ component: Block,
7
+ tags: ['autodocs'],
8
+ argTypes: {
9
+ type: {
10
+ control: 'select',
11
+ options: ['fill', 'hug'],
12
+ },
13
+ },
14
+ };
15
+ export default meta;
16
+ export const Default = {
17
+ args: {
18
+ title: _jsx(Typo, { weight: "500", children: "Block Title" }),
19
+ children: (_jsx("div", { className: "p-4", children: _jsx(Typo, { children: "This is the content of the block." }) })),
20
+ type: 'hug',
21
+ },
22
+ };
23
+ export const WithTopAcc = {
24
+ args: {
25
+ title: _jsx(Typo, { weight: "500", children: "Settings" }),
26
+ topAcc: _jsx("button", { className: "text-xs text-accent", children: "Edit" }),
27
+ children: (_jsx("div", { className: "p-4", children: _jsx(Typo, { children: "Content with top accessory." }) })),
28
+ type: 'hug',
29
+ },
30
+ };
31
+ export const Fill = {
32
+ args: {
33
+ title: _jsx(Typo, { weight: "500", children: "Full Height Block" }),
34
+ children: (_jsx("div", { className: "p-4 h-[200px]", children: _jsx(Typo, { children: "This block is set to fill height." }) })),
35
+ type: 'fill',
36
+ maxHeight: 300,
37
+ },
38
+ };
@@ -0,0 +1,26 @@
1
+ import type { LucideProps } from 'lucide-react';
2
+ import { type FC, type MouseEvent, type ReactElement } from 'react';
3
+ import type { TTypoProps, TUIColor } from '../text/typo';
4
+ export type TAccessory = {
5
+ icon: FC<LucideProps>;
6
+ onClick?: VoidFunction;
7
+ color?: string;
8
+ strokeWidth?: number;
9
+ bgc?: CSSStyleDeclaration['backgroundColor'];
10
+ };
11
+ export type TCellProps = {
12
+ title: ReactElement<TTypoProps>;
13
+ subtitle?: ReactElement<TTypoProps>;
14
+ description?: ReactElement<TTypoProps>;
15
+ onClick?: (e: MouseEvent<HTMLDivElement>) => void;
16
+ accLeft?: TAccessory[];
17
+ accRight?: TAccessory[];
18
+ disabled?: boolean;
19
+ active?: boolean;
20
+ tags?: {
21
+ id: string;
22
+ title: string;
23
+ color?: TUIColor;
24
+ }[];
25
+ };
26
+ export declare const Cell: FC<TCellProps>;
@@ -0,0 +1,31 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import React, { Activity, createElement } from 'react';
3
+ import { jc } from '../../../utils';
4
+ import { Flex, IconAction } from '../../layout';
5
+ import { Tag } from '../tag/tag';
6
+ export const Cell = ({ title, subtitle, description, accLeft, accRight, onClick, tags, disabled = false, active = false, }) => {
7
+ const getColor = (defaultColor = 'default') => {
8
+ if (disabled)
9
+ return { ui: 'secondary', icon: 'var(--secondary-foreground)' };
10
+ if (active)
11
+ return { ui: 'accent', icon: 'var(--accent)' };
12
+ return { ui: defaultColor || 'default', icon: 'var(--foreground)' };
13
+ };
14
+ return (_jsx("div", { className: jc('w-full px-l py-m select-none min-h-[32px]', onClick && !disabled ? 'cursor-pointer transition-all duration-200 hover:bg-[var(--shadow)]' : undefined), onClick: !disabled ? onClick : undefined, children: _jsxs(Flex, { type: 'fill', justify: 'space-between', children: [_jsx(Activity, { mode: accLeft?.length ? 'visible' : 'hidden', children: accLeft?.map((acc, i) => (_jsx(IconAction, { icon: createElement(acc.icon, {
15
+ size: 16,
16
+ color: acc.color || getColor().icon,
17
+ strokeWidth: acc.strokeWidth || 2,
18
+ }), bgc: acc.bgc, onClick: acc.onClick }, acc.icon.name + i.toString()))) }), _jsxs(Flex, { direction: 'column', type: 'fill', justify: 'center', gap: '4px', children: [subtitle &&
19
+ React.cloneElement(subtitle, {
20
+ color: getColor(subtitle.props.color).ui,
21
+ }), React.cloneElement(title, {
22
+ color: getColor(title.props.color).ui,
23
+ }), description &&
24
+ React.cloneElement(description, {
25
+ color: getColor(description.props.color).ui,
26
+ }), !!tags?.length && (_jsx("span", { className: 'mt-xs flex gap-xs', children: tags?.map((tag) => (_jsx(Tag, { color: tag.color, children: tag.title }, tag.id))) }))] }), _jsx(Activity, { mode: accRight?.length ? 'visible' : 'hidden', children: accRight?.map((acc, i) => (_jsx(IconAction, { icon: createElement(acc.icon, {
27
+ size: 16,
28
+ color: acc.color || getColor().icon,
29
+ strokeWidth: acc.strokeWidth || 2,
30
+ }), bgc: acc.bgc, onClick: acc.onClick }, acc.icon.name + i.toString()))) })] }) }));
31
+ };
@@ -0,0 +1,11 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Cell } from './cell';
3
+ declare const meta: Meta<typeof Cell>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Default: Story;
7
+ export declare const WithSubtitleAndDescription: Story;
8
+ export declare const WithAccessories: Story;
9
+ export declare const WithTags: Story;
10
+ export declare const Active: Story;
11
+ export declare const Disabled: Story;
@@ -0,0 +1,62 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Mail, Settings } from 'lucide-react';
3
+ import { Cell } from './cell';
4
+ import { Typo } from '../text/typo';
5
+ const meta = {
6
+ title: 'Information/Cell',
7
+ component: Cell,
8
+ tags: ['autodocs'],
9
+ argTypes: {
10
+ onClick: { action: 'clicked' },
11
+ },
12
+ };
13
+ export default meta;
14
+ export const Default = {
15
+ args: {
16
+ title: _jsx(Typo, { weight: "500", children: "Cell Title" }),
17
+ },
18
+ };
19
+ export const WithSubtitleAndDescription = {
20
+ args: {
21
+ title: _jsx(Typo, { weight: "500", children: "John Doe" }),
22
+ subtitle: _jsx(Typo, { size: "s", children: "Lead Developer" }),
23
+ description: _jsx(Typo, { size: "xs", children: "Currently working on Storybook integration." }),
24
+ },
25
+ };
26
+ export const WithAccessories = {
27
+ args: {
28
+ title: _jsx(Typo, { weight: "500", children: "Contact Support" }),
29
+ accLeft: [
30
+ {
31
+ icon: Mail,
32
+ },
33
+ ],
34
+ accRight: [
35
+ {
36
+ icon: Settings,
37
+ onClick: () => alert('Settings clicked'),
38
+ },
39
+ ],
40
+ },
41
+ };
42
+ export const WithTags = {
43
+ args: {
44
+ title: _jsx(Typo, { weight: "500", children: "Task #123" }),
45
+ tags: [
46
+ { id: '1', title: 'High Priority', color: '#ef4444' },
47
+ { id: '2', title: 'Feature', color: '#3b82f6' },
48
+ ],
49
+ },
50
+ };
51
+ export const Active = {
52
+ args: {
53
+ title: _jsx(Typo, { weight: "500", children: "Active Cell" }),
54
+ active: true,
55
+ },
56
+ };
57
+ export const Disabled = {
58
+ args: {
59
+ title: _jsx(Typo, { weight: "500", children: "Disabled Cell" }),
60
+ disabled: true,
61
+ },
62
+ };
@@ -0,0 +1,9 @@
1
+ import type { FC, ReactElement } from 'react';
2
+ import type { TCellProps } from './cell';
3
+ import type { TTypoProps } from '../text/typo';
4
+ type TProps = {
5
+ title?: ReactElement<TTypoProps>;
6
+ children: ReactElement<TCellProps> | ReactElement<TCellProps>[];
7
+ };
8
+ export declare const CellsBlock: FC<TProps>;
9
+ export {};
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Block } from '../block/block';
3
+ export const CellsBlock = ({ children, title }) => {
4
+ return _jsx(Block, { title: title, children: children });
5
+ };
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { CellsBlock } from './cells-block';
3
+ declare const meta: Meta<typeof CellsBlock>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Default: Story;
@@ -0,0 +1,20 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Cell } from './cell';
3
+ import { CellsBlock } from './cells-block';
4
+ import { Typo } from '../text/typo';
5
+ const meta = {
6
+ title: 'Information/CellsBlock',
7
+ component: CellsBlock,
8
+ tags: ['autodocs'],
9
+ };
10
+ export default meta;
11
+ export const Default = {
12
+ args: {
13
+ title: _jsx(Typo, { weight: "500", children: "Group of Cells" }),
14
+ children: [
15
+ _jsx(Cell, { title: _jsx(Typo, { children: "First Cell" }) }, "1"),
16
+ _jsx(Cell, { title: _jsx(Typo, { children: "Second Cell" }) }, "2"),
17
+ _jsx(Cell, { title: _jsx(Typo, { children: "Third Cell" }) }, "3"),
18
+ ],
19
+ },
20
+ };
@@ -0,0 +1,6 @@
1
+ export * from './block/block';
2
+ export * from './cell/cell';
3
+ export * from './cell/cells-block';
4
+ export * from './spinner/spinner';
5
+ export * from './tag/tag';
6
+ export * from './text/typo';
@@ -0,0 +1,6 @@
1
+ export * from './block/block';
2
+ export * from './cell/cell';
3
+ export * from './cell/cells-block';
4
+ export * from './spinner/spinner';
5
+ export * from './tag/tag';
6
+ export * from './text/typo';
@@ -0,0 +1,2 @@
1
+ import React from 'react';
2
+ export declare const Spinner: React.FC;
@@ -0,0 +1,5 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Loader2 } from 'lucide-react';
3
+ export const Spinner = () => {
4
+ return (_jsxs("span", { role: "status", "aria-label": "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430", className: "inline-flex items-center", children: [_jsx(Loader2, { size: 16, strokeWidth: 2, className: "animate-spin text-accent" }), _jsx("span", { className: "sr-only", children: "\u0417\u0430\u0433\u0440\u0443\u0437\u043A\u0430" })] }));
5
+ };
@@ -0,0 +1,6 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Spinner } from './spinner';
3
+ declare const meta: Meta<typeof Spinner>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Default: Story;
@@ -0,0 +1,8 @@
1
+ import { Spinner } from './spinner';
2
+ const meta = {
3
+ title: 'Information/Spinner',
4
+ component: Spinner,
5
+ tags: ['autodocs'],
6
+ };
7
+ export default meta;
8
+ export const Default = {};
@@ -0,0 +1,6 @@
1
+ import type { FC } from 'react';
2
+ export type TTagProps = {
3
+ children: string;
4
+ color?: string;
5
+ };
6
+ export declare const Tag: FC<TTagProps>;
@@ -0,0 +1,7 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Typo } from '../text/typo';
3
+ export const Tag = ({ children, color }) => {
4
+ return (_jsx("span", { className: `inline py-xs text-nowrap px-m no-underline rounded-xl text-xxs w-min`, style: {
5
+ backgroundColor: `${color}22`,
6
+ }, children: _jsx(Typo, { size: 'inherit', weight: '500', color: color, children: children }) }));
7
+ };
@@ -0,0 +1,8 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Tag } from './tag';
3
+ declare const meta: Meta<typeof Tag>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Default: Story;
7
+ export declare const Blue: Story;
8
+ export declare const Green: Story;
@@ -0,0 +1,25 @@
1
+ import { Tag } from './tag';
2
+ const meta = {
3
+ title: 'Information/Tag',
4
+ component: Tag,
5
+ tags: ['autodocs'],
6
+ };
7
+ export default meta;
8
+ export const Default = {
9
+ args: {
10
+ children: 'Priority',
11
+ color: '#ef4444',
12
+ },
13
+ };
14
+ export const Blue = {
15
+ args: {
16
+ children: 'Feature',
17
+ color: '#3b82f6',
18
+ },
19
+ };
20
+ export const Green = {
21
+ args: {
22
+ children: 'Completed',
23
+ color: '#10b981',
24
+ },
25
+ };
@@ -0,0 +1,12 @@
1
+ import { type CSSProperties, type FC, type PropsWithChildren } from 'react';
2
+ type TypoSize = 'inherit' | 'xs' | 's' | 'm' | 'l' | 'xl';
3
+ export type TUIColor = 'accent' | 'secondary' | 'default' | 'error' | string;
4
+ type TypoWeight = '300' | '400' | '500';
5
+ export type TTypoProps = PropsWithChildren<{
6
+ size?: TypoSize;
7
+ color?: TUIColor;
8
+ weight?: TypoWeight;
9
+ textDecoration?: CSSProperties['textDecoration'];
10
+ }>;
11
+ export declare const Typo: FC<TTypoProps>;
12
+ export {};
@@ -0,0 +1,41 @@
1
+ import { createElement } from 'react';
2
+ import { jc } from '../../../utils';
3
+ const SIZE_TO_TAG_CONFIG = {
4
+ inherit: 'span',
5
+ xs: 'p',
6
+ s: 'p',
7
+ m: 'p',
8
+ l: 'h2',
9
+ xl: 'h1',
10
+ };
11
+ const sizeMap = {
12
+ inherit: 'text-inherit',
13
+ xs: 'text-xs',
14
+ s: 'text-s',
15
+ m: 'text-m',
16
+ l: 'text-l',
17
+ xl: 'text-xl',
18
+ };
19
+ const weightMap = {
20
+ '300': 'font-light',
21
+ '400': 'font-normal',
22
+ '500': 'font-medium',
23
+ };
24
+ const colorMap = {
25
+ default: 'text-foreground',
26
+ secondary: 'text-secondary-foreground',
27
+ accent: 'text-accent',
28
+ error: 'text-error',
29
+ };
30
+ export const Typo = ({ children, size = 'm', color = 'default', weight = '400', textDecoration = 'none', }) => {
31
+ const tag = SIZE_TO_TAG_CONFIG[size];
32
+ const colorClass = colorMap[color] || '';
33
+ const inlineColor = !colorMap[color] ? color : undefined;
34
+ return createElement(tag, {
35
+ className: jc(sizeMap[size], colorClass, weightMap[weight]),
36
+ style: {
37
+ color: inlineColor,
38
+ textDecoration: textDecoration,
39
+ },
40
+ }, children);
41
+ };
@@ -0,0 +1,10 @@
1
+ import type { Meta, StoryObj } from '@storybook/react-vite';
2
+ import { Typo } from './typo';
3
+ declare const meta: Meta<typeof Typo>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof meta>;
6
+ export declare const Default: Story;
7
+ export declare const LargeHeading: Story;
8
+ export declare const AccentText: Story;
9
+ export declare const ErrorText: Story;
10
+ export declare const CustomColor: Story;