@rovula/ui 0.1.21 → 0.1.23

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 (85) hide show
  1. package/dist/cjs/bundle.css +204 -26
  2. package/dist/cjs/bundle.js +675 -675
  3. package/dist/cjs/bundle.js.map +1 -1
  4. package/dist/cjs/types/components/Badge/Badge.d.ts +40 -0
  5. package/dist/cjs/types/components/Badge/Badge.stories.d.ts +295 -0
  6. package/dist/cjs/types/components/Badge/Badge.styles.d.ts +7 -0
  7. package/dist/cjs/types/components/Badge/index.d.ts +2 -0
  8. package/dist/cjs/types/components/Dropdown/Dropdown.d.ts +4 -8
  9. package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +1 -6
  10. package/dist/cjs/types/components/DropdownMenu/DropdownMenu.d.ts +5 -1
  11. package/dist/cjs/types/components/DropdownMenu/DropdownMenu.stories.d.ts +16 -0
  12. package/dist/cjs/types/index.d.ts +3 -1
  13. package/dist/cjs/types/patterns/menu/Menu.d.ts +72 -0
  14. package/dist/cjs/types/{components/Menu → patterns/menu}/Menu.stories.d.ts +18 -10
  15. package/dist/cjs/types/utils/mergeRefs.d.ts +20 -0
  16. package/dist/components/ActionButton/ActionButton.styles.js +9 -1
  17. package/dist/components/Avatar/Avatar.styles.js +2 -2
  18. package/dist/components/Badge/Badge.js +36 -0
  19. package/dist/components/Badge/Badge.stories.js +51 -0
  20. package/dist/components/Badge/Badge.styles.js +62 -0
  21. package/dist/components/Badge/index.js +2 -0
  22. package/dist/components/Dropdown/Dropdown.js +54 -163
  23. package/dist/components/Dropdown/Dropdown.stories.js +29 -0
  24. package/dist/components/DropdownMenu/DropdownMenu.js +24 -11
  25. package/dist/components/DropdownMenu/DropdownMenu.stories.js +54 -10
  26. package/dist/components/TextInput/TextInput.js +9 -4
  27. package/dist/esm/bundle.css +204 -26
  28. package/dist/esm/bundle.js +1545 -1545
  29. package/dist/esm/bundle.js.map +1 -1
  30. package/dist/esm/types/components/Badge/Badge.d.ts +40 -0
  31. package/dist/esm/types/components/Badge/Badge.stories.d.ts +295 -0
  32. package/dist/esm/types/components/Badge/Badge.styles.d.ts +7 -0
  33. package/dist/esm/types/components/Badge/index.d.ts +2 -0
  34. package/dist/esm/types/components/Dropdown/Dropdown.d.ts +4 -8
  35. package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +1 -6
  36. package/dist/esm/types/components/DropdownMenu/DropdownMenu.d.ts +5 -1
  37. package/dist/esm/types/components/DropdownMenu/DropdownMenu.stories.d.ts +16 -0
  38. package/dist/esm/types/index.d.ts +3 -1
  39. package/dist/esm/types/patterns/menu/Menu.d.ts +72 -0
  40. package/dist/esm/types/{components/Menu → patterns/menu}/Menu.stories.d.ts +18 -10
  41. package/dist/esm/types/utils/mergeRefs.d.ts +20 -0
  42. package/dist/index.d.ts +118 -73
  43. package/dist/index.js +2 -1
  44. package/dist/patterns/menu/Menu.js +95 -0
  45. package/dist/patterns/menu/Menu.stories.js +611 -0
  46. package/dist/src/theme/global.css +393 -43
  47. package/dist/utils/mergeRefs.js +42 -0
  48. package/package.json +1 -1
  49. package/src/components/ActionButton/ActionButton.styles.ts +9 -1
  50. package/src/components/Avatar/Avatar.styles.ts +2 -2
  51. package/src/components/Badge/Badge.stories.tsx +128 -0
  52. package/src/components/Badge/Badge.styles.ts +70 -0
  53. package/src/components/Badge/Badge.tsx +103 -0
  54. package/src/components/Badge/index.ts +3 -0
  55. package/src/components/Dropdown/Dropdown.stories.tsx +170 -1
  56. package/src/components/Dropdown/Dropdown.tsx +186 -276
  57. package/src/components/DropdownMenu/DropdownMenu.stories.tsx +1050 -113
  58. package/src/components/DropdownMenu/DropdownMenu.tsx +117 -56
  59. package/src/components/TextInput/TextInput.tsx +42 -32
  60. package/src/index.ts +3 -1
  61. package/src/patterns/menu/Menu.stories.tsx +1100 -0
  62. package/src/patterns/menu/Menu.tsx +286 -0
  63. package/src/theme/presets/colors.js +14 -0
  64. package/src/theme/themes/variable-mapping.css +30 -0
  65. package/src/theme/themes/variable.css +37 -6
  66. package/src/theme/themes/xspector/baseline.css +0 -1
  67. package/src/theme/tokens/baseline.css +2 -1
  68. package/src/theme/tokens/components/badge.css +54 -0
  69. package/src/theme/tokens/components/dropdown-menu.css +15 -4
  70. package/src/utils/mergeRefs.ts +46 -0
  71. package/dist/cjs/types/components/Menu/Menu.d.ts +0 -65
  72. package/dist/cjs/types/components/Menu/helpers.d.ts +0 -19
  73. package/dist/cjs/types/components/Menu/index.d.ts +0 -4
  74. package/dist/components/Menu/Menu.js +0 -64
  75. package/dist/components/Menu/Menu.stories.js +0 -406
  76. package/dist/components/Menu/helpers.js +0 -28
  77. package/dist/components/Menu/index.js +0 -3
  78. package/dist/esm/types/components/Menu/Menu.d.ts +0 -65
  79. package/dist/esm/types/components/Menu/helpers.d.ts +0 -19
  80. package/dist/esm/types/components/Menu/index.d.ts +0 -4
  81. package/src/components/Menu/Menu.stories.tsx +0 -586
  82. package/src/components/Menu/Menu.tsx +0 -235
  83. package/src/components/Menu/helpers.ts +0 -45
  84. package/src/components/Menu/index.ts +0 -7
  85. package/src/theme/themes/xspector/components/dropdown-menu.css +0 -28
