oneslash-design-system 1.2.23 → 1.2.25

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 (84) hide show
  1. package/dist/components/alert.d.ts +4 -2
  2. package/dist/components/alert.jsx +18 -13
  3. package/dist/components/button.d.ts +2 -1
  4. package/dist/components/button.jsx +5 -2
  5. package/dist/components/checkBox.d.ts +3 -1
  6. package/dist/components/checkBox.jsx +28 -9
  7. package/dist/components/emptyBox.d.ts +2 -1
  8. package/dist/components/emptyBox.jsx +9 -4
  9. package/dist/components/icon.d.ts +12 -0
  10. package/dist/components/icon.jsx +30 -0
  11. package/dist/components/iconButton.jsx +28 -22
  12. package/dist/components/line.d.ts +7 -0
  13. package/dist/components/line.jsx +10 -0
  14. package/dist/components/link.d.ts +11 -0
  15. package/dist/components/link.jsx +59 -0
  16. package/dist/components/menuItem.d.ts +2 -1
  17. package/dist/components/menuItem.jsx +12 -7
  18. package/dist/components/modal.d.ts +3 -2
  19. package/dist/components/modal.jsx +43 -23
  20. package/dist/components/radioGroup.d.ts +1 -0
  21. package/dist/components/radioGroup.jsx +4 -1
  22. package/dist/components/tab.d.ts +6 -1
  23. package/dist/components/tab.jsx +11 -9
  24. package/dist/components/tabsContainer.jsx +4 -1
  25. package/dist/components/tag.d.ts +6 -3
  26. package/dist/components/tag.jsx +88 -28
  27. package/dist/components/textField.d.ts +5 -2
  28. package/dist/components/textField.jsx +29 -16
  29. package/dist/components/textarea.d.ts +4 -2
  30. package/dist/components/textarea.jsx +31 -11
  31. package/dist/output.css +600 -385
  32. package/dist/stories/Alert.stories.d.ts +15 -0
  33. package/dist/stories/Alert.stories.jsx +121 -0
  34. package/dist/stories/Button.stories.d.ts +12 -0
  35. package/dist/stories/Button.stories.jsx +81 -0
  36. package/dist/stories/Checkbox.stories.d.ts +10 -0
  37. package/dist/stories/Checkbox.stories.jsx +45 -0
  38. package/dist/stories/EmptyBox.stories.d.ts +7 -0
  39. package/dist/stories/EmptyBox.stories.jsx +30 -0
  40. package/dist/stories/Icon.stories.d.ts +13 -0
  41. package/dist/stories/Icon.stories.jsx +130 -0
  42. package/dist/stories/IconButton.stories.d.ts +13 -0
  43. package/dist/stories/IconButton.stories.jsx +87 -0
  44. package/dist/stories/Line.stories.d.ts +9 -0
  45. package/dist/stories/Line.stories.jsx +64 -0
  46. package/dist/stories/Link.stories.d.ts +10 -0
  47. package/dist/stories/Link.stories.jsx +59 -0
  48. package/dist/stories/LoadingScreen.stories.d.ts +10 -0
  49. package/dist/stories/LoadingScreen.stories.jsx +39 -0
  50. package/dist/stories/Menu.stories.d.ts +8 -0
  51. package/dist/stories/Menu.stories.jsx +42 -0
  52. package/dist/stories/MenuItem.stories.d.ts +11 -0
  53. package/dist/stories/MenuItem.stories.jsx +62 -0
  54. package/dist/stories/Modal.stories.d.ts +10 -0
  55. package/dist/stories/Modal.stories.jsx +77 -0
  56. package/dist/stories/Navigation.stories.d.ts +7 -0
  57. package/dist/stories/Navigation.stories.jsx +31 -0
  58. package/dist/stories/Popover.stories.d.ts +7 -0
  59. package/dist/stories/Popover.stories.jsx +47 -0
  60. package/dist/stories/RadioGroup.stories.d.ts +8 -0
  61. package/dist/stories/RadioGroup.stories.jsx +53 -0
  62. package/dist/stories/Select.stories.d.ts +10 -0
  63. package/dist/stories/Select.stories.jsx +85 -0
  64. package/dist/stories/Tab.stories.d.ts +11 -0
  65. package/dist/stories/Tab.stories.jsx +63 -0
  66. package/dist/stories/Table.stories.d.ts +8 -0
  67. package/dist/stories/Table.stories.jsx +84 -0
  68. package/dist/stories/TabsContainer.stories.d.ts +10 -0
  69. package/dist/stories/TabsContainer.stories.jsx +52 -0
  70. package/dist/stories/Tag.stories.d.ts +17 -0
  71. package/dist/stories/Tag.stories.jsx +143 -0
  72. package/dist/stories/TextField.stories.d.ts +13 -0
  73. package/dist/stories/TextField.stories.jsx +96 -0
  74. package/dist/stories/Textarea.stories.d.ts +12 -0
  75. package/dist/stories/Textarea.stories.jsx +84 -0
  76. package/dist/stories/TimeStamp.stories.d.ts +16 -0
  77. package/dist/stories/TimeStamp.stories.jsx +140 -0
  78. package/dist/stories/Tooltip.stories.d.ts +9 -0
  79. package/dist/stories/Tooltip.stories.jsx +52 -0
  80. package/dist/stories/UserImage.stories.d.ts +10 -0
  81. package/dist/stories/UserImage.stories.jsx +46 -0
  82. package/dist/tailwind.config.js +1 -0
  83. package/dist/tsconfig.tsbuildinfo +1 -1
  84. package/package.json +10 -3
