@rovula/ui 0.0.78 → 0.0.79

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 (42) hide show
  1. package/dist/cjs/bundle.css +15 -3
  2. package/dist/cjs/bundle.js +3 -3
  3. package/dist/cjs/bundle.js.map +1 -1
  4. package/dist/cjs/types/components/Dropdown/Dropdown.d.ts +3 -0
  5. package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +5 -1
  6. package/dist/cjs/types/components/Menu/Menu.d.ts +65 -0
  7. package/dist/cjs/types/components/Menu/Menu.stories.d.ts +31 -0
  8. package/dist/cjs/types/components/Menu/helpers.d.ts +19 -0
  9. package/dist/cjs/types/components/Menu/index.d.ts +4 -0
  10. package/dist/cjs/types/components/Search/Search.d.ts +46 -3
  11. package/dist/cjs/types/components/Search/Search.stories.d.ts +46 -27
  12. package/dist/cjs/types/index.d.ts +1 -0
  13. package/dist/components/Dropdown/Dropdown.js +41 -19
  14. package/dist/components/Dropdown/Dropdown.stories.js +13 -0
  15. package/dist/components/Menu/Menu.js +64 -0
  16. package/dist/components/Menu/Menu.stories.js +406 -0
  17. package/dist/components/Menu/helpers.js +28 -0
  18. package/dist/components/Menu/index.js +3 -0
  19. package/dist/esm/bundle.css +15 -3
  20. package/dist/esm/bundle.js +3 -3
  21. package/dist/esm/bundle.js.map +1 -1
  22. package/dist/esm/types/components/Dropdown/Dropdown.d.ts +3 -0
  23. package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +5 -1
  24. package/dist/esm/types/components/Menu/Menu.d.ts +65 -0
  25. package/dist/esm/types/components/Menu/Menu.stories.d.ts +31 -0
  26. package/dist/esm/types/components/Menu/helpers.d.ts +19 -0
  27. package/dist/esm/types/components/Menu/index.d.ts +4 -0
  28. package/dist/esm/types/components/Search/Search.d.ts +46 -3
  29. package/dist/esm/types/components/Search/Search.stories.d.ts +46 -27
  30. package/dist/esm/types/index.d.ts +1 -0
  31. package/dist/index.d.ts +111 -3
  32. package/dist/index.js +1 -0
  33. package/dist/src/theme/global.css +20 -4
  34. package/package.json +1 -1
  35. package/src/components/Dropdown/Dropdown.stories.tsx +31 -0
  36. package/src/components/Dropdown/Dropdown.tsx +73 -54
  37. package/src/components/Menu/Menu.stories.tsx +586 -0
  38. package/src/components/Menu/Menu.tsx +235 -0
  39. package/src/components/Menu/helpers.ts +45 -0
  40. package/src/components/Menu/index.ts +7 -0
  41. package/src/components/Search/Search.tsx +24 -11
  42. package/src/index.ts +1 -0
