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.
@@ -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
- declare const Icon: React.ForwardRefExoticComponent<Omit<Props, "ref"> & React.RefAttributes<HTMLSpanElement>>;
16
- export default Icon;
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
- const Icon = React.forwardRef(function Icon({ name, className = '', size, weight = 'regular', filled = false, disabled = false, title, onClick, onMouseDown, onMouseUp, }, ref) {
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", { ref: ref, 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 }));
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: import("react").ForwardRefExoticComponent<Omit<import("./Icon").Props, "ref"> & import("react").RefAttributes<HTMLSpanElement>>;
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
- hideInfoIcon?: boolean;
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, password, rows, hideInfoIcon, inputRef, }: Props): import("react/jsx-runtime").JSX.Element;
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, password, rows = 4, hideInfoIcon, inputRef, }) {
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
- if (password) {
24
- return (_jsx(Icon, { name: showPassword ? 'visibility_off' : 'visibility', size: "small", onClick: () => setShowPassword(!showPassword), className: "pointer" }));
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
- if (!hideInfoIcon && value === undefined) {
27
- return (_jsx(Icon, { name: "info", size: "small", className: `icon-info pointer ${disabled ? 'd-none' : ''}` }));
42
+ // Append custom endAdornments if provided
43
+ if (endAdornment && endAdornment.length > 0) {
44
+ adornments.push(...endAdornment);
28
45
  }
29
- if (value !== undefined || (hideInfoIcon && onRemove)) {
30
- return (_jsx(Icon, { name: "close", size: "small", className: `${disabled ? 'd-none' : ''} pointer`, onClick: () => onRemove && onRemove() }));
46
+ if (adornments.length === 0) {
47
+ return null;
31
48
  }
32
- return null;
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 === undefined
43
- ? 'text'
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', fullWidth: true, required: required, disabled: disabled, variant: "filled", placeholder: !focus ? placeholder : '', color: "error", multiline: multiline, minRows: rows, slotProps: {
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
  },
@@ -4,3 +4,5 @@ declare const meta: Meta<typeof TextField>;
4
4
  export default meta;
5
5
  type Story = StoryObj<typeof TextField>;
6
6
  export declare const Default: Story;
7
+ export declare const WithEndAdornment: Story;
8
+ export declare const WithInfoIcon: Story;
@@ -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
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "tycho-storybook",
3
3
  "private": false,
4
- "version": "0.1.14",
4
+ "version": "0.2.1",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
7
7
  "exports": {