@rovula/ui 0.0.68 → 0.0.70

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 (39) hide show
  1. package/dist/cjs/bundle.css +67 -0
  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.stories.d.ts +2 -0
  5. package/dist/cjs/types/components/FocusedScrollView/FocusedScrollView.d.ts +12 -0
  6. package/dist/cjs/types/components/FocusedScrollView/FocusedScrollView.stories.d.ts +7 -0
  7. package/dist/cjs/types/components/InputFilter/InputFilter.stories.d.ts +2 -0
  8. package/dist/cjs/types/components/Search/Search.stories.d.ts +2 -0
  9. package/dist/cjs/types/components/TextInput/TextInput.d.ts +4 -0
  10. package/dist/cjs/types/components/TextInput/TextInput.stories.d.ts +11 -0
  11. package/dist/cjs/types/components/TextInput/TextInput.styles.d.ts +1 -0
  12. package/dist/cjs/types/index.d.ts +1 -0
  13. package/dist/components/FocusedScrollView/FocusedScrollView.js +67 -0
  14. package/dist/components/FocusedScrollView/FocusedScrollView.stories.js +33 -0
  15. package/dist/components/TextInput/TextInput.js +66 -14
  16. package/dist/components/TextInput/TextInput.stories.js +15 -0
  17. package/dist/components/TextInput/TextInput.styles.js +116 -7
  18. package/dist/esm/bundle.css +67 -0
  19. package/dist/esm/bundle.js +3 -3
  20. package/dist/esm/bundle.js.map +1 -1
  21. package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +2 -0
  22. package/dist/esm/types/components/FocusedScrollView/FocusedScrollView.d.ts +12 -0
  23. package/dist/esm/types/components/FocusedScrollView/FocusedScrollView.stories.d.ts +7 -0
  24. package/dist/esm/types/components/InputFilter/InputFilter.stories.d.ts +2 -0
  25. package/dist/esm/types/components/Search/Search.stories.d.ts +2 -0
  26. package/dist/esm/types/components/TextInput/TextInput.d.ts +4 -0
  27. package/dist/esm/types/components/TextInput/TextInput.stories.d.ts +11 -0
  28. package/dist/esm/types/components/TextInput/TextInput.styles.d.ts +1 -0
  29. package/dist/esm/types/index.d.ts +1 -0
  30. package/dist/index.d.ts +17 -2
  31. package/dist/index.js +1 -0
  32. package/dist/src/theme/global.css +86 -0
  33. package/package.json +1 -1
  34. package/src/components/FocusedScrollView/FocusedScrollView.stories.tsx +114 -0
  35. package/src/components/FocusedScrollView/FocusedScrollView.tsx +112 -0
  36. package/src/components/TextInput/TextInput.stories.tsx +83 -0
  37. package/src/components/TextInput/TextInput.styles.ts +117 -7
  38. package/src/components/TextInput/TextInput.tsx +115 -21
  39. package/src/index.ts +1 -0