@@ -27,13 +27,13 @@ const DropdownMenuSubTrigger = React.forwardRef<
27
27
  <DropdownMenuPrimitive.SubTrigger
28
28
  ref={ref}
29
29
  className={cn(
30
- "relative flex gap-4 cursor-pointer select-none box-border items-center py-4 pl-9 pr-4 typography-subtitle4 outline-none transition-colors data-[disabled]:pointer-events-none",
30
+ "relative flex gap-4 cursor-pointer select-none box-border items-center py-4 pl-4 pr-4 typography-subtitle4 outline-none transition-colors data-[disabled]:pointer-events-none",
31
31
  "bg-[var(--dropdown-menu-default-bg)] text-[var(--dropdown-menu-default-text)]",
32
32
  "active:opacity-75",
33
33
  "focus:!bg-[var(--dropdown-menu-hover-bg)] focus:!text-[var(--dropdown-menu-hover-text)]",
34
34
  "data-[disabled]:!bg-[var(--dropdown-menu-disabled-bg)] data-[disabled]:!text-[var(--dropdown-menu-disabled-text)]",
35
35
  inset && "pl-8",
36
- className
36
+ className,
37
37
  )}
38
38
  {...props}
39
39
  >
@@ -51,8 +51,8 @@ const DropdownMenuSubContent = React.forwardRef<
51
51
  <DropdownMenuPrimitive.SubContent
52
52
  ref={ref}