@@ -36,12 +36,9 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
36
36
  }
37
37
  };
38
38
  import React, { useState, useEffect, useCallback } from 'react';
39
- import { useRouter, usePathname } from 'next/navigation';
40
39
  export default function Tab(_a) {
41
40
  var _this = this;
42
- var label = _a.label, href = _a.href, isSelected = _a.isSelected, onClickTab = _a.onClickTab, onClickActionIcon = _a.onClickActionIcon, decoIcon = _a.decoIcon, actionIcon = _a.actionIcon;
43
- var router = useRouter();
44
- var pathname = usePathname();
41
+ var label = _a.label, secondLabel = _a.secondLabel, href = _a.href, isSelected = _a.isSelected, onClickTab = _a.onClickTab, onClickActionIcon = _a.onClickActionIcon, decoIcon = _a.decoIcon, actionIcon = _a.actionIcon, router = _a.router;
45
42
  var _b = useState(null), IconLeft = _b[0], setIconLeft = _b[1];
46
43
  var _c = useState(null), IconRight = _c[0], setIconRight = _c[1];
47
44
  // Load icon dynamically
@@ -95,17 +92,22 @@ export default function Tab(_a) {
95
92
  }, [decoIcon, actionIcon, loadIcon]);
96
93
  var handleClick = function () {
97
94
  onClickTab();
98
- if (href) {
95
+ if (href && router) {
99
96
  router.push(href);
100
97
  }
101
98
  };
102
99
  return (<div className={"\n flex items-center space-x-1 py-1 px-[6px] rounded-[8px] cursor-pointer justify-start transition-colors duration-200 ease-in-out\n ".concat(isSelected
103
100
  ? 'bg-light-primary-dark dark:bg-dark-primary-dark text-light-text-contrast dark:text-dark-text-contrast'
104
- : 'hover:bg-light-background-accent200 dark:hover:bg-dark-background-accent200', "\n ")} onClick={handleClick}>
101
+ : 'text-light-text-primary dark:text-dark-text-primary hover:bg-light-background-accent200 dark:hover:bg-dark-background-accent200', "\n ")} onClick={handleClick}>
105
102
  {IconLeft && <IconLeft className="w-6 h-6" strokeWidth={2}/>}
106
- <span className="whitespace-nowrap text-body1 px-[6px]">
107
- {label}
108
- </span>
103
+ <div className="flex flex-col px-[6px] text-center">
104
+ <span className="whitespace-nowrap text-body1">
105
+ {label}
106
+ </span>
107
+ {secondLabel && (<span className="whitespace-nowrap text-body2 opacity-70">
108
+ {secondLabel}
109
+ </span>)}
110
+ </div>
109
111
  {IconRight && (<div onClick={onClickActionIcon} className="cursor-pointer">
110
112
  <IconRight className="w-6 h-6" strokeWidth={2}/>
111
113
  </div>)}
