@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.
- package/dist/cjs/bundle.css +67 -0
- package/dist/cjs/bundle.js +3 -3
- package/dist/cjs/bundle.js.map +1 -1
- package/dist/cjs/types/components/Dropdown/Dropdown.stories.d.ts +2 -0
- package/dist/cjs/types/components/FocusedScrollView/FocusedScrollView.d.ts +12 -0
- package/dist/cjs/types/components/FocusedScrollView/FocusedScrollView.stories.d.ts +7 -0
- package/dist/cjs/types/components/InputFilter/InputFilter.stories.d.ts +2 -0
- package/dist/cjs/types/components/Search/Search.stories.d.ts +2 -0
- package/dist/cjs/types/components/TextInput/TextInput.d.ts +4 -0
- package/dist/cjs/types/components/TextInput/TextInput.stories.d.ts +11 -0
- package/dist/cjs/types/components/TextInput/TextInput.styles.d.ts +1 -0
- package/dist/cjs/types/index.d.ts +1 -0
- package/dist/components/FocusedScrollView/FocusedScrollView.js +67 -0
- package/dist/components/FocusedScrollView/FocusedScrollView.stories.js +33 -0
- package/dist/components/TextInput/TextInput.js +66 -14
- package/dist/components/TextInput/TextInput.stories.js +15 -0
- package/dist/components/TextInput/TextInput.styles.js +116 -7
- package/dist/esm/bundle.css +67 -0
- package/dist/esm/bundle.js +3 -3
- package/dist/esm/bundle.js.map +1 -1
- package/dist/esm/types/components/Dropdown/Dropdown.stories.d.ts +2 -0
- package/dist/esm/types/components/FocusedScrollView/FocusedScrollView.d.ts +12 -0
- package/dist/esm/types/components/FocusedScrollView/FocusedScrollView.stories.d.ts +7 -0
- package/dist/esm/types/components/InputFilter/InputFilter.stories.d.ts +2 -0
- package/dist/esm/types/components/Search/Search.stories.d.ts +2 -0
- package/dist/esm/types/components/TextInput/TextInput.d.ts +4 -0
- package/dist/esm/types/components/TextInput/TextInput.stories.d.ts +11 -0
- package/dist/esm/types/components/TextInput/TextInput.styles.d.ts +1 -0
- package/dist/esm/types/index.d.ts +1 -0
- package/dist/index.d.ts +17 -2
- package/dist/index.js +1 -0
- package/dist/src/theme/global.css +86 -0
- package/package.json +1 -1
- package/src/components/FocusedScrollView/FocusedScrollView.stories.tsx +114 -0
- package/src/components/FocusedScrollView/FocusedScrollView.tsx +112 -0
- package/src/components/TextInput/TextInput.stories.tsx +83 -0
- package/src/components/TextInput/TextInput.styles.ts +117 -7
- package/src/components/TextInput/TextInput.tsx +115 -21
- 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:
|
|
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
|
|
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
|
-
|
|
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
|
-
|
|
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 }) })),
|
|
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: "
|
|
347
|
-
normal: "
|
|
348
|
-
full: "
|
|
405
|
+
none: "",
|
|
406
|
+
normal: "",
|
|
407
|
+
full: "",
|
|
349
408
|
},
|
|
350
409
|
error: {
|
|
351
|
-
|
|
410
|
+
false: "",
|
|
352
411
|
},
|
|
353
412
|
position: {
|
|
354
|
-
start:
|
|
355
|
-
|
|
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",
|