@@ -359,10 +359,12 @@ declare const meta: {
359
359
  placeholder?: string | undefined | undefined;
360
360
  readOnly?: boolean | undefined | undefined;
361
361
  src?: string | undefined | undefined;
362
+ iconMode?: "flat" | "solid" | undefined;
362
363
  keepCloseIconOnValue?: boolean | undefined;
363
364
  labelClassName?: string | undefined;
364
365
  onClickStartIcon?: (() => void) | undefined;
365
366
  onClickEndIcon?: (() => void) | undefined;
367
+ renderStartIcon?: (() => React.ReactNode) | undefined;
366
368
  renderEndIcon?: (() => React.ReactNode) | undefined;
367
369
  ref?: React.LegacyRef<HTMLInputElement> | undefined;
368
370
  key?: React.Key | null | undefined;
@@ -0,0 +1,12 @@
1
+ import React, { ReactNode, HTMLAttributes } from "react";
2
+ type ScrollAlign = "start" | "center" | "end";
3
+ type FocusedScrollViewProps = {
4
+ selectedKey?: string;
5
+ children: ReactNode;
6
+ direction?: "vertical" | "horizontal";
7
+ className?: string;
8
+ containerProps?: HTMLAttributes<HTMLDivElement>;
9
+ scrollAlign?: ScrollAlign;
10
+ };
11
+ export declare const FocusedScrollView: React.FC<FocusedScrollViewProps>;
12
+ export {};
@@ -0,0 +1,7 @@
1
+ import { Meta, StoryObj } from "@storybook/react";
2
+ import { FocusedScrollView } from "./FocusedScrollView";
3
+ declare const meta: Meta<typeof FocusedScrollView>;
4
+ export default meta;
5
+ type Story = StoryObj<typeof FocusedScrollView>;
6
+ export declare const VerticalScroll: Story;
7
+ export declare const HorizontalScroll: Story;
@@ -349,10 +349,12 @@ declare const meta: {
349
349
  placeholder?: string | undefined | undefined;
350
350
  readOnly?: boolean | undefined | undefined;
351
351
  src?: string | undefined | undefined;
352
+ iconMode?: "flat" | "solid" | undefined;
352
353
  keepCloseIconOnValue?: boolean | undefined;
353
354
  labelClassName?: string | undefined;
354
355
  onClickStartIcon?: (() => void) | undefined;
355
356
  onClickEndIcon?: (() => void) | undefined;
357
+ renderStartIcon?: (() => React.ReactNode) | undefined;
356
358
  renderEndIcon?: (() => React.ReactNode) | undefined;
357
359
  ref?: React.LegacyRef<HTMLInputElement> | undefined;
358
360
  key?: React.Key | null | undefined;
@@ -310,11 +310,13 @@ declare const meta: {
310
310
  required?: boolean | undefined;
311
311
  src?: string | undefined | undefined;
312
312
  label?: string | undefined;
313
+ iconMode?: "flat" | "solid" | undefined;
313
314
  helperText?: string | undefined;
314
315
  errorMessage?: string | undefined;
315
316
  labelClassName?: string | undefined;
316
317
  onClickStartIcon?: (() => void) | undefined;
317
318
  onClickEndIcon?: (() => void) | undefined;
319
+ renderStartIcon?: (() => React.ReactNode) | undefined;
318
320
  renderEndIcon?: (() => React.ReactNode) | undefined;
319
321
  modal?: boolean | undefined;
320
322
  optionContainerClassName?: string | undefined;
@@ -5,6 +5,7 @@ export type InputProps = {
5
5
  size?: "sm" | "md" | "lg";
6
6
  rounded?: "none" | "normal" | "full";
7
7
  variant?: "flat" | "outline" | "underline";
8
+ iconMode?: "flat" | "solid";
8
9
  type?: React.HTMLInputTypeAttribute;
9
10
  helperText?: string;
10
11
  errorMessage?: string;
@@ -22,6 +23,7 @@ export type InputProps = {
22
23
  labelClassName?: string;
23
24
  onClickStartIcon?: () => void;
24
25
  onClickEndIcon?: () => void;
26
+ renderStartIcon?: () => ReactNode;
25
27
  renderEndIcon?: () => ReactNode;
26
28
  } & Omit<React.InputHTMLAttributes<HTMLInputElement>, "size">;
27
29
  export declare const TextInput: React.ForwardRefExoticComponent<{
@@ -30,6 +32,7 @@ export declare const TextInput: React.ForwardRefExoticComponent<{
30
32
  size?: "sm" | "md" | "lg";
31
33
  rounded?: "none" | "normal" | "full";
32
34
  variant?: "flat" | "outline" | "underline";
35
+ iconMode?: "flat" | "solid";
33
36
  type?: React.HTMLInputTypeAttribute;
34
37
  helperText?: string;
35
38
  errorMessage?: string;
@@ -47,6 +50,7 @@ export declare const TextInput: React.ForwardRefExoticComponent<{
47
50
  labelClassName?: string;
48
51
  onClickStartIcon?: () => void;
49
52
  onClickEndIcon?: () => void;
53
+ renderStartIcon?: () => ReactNode;
50
54
  renderEndIcon?: () => ReactNode;
51
55
  } & Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & React.RefAttributes<HTMLInputElement>>;
52
56
  export default TextInput;
@@ -7,6 +7,7 @@ declare const meta: {
7
7
  size?: "sm" | "md" | "lg";
8
8
  rounded?: "none" | "normal" | "full";
9
9
  variant?: "flat" | "outline" | "underline";
10
+ iconMode?: "flat" | "solid";
10
11
  type?: React.HTMLInputTypeAttribute;
11
12
  helperText?: string;
12
13
  errorMessage?: string;
@@ -24,6 +25,7 @@ declare const meta: {
24
25
  labelClassName?: string;
25
26
  onClickStartIcon?: () => void;
26
27
  onClickEndIcon?: () => void;
28
+ renderStartIcon?: () => React.ReactNode;
27
29
  renderEndIcon?: () => React.ReactNode;
28
30
  } & Omit<React.InputHTMLAttributes<HTMLInputElement>, "size"> & React.RefAttributes<HTMLInputElement>>;
29
31
  tags: string[];
@@ -36,6 +38,7 @@ declare const meta: {
36
38
  size?: "sm" | "md" | "lg" | undefined;
37
39
  rounded?: "none" | "normal" | "full" | undefined;
38
40
  variant?: "flat" | "outline" | "underline" | undefined;
41
+ iconMode?: "flat" | "solid" | undefined;
39
42
  type?: React.HTMLInputTypeAttribute | undefined;
40
43
  helperText?: string | undefined;
41
44
  errorMessage?: string | undefined;
@@ -53,6 +56,7 @@ declare const meta: {
53
56
  labelClassName?: string | undefined;
54
57
  onClickStartIcon?: (() => void) | undefined;
55
58
  onClickEndIcon?: (() => void) | undefined;
59
+ renderStartIcon?: (() => React.ReactNode) | undefined;
56
60
  renderEndIcon?: (() => React.ReactNode) | undefined;
57
61
  suppressHydrationWarning?: boolean | undefined | undefined;
58
62
  color?: string | undefined | undefined;
@@ -371,3 +375,10 @@ export declare const FuctionInput: {
371
375
  };
372
376
  render: (args: {}) => import("react/jsx-runtime").JSX.Element;
373
377
  };
378
+ export declare const CustomIcon: {
379
+ args: {
380
+ label: string;
381
+ disabled: boolean;
382
+ };
383
+ render: (args: {}) => import("react/jsx-runtime").JSX.Element;
384
+ };
@@ -15,6 +15,7 @@ export declare const labelVariant: (props?: ({
15
15
  disabled?: boolean | null | undefined;
16
16
  error?: boolean | null | undefined;
17
17
  hasSearchIcon?: boolean | null | undefined;
18
+ hasLeftSectionIcon?: boolean | null | undefined;
18
19
  isFloatingLabel?: boolean | null | undefined;
19
20
  } & import("class-variance-authority/dist/types").ClassProp) | undefined) => string;
20
21
  export declare const helperTextVariant: (props?: ({
@@ -33,6 +33,7 @@ export * from "./components/Toast/Toast";
33
33
  export * from "./components/Toast/Toaster";
34
34
  export * from "./components/Toast/useToast";
35
35
  export * from "./components/Tree";
36
+ export * from "./components/FocusedScrollView/FocusedScrollView";
36
37
  export type { ButtonProps } from "./components/Button/Button";
37
38
  export type { InputProps } from "./components/TextInput/TextInput";
38
39
  export type { DropdownProps, Options } from "./components/Dropdown/Dropdown";
@@ -0,0 +1,67 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { useRef, useEffect, cloneElement, isValidElement, } from "react";
3
+ export const FocusedScrollView = ({ selectedKey, children, direction = "vertical", className, containerProps, scrollAlign = "center", }) => {
4
+ const containerRef = useRef(null);
5
+ const itemRefs = useRef({});
6
+ const scrollToItem = (key) => {
7
+ const container = containerRef.current;
8
+ const item = itemRefs.current[key];
9
+ if (container && item) {
10
+ if (direction === "vertical") {
11
+ const containerTop = container.getBoundingClientRect().top;
12
+ const itemTop = item.getBoundingClientRect().top;
13
+ const offset = itemTop - containerTop + container.scrollTop;
14
+ const containerHeight = container.clientHeight;
15
+ const itemHeight = item.offsetHeight;
16
+ let targetTop = offset;
17
+ if (scrollAlign === "center") {
18
+ targetTop = offset - (containerHeight / 2 - itemHeight / 2);
19
+ }
20
+ else if (scrollAlign === "end") {
21
+ targetTop = offset + (itemHeight - containerHeight);
22
+ }
23
+ container.scrollTo({
24
+ top: targetTop,
25
+ behavior: "smooth",
26
+ });
27
+ }
28
+ else if (direction === "horizontal") {
29
+ const containerLeft = container.getBoundingClientRect().left;
30
+ const itemLeft = item.getBoundingClientRect().left;
31
+ const offset = itemLeft - containerLeft + container.scrollLeft;
32
+ const containerWidth = container.clientWidth;
33
+ const itemWidth = item.offsetWidth;
34
+ let targetLeft = offset;
35
+ if (scrollAlign === "center") {
36
+ targetLeft = offset - (containerWidth / 2 - itemWidth / 2);
37
+ }
38
+ else if (scrollAlign === "end") {
39
+ targetLeft = offset + (itemWidth - containerWidth);
40
+ }
41
+ container.scrollTo({
42
+ left: targetLeft,
43
+ behavior: "smooth",
44
+ });
45
+ }
46
+ }
47
+ };
48
+ useEffect(() => {
49
+ if (selectedKey) {
50
+ scrollToItem(selectedKey);
51
+ }
52
+ }, [selectedKey, direction, scrollAlign]);
53
+ const enhancedChildren = Array.isArray(children)
54
+ ? children.map((child) => {
55
+ if (isValidElement(child) && child.key) {
56
+ return cloneElement(child, {
57
+ // @ts-ignore
58
+ ref: (el) => {
59
+ itemRefs.current[String(child.key)] = el;
60
+ },
61
+ });
62
+ }
63
+ return child;
64
+ })
65
+ : children;
66
+ return (_jsx("div", Object.assign({ ref: containerRef, className: `overflow-auto ${direction === "vertical" ? "max-h-60" : "max-w-full whitespace-nowrap"} ${className !== null && className !== void 0 ? className : ""}` }, containerProps, { children: enhancedChildren })));
67
+ };
@@ -0,0 +1,33 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { useState } from "react";
3
+ import { FocusedScrollView } from "./FocusedScrollView";
4
+ const meta = {
5
+ title: "Components/FocusedScrollView",
6
+ component: FocusedScrollView,
7
+ args: {
8
+ direction: "vertical",
9
+ scrollAlign: "center",
10
+ className: "border border-input-default-stroke rounded",
11
+ },
12
+ };
13
+ export default meta;
14
+ const items = Array.from({ length: 30 }, (_, i) => `Item ${i + 1}`);
15
+ export const VerticalScroll = {
16
+ render: (args) => {
17
+ const [selected, setSelected] = useState("item-5");
18
+ return (_jsxs("div", { className: "p-6 space-y-4", children: [_jsxs("div", { className: "flex gap-2", children: [_jsx("button", { onClick: () => setSelected("item-5"), className: "px-3 py-1 bg-primary text-white rounded", children: "Scroll to Item 5" }), _jsx("button", { onClick: () => setSelected("item-20"), className: "px-3 py-1 bg-primary text-white rounded", children: "Scroll to Item 20" }), _jsx("button", { onClick: () => setSelected("item-29"), className: "px-3 py-1 bg-primary text-white rounded", children: "Scroll to Item 30" })] }), _jsx(FocusedScrollView, Object.assign({}, args, { selectedKey: selected, children: items.map((item, index) => (_jsx("div", { className: `px-4 py-2 ${selected === `item-${index + 1}`
19
+ ? "bg-secondary text-secondary-foreground"
20
+ : "bg-white"}`, children: item }, `item-${index + 1}`))) }))] }));
21
+ },
22
+ };
23
+ export const HorizontalScroll = {
24
+ args: {
25
+ direction: "horizontal",
26
+ },
27
+ render: (args) => {
28
+ const [selected, setSelected] = useState("item-15");
29
+ return (_jsxs("div", { className: "p-6 space-y-4", children: [_jsxs("div", { className: "flex gap-2", children: [_jsx("button", { onClick: () => setSelected("item-5"), className: "px-3 py-1 bg-primary text-white rounded", children: "Scroll to Item 5" }), _jsx("button", { onClick: () => setSelected("item-15"), className: "px-3 py-1 bg-primary text-white rounded", children: "Scroll to Item 15" }), _jsx("button", { onClick: () => setSelected("item-25"), className: "px-3 py-1 bg-primary text-white rounded", children: "Scroll to Item 25" })] }), _jsx(FocusedScrollView, Object.assign({}, args, { selectedKey: selected, children: items.map((item, index) => (_jsx("div", { className: `inline-block w-28 h-12 mx-2 text-center leading-[3rem] rounded ${selected === `item-${index + 1}`
30
+ ? "bg-secondary text-secondary-foreground"
31
+ : "bg-gray-200"}`, children: item }, `item-${index + 1}`))) }))] }));
32
+ },
33
+ };
@@ -10,16 +10,16 @@ var __rest = (this && this.__rest) || function (s, e) {
10
10
  return t;
11
11
  };
12
12
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
13
- import { forwardRef, useCallback, useImperativeHandle, useRef, } from "react";
13
+ import { forwardRef, useCallback, useImperativeHandle, useMemo, useRef, } from "react";
14
14
  import { helperTextVariant, iconSearchWrapperVariant, iconVariant, iconWrapperVariant, inputVariant, labelVariant, sectionIconWrapperVariant, } from "./TextInput.styles";
15
15
  import { XCircleIcon, ExclamationCircleIcon, MagnifyingGlassIcon, } from "@heroicons/react/16/solid";
16
16
  import { cn } from "@/utils/cn";
17
17
  export const TextInput = forwardRef((_a, ref) => {
18
- var { id, label, size = "md", rounded = "normal", variant = "outline", type = "text", helperText, errorMessage, fullwidth = true, disabled = false, error = false, required = true, isFloatingLabel = true, keepCloseIconOnValue = false, hasClearIcon = true, hasSearchIcon = false, startIcon, endIcon, labelClassName, onClickEndIcon, renderEndIcon } = _a, props = __rest(_a, ["id", "label", "size", "rounded", "variant", "type", "helperText", "errorMessage", "fullwidth", "disabled", "error", "required", "isFloatingLabel", "keepCloseIconOnValue", "hasClearIcon", "hasSearchIcon", "startIcon", "endIcon", "labelClassName", "onClickEndIcon", "renderEndIcon"]);
18
+ var { id, label, size = "md", rounded = "normal", variant = "outline", type = "text", iconMode = "solid", helperText, errorMessage, fullwidth = true, disabled = false, error = false, required = true, isFloatingLabel = true, keepCloseIconOnValue = false, hasClearIcon = true, hasSearchIcon = false, startIcon, endIcon, labelClassName, onClickStartIcon, onClickEndIcon, renderStartIcon, renderEndIcon } = _a, props = __rest(_a, ["id", "label", "size", "rounded", "variant", "type", "iconMode", "helperText", "errorMessage", "fullwidth", "disabled", "error", "required", "isFloatingLabel", "keepCloseIconOnValue", "hasClearIcon", "hasSearchIcon", "startIcon", "endIcon", "labelClassName", "onClickStartIcon", "onClickEndIcon", "renderStartIcon", "renderEndIcon"]);
19
19
  const inputRef = useRef(null);
20
20
  const _id = id || `${type}-${label}-input`;
21
- const hasLeftSectionIcon = !!startIcon;
22
- const hasRightSectionIcon = !!endIcon;
21
+ const hasLeftSectionIcon = !!startIcon || !!renderStartIcon;
22
+ const hasRightSectionIcon = !!endIcon || !!renderEndIcon;
23
23
  const inputClassname = inputVariant({
24
24
  size,
25
25
  rounded,
@@ -27,27 +27,35 @@ export const TextInput = forwardRef((_a, ref) => {
27
27
  fullwidth,
28
28
  disabled,
29
29
  error,
30
- hasSearchIcon,
31
- hasClearIcon: hasRightSectionIcon ? false : hasClearIcon,
32
- leftSectionIcon: hasLeftSectionIcon,
33
- rightSectionIcon: hasRightSectionIcon,
30
+ hasSearchIcon: (iconMode === "flat" && hasLeftSectionIcon) || hasSearchIcon,
31
+ hasClearIcon: (iconMode === "flat" && hasRightSectionIcon) || hasClearIcon,
32
+ leftSectionIcon: iconMode === "solid" ? hasLeftSectionIcon : false,
33
+ rightSectionIcon: iconMode === "solid" ? hasRightSectionIcon : false,
34
34
  });
35
35
  const labelClassname = labelVariant({
36
36
  size,
37
37
  disabled,
38
38
  error,
39
- hasSearchIcon,
39
+ hasSearchIcon: (iconMode === "flat" && hasLeftSectionIcon) || hasSearchIcon,
40
+ hasLeftSectionIcon: iconMode === "solid" ? hasLeftSectionIcon : false,
40
41
  isFloatingLabel,
41
42
  });
42
43
  const helperTextClassname = helperTextVariant({ size, error, disabled });
43
44
  const iconWrapperClassname = iconWrapperVariant({ size });
44
45
  const iconSearchWrapperClassname = iconSearchWrapperVariant({ size });
45
46
  const iconClassname = iconVariant({ size });
46
- // TODO startIcon
47
+ // TODO wait for clearify aboutm start,end, search and clearIcon with iconMode
48
+ const startIconWrapperClassname = sectionIconWrapperVariant({
49
+ size,
50
+ rounded,
51
+ error,
52
+ position: "start",
53
+ });
47
54
  const endIconWrapperClassname = sectionIconWrapperVariant({
48
55
  size,
49
56
  rounded,
50
57
  error,
58
+ position: "end",
51
59
  });
52
60
  useImperativeHandle(ref, () => inputRef === null || inputRef === void 0 ? void 0 : inputRef.current);
53
61
  const handleClearInput = useCallback(() => {
@@ -59,7 +67,14 @@ export const TextInput = forwardRef((_a, ref) => {
59
67
  }
60
68
  }
61
69
  }, [props.onChange]);
62
- // TODO startIcon
70
+ const handleOnClickLeftSectionIcon = useCallback(() => {
71
+ if (disabled)
72
+ return;
73
+ onClickStartIcon === null || onClickStartIcon === void 0 ? void 0 : onClickStartIcon();
74
+ if (inputRef.current) {
75
+ inputRef.current.focus();
76
+ }
77
+ }, [disabled, onClickStartIcon]);
63
78
  const handleOnClickRightSectionIcon = useCallback(() => {
64
79
  if (disabled)
65
80
  return;
@@ -68,10 +83,47 @@ export const TextInput = forwardRef((_a, ref) => {
68
83
  inputRef.current.focus();
69
84
  }
70
85
  }, [disabled, onClickEndIcon]);
71
- return (_jsxs("div", { className: `inline-flex flex-col ${fullwidth ? "w-full" : ""}`, children: [_jsxs("div", { className: "relative", children: [hasSearchIcon && (_jsx("div", { className: iconSearchWrapperClassname, children: _jsx(MagnifyingGlassIcon, { className: iconClassname }) })), _jsx("input", Object.assign({}, props, { placeholder: " ", ref: inputRef, type: type, id: _id, disabled: disabled, className: cn(inputClassname, props.className) })), hasClearIcon && !hasRightSectionIcon && (_jsx("div", { className: iconWrapperClassname, style: {
86
+ const startIconElement = useMemo(() => {
87
+ if (!hasLeftSectionIcon)
88
+ return;
89
+ if (renderStartIcon)
90
+ return renderStartIcon();
91
+ if (iconMode === "flat") {
92
+ return (_jsx("div", { className: iconSearchWrapperClassname, children: _jsx("div", { className: iconClassname, onClick: handleOnClickLeftSectionIcon, children: startIcon }) }));
93
+ }
94
+ return (_jsx("div", { className: startIconWrapperClassname, onClick: handleOnClickLeftSectionIcon, children: startIcon }));
95
+ }, [
96
+ hasLeftSectionIcon,
97
+ startIcon,
98
+ iconMode,
99
+ iconSearchWrapperClassname,
100
+ startIconWrapperClassname,
101
+ iconClassname,
102
+ renderStartIcon,
103
+ handleOnClickLeftSectionIcon,
104
+ ]);
105
+ const endIconElement = useMemo(() => {
106
+ if (!hasRightSectionIcon)
107
+ return;
108
+ if (renderEndIcon)
109
+ return renderEndIcon();
110
+ if (iconMode === "flat") {
111
+ return (_jsx("div", { className: cn(iconWrapperClassname, "flex"), children: _jsx("div", { className: iconClassname, onClick: handleOnClickRightSectionIcon, children: endIcon }) }));
112
+ }
113
+ return (_jsx("div", { className: endIconWrapperClassname, onClick: handleOnClickRightSectionIcon, children: endIcon }));
114
+ }, [
115
+ hasRightSectionIcon,
116
+ endIcon,
117
+ iconMode,
118
+ iconSearchWrapperClassname,
119
+ endIconWrapperClassname,
120
+ iconClassname,
121
+ renderEndIcon,
122
+ handleOnClickRightSectionIcon,
123
+ ]);
124
+ return (_jsxs("div", { className: `inline-flex flex-col ${fullwidth ? "w-full" : ""}`, children: [_jsxs("div", { className: "relative", children: [hasSearchIcon && !hasLeftSectionIcon && (_jsx("div", { className: iconSearchWrapperClassname, children: _jsx(MagnifyingGlassIcon, { className: iconClassname }) })), _jsx("input", Object.assign({}, props, { placeholder: " ", ref: inputRef, type: type, id: _id, disabled: disabled, className: cn(inputClassname, props.className) })), startIconElement, hasClearIcon && !hasRightSectionIcon && (_jsx("div", { className: iconWrapperClassname, style: {
72
125
  display: keepCloseIconOnValue && props.value ? "flex" : undefined,
73
- }, children: _jsx(XCircleIcon, { type: "button", className: iconClassname, onMouseDown: handleClearInput }) })), hasRightSectionIcon &&
74
- (renderEndIcon ? (renderEndIcon()) : (_jsx("div", { className: endIconWrapperClassname, onClick: handleOnClickRightSectionIcon, children: endIcon }))), _jsxs("label", { htmlFor: _id, className: cn(labelClassname, labelClassName), children: [label, " ", required && (_jsx("span", { className: cn("text-error", {
126
+ }, children: _jsx(XCircleIcon, { type: "button", className: iconClassname, onMouseDown: handleClearInput }) })), endIconElement, _jsxs("label", { htmlFor: _id, className: cn(labelClassname, labelClassName), children: [label, " ", required && (_jsx("span", { className: cn("text-error", {
75
127
  "text-input-disable-text": disabled,
76
128
  }), children: "*" }))] })] }), (errorMessage || helperText) && (_jsxs("span", { className: helperTextClassname, children: [_jsx("span", { className: "h-full", children: _jsx(ExclamationCircleIcon, { width: 16, height: 16, className: error ? "fill-error" : "" }) }), errorMessage || helperText] }))] }));
77
129
  });
@@ -2,6 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import { useRef } from "react";
3
3
  import TextInput from "./TextInput";
4
4
  import { CalendarIcon } from "@heroicons/react/16/solid";
5
+ import Icon from "../Icon/Icon";
5
6
  // More on how to set up stories at: https://storybook.js.org/docs/7.0/react/writing-stories/introduction
6
7
  const meta = {
7
8
  title: "Components/TextInput",
@@ -61,3 +62,17 @@ export const FuctionInput = {
61
62
  return (_jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(TextInput, Object.assign({ id: "1", size: "lg" }, args, { endIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }) })), _jsx(TextInput, Object.assign({ id: "2", size: "md" }, args, { endIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }) })), _jsx(TextInput, Object.assign({ id: "3", size: "sm" }, args, { endIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }) }))] }));
62
63
  },
63
64
  };
65
+ export const CustomIcon = {
66
+ args: {
67
+ label: "Placeholder Text",
68
+ // value: "",
69
+ disabled: true,
70
+ },
71
+ render: (args) => {
72
+ console.log("args ", args);
73
+ const props = Object.assign({}, args);
74
+ return (_jsxs("div", { className: "flex flex-col gap-4 w-full", children: [_jsx("div", { children: _jsx("h4", { children: "Icon mode: solid:" }) }), _jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(TextInput, Object.assign({ id: "1", size: "lg" }, args, { startIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }), endIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }) })), _jsx(TextInput, Object.assign({ id: "2", size: "md" }, args, { startIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }), endIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }) })), _jsx(TextInput, Object.assign({ id: "3", size: "sm" }, args, { startIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }), endIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }) }))] }), _jsx("div", { children: _jsx("h4", { children: "Icon mode: flat:" }) }), _jsxs("div", { className: "flex flex-row gap-4 w-full", children: [_jsx(TextInput, Object.assign({ id: "1", size: "lg" }, args, { iconMode: "flat", startIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }), endIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }) })), _jsx(TextInput, Object.assign({ id: "2", size: "md" }, args, { iconMode: "flat", startIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }), endIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }) })), _jsx(TextInput, Object.assign({ id: "3", size: "sm" }, args, { iconMode: "flat", startIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }), endIcon: _jsx(CalendarIcon, { className: "size-full", fill: "inherit" }) }))] }), _jsx(TextInput, Object.assign({ id: "1", size: "lg" }, args, { iconMode: "flat", startIcon: _jsx(Icon, { name: "magnifying-glass", fill: "inherit" }),
75
+ // <MagnifyingGlassIcon className="size-full" fill="inherit" />
76
+ hasClearIcon: true }))] }));
77
+ },
78
+ };
@@ -148,6 +148,9 @@ export const labelVariant = cva([
148
148
  hasSearchIcon: {
149
149
  false: "",
150
150
  },
151
+ hasLeftSectionIcon: {
152
+ false: "",
153
+ },
151
154
  isFloatingLabel: {
152
155
  false: "hidden peer-placeholder-shown:block peer-focus:bg-transparent",
153
156
  },
@@ -260,12 +263,69 @@ export const labelVariant = cva([
260
263
  "left-11 peer-placeholder-shown:top-4 peer-placeholder-shown:typography-subtitile1",
261
264
  ],
262
265
  },
266
+ // -------- hasLeftSectionIcon ------
267
+ {
268
+ isFloatingLabel: true,
269
+ hasLeftSectionIcon: true,
270
+ size: "sm",
271
+ className: [
272
+ "left-[38px] -top-1.5 typography-label2 bg-input-label-bg",
273
+ "peer-placeholder-shown:top-2 peer-placeholder-shown:typography-small1 peer-placeholder-shown:bg-transparent",
274
+ "peer-focus:-top-1.5 peer-focus:typography-label2",
275
+ ],
276
+ },
277
+ {
278
+ isFloatingLabel: true,
279
+ hasLeftSectionIcon: true,
280
+ size: "md",
281
+ className: [
282
+ "left-[46px] -top-1.5 typography-label1 bg-input-label-bg",
283
+ "peer-placeholder-shown:top-2 peer-placeholder-shown:typography-subtitile4 peer-placeholder-shown:bg-transparent",
284
+ "peer-focus:-top-1.5 peer-focus:typography-label1",
285
+ ],
286
+ },
287
+ {
288
+ isFloatingLabel: true,
289
+ hasLeftSectionIcon: true,
290
+ size: "lg",
291
+ className: [
292
+ "left-[72px] -top-1.5 typography-label1 bg-input-label-bg",
293
+ "peer-placeholder-shown:top-4 peer-placeholder-shown:typography-subtitile1 peer-placeholder-shown:bg-transparent",
294
+ "peer-focus:-top-1.5 peer-focus:typography-label1",
295
+ ],
296
+ },
297
+ // floating = false and has search icon
298
+ {
299
+ isFloatingLabel: false,
300
+ hasLeftSectionIcon: true,
301
+ size: "sm",
302
+ className: [
303
+ "left-[38px] peer-placeholder-shown:top-2 peer-placeholder-shown:typography-small1",
304
+ ],
305
+ },
306
+ {
307
+ isFloatingLabel: false,
308
+ hasLeftSectionIcon: true,
309
+ size: "md",
310
+ className: [
311
+ "left-[46px] peer-placeholder-shown:top-2 peer-placeholder-shown:typography-subtitile4",
312
+ ],
313
+ },
314
+ {
315
+ isFloatingLabel: false,
316
+ hasLeftSectionIcon: true,
317
+ size: "lg",
318
+ className: [
319
+ "left-[72px] peer-placeholder-shown:top-4 peer-placeholder-shown:typography-subtitile1",
320
+ ],
321
+ },
263
322
  ],
264
323
  defaultVariants: {
265
324
  size: "md",
266
325
  disabled: false,
267
326
  error: false,
268
327
  hasSearchIcon: false,
328
+ hasLeftSectionIcon: false,
269
329
  isFloatingLabel: true,
270
330
  },
271
331
  });