53
53
  className={cn(
54
- "z-50 min-w-[154px] overflow-hidden rounded-lg bg-modal-surface text-text-contrast-low data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
55
- className
54
+ "z-50 min-w-[154px] overflow-hidden rounded-md bg-modal-surface text-text-contrast-low data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
55
+ className,
56
56
  )}
57
57
  {...props}
58
58
  style={{
@@ -73,8 +73,8 @@ const DropdownMenuContent = React.forwardRef<
73
73
  ref={ref}
74
74
  sideOffset={sideOffset}
75
75
  className={cn(
76
- "z-50 min-w-[154px] overflow-hidden rounded-lg bg-modal-surface text-text-contrast-low data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
77
- className
76
+ "z-50 min-w-[154px] overflow-hidden rounded-md bg-modal-surface text-text-contrast-low data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2",
77
+ className,
78
78
  )}
79
79
  {...props}
80
80
  style={{
@@ -90,45 +90,88 @@ const DropdownMenuItem = React.forwardRef<
90
90
  React.ElementRef<typeof DropdownMenuPrimitive.Item>,
91
91
  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.Item> & {
92
92
  inset?: boolean;
93
+ selected?: boolean;
94
+ icon?: React.ReactNode;
93
95
  }
94
- >(({ className, inset, ...props }, ref) => (
95
- <DropdownMenuPrimitive.Item
96
- ref={ref}
97
- className={cn(
98
- "relative flex gap-4 cursor-pointer select-none box-border items-center py-4 pl-9 pr-xxl typography-subtitle4 outline-none transition-colors data-[disabled]:pointer-events-none",
99
- "bg-[var(--dropdown-menu-default-bg)] text-[var(--dropdown-menu-default-text)]",
100
- "active:opacity-75",
101
- "focus:!bg-[var(--dropdown-menu-hover-bg)] focus:!text-[var(--dropdown-menu-hover-text)]",
102
- "data-[disabled]:!bg-[var(--dropdown-menu-disabled-bg)] data-[disabled]:!text-[var(--dropdown-menu-disabled-text)]",
103
- inset && "pl-8",
104
- className
105
- )}
106
- {...props}
107
- />
108
- ));
96
+ >(({ className, inset, selected, icon, children, ...props }, ref) => {
97
+ const hasIcon = !!icon;
98
+ return (
99
+ <DropdownMenuPrimitive.Item
100
+ ref={ref}
101
+ className={cn(
102
+ "relative flex cursor-pointer select-none box-border items-center py-4 pl-4 pr-8 typography-subtitle4 outline-none transition-colors data-[disabled]:pointer-events-none",
103
+ "bg-[var(--dropdown-menu-default-bg)] text-[var(--dropdown-menu-default-text)]",
104
+ "active:opacity-75",
105
+ "focus:!bg-[var(--dropdown-menu-hover-bg)] focus:!text-[var(--dropdown-menu-hover-text)]",
106
+ selected &&
107
+ "bg-[var(--dropdown-menu-selected-bg)] text-[var(--dropdown-menu-selected-text)] typography-subtitle5",
108
+ "data-[disabled]:!bg-[var(--dropdown-menu-disabled-bg)] data-[disabled]:!text-[var(--dropdown-menu-disabled-text)]",
109
+ inset && "pl-8",
110
+ className,
111
+ hasIcon ? "gap-4" : "gap-1",
112
+ )}
113
+ {...props}
114
+ >
115
+ <div className="flex shrink-0 flex-row gap-1">
116
+ <span className="size-4 flex items-center justify-center">
117
+ {selected && (
118
+ <Icon
119
+ type="heroicons"
120
+ name="check"
121
+ className="size-4 text-[var(--dropdown-menu-selected-text)]"
122
+ />
123
+ )}
124
+ </span>
125
+ {icon}
126
+ </div>
127
+ {children}
128
+ </DropdownMenuPrimitive.Item>
129
+ );
130
+ });
109
131
  DropdownMenuItem.displayName = DropdownMenuPrimitive.Item.displayName;
110
132
 
111
133
  const DropdownMenuCheckboxItem = React.forwardRef<
112
134
  React.ElementRef<typeof DropdownMenuPrimitive.CheckboxItem>,
113
135
  React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.CheckboxItem>
114
- >(({ className, children, checked, ...props }, ref) => (
136
+ >(({ className, children, checked, disabled, ...props }, ref) => (
115
137
  <DropdownMenuPrimitive.CheckboxItem
116
138
  ref={ref}
117
139
  className={cn(
118
- "relative flex gap-4 cursor-pointer select-none box-border items-center py-4 pl-9 pr-xxl typography-subtitle4 outline-none transition-colors data-[disabled]:pointer-events-none",
140
+ "relative flex gap-3 cursor-pointer select-none box-border items-center py-4 pl-4 pr-8 typography-subtitle4 outline-none transition-colors data-[disabled]:pointer-events-none",
119
141
  "bg-[var(--dropdown-menu-default-bg)] text-[var(--dropdown-menu-default-text)]",
120
142
  "active:opacity-75",
121
143
  "focus:!bg-[var(--dropdown-menu-hover-bg)] focus:!text-[var(--dropdown-menu-hover-text)]",
122
- "data-[state='checked']:bg-[var(--dropdown-menu-selected-bg)] data-[state='checked']:text-[var(--dropdown-menu-selected-text)] data-[state='checked']:typography-subtitle5",
144
+ "data-[state='checked']:bg-[var(--dropdown-menu-selected-bg)] data-[state='checked']:text-[var(--dropdown-menu-selected-text)]",
123
145
  "data-[disabled]:!bg-[var(--dropdown-menu-disabled-bg)] data-[disabled]:!text-[var(--dropdown-menu-disabled-text)]",
124
- className
146
+ className,
125
147
  )}
126
148
  checked={checked}
149
+ disabled={disabled}
127
150
  {...props}
128
151
  >
129
- <span className="absolute left-4 flex items-center justify-center">
152
+ <span
153
+ className={cn(
154
+ "shrink-0 size-4 rounded-[2px] border flex items-center justify-center transition-all overflow-hidden",
155
+ checked &&
156
+ !disabled &&
157
+ "bg-[var(--dropdown-menu-checkbox-checked-bg)] border-[var(--dropdown-menu-checkbox-checked-bg)]",
158
+ checked &&
159
+ disabled &&
160
+ "bg-[var(--dropdown-menu-checkbox-disabled-checked-bg)] border-transparent",
161
+ !checked &&
162
+ disabled &&
163
+ "border-[var(--dropdown-menu-checkbox-disabled-border)]",
164
+ !checked &&
165
+ !disabled &&
166
+ "border-[var(--dropdown-menu-checkbox-border)]",
167
+ )}
168
+ >
130
169
  <DropdownMenuPrimitive.ItemIndicator>
131
- <Icon type="heroicons" name="check" className="size-4" />
170
+ <Icon
171
+ type="heroicons"
172
+ name="check"
173
+ className="size-3 text-[var(--dropdown-menu-checkbox-checked-icon)]"
174
+ />
132
175
  </DropdownMenuPrimitive.ItemIndicator>
133
176
  </span>
134
177
  {children}
@@ -139,29 +182,50 @@ DropdownMenuCheckboxItem.displayName =
139
182
 
140
183
  const DropdownMenuRadioItem = React.forwardRef<
141
184
  React.ElementRef<typeof DropdownMenuPrimitive.RadioItem>,
142
- React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem>
143
- >(({ className, children, ...props }, ref) => (
144
- <DropdownMenuPrimitive.RadioItem
145
- ref={ref}
146
- className={cn(
147
- "relative flex gap-4 cursor-pointer select-none box-border items-center py-4 pl-9 pr-xxl typography-subtitle4 outline-none transition-colors data-[disabled]:pointer-events-none",
148
- "bg-[var(--dropdown-menu-default-bg)] text-[var(--dropdown-menu-default-text)]",
149
- "active:opacity-75",
150
- "focus:!bg-[var(--dropdown-menu-hover-bg)] focus:!text-[var(--dropdown-menu-hover-text)]",
151
- "data-[state='checked']:bg-[var(--dropdown-menu-selected-bg)] data-[state='checked']:text-[var(--dropdown-menu-selected-text)] data-[state='checked']:typography-subtitle5",
152
- "data-[disabled]:!bg-[var(--dropdown-menu-disabled-bg)] data-[disabled]:!text-[var(--dropdown-menu-disabled-text)]",
153
- className
154
- )}
155
- {...props}
156
- >
157
- <span className="absolute left-4 flex items-center justify-center">
158
- <DropdownMenuPrimitive.ItemIndicator>
159
- <Icon type="heroicons" name="circle" className="h-2 w-2 fill-current" />
160
- </DropdownMenuPrimitive.ItemIndicator>
161
- </span>
162
- {children}
163
- </DropdownMenuPrimitive.RadioItem>
164
- ));
185
+ React.ComponentPropsWithoutRef<typeof DropdownMenuPrimitive.RadioItem> & {
186
+ icon?: React.ReactNode;
187
+ }
188
+ >(({ className, children, disabled, icon, ...props }, ref) => {
189
+ const hasIconSlot = !!icon;
190
+
191
+ return (
192
+ <DropdownMenuPrimitive.RadioItem
193
+ ref={ref}
194
+ className={cn(
195
+ "relative flex cursor-pointer select-none box-border items-center py-4 pl-4 pr-8 typography-subtitle4 outline-none transition-colors data-[disabled]:pointer-events-none",
196
+ "bg-[var(--dropdown-menu-default-bg)] text-[var(--dropdown-menu-default-text)]",
197
+ "active:opacity-75",
198
+ "focus:!bg-[var(--dropdown-menu-hover-bg)] focus:!text-[var(--dropdown-menu-hover-text)]",
199
+ "data-[state='checked']:bg-[var(--dropdown-menu-selected-bg)] data-[state='checked']:text-[var(--dropdown-menu-selected-text)]",
200
+ "data-[disabled]:!bg-[var(--dropdown-menu-disabled-bg)] data-[disabled]:!text-[var(--dropdown-menu-radio-disabled-text)]",
201
+ "data-[state='checked']:data-[disabled]:!text-[var(--dropdown-menu-radio-selected-disabled-text)]",
202
+ className,
203
+ hasIconSlot ? "gap-4" : "gap-1",
204
+ )}
205
+ {...props}
206
+ disabled={disabled}
207
+ >
208
+ <div className="flex shrink-0 flex-row gap-1">
209
+ <span className="size-4">
210
+ <DropdownMenuPrimitive.ItemIndicator className="shrink-0">
211
+ <Icon
212
+ type="heroicons"
213
+ name="check"
214
+ className={cn(
215
+ "size-4",
216
+ disabled
217
+ ? "text-[var(--dropdown-menu-radio-selected-disabled-text)]"
218
+ : "text-[var(--dropdown-menu-selected-text)]",
219
+ )}
220
+ />
221
+ </DropdownMenuPrimitive.ItemIndicator>
222
+ </span>
223
+ {icon}
224
+ </div>
225
+ {children}
226
+ </DropdownMenuPrimitive.RadioItem>
227
+ );
228
+ });
165
229
  DropdownMenuRadioItem.displayName = DropdownMenuPrimitive.RadioItem.displayName;
166
230
 
167
231
  const DropdownMenuLabel = React.forwardRef<
@@ -173,9 +237,9 @@ const DropdownMenuLabel = React.forwardRef<
173
237
  <DropdownMenuPrimitive.Label
174
238
  ref={ref}
175
239
  className={cn(
176
- "px-3 pt-4 pb-2 typography-small4 text-text-g-contrast-high",
240
+ "px-3 py-2 typography-small4 text-text-g-contrast-high",
177
241
  inset && "pl-8",
178
- className
242
+ className,
179
243
  )}
180
244
  {...props}
181
245
  />
@@ -188,10 +252,7 @@ const DropdownMenuSeparator = React.forwardRef<
188
252
  >(({ className, ...props }, ref) => (
189
253
  <DropdownMenuPrimitive.Separator
190
254
  ref={ref}
191
- className={cn(
192
- "-mx-2 my-2 h-px bg-[var(--dropdown-menu-seperator-bg)]",
193
- className
194
- )}
255
+ className={cn("h-px bg-[var(--dropdown-menu-seperator-bg)]", className)}
195
256
  {...props}
196
257
  />
197
258
  ));
@@ -2,13 +2,13 @@ import React, {
2
2
  ReactNode,
3
3
  forwardRef,
4
4
  useCallback,
5
- useImperativeHandle,
6
5
  useMemo,
7
6
  useRef,
8
7
  FocusEvent,
9
8
  KeyboardEvent,
10
9
  ChangeEvent,
11
10
  } from "react";
11
+ import { useStableMergedRef } from "@/utils/mergeRefs";
12
12
  import {
13
13
  helperTextVariant,
14
14
  iconActionVariant,
@@ -19,11 +19,7 @@ import {
19
19
  searchIconVariant,
20
20
  segmentedIconWrapperVariant,
21
21
  } from "./TextInput.styles";
22
- import {
23
- CircleAlert,
24
- CircleX,
25
- Search,
26
- } from "lucide-react";
22
+ import { CircleAlert, CircleX, Search } from "lucide-react";
27
23
  import { cn } from "@/utils/cn";
28
24
 
29
25
  export type InputProps = {
@@ -107,10 +103,14 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
107
103
  normalizeOnCommit,
108
104
  ...props
109
105
  },
110
- ref
106
+ ref,
111
107
  ) => {
112
108
  const inputRef = useRef<HTMLInputElement>(null);
113
109
  const _id = id || `${type}-${label}-input`;
110
+
111
+ // Stable merged ref — identity never changes so Headless UI (or any library
112
+ // that watches refs) won't trigger detach/re-attach loops.
113
+ const stableRef = useStableMergedRef(ref, inputRef);
114
114
  const hasLeftSectionIcon = !!startIcon || !!renderStartIcon;
115
115
  const hasRightSectionIcon = !!endIcon || !!renderEndIcon;
116
116
  const feedbackStatus =
@@ -118,16 +118,16 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
118
118
  (error || !!errorMessage
119
119
  ? "error"
120
120
  : warning || !!warningMessage
121
- ? "warning"
122
- : "default");
121
+ ? "warning"
122
+ : "default");
123
123
  const isError = feedbackStatus === "error";
124
124
  const isWarning = feedbackStatus === "warning";
125
125
  const feedbackMessage =
126
126
  feedbackStatus === "error"
127
127
  ? errorMessage
128
128
  : feedbackStatus === "warning"
129
- ? warningMessage
130
- : helperText;
129
+ ? warningMessage
130
+ : helperText;
131
131
 
132
132
  const inputClassname = inputVariant({
133
133
  size,
@@ -183,8 +183,6 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
183
183
  position: "end",
184
184
  });
185
185
 
186
- useImperativeHandle(ref, () => inputRef?.current as HTMLInputElement);
187
-
188
186
  const handleChange = useCallback(
189
187
  (e: ChangeEvent<HTMLInputElement>) => {
190
188
  if (normalize) {
@@ -192,7 +190,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
192
190
  }
193
191
  props.onChange?.(e);
194
192
  },
195
- [normalize, props.onChange]
193
+ [normalize, props.onChange],
196
194
  );
197
195
 
198
196
  const commitValue = useCallback(
@@ -209,7 +207,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
209
207
  } as unknown as ChangeEvent<HTMLInputElement>);
210
208
  }
211
209
  },
212
- [trimOnCommit, normalizeOnCommit, props.onChange]
210
+ [trimOnCommit, normalizeOnCommit, props.onChange],
213
211
  );
214
212
 
215
213
  const handleBlur = useCallback(
@@ -217,7 +215,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
217
215
  if (trimOnCommit || normalizeOnCommit) commitValue(e);
218
216
  props.onBlur?.(e);
219
217
  },
220
- [trimOnCommit, normalizeOnCommit, commitValue, props.onBlur]
218
+ [trimOnCommit, normalizeOnCommit, commitValue, props.onBlur],
221
219
  );
222
220
 
223
221
  const handleKeyDown = useCallback(
@@ -227,7 +225,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
227
225
  }
228
226
  props.onKeyDown?.(e);
229
227
  },
230
- [trimOnCommit, normalizeOnCommit, commitValue, props.onKeyDown]
228
+ [trimOnCommit, normalizeOnCommit, commitValue, props.onKeyDown],
231
229
  );
232
230
 
233
231
  const displayValue =
@@ -273,7 +271,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
273
271
  className={cn(
274
272
  inlineStartIconWrapperClassname,
275
273
  "flex",
276
- classes?.iconSearchWrapper
274
+ classes?.iconSearchWrapper,
277
275
  )}
278
276
  >
279
277
  {renderStartIcon()}
@@ -286,7 +284,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
286
284
  <div
287
285
  className={cn(
288
286
  inlineStartIconWrapperClassname,
289
- classes?.iconSearchWrapper
287
+ classes?.iconSearchWrapper,
290
288
  )}
291
289
  >
292
290
  <div
@@ -303,7 +301,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
303
301
  <div
304
302
  className={cn(
305
303
  startSegmentIconWrapperClassname,
306
- classes?.startIconWrapper
304
+ classes?.startIconWrapper,
307
305
  )}
308
306
  onClick={handleOnClickLeftSectionIcon}
309
307
  >
@@ -330,7 +328,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
330
328
  className={cn(
331
329
  inlineEndIconWrapperClassname,
332
330
  "flex",
333
- classes?.iconWrapper
331
+ classes?.iconWrapper,
334
332
  )}
335
333
  >
336
334
  {renderEndIcon()}
@@ -344,7 +342,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
344
342
  className={cn(
345
343
  inlineEndIconWrapperClassname,
346
344
  "flex",
347
- classes?.iconWrapper
345
+ classes?.iconWrapper,
348
346
  )}
349
347
  >
350
348
  <div
@@ -359,7 +357,10 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
359
357
 
360
358
  return (
361
359
  <div
362
- className={cn(endSegmentIconWrapperClassname, classes?.endIconWrapper)}
360
+ className={cn(
361
+ endSegmentIconWrapperClassname,
362
+ classes?.endIconWrapper,
363
+ )}
363
364
  onClick={handleOnClickRightSectionIcon}
364
365
  >
365
366
  {endIcon}
@@ -382,21 +383,27 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
382
383
  <input
383
384
  {...props}
384
385
  placeholder=" "
385
- ref={inputRef}
386
+ ref={stableRef}
386
387
  type={type}
387
388
  id={_id}
388
389
  disabled={disabled}
389
390
  value={displayValue}
390
391
  className={cn(inputClassname, props.className)}
391
392
  onChange={normalize ? handleChange : props.onChange}
392
- onBlur={trimOnCommit || normalizeOnCommit ? handleBlur : props.onBlur}
393
- onKeyDown={trimOnCommit || normalizeOnCommit ? handleKeyDown : props.onKeyDown}
393
+ onBlur={
394
+ trimOnCommit || normalizeOnCommit ? handleBlur : props.onBlur
395
+ }
396
+ onKeyDown={
397
+ trimOnCommit || normalizeOnCommit
398
+ ? handleKeyDown
399
+ : props.onKeyDown
400
+ }
394
401
  />
395
402
  {hasSearchIcon && !hasLeftSectionIcon && (
396
403
  <div
397
404
  className={cn(
398
405
  inlineStartIconWrapperClassname,
399
- classes?.iconSearchWrapper
406
+ classes?.iconSearchWrapper,
400
407
  )}
401
408
  >
402
409
  <Search className={cn(searchIconClassname, classes?.icon)} />
@@ -406,7 +413,10 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
406
413
 
407
414
  {hasClearIcon && !hasRightSectionIcon && (
408
415
  <div
409
- className={cn(inlineEndIconWrapperClassname, classes?.iconWrapper)}
416
+ className={cn(
417
+ inlineEndIconWrapperClassname,
418
+ classes?.iconWrapper,
419
+ )}
410
420
  style={{
411
421
  display:
412
422
  keepCloseIconOnValue && props.value ? "flex" : undefined,
@@ -417,7 +427,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
417
427
  iconActionClassname,
418
428
  // 'fill-none stroke-current',
419
429
  // "fill-none stroke-input-default-text hover:stroke-input-filled-text active:stroke-input-filled-text",
420
- classes?.icon
430
+ classes?.icon,
421
431
  )}
422
432
  onMouseDown={handleClearInput}
423
433
  />
@@ -450,8 +460,8 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
450
460
  isError
451
461
  ? "text-input-error"
452
462
  : isWarning
453
- ? "text-warning"
454
- : "text-input-filled-text"
463
+ ? "text-warning"
464
+ : "text-input-filled-text",
455
465
  )}
456
466
  />
457
467
  </span>
@@ -464,7 +474,7 @@ export const TextInput = forwardRef<HTMLInputElement, InputProps>(
464
474
  )}
465
475
  </div>
466
476
  );
467
- }
477
+ },
468
478
  );
