kahuna-base-react-components 0.2.18 → 0.2.20
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/components/KButton/KButton.d.ts +1 -0
- package/dist/components/KCodeInput/KCodeInput.d.ts +36 -0
- package/dist/components/KCodeInput/index.d.ts +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.esm.js +2 -2
- package/dist/index.esm.js.map +1 -1
- package/dist/index.js +2 -2
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +37 -2
- package/package.json +1 -1
- package/src/components/KButton/KButton.tsx +3 -2
- package/src/components/KCodeInput/KCodeInput.stories.tsx +84 -0
- package/src/components/KCodeInput/KCodeInput.tsx +260 -0
- package/src/components/KCodeInput/index.ts +1 -0
- package/src/components/KLogo/KLogo.tsx +1 -1
- package/src/components/KSliderLabel/KSliderLabel.stories.tsx +51 -47
- package/src/components/KSliderLabel/KSliderLabel.tsx +5 -2
- package/src/index.ts +3 -1
- package/src/main.css +11 -2
package/dist/types.d.ts
CHANGED
|
@@ -18,6 +18,7 @@ interface KButtonProps {
|
|
|
18
18
|
hoverBackground?: string;
|
|
19
19
|
fontWeight?: number;
|
|
20
20
|
textDecoration?: string;
|
|
21
|
+
gap?: string;
|
|
21
22
|
}
|
|
22
23
|
declare const KButton: React.FC<KButtonProps>;
|
|
23
24
|
|
|
@@ -93,7 +94,7 @@ interface KInputProps {
|
|
|
93
94
|
iconSize?: string;
|
|
94
95
|
checked?: boolean;
|
|
95
96
|
}
|
|
96
|
-
declare const KInput: React.FC<KInputProps>;
|
|
97
|
+
declare const KInput$1: React.FC<KInputProps>;
|
|
97
98
|
|
|
98
99
|
interface KSelectOption {
|
|
99
100
|
label: string;
|
|
@@ -183,4 +184,38 @@ interface SliderLabelProps {
|
|
|
183
184
|
}
|
|
184
185
|
declare const KSliderLabel: React.FC<SliderLabelProps>;
|
|
185
186
|
|
|
186
|
-
|
|
187
|
+
interface KCodeInputProps {
|
|
188
|
+
onChange: (value: string) => void;
|
|
189
|
+
length?: number;
|
|
190
|
+
borderRadius?: number;
|
|
191
|
+
disabled?: boolean;
|
|
192
|
+
padding?: string;
|
|
193
|
+
gap?: number;
|
|
194
|
+
fontSize?: string;
|
|
195
|
+
fontWeight?: string;
|
|
196
|
+
color?: string;
|
|
197
|
+
lineHeight?: string;
|
|
198
|
+
allowedCharacters?: "numeric" | "alphaNumeric" | "alpha";
|
|
199
|
+
width?: number;
|
|
200
|
+
height?: number;
|
|
201
|
+
autoFocus?: boolean;
|
|
202
|
+
isPassword?: boolean;
|
|
203
|
+
background?: string;
|
|
204
|
+
hoverBackground?: string;
|
|
205
|
+
focusedBackground?: string;
|
|
206
|
+
filledBackground?: string;
|
|
207
|
+
border?: string;
|
|
208
|
+
hoverBorder?: string;
|
|
209
|
+
focusedBorder?: string;
|
|
210
|
+
filledBorder?: string;
|
|
211
|
+
boxShadow?: string;
|
|
212
|
+
hoverBoxShadow?: string;
|
|
213
|
+
focusedBoxShadow?: string;
|
|
214
|
+
filledBoxShadow?: string;
|
|
215
|
+
fitInContainer?: boolean;
|
|
216
|
+
isCodeCorrect?: boolean;
|
|
217
|
+
autoBlur?: boolean;
|
|
218
|
+
}
|
|
219
|
+
declare const KInput: React.FC<KCodeInputProps>;
|
|
220
|
+
|
|
221
|
+
export { KButton, KInput as KCodeInput, KDropdown, KInput$1 as KInput, KLogo, KSelectDate, KSlider, KSliderLabel, KSpan, KTitleSpan, KTooltip };
|
package/package.json
CHANGED
|
@@ -19,6 +19,7 @@ export interface KButtonProps {
|
|
|
19
19
|
hoverBackground?: string
|
|
20
20
|
fontWeight?: number
|
|
21
21
|
textDecoration?: string
|
|
22
|
+
gap?: string
|
|
22
23
|
}
|
|
23
24
|
|
|
24
25
|
const KButton: React.FC<KButtonProps> = (props) => {
|
|
@@ -35,7 +36,7 @@ const KButton: React.FC<KButtonProps> = (props) => {
|
|
|
35
36
|
const hoverBackground = props.hoverBackground || background
|
|
36
37
|
const fontWeight = props.fontWeight || 500
|
|
37
38
|
const textDecoration = props.textDecoration || "none"
|
|
38
|
-
|
|
39
|
+
const gap = props.gap || "0px"
|
|
39
40
|
return (
|
|
40
41
|
<button
|
|
41
42
|
onMouseEnter={() => setHover(true)}
|
|
@@ -45,7 +46,7 @@ const KButton: React.FC<KButtonProps> = (props) => {
|
|
|
45
46
|
onClick={props.onClick}
|
|
46
47
|
style={{ background: hover ? hoverBackground : background, borderRadius, width, height, padding, boxShadow }}
|
|
47
48
|
>
|
|
48
|
-
<div className={"flex"}>
|
|
49
|
+
<div className={"flex items-center"} style={{gap}}>
|
|
49
50
|
{props.leftIcon && <img src={props.leftIcon} alt={"button-left-icon"} />}
|
|
50
51
|
{props.text && (
|
|
51
52
|
<KSpan text={props.text} color={textColor} fontWeight={fontWeight} textDecoration={textDecoration} />
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Meta, StoryFn } from "@storybook/react"
|
|
2
|
+
import KCodeInput, { KCodeInputProps } from "./KCodeInput"
|
|
3
|
+
// @ts-ignore
|
|
4
|
+
import { useEffect, useState } from "react"
|
|
5
|
+
|
|
6
|
+
export default {
|
|
7
|
+
title: "ReactComponentLibrary/KCodeInput",
|
|
8
|
+
component: KCodeInput,
|
|
9
|
+
parameters: {
|
|
10
|
+
layout: "centered"
|
|
11
|
+
}
|
|
12
|
+
} as Meta<typeof KCodeInput>
|
|
13
|
+
|
|
14
|
+
const KCodeInputWrapper: React.FC<KCodeInputProps> = (args) => {
|
|
15
|
+
const [code, setCode] = useState<string>("");
|
|
16
|
+
|
|
17
|
+
useEffect(() => {
|
|
18
|
+
console.log("code: ", code);
|
|
19
|
+
}, [code]);
|
|
20
|
+
|
|
21
|
+
return (
|
|
22
|
+
<div className="w-[300px] p-4">
|
|
23
|
+
<KCodeInput
|
|
24
|
+
{...args}
|
|
25
|
+
onChange={(value:string) => {
|
|
26
|
+
//console.log("value: ", value);
|
|
27
|
+
setCode(value);
|
|
28
|
+
//console.log("Value updated to: ", option.value);
|
|
29
|
+
}}
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
const Template: StoryFn<typeof KCodeInput> = (args) => <KCodeInputWrapper {...args} />
|
|
37
|
+
|
|
38
|
+
export const KCodeInputPrimary = Template.bind({})
|
|
39
|
+
KCodeInputPrimary.args = {
|
|
40
|
+
length: 6,
|
|
41
|
+
allowedCharacters: 'alpha',
|
|
42
|
+
isPassword: false,
|
|
43
|
+
disabled: false,
|
|
44
|
+
autoFocus:true,
|
|
45
|
+
gap:2,
|
|
46
|
+
width: 150,
|
|
47
|
+
background: "red",
|
|
48
|
+
hoverBackground: "green",
|
|
49
|
+
focusedBackground: "blue",
|
|
50
|
+
filledBackground: "black",
|
|
51
|
+
fitInContainer: true,
|
|
52
|
+
border: "1px solid black",
|
|
53
|
+
hoverBorder: "1px solid yellow",
|
|
54
|
+
focusedBorder: "1px solid white",
|
|
55
|
+
filledBorder: "1px solid gray",
|
|
56
|
+
fontSize: "15px",
|
|
57
|
+
padding: "10px",
|
|
58
|
+
color: "white",
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export const KCodeInputSecondary = Template.bind({})
|
|
62
|
+
KCodeInputSecondary.args = {
|
|
63
|
+
isCodeCorrect: true,
|
|
64
|
+
boxShadow: "1px 2px 10px black",
|
|
65
|
+
hoverBoxShadow: "1px 2px 10px red",
|
|
66
|
+
focusedBoxShadow: "1px 2px 10px yellow",
|
|
67
|
+
filledBoxShadow: "1px 2px 10px purple",
|
|
68
|
+
fontSize: "30px",
|
|
69
|
+
padding: "10px",
|
|
70
|
+
color: "orange",
|
|
71
|
+
autoBlur: true,
|
|
72
|
+
autoFocus: true,
|
|
73
|
+
width: 50,
|
|
74
|
+
height: 90,
|
|
75
|
+
fitInContainer: true,
|
|
76
|
+
gap: 12
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
export const KCodeInputDefault = Template.bind({})
|
|
80
|
+
KCodeInputDefault.args = {
|
|
81
|
+
isCodeCorrect: false,
|
|
82
|
+
allowedCharacters:"numeric",
|
|
83
|
+
autoBlur:true
|
|
84
|
+
}
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
import React, { useEffect, useState, KeyboardEvent, useRef } from "react"
|
|
2
|
+
import "../../main.css"
|
|
3
|
+
|
|
4
|
+
export interface KCodeInputProps {
|
|
5
|
+
onChange: (value: string) => void
|
|
6
|
+
length?: number
|
|
7
|
+
borderRadius?: number
|
|
8
|
+
disabled?: boolean
|
|
9
|
+
padding?: string
|
|
10
|
+
gap?: number
|
|
11
|
+
fontSize?: string
|
|
12
|
+
fontWeight?: string
|
|
13
|
+
color?: string
|
|
14
|
+
lineHeight?: string
|
|
15
|
+
allowedCharacters?: "numeric" | "alphaNumeric" | "alpha"
|
|
16
|
+
width?: number
|
|
17
|
+
height?: number
|
|
18
|
+
autoFocus?: boolean
|
|
19
|
+
isPassword?: boolean
|
|
20
|
+
background?: string
|
|
21
|
+
hoverBackground?: string
|
|
22
|
+
focusedBackground?: string
|
|
23
|
+
filledBackground?: string
|
|
24
|
+
border?: string
|
|
25
|
+
hoverBorder?: string
|
|
26
|
+
focusedBorder?: string
|
|
27
|
+
filledBorder?: string
|
|
28
|
+
boxShadow?: string
|
|
29
|
+
hoverBoxShadow?: string
|
|
30
|
+
focusedBoxShadow?: string
|
|
31
|
+
filledBoxShadow?: string
|
|
32
|
+
fitInContainer?: boolean
|
|
33
|
+
isCodeCorrect?: boolean
|
|
34
|
+
autoBlur?: boolean
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const KInput: React.FC<KCodeInputProps> = (props) => {
|
|
38
|
+
const autoFocus = props.autoFocus || false
|
|
39
|
+
const autoBlur = props.autoBlur || false
|
|
40
|
+
const borderRadius = props.borderRadius || 10
|
|
41
|
+
const disabled = props.disabled || false
|
|
42
|
+
const length = props.length || 6
|
|
43
|
+
const padding = props.padding || "6px"
|
|
44
|
+
const gap = props.gap || 6
|
|
45
|
+
const allowedCharacters = props.allowedCharacters || "numeric"
|
|
46
|
+
const password = props.isPassword || false
|
|
47
|
+
const fitInContainer = props.fitInContainer || false
|
|
48
|
+
const width = props.width || "60px"
|
|
49
|
+
const height = props.height || "60px"
|
|
50
|
+
const fontSize = props.fontSize || "24px"
|
|
51
|
+
const fontWeight = props.fontWeight || 500
|
|
52
|
+
const lineHeight = props.lineHeight || "32px"
|
|
53
|
+
const defaultBorder = props.border || ""
|
|
54
|
+
const hoverBorder = props.hoverBorder || "1px solid #F3F3F3"
|
|
55
|
+
const focusedBorder = props.focusedBorder || "1px solid #F3F3F3"
|
|
56
|
+
const filledBorder = props.filledBorder || "1px solid #B7B7B7"
|
|
57
|
+
const defaultBoxShadow = props.boxShadow || ""
|
|
58
|
+
const hoverBoxShadow = props.hoverBoxShadow || ""
|
|
59
|
+
const focusedBoxShadow = props.focusedBoxShadow || " 0px 1px 2px 0px rgba(228, 229, 231, 0.24)"
|
|
60
|
+
const filledBoxShadow = props.filledBoxShadow || " 0px 1px 2px 0px rgba(228, 229, 231, 0.24)"
|
|
61
|
+
const defaultBackground = props.background || "#F5F5F5"
|
|
62
|
+
const hoverBackground = props.hoverBackground || defaultBackground
|
|
63
|
+
const focusedBackground = props.focusedBackground || "#FFF"
|
|
64
|
+
const filledBackground = props.filledBackground || "#FFF"
|
|
65
|
+
const color = props.color || "#000"
|
|
66
|
+
const isCodeCorrect = props.isCodeCorrect !== undefined ? props.isCodeCorrect : true
|
|
67
|
+
|
|
68
|
+
const [focusedIndex, setFocusedIndex] = useState<number>(autoFocus ? 0 : -1)
|
|
69
|
+
const inputRefs = useRef<HTMLInputElement[]>([])
|
|
70
|
+
|
|
71
|
+
const [allCharactersWritten, setAllCharactersWritten] = useState<boolean>(false)
|
|
72
|
+
|
|
73
|
+
const [values, setValues] = useState<string[]>(Array(length).fill(""))
|
|
74
|
+
const [hoveredIndexes, setHoveredIndexes] = useState<boolean[]>(Array(length).fill(false))
|
|
75
|
+
const [focusedIndexes, setFocusedIndexes] = useState<boolean[]>(Array(length).fill(false))
|
|
76
|
+
|
|
77
|
+
const handleMouseEnter = (index: number) => {
|
|
78
|
+
setHoveredIndexes((prev) => prev.map((hovered, i) => (i === index ? true : hovered)))
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
const handleMouseLeave = (index: number) => {
|
|
82
|
+
setHoveredIndexes((prev) => prev.map((hovered, i) => (i === index ? false : hovered)))
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
const handleFocus = (index: number) => {
|
|
86
|
+
setFocusedIndexes((prev) => prev.map((focused, i) => (i === index ? true : focused)))
|
|
87
|
+
}
|
|
88
|
+
const handleBlur = (index: number) => {
|
|
89
|
+
setFocusedIndexes((prev) => prev.map((focused, i) => (i === index ? false : focused)))
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
useEffect(() => {
|
|
93
|
+
if (inputRefs.current[focusedIndex]) {
|
|
94
|
+
inputRefs.current[focusedIndex].focus()
|
|
95
|
+
}
|
|
96
|
+
}, [focusedIndex])
|
|
97
|
+
|
|
98
|
+
useEffect(() => {
|
|
99
|
+
if (disabled) {
|
|
100
|
+
setFocusedIndexes((prev) => prev.map((focused, i) => false))
|
|
101
|
+
setHoveredIndexes((prev) => prev.map((hovered, i) => false))
|
|
102
|
+
setValues(Array(length).fill(""))
|
|
103
|
+
setAllCharactersWritten(false)
|
|
104
|
+
}
|
|
105
|
+
}, [disabled])
|
|
106
|
+
|
|
107
|
+
const handleClick = (index: number) => {
|
|
108
|
+
if (values[index]) {
|
|
109
|
+
setFocusedIndex(index)
|
|
110
|
+
} else if (!values[index]) {
|
|
111
|
+
const firstEmptyInputIndex = values.findIndex((value) => value === "")
|
|
112
|
+
setFocusedIndex(firstEmptyInputIndex)
|
|
113
|
+
if (inputRefs.current[focusedIndex]) {
|
|
114
|
+
inputRefs.current[focusedIndex].focus()
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
const handleChange = (text: string, index: number) => {
|
|
120
|
+
const patterns: Record<string, RegExp> = {
|
|
121
|
+
numeric: /^\d*$/,
|
|
122
|
+
alpha: /^[a-zA-Z]*$/,
|
|
123
|
+
alphaNumeric: /^[a-zA-Z0-9]*$/
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (patterns[allowedCharacters]?.test(text)) {
|
|
127
|
+
const newValues = [...values]
|
|
128
|
+
if (text.length === 1) {
|
|
129
|
+
newValues[index] = text
|
|
130
|
+
} else if (text.length === 2) {
|
|
131
|
+
newValues[index] = newValues[index] === text[0] ? text[1] : text[0]
|
|
132
|
+
}
|
|
133
|
+
setValues(newValues)
|
|
134
|
+
if (text && index < length - 1) {
|
|
135
|
+
setFocusedIndex(index + 1)
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
const handleDelete = (event: React.KeyboardEvent<HTMLInputElement>, index: number) => {
|
|
141
|
+
if (event?.key === "Backspace") {
|
|
142
|
+
const newValues = [...values]
|
|
143
|
+
newValues[index] = ""
|
|
144
|
+
if (index > 0) {
|
|
145
|
+
setFocusedIndex(index - 1)
|
|
146
|
+
}
|
|
147
|
+
setValues(newValues)
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const handlePaste = (event: React.ClipboardEvent<HTMLInputElement>) => {
|
|
152
|
+
event.preventDefault()
|
|
153
|
+
const pastedText = event.clipboardData.getData("text").replace(/\s+/g, "")
|
|
154
|
+
const patterns: Record<string, RegExp> = {
|
|
155
|
+
numeric: /^\d*$/,
|
|
156
|
+
alpha: /^[a-zA-Z]*$/,
|
|
157
|
+
alphaNumeric: /^[a-zA-Z0-9]*$/
|
|
158
|
+
}
|
|
159
|
+
if (patterns[allowedCharacters]?.test(pastedText) && pastedText.length > 0) {
|
|
160
|
+
const newValues = [...values]
|
|
161
|
+
const currentIndex = focusedIndex
|
|
162
|
+
const pastedCharacters = pastedText.includes(" ") ? pastedText.split(" ") : pastedText.split("")
|
|
163
|
+
pastedCharacters.forEach((character, index) => {
|
|
164
|
+
const i = currentIndex + index
|
|
165
|
+
if (i < length) {
|
|
166
|
+
newValues[i] = character
|
|
167
|
+
}
|
|
168
|
+
})
|
|
169
|
+
setValues(newValues)
|
|
170
|
+
setFocusedIndex(
|
|
171
|
+
pastedCharacters.length + currentIndex >= length ? length - 1 : pastedCharacters.length + currentIndex
|
|
172
|
+
)
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
useEffect(() => {
|
|
177
|
+
const allDone = values.every((value) => value.length > 0)
|
|
178
|
+
setAllCharactersWritten(allDone)
|
|
179
|
+
props.onChange(values.join(""))
|
|
180
|
+
}, [values])
|
|
181
|
+
|
|
182
|
+
useEffect(() => {
|
|
183
|
+
if (allCharactersWritten && autoBlur) {
|
|
184
|
+
inputRefs.current[focusedIndex].blur()
|
|
185
|
+
}
|
|
186
|
+
}, [allCharactersWritten])
|
|
187
|
+
|
|
188
|
+
const renderCharacterComponent = (index: number) => {
|
|
189
|
+
const isHovered = hoveredIndexes[index]
|
|
190
|
+
const isFocused = focusedIndexes[index]
|
|
191
|
+
const isFilled = values[index]
|
|
192
|
+
|
|
193
|
+
const background = isFilled
|
|
194
|
+
? filledBackground
|
|
195
|
+
: isFocused
|
|
196
|
+
? focusedBackground
|
|
197
|
+
: isHovered
|
|
198
|
+
? hoverBackground
|
|
199
|
+
: defaultBackground
|
|
200
|
+
|
|
201
|
+
const boxShadow = isFilled
|
|
202
|
+
? filledBoxShadow
|
|
203
|
+
: isFocused
|
|
204
|
+
? focusedBoxShadow
|
|
205
|
+
: isHovered
|
|
206
|
+
? hoverBoxShadow
|
|
207
|
+
: defaultBoxShadow
|
|
208
|
+
|
|
209
|
+
const border = isFilled ? filledBorder : isFocused ? focusedBorder : isHovered ? hoverBorder : defaultBorder
|
|
210
|
+
|
|
211
|
+
return (
|
|
212
|
+
<input
|
|
213
|
+
key={`k-code-input-${index}`}
|
|
214
|
+
value={values[index]}
|
|
215
|
+
className={`k-code-input-character-container`}
|
|
216
|
+
style={{
|
|
217
|
+
padding,
|
|
218
|
+
background,
|
|
219
|
+
borderRadius,
|
|
220
|
+
height,
|
|
221
|
+
border: allCharactersWritten && !isCodeCorrect ? "1px solid #FF5865" : border,
|
|
222
|
+
boxShadow,
|
|
223
|
+
fontSize,
|
|
224
|
+
fontWeight,
|
|
225
|
+
lineHeight,
|
|
226
|
+
color,
|
|
227
|
+
width: !fitInContainer ? width : `calc((100% - ${(length - 1) * gap}px) / ${length})`
|
|
228
|
+
}}
|
|
229
|
+
required
|
|
230
|
+
type={password ? "password" : "text"}
|
|
231
|
+
onChange={(event) => {
|
|
232
|
+
handleChange(event.target.value, index)
|
|
233
|
+
}}
|
|
234
|
+
onClick={(event) => {
|
|
235
|
+
handleClick(index)
|
|
236
|
+
}}
|
|
237
|
+
onKeyDown={(event) => {
|
|
238
|
+
handleDelete(event, index)
|
|
239
|
+
}}
|
|
240
|
+
onPaste={(event) => {
|
|
241
|
+
handlePaste(event)
|
|
242
|
+
}}
|
|
243
|
+
ref={(el: HTMLInputElement) => (inputRefs.current[index] = el)}
|
|
244
|
+
disabled={disabled}
|
|
245
|
+
onMouseEnter={() => handleMouseEnter(index)}
|
|
246
|
+
onMouseLeave={() => handleMouseLeave(index)}
|
|
247
|
+
onFocus={() => handleFocus(index)}
|
|
248
|
+
onBlur={() => handleBlur(index)}
|
|
249
|
+
/>
|
|
250
|
+
)
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
return (
|
|
254
|
+
<div className="flex flex-row items-center justify-between" style={{ width: "100%", gap }}>
|
|
255
|
+
{Array.from({ length }, (_, index) => renderCharacterComponent(index))}
|
|
256
|
+
</div>
|
|
257
|
+
)
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
export default KInput
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {default} from './KCodeInput';
|
|
@@ -35,7 +35,7 @@ export interface KLogoProps {
|
|
|
35
35
|
const KLogo: React.FC<KLogoProps> = (props) => {
|
|
36
36
|
const width = props.width || 88
|
|
37
37
|
const height = props.height || 88
|
|
38
|
-
const borderRadius = props.borderRadius
|
|
38
|
+
const borderRadius = props.borderRadius !== undefined ? props.borderRadius : 10
|
|
39
39
|
const logoColor = props.logoColor || "black"
|
|
40
40
|
|
|
41
41
|
const logoIcon = logoColor === "black" ? Logo : logoColor === "white" ? LogoWhite : LogoGray
|
|
@@ -1,57 +1,61 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
1
|
+
import React, { useEffect, useState } from "react";
|
|
2
|
+
import { Meta, StoryFn } from "@storybook/react";
|
|
3
|
+
import KSliderLabel, { SliderLabelProps, SliderLabelOption } from "./KSliderLabel";
|
|
4
4
|
|
|
5
5
|
export default {
|
|
6
6
|
title: "ReactComponentLibrary/KSliderLabel",
|
|
7
7
|
component: KSliderLabel,
|
|
8
8
|
parameters: {
|
|
9
|
-
layout: "centered"
|
|
10
|
-
}
|
|
11
|
-
} as Meta<typeof KSliderLabel
|
|
9
|
+
layout: "centered",
|
|
10
|
+
},
|
|
11
|
+
} as Meta<typeof KSliderLabel>;
|
|
12
12
|
|
|
13
13
|
const KSliderLabelWrapper: React.FC<SliderLabelProps> = (args) => {
|
|
14
|
-
const [
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
{ value: 4, label: "3 years" },
|
|
20
|
-
{ value: 5, label: "5 years" }
|
|
21
|
-
]
|
|
14
|
+
const [selectedValue, setSelectedValue] = useState<number | undefined>(0);
|
|
15
|
+
|
|
16
|
+
useEffect(() => {
|
|
17
|
+
console.log("selectedValue: ", selectedValue);
|
|
18
|
+
}, [selectedValue]);
|
|
22
19
|
|
|
23
20
|
return (
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
21
|
+
<KSliderLabel
|
|
22
|
+
{...args}
|
|
23
|
+
value={selectedValue}
|
|
24
|
+
onChange={(option) => {
|
|
25
|
+
console.log("option: ", option);
|
|
26
|
+
setSelectedValue(option.value);
|
|
27
|
+
console.log("Value updated to: ", option.value);
|
|
28
|
+
}}
|
|
29
|
+
/>
|
|
30
|
+
);
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
const Template: StoryFn<typeof KSliderLabelWrapper> = (args) => <KSliderLabelWrapper {...args} />;
|
|
34
|
+
|
|
35
|
+
const options: SliderLabelOption[] = [
|
|
36
|
+
{ label: "Low", value: 0 },
|
|
37
|
+
{ label: "Medium", value: 1 },
|
|
38
|
+
{ label: "Medium", value: 3 },
|
|
39
|
+
{ label: "Medium", value: 4 },
|
|
40
|
+
{ label: "Medium", value: 5 },
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
export const KSliderLabelPrimary = Template.bind({});
|
|
42
44
|
KSliderLabelPrimary.args = {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
45
|
+
options,
|
|
46
|
+
disabled: false,
|
|
47
|
+
width: "440px",
|
|
48
|
+
titleText: "Slider Title",
|
|
49
|
+
valueText: "50",
|
|
50
|
+
fontSize: 14,
|
|
51
|
+
color: "#000",
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
export const KSliderLabelHoverText = Template.bind({});
|
|
55
|
+
KSliderLabelHoverText.args = {
|
|
56
|
+
options,
|
|
57
|
+
titleText: "Hover to see me!",
|
|
58
|
+
valueText: "50",
|
|
59
|
+
fontSize: 14,
|
|
60
|
+
color: "#000",
|
|
61
|
+
};
|
|
@@ -67,7 +67,8 @@ const KSliderLabel: React.FC<SliderLabelProps> = (props) => {
|
|
|
67
67
|
ref={titleTextRef}
|
|
68
68
|
className="relative pl-4"
|
|
69
69
|
style={{
|
|
70
|
-
top: titleFits ? "40px" : "0px"
|
|
70
|
+
top: titleFits ? "40px" : "0px",
|
|
71
|
+
transitionDuration: "0.3s"
|
|
71
72
|
}}
|
|
72
73
|
>
|
|
73
74
|
<KSpan
|
|
@@ -83,7 +84,9 @@ const KSliderLabel: React.FC<SliderLabelProps> = (props) => {
|
|
|
83
84
|
ref={valueTextRef}
|
|
84
85
|
className="relative pr-4"
|
|
85
86
|
style={{
|
|
86
|
-
top: valueFits ? "40px" : "0px"
|
|
87
|
+
top: valueFits ? "40px" : "0px",
|
|
88
|
+
transitionDuration: "0.3s"
|
|
89
|
+
|
|
87
90
|
}}
|
|
88
91
|
>
|
|
89
92
|
<KSpan
|
package/src/index.ts
CHANGED
|
@@ -8,7 +8,9 @@ import KSlider from "./components/KSlider"
|
|
|
8
8
|
import KSelectDate from "./components/KSelectDate"
|
|
9
9
|
import KTooltip from "./components/KTooltip"
|
|
10
10
|
import KSliderLabel from "./components/KSliderLabel"
|
|
11
|
+
import KCodeInput from "./components/KCodeInput"
|
|
12
|
+
|
|
11
13
|
|
|
12
14
|
export {
|
|
13
|
-
KButton, KSpan, KLogo, KTitleSpan, KInput, KDropdown, KSlider, KSelectDate, KTooltip, KSliderLabel
|
|
15
|
+
KButton, KSpan, KLogo, KTitleSpan, KInput, KDropdown, KSlider, KSelectDate, KTooltip, KSliderLabel, KCodeInput
|
|
14
16
|
}
|
package/src/main.css
CHANGED
|
@@ -224,7 +224,6 @@
|
|
|
224
224
|
}
|
|
225
225
|
|
|
226
226
|
.k-slider-label-input::-webkit-slider-thumb {
|
|
227
|
-
-webkit-appearance: none;
|
|
228
227
|
margin-top: -4px;
|
|
229
228
|
/* Align the thumb vertically with the track */
|
|
230
229
|
/* Width of the thumb */
|
|
@@ -234,9 +233,19 @@
|
|
|
234
233
|
margin-top: 16px ;
|
|
235
234
|
background-position: center;
|
|
236
235
|
position: relative;
|
|
237
|
-
opacity: 0;
|
|
238
236
|
cursor: grab;
|
|
237
|
+
opacity: 0;
|
|
239
238
|
}
|
|
240
239
|
.k-slider-label-input::-webkit-slider-thumb:active {
|
|
241
240
|
cursor: grabbing;
|
|
241
|
+
}
|
|
242
|
+
.k-code-input-character-container {
|
|
243
|
+
outline: none !important;
|
|
244
|
+
text-align: center;
|
|
245
|
+
font-family: "Inter";
|
|
246
|
+
caret-color: #B7B7B7;
|
|
247
|
+
}
|
|
248
|
+
.k-code-input-character-container:disabled {
|
|
249
|
+
background: #F7F7F7 !important;
|
|
250
|
+
border: none !important;
|
|
242
251
|
}
|