@@ -333,7 +393,6 @@ export const iconVariant = cva([
333
393
  export const sectionIconWrapperVariant = cva([
334
394
  "cursor-pointer",
335
395
  "absolute items-center justify-center flex",
336
- "border-l border-l-input-default-stroke peer-hover:border-l-input-active-stroke peer-focus:border-l-input-active-stroke peer-disabled:border-l-input-disable-stroke",
337
396
  "fill-input-default-text peer-hover:fill-input-filled-text peer-focus:fill-input-filled-text peer-disabled:fill-input-disable-stroke",
338
397
  ], {
339
398
  variants: {
@@ -343,18 +402,68 @@ export const sectionIconWrapperVariant = cva([
343
402
  lg: "p-3 size-14",
344
403
  },
345
404
  rounded: {
346
- none: "rounded-r-none",
347
- normal: "rounded-r-xl",
348
- full: "rounded-r-full",
405
+ none: "",
406
+ normal: "",
407
+ full: "",
349
408
  },
350
409
  error: {
351
- true: "border-l-input-error",
410
+ false: "",
352
411
  },
353
412
  position: {
354
- start: "inset-y-0 left-0 ",
355
- end: "inset-y-0 right-0 ",
413
+ start: [
414
+ "inset-y-0 left-0 ",
415
+ "border-r border-r-input-default-stroke peer-hover:border-r-input-active-stroke peer-focus:border-r-input-active-stroke peer-disabled:border-r-input-disable-stroke",
416
+ ],
417
+ end: [
418
+ "inset-y-0 right-0 ",
419
+ "border-l border-l-input-default-stroke peer-hover:border-l-input-active-stroke peer-focus:border-l-input-active-stroke peer-disabled:border-l-input-disable-stroke",
420
+ ],
356
421
  },
357
422
  },
423
+ compoundVariants: [
424
+ // --- start rounded ---
425
+ {
426
+ position: "start",
427
+ rounded: "none",
428
+ className: "rounded-l-none",
429
+ },
430
+ {
431
+ position: "start",
432
+ rounded: "normal",
433
+ className: "rounded-l-xl",
434
+ },
435
+ {
436
+ position: "start",
437
+ rounded: "full",
438
+ className: "rounded-l-full",
439
+ },
440
+ {
441
+ position: "end",
442
+ rounded: "none",
443
+ className: "rounded-r-none",
444
+ },
445
+ {
446
+ position: "end",
447
+ rounded: "normal",
448
+ className: "rounded-r-xl",
449
+ },
450
+ {
451
+ position: "end",
452
+ rounded: "full",
453
+ className: "rounded-r-full",
454
+ },
455
+ // --- Error start ---
456
+ {
457
+ position: "start",
458
+ error: true,
459
+ className: "border-r-input-error",
460
+ },
461
+ {
462
+ position: "end",
463
+ error: true,
464
+ className: "border-l-input-error",
465
+ },
466
+ ],
358
467
  defaultVariants: {
359
468
  size: "md",
360
469
  rounded: "normal",