@@ -3,7 +3,10 @@ import React from 'react';
3
3
  export default function TabsContainer(_a) {
4
4
  var children = _a.children;
5
5
  var tabCount = React.Children.count(children);
6
- return (<div className={"\n flex space-x-2 p-1 rounded-[12px]\n ".concat(tabCount > 0 ? 'bg-light-background-accent100 dark:bg-dark-background-accent100' : 'bg-transparent', "\n ")}>
6
+ return (<div className={"\n flex space-x-2 p-1 rounded-[12px] overflow-x-auto\n ".concat(tabCount > 0 ? 'bg-light-background-accent100 dark:bg-dark-background-accent100' : 'bg-transparent', "\n ")} style={{
7
+ scrollbarWidth: 'none',
8
+ msOverflowStyle: 'none',
9
+ }}>
7
10
  {children}
8
11
  </div>);
9
12
  }
@@ -1,12 +1,15 @@
1
1
  import React from 'react';
2
- import * as LucideIcons from 'lucide-react';
2
+ import { icons } from 'lucide-react';
3
+ type IconName = keyof typeof icons;
3
4
  interface TagProps {
4
5
  variant: 'contained' | 'textOnly';
5
6
  size: 'medium' | 'small';
6
7
  state?: 'enabled' | 'selected';
8
+ color?: 'default' | 'success' | 'warning' | 'error' | 'info';
7
9
  label: React.ReactNode;
8
- iconName?: keyof typeof LucideIcons;
10
+ secondLabel?: string;
11
+ iconName?: IconName;
9
12
  onClick?: React.MouseEventHandler<HTMLDivElement>;
10
13
  }
11
- export default function Tag({ variant, size, state, label, iconName, onClick, }: TagProps): JSX.Element;
14
+ export default function Tag({ variant, size, state, color, label, secondLabel, iconName, onClick, }: TagProps): JSX.Element;
12
15
  export {};
@@ -1,43 +1,103 @@
1
1
  'use client';
2
- import React, { useState, useEffect } from 'react';
3
- import * as LucideIcons from 'lucide-react';
2
+ import React, { useState } from 'react';
3
+ import { icons } from 'lucide-react';
4
+ var colorConfig = {
5
+ default: {
6
+ bg: 'bg-light-secondary-light dark:bg-dark-secondary-light',
7
+ text: 'text-light-text-primary dark:text-dark-text-primary',
8
+ textOnly: 'text-light-text-secondary dark:text-dark-text-secondary',
9
+ border: 'border-light-misc-divider dark:border-dark-misc-divider',
10
+ hasBorderTextOnly: false,
11
+ },
12
+ success: {
13
+ bg: 'bg-light-success-main dark:bg-dark-success-main',
14
+ text: 'text-light-text-primary dark:text-dark-text-primary',
15
+ textOnly: 'text-light-success-main dark:text-dark-success-main',
16
+ border: 'border-light-success-main dark:border-dark-success-main',
17
+ hasBorderTextOnly: true,
18
+ },
19
+ warning: {
20
+ bg: 'bg-light-warning-main dark:bg-dark-warning-main',
21
+ text: 'text-light-text-primary dark:text-dark-text-primary',
22
+ textOnly: 'text-light-warning-main dark:text-dark-warning-main',
23
+ border: 'border-light-warning-main dark:border-dark-warning-main',
24
+ hasBorderTextOnly: true,
25
+ },
26
+ error: {
27
+ bg: 'bg-light-error-main dark:bg-dark-error-main',
28
+ text: 'text-light-text-primary dark:text-dark-text-primary',
29
+ textOnly: 'text-light-error-main dark:text-dark-error-main',
30
+ border: 'border-light-error-main dark:border-dark-error-main',
31
+ hasBorderTextOnly: true,
32
+ },
33
+ info: {
34
+ bg: 'bg-light-info-main dark:bg-dark-info-main',
35
+ text: 'text-light-text-primary dark:text-dark-text-primary',
36
+ textOnly: 'text-light-info-main dark:text-dark-info-main',
37
+ border: 'border-light-info-main dark:border-dark-info-main',
38
+ hasBorderTextOnly: true,
39
+ },
40
+ };
4
41
  export default function Tag(_a) {
5
- var variant = _a.variant, size = _a.size, _b = _a.state, state = _b === void 0 ? 'enabled' : _b, label = _a.label, iconName = _a.iconName, onClick = _a.onClick;
42
+ var variant = _a.variant, size = _a.size, _b = _a.state, state = _b === void 0 ? 'enabled' : _b, color = _a.color, label = _a.label, secondLabel = _a.secondLabel, iconName = _a.iconName, onClick = _a.onClick;
6
43
  var _c = useState(false), isHovered = _c[0], setIsHovered = _c[1];
7
- var _d = useState(null), Icon = _d[0], setIcon = _d[1];
8
- // Load icon directly from Lucide
9
- useEffect(function () {
10
- if (iconName) {
11
- setIcon(LucideIcons[iconName]);
12
- }
13
- }, [iconName]);
44
+ // Get icon directly from icons map
45
+ var Icon = iconName ? icons[iconName] : null;
14
46
  // Size and padding
15
47
  var sizeClasses = size === 'medium' ? 'text-body2 px-2 py-1' : 'text-caption px-2 py-[3px]';
16
48
  // Selected state styles
17
49
  var isSelected = state === 'selected';
50
+ // When color is provided, use color-based styling
51
+ var colorStyles = color ? colorConfig[color] : null;
18
52
  // Background color
19
- var bgClasses = isSelected && variant === 'contained'
20
- ? 'bg-light-accent-main dark:bg-dark-accent-main'
21
- : variant === 'contained'
22
- ? 'bg-light-background-accent300 dark:bg-dark-background-accent300'
23
- : '';
53
+ var bgClasses = '';
54
+ if (colorStyles) {
55
+ bgClasses = variant === 'contained' ? colorStyles.bg : '';
56
+ }
57
+ else if (isSelected && variant === 'contained') {
58
+ bgClasses = 'bg-light-accent-main dark:bg-dark-accent-main';
59
+ }
60
+ else if (variant === 'contained') {
61
+ bgClasses = 'bg-light-background-accent300 dark:bg-dark-background-accent300';
62
+ }
24
63
  // Font color
25
- var fontClasses = isSelected
26
- ? 'text-white'
27
- : 'text-light-text-primary dark:text-dark-text-primary';
64
+ var fontClasses = '';
65
+ if (colorStyles) {
66
+ fontClasses = variant === 'textOnly' ? colorStyles.textOnly : colorStyles.text;
67
+ }
68
+ else if (isSelected) {
69
+ fontClasses = 'text-white';
70
+ }
71
+ else {
72
+ fontClasses = 'text-light-text-primary dark:text-dark-text-primary';
73
+ }
28
74
  // Border styles
29
- var borderClasses = isSelected && variant === 'textOnly'
30
- ? 'border border-light-accent-main dark:border-dark-accent-main'
31
- : variant === 'contained'
32
- ? 'border border-light-misc-divider dark:border-dark-misc-divider'
33
- : '';
34
- // Hover (only when not selected and onClick is provided)
35
- var hoverClasses = !isSelected && variant === 'contained' && isHovered && onClick
75
+ var borderClasses = '';
76
+ if (colorStyles) {
77
+ if (variant === 'textOnly' && colorStyles.hasBorderTextOnly) {
78
+ borderClasses = "border ".concat(colorStyles.border);
79
+ }
80
+ else if (variant === 'contained') {
81
+ borderClasses = "border ".concat(colorStyles.border);
82
+ }
83
+ }
84
+ else if (isSelected && variant === 'textOnly') {
85
+ borderClasses = 'border border-light-accent-main dark:border-dark-accent-main';
86
+ }
87
+ else if (variant === 'contained') {
88
+ borderClasses = 'border border-light-misc-divider dark:border-dark-misc-divider';
89
+ }
90
+ // Hover (only when not selected, no color, and onClick is provided)
91
+ var hoverClasses = !isSelected && !color && variant === 'contained' && isHovered && onClick
36
92
  ? 'bg-light-background-accent200 dark:bg-dark-background-accent200'
37
93
  : '';
38
94
  var cursorClass = onClick && !isSelected ? 'cursor-pointer' : '';
39
- return (<div className={"\n flex items-center space-x-1 rounded-full\n ".concat(sizeClasses, " ").concat(bgClasses, " ").concat(fontClasses, " ").concat(borderClasses, " ").concat(hoverClasses, " ").concat(cursorClass, "\n transition-colors duration-200 ease-in-out\n ")} onMouseEnter={function () { return onClick && setIsHovered(true); }} onMouseLeave={function () { return onClick && setIsHovered(false); }} onClick={onClick}>
40
- {Icon && <Icon className="w-4 h-4" strokeWidth={2}/>}
41
- <span>{label}</span>
95
+ var baseClasses = 'flex space-x-2 items-center gap-1 rounded-full whitespace-nowrap transition-colors duration-200 ease-in-out';
96
+ return (<div className={"".concat(baseClasses, " ").concat(sizeClasses, " ").concat(bgClasses, " ").concat(fontClasses, " ").concat(borderClasses, " ").concat(hoverClasses, " ").concat(cursorClass)} onMouseEnter={function () { return onClick && setIsHovered(true); }} onMouseLeave={function () { return onClick && setIsHovered(false); }} onClick={onClick}>
97
+ {Icon && <Icon className="w-4 h-4 flex-shrink-0" strokeWidth={2}/>}
98
+ <div className="flex flex-col text-center">
99
+ <span>{label}</span>
100
+ {secondLabel && (<span className="text-caption opacity-70">{secondLabel}</span>)}
101
+ </div>
42
102
  </div>);
43
103
  }
@@ -3,17 +3,20 @@ interface TextFieldProps {
3
3
  id: string;
4
4
  label?: string;
5
5
  value: string;
6
+ type?: 'text' | 'password' | 'email' | 'number' | 'tel' | 'url' | 'search';
6
7
  onChange: (e: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
7
8
  onBlur?: (e: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
8
9
  onFocus?: (e: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
9
10
  onKeyDown?: (e: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => void;
11
+ onSubmit?: () => void;
10
12
  autoFocus?: boolean;
11
13
  multiline?: boolean;
12
14
  maxRows?: number;
13
15
  disabled?: boolean;
14
16
  error?: boolean;
17
+ required?: boolean;
15
18
  size?: 'large' | 'medium' | 'small';
19
+ placeholder?: string;
16
20
  }
17
- export default function TextField({ id, label, value, onChange, onBlur, onFocus, onKeyDown, autoFocus, // Accept the autoFocus prop with default value
18
- multiline, maxRows, disabled, error, size, }: TextFieldProps): React.JSX.Element;
21
+ export default function TextField({ id, label, value, type, onChange, onBlur, onFocus, onKeyDown, onSubmit, autoFocus, multiline, maxRows, disabled, error, required, size, placeholder, }: TextFieldProps): React.JSX.Element;
19
22
  export {};
@@ -1,20 +1,37 @@
1
1
  'use client';
2
2
  import React, { useState } from 'react';
3
3
  export default function TextField(_a) {
4
- var id = _a.id, label = _a.label, value = _a.value, onChange = _a.onChange, onBlur = _a.onBlur, onFocus = _a.onFocus, onKeyDown = _a.onKeyDown, _b = _a.autoFocus, autoFocus = _b === void 0 ? false : _b, // Accept the autoFocus prop with default value
5
- _c = _a.multiline, // Accept the autoFocus prop with default value
6
- multiline = _c === void 0 ? false : _c, _d = _a.maxRows, maxRows = _d === void 0 ? 6 : _d, _e = _a.disabled, disabled = _e === void 0 ? false : _e, _f = _a.error, error = _f === void 0 ? false : _f, _g = _a.size, size = _g === void 0 ? 'medium' : _g;
7
- var _h = useState(false), isFocused = _h[0], setIsFocused = _h[1];
4
+ var id = _a.id, label = _a.label, value = _a.value, _b = _a.type, type = _b === void 0 ? 'text' : _b, onChange = _a.onChange, onBlur = _a.onBlur, onFocus = _a.onFocus, onKeyDown = _a.onKeyDown, onSubmit = _a.onSubmit, _c = _a.autoFocus, autoFocus = _c === void 0 ? false : _c, _d = _a.multiline, multiline = _d === void 0 ? false : _d, _e = _a.maxRows, maxRows = _e === void 0 ? 6 : _e, _f = _a.disabled, disabled = _f === void 0 ? false : _f, _g = _a.error, error = _g === void 0 ? false : _g, _h = _a.required, required = _h === void 0 ? false : _h, _j = _a.size, size = _j === void 0 ? 'medium' : _j, placeholder = _a.placeholder;
5
+ var _k = useState(false), isFocused = _k[0], setIsFocused = _k[1];
6
+ var handleKeyDown = function (e) {
7
+ // Ctrl+Enter or Cmd+Enter to submit
8
+ if ((e.ctrlKey || e.metaKey) && e.key === 'Enter' && onSubmit) {
9
+ e.preventDefault();
10
+ onSubmit();
11
+ }
12
+ if (onKeyDown)
13
+ onKeyDown(e);
14
+ };
8
15
  // Define classes for size: text size and padding
9
16
  var sizeClasses = {
10
- large: 'text-body1 p-[7px] leading-[22px]', // body1 (16px), padding 8px(7 + border 1) height 40
11
- medium: 'text-body1 p-[3px] leading-[22px]', // body1 (16px), padding 4px(3 + border 1), height 32
12
- small: 'text-body2 p-[3px] leading-[18px]', // body2 (14px), padding 4px(3 + border 1), height 28
17
+ large: 'text-body1 p-2 leading-[22px]', // body1 (16px), padding 8px
18
+ medium: 'text-body1 p-2 leading-[22px]', // body1 (16px), padding 8px
19
+ small: 'text-body2 p-2 leading-[18px]', // body2 (14px), padding 8px
13
20
  }[size];
14
- var baseClasses = 'w-full border rounded-[8px]';
21
+ var baseClasses = 'w-full border rounded-[8px] outline-none';
22
+ var textColor = 'text-light-text-primary dark:text-dark-text-primary';
15
23
  var bgColor = 'bg-light-background-default dark:bg-dark-background-default transition-colors duration-200 ease-in-out';
16
- var borderColor = 'border-light-outlinedBorder-active dark:border-dark-outlinedBorder-active';
17
- var containerClasses = "\n ".concat(bgColor, "\n ").concat(borderColor, "\n ").concat(baseClasses, "\n ").concat(sizeClasses, "\n ").concat(disabled ? 'bg-gray-200 cursor-not-allowed' : '', "\n ").concat(error ? 'border-red-500 focus:ring-red-500' : '', "\n ").concat(isFocused ? 'focus:border-light-accent-main focus:dark:border-dark-accent-main outline-none' : '', "\n ").concat(!disabled && !error ? 'hover:border-light-outlinedBorder-hover' : '', "\n border-gray-300\n ");
24
+ // Border color logic: error > focused > default (misc-divider)
25
+ var getBorderColor = function () {
26
+ if (error) {
27
+ return 'border-light-error-main dark:border-dark-error-main';
28
+ }
29
+ if (isFocused) {
30
+ return 'border-light-text-primary dark:border-dark-text-primary';
31
+ }
32
+ return 'border-light-text-disabled dark:border-dark-text-disabled';
33
+ };
34
+ var containerClasses = "\n ".concat(bgColor, "\n ").concat(textColor, "\n ").concat(baseClasses, "\n ").concat(sizeClasses, "\n ").concat(getBorderColor(), "\n ").concat(disabled ? 'bg-light-actionBackground-disabled dark:bg-dark-actionBackground-disabled cursor-not-allowed' : '', "\n ");
18
35
  return (<div className="flex flex-col w-full">
19
36
  {label && (<label htmlFor={id} className="mb-1 text-body2 text-light-text-secondary dark:text-dark-text-secondary">
20
37
  {label}
@@ -28,9 +45,7 @@ export default function TextField(_a) {
28
45
  setIsFocused(false);
29
46
  if (onBlur)
30
47
  onBlur(e);
31
- }} onKeyDown={onKeyDown} autoFocus={autoFocus} // Pass autoFocus to textarea
32
- disabled={disabled} autoComplete="off" // Disable browser autocomplete/autofill
33
- />) : (<input id={id} type="text" className={containerClasses} value={value} onChange={onChange} onFocus={function (e) {
48
+ }} onKeyDown={handleKeyDown} autoFocus={autoFocus} disabled={disabled} required={required} autoComplete="off"/>) : (<input id={id} type={type} className={containerClasses} value={value} onChange={onChange} placeholder={placeholder} onFocus={function (e) {
34
49
  setIsFocused(true);
35
50
  if (onFocus)
36
51
  onFocus(e);
@@ -38,9 +53,7 @@ export default function TextField(_a) {
38
53
  setIsFocused(false);
39
54
  if (onBlur)
40
55
  onBlur(e);
41
- }} onKeyDown={onKeyDown} autoFocus={autoFocus} // Pass autoFocus to input
42
- disabled={disabled} autoComplete="off" // Disable browser autocomplete/autofill
43
- />)}
56
+ }} onKeyDown={handleKeyDown} autoFocus={autoFocus} disabled={disabled} required={required} autoComplete="off"/>)}
44
57
  </div>
45
58
  {error && (<p className="mt-1 text-light-error-main text-body2">
46
59
  This field is required
@@ -7,11 +7,13 @@ interface TextareaProps {
7
7
  onBlur?: (e: React.FocusEvent<HTMLTextAreaElement>) => void;
8
8
  onFocus?: (e: React.FocusEvent<HTMLTextAreaElement>) => void;
9
9
  onKeyDown?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void;
10
+ onSubmit?: () => void;
10
11
  autoFocus?: boolean;
11
12
  maxRows?: number;
12
13
  disabled?: boolean;
13
14
  error?: boolean;
14
- size?: 'large' | 'medium' | 'small';
15
+ size?: 'medium' | 'small';
16
+ placeholder?: string;
15
17
  }
16
- export default function Textarea({ id, label, value, onChange, onBlur, onFocus, onKeyDown, autoFocus, maxRows, disabled, error, size, }: TextareaProps): React.JSX.Element;
18
+ export default function Textarea({ id, label, value, onChange, onBlur, onFocus, onKeyDown, onSubmit, autoFocus, maxRows, disabled, error, size, placeholder, }: TextareaProps): React.JSX.Element;
17
19
  export {};
@@ -1,9 +1,18 @@
1
1
  'use client';
2
2
  import React, { useEffect, useRef, useState } from 'react';
3
3
  export default function Textarea(_a) {
4
- var id = _a.id, label = _a.label, value = _a.value, onChange = _a.onChange, onBlur = _a.onBlur, onFocus = _a.onFocus, onKeyDown = _a.onKeyDown, _b = _a.autoFocus, autoFocus = _b === void 0 ? false : _b, _c = _a.maxRows, maxRows = _c === void 0 ? 6 : _c, _d = _a.disabled, disabled = _d === void 0 ? false : _d, _e = _a.error, error = _e === void 0 ? false : _e, _f = _a.size, size = _f === void 0 ? 'medium' : _f;
4
+ var id = _a.id, label = _a.label, value = _a.value, onChange = _a.onChange, onBlur = _a.onBlur, onFocus = _a.onFocus, onKeyDown = _a.onKeyDown, onSubmit = _a.onSubmit, _b = _a.autoFocus, autoFocus = _b === void 0 ? false : _b, _c = _a.maxRows, maxRows = _c === void 0 ? 6 : _c, _d = _a.disabled, disabled = _d === void 0 ? false : _d, _e = _a.error, error = _e === void 0 ? false : _e, _f = _a.size, size = _f === void 0 ? 'medium' : _f, placeholder = _a.placeholder;
5
5
  var textareaRef = useRef(null);
6
6
  var _g = useState(false), isFocused = _g[0], setIsFocused = _g[1];
7
+ var handleKeyDown = function (e) {
8
+ // Ctrl+Enter or Cmd+Enter to submit
9
+ if ((e.ctrlKey || e.metaKey) && e.key === 'Enter' && onSubmit) {
10
+ e.preventDefault();
11
+ onSubmit();
12
+ }
13
+ if (onKeyDown)
14
+ onKeyDown(e);
15
+ };
7
16
  useEffect(function () {
8
17
  var textarea = textareaRef.current;
9
18
  if (!textarea)
@@ -15,8 +24,10 @@ export default function Textarea(_a) {
15
24
  var scrollHeight = textarea.scrollHeight;
16
25
  // Set height to scrollHeight, capped at maxRows, but at least 1 line
17
26
  textarea.style.height = "".concat(Math.max(Math.min(scrollHeight, maxHeight), lineHeight), "px");
18
- // Enable vertical scroll if content exceeds maxRows
19
- textarea.style.overflowY = scrollHeight > maxHeight ? 'auto' : 'hidden';
27
+ // Enable vertical scroll if content exceeds maxRows (hide scrollbar)
28
+ textarea.style.overflowY = scrollHeight > maxHeight ? 'scroll' : 'hidden';
29
+ textarea.style.scrollbarWidth = 'none'; // Firefox
30
+ textarea.style.msOverflowStyle = 'none'; // IE/Edge
20
31
  };
21
32
  // Set initial rows to 1 for single-line height
22
33
  textarea.rows = 1;
@@ -26,20 +37,29 @@ export default function Textarea(_a) {
26
37
  }, [maxRows]);
27
38
  // Define classes for size: text size and padding
28
39
  var sizeClasses = {
29
- large: 'text-body1 p-[7px] leading-[22px]', // body1 (16px), padding 8px(7 + border 1) height 40
30
- medium: 'text-body1 p-[3px] leading-[22px]', // body1 (16px), padding 4px(3 + border 1), height 32
31
- small: 'text-body2 p-[3px] leading-[18px]', // body2 (14px), padding 4px(3 + border 1), height 28
40
+ medium: 'text-body1 p-2 leading-[22px]', // body1 (16px), padding 8px
41
+ small: 'text-body2 p-2 leading-[18px]', // body2 (14px), padding 8px
32
42
  }[size];
33
- var baseClasses = 'w-full border rounded-[8px]';
43
+ var baseClasses = 'w-full border rounded-[8px] outline-none [&::-webkit-scrollbar]:hidden';
44
+ var textColor = 'text-light-text-primary dark:text-dark-text-primary';
34
45
  var bgColor = 'bg-light-background-default dark:bg-dark-background-default transition-colors duration-200 ease-in-out';
35
- var borderColor = 'border-light-outlinedBorder-active dark:border-dark-outlinedBorder-active';
36
- var containerClasses = "\n ".concat(bgColor, "\n ").concat(borderColor, "\n ").concat(baseClasses, "\n ").concat(sizeClasses, "\n ").concat(disabled ? 'bg-gray-200 cursor-not-allowed' : '', "\n ").concat(error ? 'border-red-500 focus:ring-red-500' : '', "\n ").concat(isFocused ? 'focus:border-light-accent-main focus:dark:border-dark-accent-main outline-none' : '', "\n ").concat(!disabled && !error ? 'hover:border-light-outlinedBorder-hover' : '', "\n border-gray-300\n ");
46
+ // Border color logic: error > focused > default (misc-divider)
47
+ var getBorderColor = function () {
48
+ if (error) {
49
+ return 'border-light-error-main dark:border-dark-error-main';
50
+ }
51
+ if (isFocused) {
52
+ return 'border-light-text-primary dark:border-dark-text-primary';
53
+ }
54
+ return 'border-light-text-disabled dark:border-dark-text-disabled';
55
+ };
56
+ var containerClasses = "\n ".concat(bgColor, "\n ").concat(textColor, "\n ").concat(baseClasses, "\n ").concat(sizeClasses, "\n ").concat(getBorderColor(), "\n ").concat(disabled ? 'bg-light-actionBackground-disabled dark:bg-dark-actionBackground-disabled cursor-not-allowed' : '', "\n ");
37
57
  return (<div className="flex flex-col w-full">
38
58
  {label && (<label htmlFor={id} className="mb-1 text-body2 text-light-text-secondary dark:text-dark-text-secondary">
39
59
  {label}
40
60
  </label>)}
41
61
  <div className="relative">
42
- <textarea ref={textareaRef} id={id} rows={1} className={containerClasses} value={value} onChange={onChange} onFocus={function (e) {
62
+ <textarea ref={textareaRef} id={id} rows={1} className={containerClasses} value={value} onChange={onChange} placeholder={placeholder} onFocus={function (e) {
43
63
  setIsFocused(true);
44
64
  if (onFocus)
45
65
  onFocus(e);
@@ -47,7 +67,7 @@ export default function Textarea(_a) {
47
67
  setIsFocused(false);
48
68
  if (onBlur)
49
69
  onBlur(e);
50
- }} onKeyDown={onKeyDown} autoFocus={autoFocus} disabled={disabled} autoComplete="off"/>
70
+ }} onKeyDown={handleKeyDown} autoFocus={autoFocus} disabled={disabled} autoComplete="off"/>
51
71
  </div>
52
72
  {error && (<p className="mt-1 text-light-error-main text-body2">
53
73
  This field is required