tycho-storybook 0.1.14 → 0.2.1
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/Icon/Icon.d.ts +2 -3
- package/dist/Icon/Icon.js +3 -5
- package/dist/Icon/Icon.stories.d.ts +2 -1
- package/dist/TextField/TextField.d.ts +5 -3
- package/dist/TextField/TextField.js +33 -12
- package/dist/TextField/TextField.stories.d.ts +2 -0
- package/dist/TextField/TextField.stories.js +40 -1
- package/dist/TextField/styles.scss +10 -0
- package/package.json +1 -1
package/dist/Icon/Icon.d.ts
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import React from 'react';
|
|
2
1
|
import './styles.scss';
|
|
3
2
|
export declare const IconWeights: readonly ["regular", "heavy"];
|
|
4
3
|
type IconWeights = (typeof IconWeights)[number];
|
|
@@ -12,5 +11,5 @@ export type Props = JSX.IntrinsicElements['span'] & {
|
|
|
12
11
|
filled?: boolean;
|
|
13
12
|
disabled?: boolean;
|
|
14
13
|
};
|
|
15
|
-
|
|
16
|
-
export
|
|
14
|
+
export default function Icon({ name, className, size, weight, filled, disabled, title, onClick, onMouseDown, onMouseUp, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
15
|
+
export {};
|
package/dist/Icon/Icon.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
-
import React from 'react';
|
|
3
2
|
import cx from 'classnames';
|
|
4
3
|
import './styles.scss';
|
|
5
4
|
export const IconWeights = ['regular', 'heavy'];
|
|
@@ -10,13 +9,12 @@ export const IconSizes = [
|
|
|
10
9
|
'small',
|
|
11
10
|
'x-small',
|
|
12
11
|
];
|
|
13
|
-
|
|
12
|
+
export default function Icon({ name, className = '', size, weight = 'regular', filled = false, disabled = false, title, onClick, onMouseDown, onMouseUp, }) {
|
|
14
13
|
const getClassNames = cx('ds-icon material-symbols-outlined', className, size, weight, {
|
|
15
14
|
disabled: disabled,
|
|
16
15
|
});
|
|
17
16
|
const style = {
|
|
18
17
|
fontVariationSettings: `'FILL' ${filled ? 1 : 0}, 'wght' 400, 'GRAD' 0, 'opsz' 24`,
|
|
19
18
|
};
|
|
20
|
-
return (_jsx("span", {
|
|
21
|
-
}
|
|
22
|
-
export default Icon;
|
|
19
|
+
return (_jsx("span", { className: getClassNames, style: style, onClick: (e) => onClick && onClick(e), onMouseDown: (e) => onMouseDown && onMouseDown(e), onMouseUp: (e) => onMouseUp && onMouseUp(e), title: title, translate: "no", children: name }));
|
|
20
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import type { StoryObj } from '@storybook/react';
|
|
2
|
+
import Icon from './Icon';
|
|
2
3
|
declare const meta: {
|
|
3
4
|
title: string;
|
|
4
|
-
component:
|
|
5
|
+
component: typeof Icon;
|
|
5
6
|
parameters: {
|
|
6
7
|
layout: string;
|
|
7
8
|
};
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { UseFormReturn } from 'react-hook-form';
|
|
2
2
|
import './styles.scss';
|
|
3
|
+
type DefaultEndAdornmentType = 'password' | 'close';
|
|
3
4
|
type Props = {
|
|
4
5
|
attr: string;
|
|
5
6
|
label: string;
|
|
@@ -13,14 +14,15 @@ type Props = {
|
|
|
13
14
|
required?: boolean;
|
|
14
15
|
showEndAdornment?: boolean;
|
|
15
16
|
startAdornment?: React.ReactNode;
|
|
17
|
+
endAdornment?: React.ReactNode[];
|
|
18
|
+
defaultEndAdornments?: DefaultEndAdornmentType[];
|
|
16
19
|
onChange?: (attr: string, value: any) => void;
|
|
17
20
|
onFocus?: (e: React.FocusEvent<HTMLInputElement | HTMLTextAreaElement, Element>) => void;
|
|
18
21
|
onKeyDown?: (e: React.KeyboardEvent<HTMLDivElement>) => void;
|
|
19
22
|
onRemove?: () => void;
|
|
20
|
-
password?: boolean;
|
|
21
23
|
rows?: number;
|
|
22
|
-
|
|
24
|
+
infoIcon?: string;
|
|
23
25
|
inputRef?: React.Ref<HTMLInputElement | HTMLTextAreaElement>;
|
|
24
26
|
};
|
|
25
|
-
export default function TextField({ className, attr, label, createdForm, disabled, title, placeholder, multiline, maxChars, required, startAdornment, showEndAdornment, onChange, onFocus, onKeyDown, onRemove,
|
|
27
|
+
export default function TextField({ className, attr, label, createdForm, disabled, title, placeholder, multiline, maxChars, required, startAdornment, endAdornment, defaultEndAdornments, showEndAdornment, onChange, onFocus, onKeyDown, onRemove, rows, infoIcon, inputRef, }: Props): import("react/jsx-runtime").JSX.Element;
|
|
26
28
|
export {};
|
|
@@ -6,10 +6,11 @@ import cx from 'classnames';
|
|
|
6
6
|
import { useEffect, useState } from 'react';
|
|
7
7
|
import { Controller } from 'react-hook-form';
|
|
8
8
|
import Icon from '../Icon';
|
|
9
|
+
import Tooltip from '../Tooltip';
|
|
9
10
|
import { textFieldTheme } from './TextFieldTheme';
|
|
10
11
|
import { setCurrentInput } from './inputRefManager';
|
|
11
12
|
import './styles.scss';
|
|
12
|
-
export default function TextField({ className, attr, label, createdForm, disabled, title, placeholder, multiline, maxChars, required, startAdornment, showEndAdornment = true, onChange, onFocus, onKeyDown, onRemove,
|
|
13
|
+
export default function TextField({ className, attr, label, createdForm, disabled, title, placeholder, multiline, maxChars, required, startAdornment, endAdornment, defaultEndAdornments = ['close'], showEndAdornment = true, onChange, onFocus, onKeyDown, onRemove, rows = 4, infoIcon, inputRef, }) {
|
|
13
14
|
const outerTheme = useTheme();
|
|
14
15
|
const [showPassword, setShowPassword] = useState(false);
|
|
15
16
|
const [active, setActive] = useState(false);
|
|
@@ -20,16 +21,36 @@ export default function TextField({ className, attr, label, createdForm, disable
|
|
|
20
21
|
disabled: disabled,
|
|
21
22
|
});
|
|
22
23
|
const getEndAdornmentIcon = (value) => {
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
const adornments = [];
|
|
25
|
+
if (defaultEndAdornments.length > 0) {
|
|
26
|
+
// Check for password adornment
|
|
27
|
+
if (defaultEndAdornments.includes('password')) {
|
|
28
|
+
adornments.push(_jsx(Icon, { name: showPassword ? 'visibility_off' : 'visibility', size: "small", onClick: () => setShowPassword(!showPassword), className: "pointer" }, "password"));
|
|
29
|
+
}
|
|
30
|
+
// Check for info adornment
|
|
31
|
+
if (infoIcon) {
|
|
32
|
+
const infoIconElement = (_jsx(Icon, { name: "info", size: "small", className: `icon-info pointer ${disabled ? 'd-none' : ''}` }));
|
|
33
|
+
adornments.push(_jsx(Tooltip, { title: infoIcon, mode: "simple", children: _jsx("span", { children: infoIconElement }) }, "info"));
|
|
34
|
+
}
|
|
35
|
+
// Check for close adornment - show when value is not undefined and value is not equal to defaultValue
|
|
36
|
+
if (defaultEndAdornments.includes('close') &&
|
|
37
|
+
value !== undefined &&
|
|
38
|
+
onRemove) {
|
|
39
|
+
adornments.push(_jsx(Icon, { name: "close", size: "small", className: `${disabled ? 'd-none' : ''} pointer`, onClick: () => onRemove && onRemove() }, "close"));
|
|
40
|
+
}
|
|
25
41
|
}
|
|
26
|
-
|
|
27
|
-
|
|
42
|
+
// Append custom endAdornments if provided
|
|
43
|
+
if (endAdornment && endAdornment.length > 0) {
|
|
44
|
+
adornments.push(...endAdornment);
|
|
28
45
|
}
|
|
29
|
-
if (
|
|
30
|
-
return
|
|
46
|
+
if (adornments.length === 0) {
|
|
47
|
+
return null;
|
|
31
48
|
}
|
|
32
|
-
|
|
49
|
+
if (adornments.length === 1) {
|
|
50
|
+
return adornments[0];
|
|
51
|
+
}
|
|
52
|
+
// Return multiple adornments wrapped in a div with spacing
|
|
53
|
+
return _jsx("div", { className: "ds-end-adornments", children: adornments });
|
|
33
54
|
};
|
|
34
55
|
useEffect(() => {
|
|
35
56
|
if (focus || mouseOver) {
|
|
@@ -39,11 +60,11 @@ export default function TextField({ className, attr, label, createdForm, disable
|
|
|
39
60
|
setActive(false);
|
|
40
61
|
}
|
|
41
62
|
}, [focus, mouseOver]);
|
|
42
|
-
return (_jsx("div", { className: getClassNames, children: _jsx(Controller, { name: attr, control: createdForm.control, render: ({ field }) => (_jsxs(ThemeProvider, { theme: textFieldTheme(outerTheme), children: [_jsx(MuiTextField, { ...field, inputRef: inputRef, label: label, value: field.value || '', type: password
|
|
43
|
-
?
|
|
44
|
-
: showPassword
|
|
63
|
+
return (_jsx("div", { className: getClassNames, children: _jsx(Controller, { name: attr, control: createdForm.control, render: ({ field }) => (_jsxs(ThemeProvider, { theme: textFieldTheme(outerTheme), children: [_jsx(MuiTextField, { ...field, inputRef: inputRef, label: label, value: field.value || '', type: defaultEndAdornments.includes('password')
|
|
64
|
+
? showPassword
|
|
45
65
|
? 'text'
|
|
46
|
-
: 'password'
|
|
66
|
+
: 'password'
|
|
67
|
+
: 'text', fullWidth: true, required: required, disabled: disabled, variant: "filled", placeholder: !focus ? placeholder : '', color: "error", multiline: multiline, minRows: rows, slotProps: {
|
|
47
68
|
inputLabel: {
|
|
48
69
|
shrink: true,
|
|
49
70
|
},
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import { useForm } from 'react-hook-form';
|
|
3
|
+
import Icon from '../Icon';
|
|
3
4
|
import TextField from './TextField';
|
|
4
5
|
const meta = {
|
|
5
6
|
title: 'Components/TextField',
|
|
@@ -23,7 +24,6 @@ const meta = {
|
|
|
23
24
|
},
|
|
24
25
|
};
|
|
25
26
|
export default meta;
|
|
26
|
-
// 🛠️ Now a proper render function inside the story object
|
|
27
27
|
export const Default = {
|
|
28
28
|
args: {
|
|
29
29
|
attr: 'title',
|
|
@@ -41,3 +41,42 @@ export const Default = {
|
|
|
41
41
|
return (_jsx(TextField, { ...args, createdForm: createdForm, onChange: handleChange }));
|
|
42
42
|
},
|
|
43
43
|
};
|
|
44
|
+
export const WithEndAdornment = {
|
|
45
|
+
args: {
|
|
46
|
+
attr: 'search',
|
|
47
|
+
label: 'Search',
|
|
48
|
+
placeholder: 'Type to search...',
|
|
49
|
+
},
|
|
50
|
+
render: (args) => {
|
|
51
|
+
const createdForm = useForm({
|
|
52
|
+
defaultValues: {
|
|
53
|
+
[args.attr]: '',
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
const handleChange = (attr, value) => {
|
|
57
|
+
console.log(`Attribute: ${attr}, Value: ${String(value)}`);
|
|
58
|
+
};
|
|
59
|
+
return (_jsx(TextField, { ...args, createdForm: createdForm, onChange: handleChange, endAdornment: [
|
|
60
|
+
_jsx(Icon, { name: "search", size: "small", className: "pointer" }, "search"),
|
|
61
|
+
] }));
|
|
62
|
+
},
|
|
63
|
+
};
|
|
64
|
+
export const WithInfoIcon = {
|
|
65
|
+
args: {
|
|
66
|
+
attr: 'email',
|
|
67
|
+
label: 'Email Address',
|
|
68
|
+
placeholder: 'Enter your email...',
|
|
69
|
+
infoIcon: 'Please enter a valid email address',
|
|
70
|
+
},
|
|
71
|
+
render: (args) => {
|
|
72
|
+
const createdForm = useForm({
|
|
73
|
+
defaultValues: {
|
|
74
|
+
[args.attr]: '',
|
|
75
|
+
},
|
|
76
|
+
});
|
|
77
|
+
const handleChange = (attr, value) => {
|
|
78
|
+
console.log(`Attribute: ${attr}, Value: ${String(value)}`);
|
|
79
|
+
};
|
|
80
|
+
return (_jsx(TextField, { ...args, createdForm: createdForm, onChange: handleChange }));
|
|
81
|
+
},
|
|
82
|
+
};
|
|
@@ -2,6 +2,10 @@
|
|
|
2
2
|
width: 100%;
|
|
3
3
|
position: relative;
|
|
4
4
|
|
|
5
|
+
span {
|
|
6
|
+
line-height: 1 !important;
|
|
7
|
+
}
|
|
8
|
+
|
|
5
9
|
> .helper {
|
|
6
10
|
@include helper-small-1;
|
|
7
11
|
margin-top: 4px;
|
|
@@ -32,3 +36,9 @@
|
|
|
32
36
|
left: 16px;
|
|
33
37
|
}
|
|
34
38
|
}
|
|
39
|
+
|
|
40
|
+
.ds-end-adornments {
|
|
41
|
+
display: flex;
|
|
42
|
+
align-items: center;
|
|
43
|
+
gap: 8px;
|
|
44
|
+
}
|