diff --git a/components/auto-complete/auto-complete-context.ts b/components/auto-complete/auto-complete-context.ts new file mode 100644 index 0000000..5ba965f --- /dev/null +++ b/components/auto-complete/auto-complete-context.ts @@ -0,0 +1,22 @@ +import React, { MutableRefObject } from 'react' +import { NormalSizes } from '../utils/prop-types' + +export interface SelectConfig { + value?: string + updateValue?: Function + visible?: boolean + updateVisible?: Function + size?: NormalSizes + disableAll?: boolean + ref?: MutableRefObject +} + +const defaultContext = { + visible: false, + size: 'medium' as NormalSizes, + disableAll: false, +} + +export const SelectContext = React.createContext(defaultContext) + +export const useSelectContext = (): SelectConfig => React.useContext(SelectContext) diff --git a/components/auto-complete/auto-complete-dropdown.tsx b/components/auto-complete/auto-complete-dropdown.tsx new file mode 100644 index 0000000..35822b4 --- /dev/null +++ b/components/auto-complete/auto-complete-dropdown.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const AutoComplete = () => { + return ( +
+ +
+ ) +} + +export default AutoComplete diff --git a/components/auto-complete/auto-complete-empty.tsx b/components/auto-complete/auto-complete-empty.tsx new file mode 100644 index 0000000..ec2a88e --- /dev/null +++ b/components/auto-complete/auto-complete-empty.tsx @@ -0,0 +1,45 @@ +import React from 'react' +import withDefaults from '../utils/with-defaults' +import useTheme from '../styles/use-theme' + +interface Props { + className?: string +} + +const defaultProps = { + className: '', +} + +export type AutoCompleteSearchProps = Props & typeof defaultProps & React.HTMLAttributes + +const AutoCompleteSearch: React.FC> = ({ + children, className, +}) => { + const theme = useTheme() + + return ( +
+ {children} + +
+ ) +} + +export default withDefaults(AutoCompleteSearch, defaultProps) diff --git a/components/auto-complete/auto-complete-item.tsx b/components/auto-complete/auto-complete-item.tsx new file mode 100644 index 0000000..35822b4 --- /dev/null +++ b/components/auto-complete/auto-complete-item.tsx @@ -0,0 +1,11 @@ +import React from 'react' + +const AutoComplete = () => { + return ( +
+ +
+ ) +} + +export default AutoComplete diff --git a/components/auto-complete/auto-complete-searching.tsx b/components/auto-complete/auto-complete-searching.tsx new file mode 100644 index 0000000..ddae453 --- /dev/null +++ b/components/auto-complete/auto-complete-searching.tsx @@ -0,0 +1,72 @@ +import React, { useMemo } from 'react' +import withDefaults from '../utils/with-defaults' +import useTheme from '../styles/use-theme' +import { useAutoCompleteContext } from './auto-complete-context' + +interface Props { + value: string + disabled?: boolean +} + +const defaultProps = { + disabled: false, +} + +export type AutoCompleteItemProps = Props & typeof defaultProps & React.HTMLAttributes + +const AutoCompleteItem: React.FC> = ({ + value: identValue, children, disabled, +}) => { + const theme = useTheme() + const { value, updateValue } = useAutoCompleteContext() + const selectHandler = () => { + updateValue && updateValue(identValue) + } + + const isActive = useMemo(() => value === identValue, [identValue, value]) + + return ( +
+ {children} + +
+ ) +} + +export default withDefaults(AutoCompleteItem, defaultProps) diff --git a/components/auto-complete/auto-complete.tsx b/components/auto-complete/auto-complete.tsx new file mode 100644 index 0000000..e69de29 diff --git a/components/auto-complete/index.ts b/components/auto-complete/index.ts new file mode 100644 index 0000000..e69de29 diff --git a/components/input/input-icon-clear.tsx b/components/input/input-icon-clear.tsx index ded07ae..05f4d9b 100644 --- a/components/input/input-icon-clear.tsx +++ b/components/input/input-icon-clear.tsx @@ -2,13 +2,14 @@ import React, { useMemo } from 'react' import useTheme from '../styles/use-theme' interface Props { + visibale: boolean onClick?: (event: React.MouseEvent) => void heightRatio?: string | undefined disabled?: boolean } const InputIconClear: React.FC = ({ - onClick, heightRatio, disabled, + onClick, heightRatio, disabled, visibale, }) => { const theme = useTheme() const width = useMemo(() => { @@ -21,7 +22,7 @@ const InputIconClear: React.FC = ({ onClick && onClick(event) } return ( -
+
@@ -39,6 +40,13 @@ const InputIconClear: React.FC = ({ box-sizing: border-box; transition: color 150ms ease 0s; color: ${theme.palette.accents_3}; + visibility: hidden; + opacity: 0; + } + + .visibale { + visibility: visible; + opacity: 1; } div:hover { diff --git a/components/input/input-icon.tsx b/components/input/input-icon.tsx index 6756862..a9fa558 100644 --- a/components/input/input-icon.tsx +++ b/components/input/input-icon.tsx @@ -32,6 +32,7 @@ const InputIcon: React.FC = React.memo(({ margin: 0; padding: 0 ${padding}; line-height: 1; + position: relative; } `} diff --git a/components/input/input.tsx b/components/input/input.tsx index 3d4344b..716a173 100644 --- a/components/input/input.tsx +++ b/components/input/input.tsx @@ -24,6 +24,9 @@ interface Props { clearable?: boolean onChange?: (e: React.ChangeEvent) => void onClearClick?: (e: React.MouseEvent) => void + onFocus?: (e: React.FocusEvent) => void + onBlur?: (e: React.FocusEvent) => void + autoComplete: string } const defaultProps = { @@ -33,6 +36,7 @@ const defaultProps = { width: 'initial', size: 'medium', status: 'default', + autoComplete: 'off', className: '', placeholder: '', initialValue: '', @@ -43,12 +47,14 @@ export type InputProps = Props & typeof defaultProps & React.InputHTMLAttributes const Input: React.FC = ({ placeholder, label, labelRight, size, status, disabled, icon, iconRight, initialValue, onChange, readOnly, value, - onClearClick, clearable, width, className, ...props + onClearClick, clearable, width, className, onBlur, onFocus, + autoComplete, ...props }) => { const theme = useTheme() const [selfValue, setSelfValue] = useState(initialValue) const [hover, setHover] = useState(false) const { heightRatio, fontSize } = useMemo(() => getSizes(size),[size]) + const showClearIcon = useMemo(() => clearable && selfValue !== '', [selfValue, clearable]) const labelClasses = useMemo( () => labelRight ? 'right-label' : (label ? 'left-label' : ''), [label, labelRight], @@ -63,15 +69,23 @@ const Input: React.FC = ({ ) const changeHandler = (event: React.ChangeEvent) => { if (disabled || readOnly) return - console.log(123, event.target.value) setSelfValue(event.target.value) onChange && onChange(event) } - + const clearHandler = (event: React.MouseEvent) => { setSelfValue('') onClearClick && onClearClick(event) } + + const focusHandler = (e: React.FocusEvent) => { + setHover(true) + onFocus && onFocus(e) + } + const blurHandler = (e: React.FocusEvent) => { + setHover(false) + onBlur && onBlur(e) + } useEffect(() => { if (value === undefined) return @@ -88,12 +102,15 @@ const Input: React.FC = ({ placeholder={placeholder} disabled={disabled} readOnly={readOnly} - onFocus={() => setHover(true)} - onBlur={() => setHover(false)} + onFocus={focusHandler} + onBlur={blurHandler} onChange={changeHandler} + autoComplete={autoComplete} {...props} /> - {clearable && } {iconRight && } diff --git a/pages/docs/components/auto-complete.mdx b/pages/docs/components/auto-complete.mdx new file mode 100644 index 0000000..6bedad2 --- /dev/null +++ b/pages/docs/components/auto-complete.mdx @@ -0,0 +1,100 @@ +import { Layout, Playground, Attributes } from 'lib/components' +import { Avatar, Spacer } from 'components' + +export const meta = { + title: 'avatar', + description: 'avatar', +} + +## Avatar + +Avatars represent a user or a team. Stacked avatars represent a group of people. + + + { + const url = 'https://zeit.co/api/www/avatar/?u=evilrabbit&s=160' + return ( + <> + + + + + + + + + + + ) +} +`} /> + + + { + const url = 'https://zeit.co/api/www/avatar/?u=evilrabbit&s=160' + return ( + <> + + + + + + ) +} +`} /> + + + + + + + +`} /> + + + { + const url = 'https://zeit.co/api/www/avatar/?u=evilrabbit&s=160' + return ( + <> + + + + + + ) +} +`} /> + + +Avatar.Props + +| Attribute | Description | Type | Accepted values | Default +| ---------- | ---------- | ---- | -------------- | ------ | +| **src** | image src | `string` | - | - | +| **stacked** | stacked display group | `boolean` | - | `false` | +| **text** | display text when image is missing | `string` | - | - | +| **size** | avatar size | `string` / `number` | `'mini', 'small', 'medium', 'large', number` | `medium` | +| **isSquare** | avatar shape | `boolean` | - | `false` | +| ... | native props | `ImgHTMLAttributes` | `'alt', 'crossOrigin', 'className', ...` | - | + + + +export default ({ children }) => {children}