@@ -1,6 +1,5 @@
1
1
  import React, {
2
2
  CSSProperties,
3
- Fragment,
4
3
  ReactNode,
5
4
  forwardRef,
6
5
  useCallback,
@@ -9,10 +8,12 @@ import React, {
9
8
  useMemo,
10
9
  useRef,
11
10
  useState,
11
+ Fragment,
12
12
  } from "react";
13
13
  import * as Portal from "@radix-ui/react-portal";
14
14
  import TextInput, { InputProps } from "../TextInput/TextInput";
15
15
  import { customInputVariant, dropdownIconVariant } from "./Dropdown.styles";
16
+ import { Menu, MenuItemType, MenuOption } from "../Menu/Menu";
16
17
 
17
18
  import { ChevronDownIcon } from "@heroicons/react/16/solid";
18
19
  import { cn } from "@/utils/cn";
@@ -36,6 +37,7 @@ export type DropdownProps = {
36
37
  size?: "sm" | "md" | "lg";
37
38
  rounded?: "none" | "normal" | "full";
38
39
  variant?: "flat" | "outline" | "underline";
40
+ defaultMenuItemType?: MenuOption["type"];
39
41
  helperText?: string;
40
42
  errorMessage?: string;
41
43
  filterMode?: boolean;
@@ -71,6 +73,7 @@ const Dropdown = forwardRef<HTMLInputElement, DropdownProps>(
71
73
  size = "md",
72
74
  rounded = "normal",
73
75
  variant = "outline",
76
+ defaultMenuItemType = "checkbox",
74
77
  helperText,
75
78
  errorMessage,
76
79
  fullwidth = true,
@@ -211,66 +214,82 @@ const Dropdown = forwardRef<HTMLInputElement, DropdownProps>(
211
214
  });
212
215
  }
213
216
 
214
- return (
215
- <ul
216
- className={cn(
217
- "absolute mt-1 w-full bg-base-popup border border-base-popup text-base-popup-foreground rounded-md shadow-md z-[9999] max-h-60 overflow-y-auto",
218
- !usePortal && (isAbove ? "bottom-full mb-1" : "top-full mt-1"),
219
- optionContainerClassName
220
- )}
221
- style={dropdownStyles}
222
- ref={dropdownRef}
223
- >
224
- {optionsFiltered.map((option) => {
225
- if (option.renderLabel) {
226
- return (
227
- <Fragment key={option.value}>
228
- {option.renderLabel({
229
- value: option.value,
230
- label: option.label,
231
- handleOnClick: () => handleOptionClick(option),
232
- className: cn(
233
- `px-4 py-2 hover:bg-primary-hover-bg cursor-pointer`,
234
- optionItemClassName,
235
- {
236
- "bg-base-popup-highligh":
237
- selectedOption?.value === option.value,
238
- }
239
- ),
240
- })}
241
- </Fragment>
242
- );
243
- }
244
- return (
245
- <li
246
- key={option.value}
247
- onMouseDown={() => {
248
- handleOptionClick(option);
249
- }}
250
- className={cn(
251
- `px-4 py-2 hover:bg-primary-hover-bg cursor-pointer`,
252
- optionItemClassName,
253
- {
254
- "bg-base-popup-highligh":
255
- selectedOption?.value === option.value,
256
- }
257
- )}
258
- >
259
- {option.label}
260
- </li>
261
- );
262
- })}
263
- {optionsFiltered.length === 0 && (
264
- <li
217
+ // Convert options to MenuItemType
218
+ let finalMenuItems: MenuItemType[];
219
+
220
+ finalMenuItems = optionsFiltered.map((option) => {
221
+ if (option.renderLabel) {
222
+ return {
223
+ type: "custom",
224
+ render: () => (
225
+ <Fragment key={option.value}>
226
+ {option.renderLabel!({
227
+ value: option.value,
228
+ label: option.label,
229
+ handleOnClick: () => handleOptionClick(option),
230
+ className: cn(
231
+ "relative flex gap-3 cursor-pointer select-none box-border items-center py-4 pl-9 pr-4 typography-subtitile4 outline-none transition-colors",
232
+ "bg-[var(--dropdown-menu-default-bg)] text-[var(--dropdown-menu-default-text)]",
233
+ "active:opacity-75",
234
+ "hover:bg-[var(--dropdown-menu-hover-bg)] hover:text-[var(--dropdown-menu-hover-text)]",
235
+ {
236
+ "bg-[var(--dropdown-menu-selected-bg)] text-[var(--dropdown-menu-selected-text)] typography-subtitile5":
237
+ selectedOption?.value === option.value,
238
+ },
239
+ optionItemClassName
240
+ ),
241
+ })}
242
+ </Fragment>
243
+ ),
244
+ };
245
+ }
246
+
247
+ return {
248
+ type: "item",
249
+ item: {
250
+ type: defaultMenuItemType,
251
+ value: option.value,
252
+ label: option.label,
253
+ },
254
+ };
255
+ });
256
+
257
+ // Add "not found" message if no results
258
+ if (finalMenuItems.length === 0) {
259
+ finalMenuItems.push({
260
+ type: "custom",
261
+ render: () => (
262
+ <div
263
+ key="not-found"
265
264
  className={cn(
266
265
  "px-4 py-14 text-center text-input-text",
267
266
  optionNotFoundItemClassName
268
267
  )}
269
268
  >
270
269
  Not found
271
- </li>
270
+ </div>
271
+ ),
272
+ });
273
+ }
274
+
275
+ return (
276
+ <Menu
277
+ ref={dropdownRef as any}
278
+ items={finalMenuItems}
279
+ selectedValues={selectedOption?.value ? [selectedOption.value] : []}
280
+ onSelect={(value) => {
281
+ const option = optionsFiltered.find((opt) => opt.value === value);
282
+ if (option) {
283
+ handleOptionClick(option);
284
+ }
285
+ }}
286
+ className={cn(
287
+ "absolute mt-1 w-full max-h-60 overflow-y-auto",
288
+ !usePortal && (isAbove ? "bottom-full mb-1" : "top-full mt-1"),
289
+ optionContainerClassName
272
290
  )}
273
- </ul>
291
+ style={dropdownStyles}
292
+ />
274
293
  );
275
294
  };
276
295