469
479
 
470
480
  export default TextInput;
package/src/index.ts CHANGED
@@ -19,6 +19,7 @@ export { Navbar } from "./components/Navbar";
19
19
  export { Footer } from "./components/Footer";
20
20
  export { default as ActionButton } from "./components/ActionButton/ActionButton";
21
21
  export { Avatar, AvatarGroup } from "./components/Avatar";
22
+ export { Badge, SeverityBadge } from "./components/Badge";
22
23
  export { Collapsible } from "./components/Collapsible";
23
24
  export { Calendar } from "./components/Calendar";
24
25
  export { default as DatePicker } from "./components/DatePicker/DatePicker";
@@ -41,7 +42,6 @@ export * from "./components/InputFilter/InputFilter";
41
42
  export * from "./components/Slider/Slider";
42
43
  export * from "./components/Switch/Switch";
43
44
  export * from "./components/DropdownMenu/DropdownMenu";
44
- export * from "./components/Menu/Menu";
45
45
  export * from "./components/Tooltip/Tooltip";
46
46
  export * from "./components/Tooltip/TooltipSimple";
47
47
  export * from "./components/Toast/Toast";
@@ -56,6 +56,7 @@ export * from "./components/Form";
56
56
  // Patterns
57
57
  export * from "./patterns/confirm-dialog/ConfirmDialog";
58
58
  export * from "./patterns/form-dialog/FormDialog";
59
+ export * from "./patterns/menu/Menu";
59
60
 
60
61
  // Export component types
61
62
  export type { ButtonProps } from "./components/Button/Button";
@@ -74,6 +75,7 @@ export type { NavbarProps, NavbarVariant } from "./components/Navbar/Navbar";
74
75
  export type { FooterProps, FooterVariant } from "./components/Footer/Footer";
75
76
  export type { AvatarProps } from "./components/Avatar/Avatar";
76
77
  export type { AvatarGroupProps } from "./components/Avatar/AvatarGroup";
78
+ export type { BadgeProps, BadgeColor, SeverityBadgeProps, SeverityLevel } from "./components/Badge/Badge";
77
79
 
78
80
  // UTILS
79
81
  export {