1
1
mirror of https://github.com/leon-ai/leon.git synced 2024-11-27 08:06:03 +03:00

feat(web app): import Aurora

This commit is contained in:
louistiti 2023-06-29 22:18:46 +08:00
parent 0ad8b9e8e5
commit f61e4f08a4
96 changed files with 2681 additions and 64 deletions

View File

@ -1,9 +0,0 @@
import type React from 'react'
interface Props {
children: React.ReactNode
}
export function Button({ children }: Props) {
return <button>{children}</button>
}

View File

@ -0,0 +1,61 @@
@import '../../styles/main.sass'
.aurora-button
position: relative
display: inline-block
font-size: var(--a-font-size-md)
line-height: var(--a-line-height-md)
font-weight: var(--a-font-weight-semi-bold)
border-radius: var(--a-border-radius-md)
height: var(--a-button-size-md)
border: none
cursor: pointer
padding: 0 var(--a-space-lg)
box-shadow: 0 0 10px 2px transparent
transition: opacity var(--a-transition-duration-main) var(--a-transition-timing-main), transform var(--a-transition-duration-main), background-color var(--a-transition-duration-main) var(--a-transition-timing-main), border-color var(--a-transition-duration-main) var(--a-transition-timing-main), color var(--a-transition-duration-main) var(--a-transition-timing-main), box-shadow var(--a-transition-duration-main) var(--a-transition-timing-main)
&:hover:not(&--disabled, &--loading)
transform: scale3d(1.01, 1.01, 1.01)
&:active:not(&--disabled, &--loading)
transform: scale3d(.96, .96, .96)
&--primary
color: var(--a-color-text)
background-color: var(--a-color-accent)
&:hover:not(.aurora-button--disabled, .aurora-button--loading)
background-color: var(--a-color-accent-hover)
&--secondary
background-color: transparent
color: var(--a-color-accent)
border: 1px solid var(--a-color-accent)
&:hover:not(.aurora-button--disabled, .aurora-button--loading), &:hover:not(.aurora-button--disabled, .aurora-button--loading) .aurora-icon
border-color: var(--a-color-accent-hover)
color: var(--a-color-accent-hover)
.aurora-icon
color: var(--a-color-accent)
&--danger
background-color: var(--a-color-background-danger)
color: var(--a-color-text-danger)
&:hover:not(.aurora-button--disabled, .aurora-button--loading)
background-color: var(--a-color-danger-hover)
&--light
background-color: transparent
color: var(--a-color-accent)
&:hover:not(.aurora-button--disabled, .aurora-button--loading), &:hover:not(.aurora-button--disabled, .aurora-button--loading) .aurora-icon
color: var(--a-color-accent-hover)
.aurora-icon
color: var(--a-color-accent)
&--disabled
opacity: var(--a-opacity-disabled)
cursor: not-allowed
&--loading
opacity: var(--a-opacity-disabled)
cursor: wait
.aurora-loader
&::before, &::after
background-color: var(--a-color-white)

View File

@ -0,0 +1,85 @@
import type React from 'react'
import classNames from 'classnames'
import { Flexbox, Icon, Loader } from '..'
import './button.sass'
interface Props {
children?: React.ReactNode
type?: 'button' | 'submit' | 'reset'
iconName?: string
iconPosition?: 'left' | 'right'
secondary?: boolean
danger?: boolean
light?: boolean
disabled?: boolean
loading?: boolean
onClick?: () => void
}
export function Button({
children,
type = 'button',
iconName,
iconPosition = 'left',
secondary,
danger,
light,
disabled,
loading,
onClick
}: Props) {
let variant = 'primary'
if (secondary) {
variant = 'secondary'
} else if (danger) {
variant = 'danger'
} else if (light) {
variant = 'light'
}
return (
<button
type={type}
className={classNames('aurora-button', {
'aurora-button--disabled': disabled,
'aurora-button--loading': loading,
[`aurora-button--${variant}`]: variant
})}
disabled={disabled || loading}
onClick={onClick}
>
{loading ? (
<Loader />
) : (
<>
{iconName && iconPosition === 'left' && (
<Flexbox
flexDirection="row"
justifyContent="center"
alignItems="center"
gap="xs"
>
<Icon name={iconName} type="line" />
{children}
</Flexbox>
)}
{iconName && iconPosition === 'right' && (
<Flexbox
flexDirection="row"
justifyContent="center"
alignItems="center"
gap="xs"
>
{children}
<Icon name={iconName} type="line" />
</Flexbox>
)}
{!iconName && children}
</>
)}
</button>
)
}

View File

@ -0,0 +1 @@
export * from './button'

View File

@ -0,0 +1,12 @@
@import '../../styles/main.sass'
.aurora-card
position: relative
display: inline-block
width: auto
padding: var(--a-space-md)
background-color: var(--a-color-background-surface-secondary)
border-radius: var(--a-border-radius-md)
&--full-width
width: 100%

View File

@ -0,0 +1,21 @@
import type React from 'react'
import classNames from 'classnames'
import './card.sass'
interface Props {
children: React.ReactNode
fullWidth?: boolean
}
export function Card({ children, fullWidth }: Props) {
return (
<div
className={classNames('aurora-card', {
'aurora-card--full-width': fullWidth
})}
>
{children}
</div>
)
}

View File

@ -0,0 +1 @@
export * from './card'

View File

@ -0,0 +1,40 @@
@import '../../styles/main.sass'
.aurora-checkbox
display: flex
align-items: center
gap: var(--a-space-sm)
cursor: pointer
&[data-disabled]
cursor: not-allowed
.aurora-checkbox-placeholder
width: var(--a-checkbox-radio-size)
height: var(--a-checkbox-radio-size)
.aurora-checkbox-control
display: flex
justify-content: center
align-items: center
width: var(--a-checkbox-radio-size)
height: var(--a-checkbox-radio-size)
border-radius: var(--a-border-radius-xs)
border: 1px solid var(--a-color-input-border)
background-color: var(--a-color-input-background)
transition: background-color var(--a-transition-duration-main) var(--a-transition-timing-main), border-color var(--a-transition-duration-main) var(--a-transition-timing-main)
&[data-hover]:not([data-checked])
border-color: var(--a-color-input-border-hover)
background-color: var(--a-color-input-background-hover)
&[data-checked]
border-color: transparent
background-color: var(--a-color-input-border-focus)
&[data-disabled]
opacity: var(--a-opacity-disabled)
.aurora-checkbox-label
color: var(--a-color-text)
font-size: var(--a-font-size-md)
&[data-disabled]
opacity: var(--a-opacity-disabled)
color: inherit

View File

@ -0,0 +1,53 @@
import React, { useState } from 'react'
import {
Checkbox as ArkCheckbox,
CheckboxLabel,
CheckboxInput,
CheckboxControl,
type CheckboxProps
} from '@ark-ui/react'
import { Icon } from '../icon'
import './checkbox.sass'
interface Props
extends Pick<CheckboxProps, 'value' | 'checked' | 'disabled' | 'onChange'> {
label?: string
}
export function Checkbox({ label, checked, value, disabled, onChange }: Props) {
const [isChecked, setIsChecked] = useState(checked)
return (
<ArkCheckbox
className="aurora-checkbox"
value={value}
checked={isChecked}
disabled={disabled}
onChange={(e) => {
setIsChecked(e.checked)
if (onChange) {
onChange(e)
}
}}
>
{(state) => (
<>
<CheckboxInput />
<CheckboxControl className="aurora-checkbox-control">
{state.isChecked ? (
<Icon name="check" size="sm" animated />
) : (
<div className="aurora-checkbox-placeholder" />
)}
</CheckboxControl>
<CheckboxLabel className="aurora-checkbox-label">
{label}
</CheckboxLabel>
</>
)}
</ArkCheckbox>
)
}

View File

@ -0,0 +1 @@
export * from './checkbox'

View File

@ -0,0 +1,28 @@
.aurora-circular-progress
position: relative
&--sm
width: 64px
height: 64px
&--md
width: 128px
height: 128px
&--lg
width: 256px
height: 256px
path
transition: stroke-dashoffset var(--a-transition-duration-main) var(--a-transition-timing-main)
&:nth-child(1)
stroke: var(--a-color-background-surface-secondary)
stroke-width: 32px
&:nth-child(2)
stroke: var(--a-color-accent)
stroke-width: 12px
stroke-linecap: round
.aurora-circular-progress-content
position: absolute
top: 50%
left: 50%
transform: translate(-50%, -50%)

View File

@ -0,0 +1,35 @@
import React from 'react'
import classNames from 'classnames'
import { type Size } from '../../lib/types'
import './circular-progress.sass'
interface Props {
value: number
children?: React.ReactNode
size?: 'sm' | 'md' | 'lg'
}
export function CircularProgress({ value, children, size = 'md' }: Props) {
const total = 100
return (
<div
className={classNames('aurora-circular-progress', {
[`aurora-circular-progress--${size}`]: size
})}
>
<svg viewBox="0 0 276 276" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M138 16C154.021 16 169.886 19.1556 184.687 25.2867C199.489 31.4178 212.938 40.4042 224.267 51.733C235.596 63.0617 244.582 76.5109 250.713 91.3126C256.844 106.114 260 121.979 260 138C260 154.021 256.844 169.886 250.713 184.687C244.582 199.489 235.596 212.938 224.267 224.267C212.938 235.596 199.489 244.582 184.687 250.713C169.886 256.844 154.021 260 138 260C121.979 260 106.114 256.844 91.3126 250.713C76.5109 244.582 63.0617 235.596 51.7329 224.267C40.4042 212.938 31.4177 199.489 25.2867 184.687C19.1556 169.886 16 154.021 16 138C16 121.979 19.1556 106.114 25.2867 91.3126C31.4178 76.5108 40.4043 63.0617 51.733 51.7329C63.0618 40.4042 76.511 31.4177 91.3127 25.2867C106.114 19.1556 121.979 16 138 16L138 16Z" />
<path
pathLength={total}
strokeDasharray={total}
strokeDashoffset={total - value}
d="M138 16C154.021 16 169.886 19.1556 184.687 25.2867C199.489 31.4178 212.938 40.4042 224.267 51.733C235.596 63.0617 244.582 76.5109 250.713 91.3126C256.844 106.114 260 121.979 260 138C260 154.021 256.844 169.886 250.713 184.687C244.582 199.489 235.596 212.938 224.267 224.267C212.938 235.596 199.489 244.582 184.687 250.713C169.886 256.844 154.021 260 138 260C121.979 260 106.114 256.844 91.3126 250.713C76.5109 244.582 63.0617 235.596 51.7329 224.267C40.4042 212.938 31.4177 199.489 25.2867 184.687C19.1556 169.886 16 154.021 16 138C16 121.979 19.1556 106.114 25.2867 91.3126C31.4178 76.5108 40.4043 63.0617 51.733 51.7329C63.0618 40.4042 76.511 31.4177 91.3127 25.2867C106.114 19.1556 121.979 16 138 16L138 16Z"
/>
</svg>
<div className="aurora-circular-progress-content">{children}</div>
</div>
)
}

View File

@ -0,0 +1 @@
export * from './circular-progress'

View File

@ -0,0 +1,92 @@
@import '../../styles/main.sass'
.aurora-flexbox
position: relative
display: flex
flex-direction: column
height: 100%
&--padding
padding: var(--a-space-xl) var(--a-space-md)
&--padding-x
padding-left: var(--a-space-md)
padding-right: var(--a-space-md)
&--padding-y
padding-top: var(--a-space-xl)
padding-bottom: var(--a-space-xl)
&--full-width
width: 100%
&--flex
display: flex
&--inline-flex
display: inline-flex
&--row
flex-direction: row
&--row-reverse
flex-direction: row-reverse
&--column
flex-direction: column
&--column-reverse
flex-direction: column-reverse
&--align-flex-start
align-items: flex-start
&--align-center
align-items: center
&--align-flex-end
align-items: flex-end
&--align-stretch
align-items: stretch
&--align-baseline
align-items: baseline
&--justify-flex-start
justify-content: flex-start
&--justify-center
justify-content: center
&--justify-flex-end
justify-content: flex-end
&--justify-space-between
justify-content: space-between
&--justify-space-around
justify-content: space-around
&--justify-space-evenly
justify-content: space-evenly
&--justify-stretch
justify-content: stretch
&--gap-xs
gap: var(--a-space-xs)
&--gap-sm
gap: var(--a-space-sm)
&--gap-md
gap: var(--a-space-md)
&--gap-lg
gap: var(--a-space-lg)
&--gap-xl
gap: var(--a-space-xl)
&--row-gap-xs
row-gap: var(--a-space-xs)
&--row-gap-sm
row-gap: var(--a-space-sm)
&--row-gap-md
row-gap: var(--a-space-md)
&--row-gap-lg
row-gap: var(--a-space-lg)
&--row-gap-xl
row-gap: var(--a-space-xl)
&--column-gap-xs
column-gap: var(--a-space-xs)
&--column-gap-sm
column-gap: var(--a-space-sm)
&--column-gap-md
column-gap: var(--a-space-md)
&--column-gap-lg
column-gap: var(--a-space-lg)
&--column-gap-xl
column-gap: var(--a-space-xl)

View File

@ -0,0 +1,63 @@
import type React from 'react'
import classNames from 'classnames'
import { type Size } from '../../lib/types'
import './flexbox.sass'
interface Props {
children: React.ReactNode
fullWidth?: boolean
display?: 'flex' | 'inline-flex'
alignItems?: 'center' | 'flex-start' | 'flex-end' | 'baseline' | 'stretch'
justifyContent?:
| 'center'
| 'flex-start'
| 'flex-end'
| 'space-between'
| 'space-around'
| 'space-evenly'
| 'stretch'
flexDirection?: 'row' | 'row-reverse' | 'column' | 'column-reverse'
gap?: Size
rowGap?: Size
columnGap?: Size
padding?: boolean
paddingX?: boolean
paddingY?: boolean
}
export function Flexbox({
children,
fullWidth,
display,
alignItems,
justifyContent,
flexDirection,
gap,
rowGap,
columnGap,
padding,
paddingX,
paddingY
}: Props) {
return (
<div
className={classNames('aurora-flexbox', {
'aurora-flexbox--full-width': fullWidth,
'aurora-flexbox--padding': padding,
'aurora-flexbox--padding-x': paddingX,
'aurora-flexbox--padding-y': paddingY,
[`aurora-flexbox--${display}`]: display,
[`aurora-flexbox--align-${alignItems}`]: alignItems,
[`aurora-flexbox--justify-${justifyContent}`]: justifyContent,
[`aurora-flexbox--${flexDirection}`]: flexDirection,
[`aurora-flexbox--gap-${gap}`]: gap,
[`aurora-flexbox--row-gap-${rowGap}`]: rowGap,
[`aurora-flexbox--column-gap-${columnGap}`]: columnGap
})}
>
{children}
</div>
)
}

View File

@ -0,0 +1 @@
export * from './flexbox'

View File

@ -0,0 +1,70 @@
@import '../../styles/main.sass'
.aurora-icon-button
position: relative
width: var(--a-button-size-md)
height: var(--a-button-size-md)
display: flex
align-items: center
justify-content: center
padding: 0
text-align: center
&.aurora-button:hover:not(.aurora-button--disabled, .aurora-button--loading)
transform: scale3d(1.03, 1.03, 1.03)
&.aurora-button:active:not(.aurora-button--disabled, .aurora-button--loading)
transform: scale3d(.96, .96, .96)
&.aurora-button.aurora-button--light:hover:not(.aurora-button--disabled, .aurora-button--loading)
transform: scale3d(1.06, 1.06, 1.06)
&.aurora-button.aurora-button--light:active:not(.aurora-button--disabled, .aurora-button--loading)
transform: scale3d(.96, .96, .96)
&--square
width: var(--a-button-size-md)
height: var(--a-button-size-md)
border-radius: var(--a-border-radius-md)
&--circle
width: var(--a-button-size-md)
height: var(--a-button-size-md)
border-radius: 50%
&--xs
width: 22px
height: 22px
&--sm
width: 30px
height: 30px
&--md
width: var(--a-button-size-md)
height: var(--a-button-size-md)
&--lg
width: 56px
height: 56px
&--xl
width: 96px
height: 96px
&--xxl
width: 164px
height: 164px
&.aurora-button--light .aurora-icon
color: var(--a-color-text)
&.aurora-button--secondary:hover, &.aurora-button--light:hover
background-color: transparent
&.aurora-button--light:hover .aurora-icon
color: var(--a-color-text)
&.aurora-button--light.aurora-button--secondary
background-color: transparent
border: none
.aurora-icon
color: var(--a-color-white-secondary)
&:hover:not(.aurora-button--disabled, .aurora-button--loading) .aurora-icon
color: var(--a-color-text)
&:hover.aurora-icon-button--activated .aurora-icon
color: var(--a-color-accent)
&.aurora-button--light.aurora-icon-button--activated .aurora-icon
color: var(--a-color-accent)

View File

@ -0,0 +1,82 @@
import React, { useState } from 'react'
import classNames from 'classnames'
import { Icon, Loader } from '..'
import { type Props as IconProps } from '../icon'
import './icon-button.sass'
interface Props {
name: string
type?: 'button' | 'submit' | 'reset'
iconType?: IconProps['type']
size?: IconProps['size']
shape?: IconProps['bgShape']
activated?: boolean
secondary?: boolean
danger?: boolean
light?: boolean
disabled?: boolean
loading?: boolean
onClick?: (isActivated: boolean) => void
}
export function IconButton({
name,
type = 'button',
iconType = 'line',
size,
shape,
activated,
secondary,
danger,
light,
disabled,
loading,
onClick
}: Props) {
const [isActivated, setIsActivated] = useState(activated || false)
let variant = 'primary'
if (danger) {
variant = 'danger'
}
return (
<button
type={type}
className={classNames('aurora-icon-button aurora-button', {
'aurora-button--secondary': secondary,
'aurora-button--light': light,
'aurora-button--disabled': disabled,
'aurora-button--loading': loading,
'aurora-icon-button--activated': isActivated,
[`aurora-button--${variant}`]: variant,
[`aurora-icon-button--${size}`]: size,
[`aurora-icon-button--${shape}`]: shape
})}
disabled={disabled || loading}
onClick={() => {
if (onClick) {
if (typeof activated === 'undefined') {
onClick(false)
} else {
const newActivatedState = !isActivated
setIsActivated(newActivatedState)
onClick(newActivatedState)
}
}
}}
>
{loading ? (
<Loader />
) : (
<>
<Icon type={iconType} name={name} size={size} />
</>
)}
</button>
)
}

View File

@ -0,0 +1 @@
export * from './icon-button'

View File

@ -0,0 +1,115 @@
@import '../../styles/main.sass'
.aurora-icon
position: relative
display: inline-flex
align-items: center
justify-content: center
border-radius: var(--a-border-radius-xs)
color: var(--a-color-white)
font-size: var(--a-font-size-md)
background-color: transparent
padding: var(--a-space-xs)
transition: opacity var(--a-transition-duration-main) var(--a-transition-timing-main), color var(--a-transition-duration-main) var(--a-transition-timing-main), background-color var(--a-transition-duration-main) var(--a-transition-timing-main), transform var(--a-transition-duration-main) var(--a-transition-timing-main)
&--animated
opacity: 0
animation: aurora-animation-fade-in var(--a-transition-duration-main) var(--a-transition-timing-main) var(--a-transition-duration-main) forwards
&--xs
width: 12px
height: 12px
font-size: var(--a-font-size-xs)
border-radius: var(--a-border-radius-xs)
&--sm
width: 20px
height: 20px
font-size: var(--a-font-size-sm)
border-radius: var(--a-border-radius-xs)
&--md
width: 28px
height: 28px
font-size: var(--a-font-size-md)
border-radius: var(--a-border-radius-xs)
&--lg
width: 56px
height: 56px
font-size: var(--a-font-size-lg)
border-radius: var(--a-border-radius-md)
&--xl
width: 96px
height: 96px
font-size: var(--a-font-size-xl)
border-radius: var(--a-border-radius-md)
&--xxl
width: 128px
height: 128px
font-size: var(--a-font-size-xxl)
border-radius: var(--a-border-radius-md)
&--square
border-radius: var(--a-border-radius-xs)
&--circle
border-radius: var(--a-border-radius-circle)
&--white
color: var(--a-color-white)
&--transparent-white
color: var(--a-color-transparent-white)
&--black
color: var(--a-color-black)
&--blue
color: var(--a-color-blue)
&--secondary-blue
color: var(--a-color-secondary-blue)
&--transparent-blue
color: var(--a-color-transparent-blue)
&--red
color: var(--a-color-red)
&--secondary-red
color: var(--a-color-secondary-red)
&--transparent-red
color: var(--a-color-transparent-red)
&--green
color: var(--a-color-green)
&--secondary-green
color: var(--a-color-secondary-green)
&--transparent-green
color: var(--a-color-transparent-green)
&--yellow
color: var(--a-color-yellow)
&--secondary-yellow
color: var(--a-color-secondary-yellow)
&--transparent-yellow
color: var(--a-color-transparent-yellow)
&--bg-white
background-color: var(--a-color-white)
&--bg-transparent-white
background-color: var(--a-color-transparent-white)
&--bg-black
background-color: var(--a-color-black)
&--bg-blue
background-color: var(--a-color-blue)
&--bg-secondary-blue
background-color: var(--a-color-secondary-blue)
&--bg-transparent-blue
background-color: var(--a-color-transparent-blue)
&--bg-red
background-color: var(--a-color-red)
&--bg-secondary-red
background-color: var(--a-color-secondary-red)
&--bg-transparent-red
background-color: var(--a-color-transparent-red)
&--bg-green
background-color: var(--a-color-green)
&--bg-secondary-green
background-color: var(--a-color-secondary-green)
&--bg-transparent-green
background-color: var(--a-color-transparent-green)
&--bg-yellow
background-color: var(--a-color-yellow)
&--bg-secondary-yellow
background-color: var(--a-color-secondary-yellow)
&--bg-transparent-yellow
background-color: var(--a-color-transparent-yellow)

View File

@ -0,0 +1,68 @@
import React from 'react'
import classNames from 'classnames'
import type { Color, Size, IconType } from '../../lib/types'
import './icon.sass'
export interface Props {
name?: string
svg?: React.ReactNode
type?: IconType
color?: Color
size?: Size | 'xxl'
bgShape?: 'square' | 'circle'
bgColor?: Color
animated?: boolean
}
const REMIX_SIZE_MAPPING = {
xs: 'xs',
sm: 'sm',
md: '1x',
lg: 'lg',
xl: 'xl',
xxl: '2x'
}
/**
* @see https://remixicon.com/
*/
export function Icon({
name,
svg,
type = 'line',
color,
size = 'md',
bgShape,
bgColor,
animated
}: Props) {
let iconClassName = `ri-${name}`
if (type) {
iconClassName = `${iconClassName}-${type}`
}
return (
<div
className={classNames('aurora-icon', {
[`aurora-icon--${size}`]: size,
[`aurora-icon--${bgShape}`]: bgShape,
[`aurora-icon--bg-${bgColor}`]: bgColor,
[`aurora-icon--${color}`]: color,
'aurora-icon--animated': animated
})}
>
{svg ? (
svg
) : (
<i
className={classNames(iconClassName, {
[`ri-${REMIX_SIZE_MAPPING[size]}`]: size
})}
/>
)}
</div>
)
}

View File

@ -0,0 +1 @@
export * from './icon'

View File

@ -0,0 +1,76 @@
@import '../../styles/main.sass'
.aurora-image
position: relative
border-radius: var(--a-border-radius-md)
background-repeat: no-repeat
background-size: cover
background-position: center center
&--overlay
&::before
content: ''
position: absolute
width: 100%
height: 100%
background-color: rgba(0, 0, 0, .2)
transition: background-color var(--a-transition-duration-main) var(--a-transition-timing-main)
&:hover
&::before
background-color: rgba(0, 0, 0, 0)
&--gradient
&::after
content: ''
position: absolute
top: auto
bottom: 0
width: 100%
height: 64px
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--a-color-background-surface))
&--gradient-top
&::after
top: 0
bottom: auto
background-image: linear-gradient(to top, rgba(0, 0, 0, 0), var(--a-color-background-surface))
&--gradient-bottom
&::after
top: auto
bottom: 0
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), var(--a-color-background-surface))
&--gradient-left
&::after
left: 0
top: 0
bottom: 0
width: 64px
height: 100%
background-image: linear-gradient(to left, rgba(0, 0, 0, 0), var(--a-color-background-surface))
&--gradient-right
&::after
right: 0
top: 0
bottom: 0
width: 64px
height: 100%
background-image: linear-gradient(to right, rgba(0, 0, 0, 0), var(--a-color-background-surface))
&--cover
background-size: cover
&--contain
background-size: contain
&--square
border-radius: var(--a-border-radius-md)
&--circle
border-radius: var(--a-border-radius-circle)
&--blue-border
border: 1px solid var(--a-color-blue)
&--white-border
border: 1px solid var(--a-color-white)
&--radius-top
border-radius: var(--a-border-radius-md) var(--a-border-radius-md) 0 0
&--radius-bottom
border-radius: 0 0 var(--a-border-radius-md) var(--a-border-radius-md)

View File

@ -0,0 +1,52 @@
import type React from 'react'
import classNames from 'classnames'
import './image.sass'
interface Props {
src: string
width?: number | string
height?: number | string
shape?: 'circle' | 'square'
borderColor?: 'white' | 'blue'
backgroundSize?: 'cover' | 'contain'
radiusTop?: boolean
radiusBottom?: boolean
overlay?: boolean
gradient?: boolean
gradientPosition?: 'top' | 'bottom' | 'left' | 'right'
}
export function Image({
src,
width,
height,
shape,
borderColor,
backgroundSize,
radiusTop,
radiusBottom,
overlay,
gradient,
gradientPosition
}: Props) {
return (
<div
className={classNames('aurora-image', {
[`aurora-image--${shape}`]: shape,
[`aurora-image--${borderColor}-border`]: borderColor,
[`aurora-image--${backgroundSize}`]: backgroundSize,
[`aurora-image--gradient-${gradientPosition}`]: gradientPosition,
'aurora-image--radius-top': radiusTop,
'aurora-image--radius-bottom': radiusBottom,
'aurora-image--overlay': overlay,
'aurora-image--gradient': gradient
})}
style={{
width,
height,
backgroundImage: `url(${src})`
}}
/>
)
}

View File

@ -0,0 +1 @@
export * from './image'

View File

@ -0,0 +1,22 @@
export * from './button'
export * from './card'
export * from './checkbox'
export * from './circular-progress'
export * from './flexbox'
export * from './icon'
export * from './icon-button'
export * from './image'
export * from './link'
export * from './lists'
export * from './loader'
export * from './input'
export * from './progress'
export * from './radios'
export * from './scroll-container'
export * from './selects'
export * from './slider'
export * from './status'
export * from './switch'
export * from './tabs'
export * from './text'
export * from './widget-wrapper'

View File

@ -0,0 +1 @@
export * from './text-input'

View File

@ -0,0 +1,83 @@
@import '../../styles/main.sass'
.aurora-text-input-container
--a-icon-container-width: calc(var(--a-input-size-md) + var(--a-space-sm))
position: relative
display: flex
flex-direction: column
.aurora-text-input
position: relative
display: inline-block
color: var(--a-color-text)
background-color: var(--a-color-input-background)
font-size: var(--a-font-size-md)
border: 1px solid var(--a-color-input-border)
border-radius: var(--a-border-radius-md)
height: var(--a-input-size-md)
padding: 0 var(--a-space-md)
width: 100%
outline: none
transition: background-color var(--a-transition-duration-main) var(--a-transition-timing-main), border-color var(--a-transition-duration-main) var(--a-transition-timing-main)
&:hover
border-color: var(--a-color-input-border-hover)
background-color: var(--a-color-input-background-hover)
&:hover:not([disabled]) ~ .aurora-text-input-icon-container
border-color: var(--a-color-input-border-hover)
&:focus
border-color: var(--a-color-input-border-focus)
background-color: var(--a-color-input-background-hover)
&:focus:not([disabled])
&~ .aurora-text-input-icon-container
border-color: var(--a-color-input-border-focus)
i
color: var(--a-color-accent)
&:placeholder-shown ~ .aurora-text-input-icon-container i
color: var(--color-secondary-white)
&--multiline
height: calc(var(--a-input-size-md) * 2)
padding: var(--a-space-sm) var(--a-space-md)
resize: vertical
min-height: calc(var(--a-input-size-md) * 2)
max-height: 512px
&~ .aurora-text-input-icon-container
height: 100%
&--disabled, &--disabled:hover
opacity: var(--a-opacity-disabled)
color: inherit
background-color: var(--a-color-input-background)
border-color: var(--a-color-input-border)
cursor: not-allowed
&--disabled ~ .aurora-text-input-icon-container
opacity: var(--a-opacity-disabled)
i
color: inherit
opacity: var(--a-opacity-disabled)
&--with-icon
padding-left: calc(var(--a-icon-container-width) + var(--a-space-md))
.aurora-text-input-icon-container
position: absolute
left: 0
top: 0
bottom: 0
display: flex
align-items: center
justify-content: center
color: var(--a-color-text)
pointer-events: none
border-right: 1px solid var(--a-color-input-border)
width: var(--a-icon-container-width)
height: var(--a-input-size-md)
transition: background-color var(--a-transition-duration-main) var(--a-transition-timing-main), border-color var(--a-transition-duration-main) var(--a-transition-timing-main)
i
color: var(--a-color-text)
transition: color var(--a-transition-duration-main) var(--a-transition-timing-main)
.aurora-text-input-hint-container
padding-left: var(--a-space-md)
margin-top: var(--a-space-xs)

View File

@ -0,0 +1,105 @@
import React, { useState } from 'react'
import classNames from 'classnames'
import { Text, Icon } from '..'
import './text-input.sass'
interface Props {
placeholder: string
value?: string
type?: 'text' | 'password' | 'email' | 'tel' | 'url'
iconName?: string
hint?: string
disabled?: boolean
height?: number | 'auto'
maxLength?: number
multiline?: boolean
autofocus?: boolean
onChange?: (value: string) => void
}
export function TextInput({
placeholder,
type = 'text',
iconName,
hint,
value,
disabled,
height = 'auto',
maxLength,
multiline,
autofocus,
onChange
}: Props) {
const [inputValue, setInputValue] = useState(value || '')
if (!multiline) {
if (!maxLength) {
maxLength = 64
}
if (height !== 'auto') {
height = 'auto'
}
}
return (
<div className="aurora-text-input-container">
{multiline ? (
<textarea
placeholder={placeholder}
value={inputValue}
disabled={disabled}
autoFocus={autofocus}
maxLength={maxLength}
onChange={(e) => {
setInputValue(e.target.value)
if (onChange) {
onChange(e.target.value)
}
}}
style={{ height }}
className={classNames('aurora-text-input', {
'aurora-text-input--multiline': true,
'aurora-text-input--disabled': disabled,
'aurora-text-input--with-icon': !!iconName
})}
/>
) : (
<input
type={type}
placeholder={placeholder}
value={inputValue}
disabled={disabled}
autoFocus={autofocus}
maxLength={maxLength}
onChange={(e) => {
setInputValue(e.target.value)
if (onChange) {
onChange(e.target.value)
}
}}
className={classNames('aurora-text-input', {
'aurora-text-input--disabled': disabled,
'aurora-text-input--with-icon': !!iconName
})}
/>
)}
{iconName && (
<div className="aurora-text-input-icon-container">
<Icon name={iconName} type="fill" />
</div>
)}
{hint && (
<div className="aurora-text-input-hint-container">
<Text fontSize="xs" tertiary>
{hint}
</Text>
</div>
)}
</div>
)
}

View File

@ -0,0 +1 @@
export * from './link'

View File

@ -0,0 +1,14 @@
@import '../../styles/main.sass'
.aurora-link
display: inline-block
position: relative
text-decoration: none
transition: color var(--a-transition-duration-main) var(--a-transition-timing-main)
&:hover
text-decoration: 1px underline var(--a-color-accent)
.aurora-text, .aurora-icon
color: var(--a-color-accent-hover)
.aurora-text, .aurora-icon
color: var(--a-color-accent)

View File

@ -0,0 +1,21 @@
import type React from 'react'
import classNames from 'classnames'
import { Text } from '..'
import { type Size } from '../../lib/types'
import './link.sass'
interface Props {
href: string
children: React.ReactNode
fontSize?: Size
}
export function Link({ href, children, fontSize }: Props) {
return (
<a className={classNames('aurora-link')} href={href} target="_blank">
<Text fontSize={fontSize}>{children}</Text>
</a>
)
}

View File

@ -0,0 +1,3 @@
export * from './list'
export * from './list-header'
export * from './list-item'

View File

@ -0,0 +1 @@
export * from './list-header'

View File

@ -0,0 +1,21 @@
import type React from 'react'
import classNames from 'classnames'
import { Text } from '../..'
interface Props {
children: React.ReactNode
align?: 'left' | 'center'
}
export function ListHeader({ children, align }: Props) {
return (
<div
className={classNames('aurora-list-header', {
[`aurora-list-header--${align}`]: align
})}
>
<Text fontWeight="semi-bold">{children}</Text>
</div>
)
}

View File

@ -0,0 +1 @@
export * from './list-item'

View File

@ -0,0 +1,39 @@
import type React from 'react'
import classNames from 'classnames'
import { Icon } from '../..'
interface Props {
children: React.ReactNode
align?: 'left' | 'center'
onClick?: () => void
}
export function ListItem({ children, align, onClick }: Props) {
let isClickable = false
if (onClick) {
isClickable = true
}
return (
<li
className={classNames('aurora-list-item', {
'aurora-list-item--clickable': isClickable,
[`aurora-list-item--${align}`]: align
})}
onClick={isClickable ? onClick : undefined}
>
{isClickable ? (
<>
{children}
<div className="aurora-list-item-clickable-icon">
<Icon name="arrow-right-double" />
</div>
</>
) : (
children
)}
</li>
)
}

View File

@ -0,0 +1 @@
export * from './list'

View File

@ -0,0 +1,54 @@
@import '../../../styles/main.sass'
.aurora-list
position: relative
display: flex
flex-direction: column
.aurora-list-item:last-child
border-bottom: none
.aurora-list-header
position: relative
display: flex
align-items: center
justify-content: flex-start
width: 100%
text-align: left
padding: var(--a-space-lg) var(--a-space-md)
border-bottom: 1px solid var(--a-color-separator)
&--left
justify-content: flex-start
&--center
justify-content: center
.aurora-list-item
position: relative
display: flex
justify-content: flex-start
padding: var(--a-space-md)
border-bottom: 1px solid var(--a-color-separator)
background-color: transparent
transition: background-color var(--a-transition-duration-main) var(--a-transition-timing-main)
&:hover
background-color: var(--a-color-black)
&--left
justify-content: flex-start
&--center
justify-content: center
&--clickable
cursor: pointer
&:hover .aurora-list-item-clickable-icon .aurora-icon
color: var(--a-color-accent)
.aurora-list-item-clickable-icon
align-self: center
position: absolute
right: var(--a-space-md)
cursor: pointer
z-index: 1
.aurora-icon
color: var(--a-color-grey-blue)

View File

@ -0,0 +1,11 @@
import type React from 'react'
import './list.sass'
interface Props {
children: React.ReactNode
}
export function List({ children }: Props) {
return <ul className="aurora-list">{children}</ul>
}

View File

@ -0,0 +1 @@
export * from './loader'

View File

@ -0,0 +1,29 @@
@import '../../styles/main.sass'
.aurora-loader
width: var(--a-loader-size-md)
height: var(--a-loader-size-md)
display: inline-block
position: relative
&::before, &::after
content: ''
box-sizing: border-box
width: var(--a-loader-size-md)
height: var(--a-loader-size-md)
border-radius: 50%
background-color: var(--a-color-accent)
position: absolute
left: 0
top: 0
animation: aurora-animation-loader 1s linear infinite
&::after
opacity: 0
animation-delay: .4s
@keyframes aurora-animation-loader
0%
transform: scale(0)
opacity: 1
100%
transform: scale(1)
opacity: 0

View File

@ -0,0 +1,20 @@
import React from 'react'
// import classNames from 'classnames'
import './loader.sass'
interface Props {
// size?: 'sm' | 'md'
}
export function Loader({}: // size
Props) {
return (
<span className="aurora-loader" />
/*<span
className={classNames('aurora-loader', {
[`aurora-loader--${size}`]: size
})}
/>*/
)
}

View File

@ -0,0 +1 @@
export * from './progress'

View File

@ -0,0 +1,34 @@
@import '../../styles/main.sass'
.aurora-progress
position: relative
display: flex
align-items: flex-end
border-radius: var(--a-border-radius-pill)
background-color: var(--a-color-background-surface-secondary)
&--horizontal
width: 100%
&.aurora-progress--sm
height: 9px
&.aurora-progress--md
height: 18px
&.aurora-progress--lg
height: 24px
.aurora-progress-value
height: 100%
&--vertical
height: 100%
&.aurora-progress--sm
width: 9px
&.aurora-progress--md
width: 18px
&.aurora-progress--lg
width: 24px
.aurora-progress-value
width: 100%
.aurora-progress-value
border-radius: var(--a-border-radius-pill)
background-color: var(--a-color-accent)

View File

@ -0,0 +1,32 @@
import React from 'react'
import classNames from 'classnames'
import './progress.sass'
interface Props {
value: number
orientation?: 'horizontal' | 'vertical'
size?: 'sm' | 'md' | 'lg'
}
export function Progress({
value,
orientation = 'horizontal',
size = 'md'
}: Props) {
return (
<div
className={classNames('aurora-progress', {
[`aurora-progress--${orientation}`]: orientation,
[`aurora-progress--${size}`]: size
})}
>
<div
className="aurora-progress-value"
style={{
[orientation === 'horizontal' ? 'width' : 'height']: `${value}%`
}}
/>
</div>
)
}

View File

@ -0,0 +1,2 @@
export * from './radio'
export * from './radio-group'

View File

@ -0,0 +1 @@
export * from './radio-group'

View File

@ -0,0 +1,50 @@
@import '../../../styles/main.sass'
.aurora-radio-group
&[data-disabled]
cursor: not-allowed
.aurora-radio
display: flex
align-items: center
gap: var(--a-space-sm)
cursor: pointer
&[data-disabled]
cursor: not-allowed
.aurora-radio-control
display: flex
justify-content: center
align-items: center
width: var(--a-checkbox-radio-size)
height: var(--a-checkbox-radio-size)
border-radius: var(--a-border-radius-circle)
border: 1px solid var(--a-color-input-border)
background-color: var(--a-color-input-background)
transition: background-color var(--a-transition-duration-main) var(--a-transition-timing-main), border-color var(--a-transition-duration-main) var(--a-transition-timing-main)
&[data-hover]:not([data-checked])
border-color: var(--a-color-input-border-hover)
background-color: var(--a-color-input-background-hover)
&[data-checked]
border-color: transparent
background-color: var(--a-color-input-border-focus)
&::after
opacity: 1
transform: scale3d(.5, .5, .5)
&::after
content: ''
width: 16px
height: 16px
border-radius: var(--a-border-radius-circle)
background-color: var(--a-color-white)
opacity: 0
transition: opacity .3s var(--a-transition-timing-main), transform .3s var(--a-transition-timing-main)
&[data-disabled]
opacity: var(--a-opacity-disabled)
.aurora-radio-label
color: var(--a-color-text)
font-size: var(--a-font-size-md)
&[data-disabled]
opacity: var(--a-opacity-disabled)
color: inherit

View File

@ -0,0 +1,32 @@
import type React from 'react'
import {
RadioGroup as ArkRadioGroup,
type RadioGroupProps
} from '@ark-ui/react'
import './radio-group.sass'
interface Props
extends Pick<
RadioGroupProps,
'children' | 'defaultValue' | 'disabled' | 'onChange'
> {}
export function RadioGroup({
children,
defaultValue,
disabled,
onChange
}: Props) {
return (
<ArkRadioGroup
className="aurora-radio-group"
defaultValue={defaultValue}
disabled={disabled}
onChange={onChange}
orientation="horizontal"
>
{children}
</ArkRadioGroup>
)
}

View File

@ -0,0 +1 @@
export * from './radio'

View File

@ -0,0 +1,22 @@
import type React from 'react'
import {
Radio as ArkRadio,
RadioLabel,
RadioInput,
RadioControl,
type RadioProps
} from '@ark-ui/react'
interface Props extends Pick<RadioProps, 'value' | 'disabled'> {
label: string
}
export function Radio({ label, value, disabled }: Props) {
return (
<ArkRadio className="aurora-radio" value={value} disabled={disabled}>
<RadioInput />
<RadioControl className="aurora-radio-control" />
<RadioLabel className="aurora-radio-label">{label}</RadioLabel>
</ArkRadio>
)
}

View File

@ -0,0 +1 @@
export * from './scroll-container'

View File

@ -0,0 +1,31 @@
@import '../../styles/main.sass'
.aurora-scroll-container
position: relative
width: 100%
padding: var(--a-space-sm) 0
.aurora-scroll-container-mask
position: absolute
pointer-events: none
&--horizontal .aurora-scroll-container-mask
top: 0
right: 0
width: 50px
height: 100%
background: linear-gradient(to right, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .3), var(--a-color-background-surface))
&--vertical .aurora-scroll-container-mask
position: absolute
content: ''
bottom: 0
left: 0
right: 0
width: 100%
height: 50px
background: linear-gradient(to bottom, rgba(0, 0, 0, 0) 0%, rgba(0, 0, 0, .3), var(--a-color-background-surface))
.aurora-scroll-container-scrollview
height: 100%
overflow-y: auto
overflow-x: auto

View File

@ -0,0 +1,34 @@
import type React from 'react'
import classNames from 'classnames'
import './scroll-container.sass'
interface Props {
children: React.ReactNode
orientation?: 'vertical' | 'horizontal'
width?: number | string
height?: number | string
}
export function ScrollContainer({
children,
orientation = 'horizontal',
width,
height
}: Props) {
return (
<div
className={classNames(
'aurora-scroll-container',
`aurora-scroll-container--${orientation}`
)}
style={{
width,
height
}}
>
<div className="aurora-scroll-container-scrollview">{children}</div>
<div className="aurora-scroll-container-mask" />
</div>
)
}

View File

@ -0,0 +1,2 @@
export * from './select'
export * from './select-option'

View File

@ -0,0 +1 @@
export * from './select-option'

View File

@ -0,0 +1,19 @@
import type React from 'react'
import {
SelectOption as ArkSelectOption,
type SelectOptionProps
} from '@ark-ui/react'
interface Props
extends Pick<SelectOptionProps, 'label' | 'value' | 'disabled'> {}
export function SelectOption({ label, value, disabled }: Props) {
return (
<ArkSelectOption
className="aurora-select-option"
label={label}
value={value}
disabled={disabled}
/>
)
}

View File

@ -0,0 +1 @@
export * from './select'

View File

@ -0,0 +1,78 @@
@import '../../../styles/main.sass'
.aurora-select-trigger
position: relative
display: inline-block
cursor: pointer
color: var(--a-color-text-placeholder)
text-align: left
background-color: var(--a-color-input-background)
font-size: var(--a-font-size-md)
border: 1px solid var(--a-color-input-border)
border-radius: var(--a-border-radius-md)
height: var(--a-input-size-md)
padding: 0 var(--a-space-md)
padding-right: 0
width: 100%
outline: none
transition: background-color var(--a-transition-duration-main) var(--a-transition-timing-main), border-color var(--a-transition-duration-main) var(--a-transition-timing-main)
&:hover
border-color: var(--a-color-input-border-hover)
background-color: var(--a-color-input-background-hover)
&--selected
color: var(--a-color-text)
&[data-expanded]
border-color: var(--a-color-input-border-focus)
background-color: var(--a-color-input-background-hover)
&:not([disabled])
.aurora-icon
color: var(--a-color-accent)
transform: rotate(-180deg)
&[disabled], &[disabled]:hover
border-color: inherit
background-color: inherit
opacity: var(--a-opacity-disabled)
cursor: not-allowed
&-placeholder-container
position: relative
overflow: hidden
white-space: nowrap
text-overflow: ellipsis
width: 100%
&-icon-container
display: flex
align-items: center
justify-content: center
width: 50px
.aurora-icon
color: var(--color-secondary-white)
.aurora-select-content
position: relative
width: var(--reference-width)
background-color: var(--a-color-background-surface)
border: 1px solid var(--a-color-separator)
border-radius: var(--a-border-radius-md)
cursor: pointer
.aurora-select-option
font-size: var(--a-font-size-md)
line-height: var(--a-line-height-md)
color: var(--a-color-text-secondary)
padding: var(--a-space-md)
border-bottom: 1px solid var(--a-color-separator)
background-color: transparent
transition: background-color var(--a-transition-duration-main) var(--a-transition-timing-main)
&:hover
background-color: var(--a-color-black)
&[data-disabled]
color: rgba(245, 245, 247, var(--a-opacity-disabled))
cursor: not-allowed
&:hover
background-color: inherit
&[data-selected]
color: var(--a-color-text)
&:last-child
border-bottom: none

View File

@ -0,0 +1,72 @@
import type React from 'react'
import {
Select as ArkSelect,
SelectContent,
SelectPositioner,
SelectTrigger,
Portal,
type SelectProps
} from '@ark-ui/react'
import classNames from 'classnames'
import { Flexbox, Icon } from '../..'
import './select.sass'
interface Props
extends Pick<
SelectProps,
'defaultValue' | 'selectedOption' | 'disabled' | 'onChange'
> {
placeholder: string
children: React.ReactNode
}
export function Select({
placeholder,
children,
selectedOption,
defaultValue,
disabled,
onChange
}: Props) {
return (
<ArkSelect
closeOnSelect
selectedOption={selectedOption}
defaultValue={defaultValue}
disabled={disabled}
onChange={onChange}
>
{({ selectedOption }) => (
<>
<SelectTrigger
className={classNames('aurora-select-trigger', {
'aurora-select-trigger--selected': selectedOption
})}
>
<Flexbox
flexDirection="row"
alignItems="center"
justifyContent="space-between"
>
<div className="aurora-select-trigger-placeholder-container">
{selectedOption ? selectedOption.label : placeholder}
</div>
<div className="aurora-select-trigger-icon-container">
<Icon name="arrow-down-s" />
</div>
</Flexbox>
</SelectTrigger>
<Portal>
<SelectPositioner>
<SelectContent className="aurora-select-content">
{children}
</SelectContent>
</SelectPositioner>
</Portal>
</>
)}
</ArkSelect>
)
}

View File

@ -0,0 +1 @@
export * from './slider'

View File

@ -0,0 +1,70 @@
@import '../../styles/main.sass'
.aurora-slider
--a-track-height: 10px
.aurora-slider-control
display: flex
align-items: center
cursor: pointer
width: 100%
&[data-disabled]
cursor: not-allowed
opacity: var(--a-opacity-disabled)
&:hover:not([data-disabled])
.aurora-slider-thumb
width: calc(var(--a-track-height) * 2.3)
height: calc(var(--a-track-height) * 2.3)
.aurora-slider-track
background-color: var(--a-color-background-surface-secondary-hover)
.aurora-slider-track
background-color: var(--a-color-background-surface-secondary)
border-radius: var(--a-border-radius-pill)
transition: background-color var(--a-transition-duration-main) var(--a-transition-timing-main)
.aurora-slider-range
background-color: var(--a-color-accent)
border-radius: var(--a-border-radius-pill)
.aurora-slider-thumb
position: relative
outline: none
width: calc(var(--a-track-height) * 2)
height: calc(var(--a-track-height) * 2)
border-radius: var(--a-border-radius-circle)
background-color: var(--a-color-accent)
transition: width var(--a-transition-duration-main) var(--a-transition-timing-main), height var(--a-transition-duration-main) var(--a-transition-timing-main)
&--hidden-thumb
&:hover .aurora-slider-thumb
opacity: 1
.aurora-slider-thumb
opacity: 0
&[data-orientation="horizontal"]
.aurora-slider-control
flex-direction: row
width: 100%
height: var(--a-track-height)
.aurora-slider-range
height: var(--a-track-height)
.aurora-slider-track
width: 100%
height: var(--a-track-height)
.aurora-slider-thumb
margin-top: 1px
&[data-orientation="vertical"]
height: 100%
.aurora-slider-control
flex-direction: column
width: var(--a-track-height)
height: 100%
.aurora-slider-range
width: var(--a-track-height)
.aurora-slider-track
width: var(--a-track-height)
height: 100%
.aurora-slider-thumb
margin-left: 1px

View File

@ -0,0 +1,89 @@
import React, { useState } from 'react'
import classNames from 'classnames'
import {
Slider as ArkSlider,
SliderControl,
SliderRange,
SliderThumb,
SliderTrack,
type SliderProps
} from '@ark-ui/react'
import './slider.sass'
interface Props
extends Pick<
SliderProps,
| 'value'
| 'defaultValue'
| 'max'
| 'min'
| 'step'
| 'disabled'
| 'orientation'
| 'onChange'
> {
width?: number | string
height?: number | string
hiddenThumb?: boolean
}
export function Slider({
width,
height,
value,
defaultValue,
max = 100,
min = 0,
step = 1,
disabled,
orientation = 'horizontal',
hiddenThumb,
onChange
}: Props) {
const [newValue, setNewValue] = useState(value)
const valueInPercent =
Number(((Number(newValue) - min) / (max - min)).toFixed(2)) * 100
return (
<div
className="aurora-slider-container"
style={{
width,
height
}}
>
<ArkSlider
className={classNames('aurora-slider', {
'aurora-slider--hidden-thumb': hiddenThumb
})}
value={newValue}
defaultValue={defaultValue}
max={max}
min={min}
step={step}
disabled={disabled}
orientation={orientation}
onChange={(details) => {
setNewValue(details.value)
onChange?.(details)
}}
>
<SliderControl className="aurora-slider-control">
<SliderTrack className="aurora-slider-track">
<SliderRange
className="aurora-slider-range"
style={{
[orientation === 'horizontal'
? 'width'
: 'height']: `${valueInPercent}%`
}}
/>
</SliderTrack>
<SliderThumb className="aurora-slider-thumb" />
</SliderControl>
</ArkSlider>
</div>
)
}

View File

@ -0,0 +1 @@
export * from './status'

View File

@ -0,0 +1,62 @@
@import '../../styles/main.sass'
.aurora-status
position: relative
display: inline-block
border-radius: var(--a-border-radius-pill)
font-size: var(--a-font-size-xs)
padding: var(--a-space-xs) var(--a-space-sm)
cursor: default
color: var(--a-color-text)
background-color: var(--a-color-transparent-white)
border: 1px solid var(--a-color-transparent-white)
transition: background-color var(--a-transition-duration-main) var(--a-transition-timing-main), border-color var(--a-transition-duration-main) var(--a-transition-timing-main)
&:hover
background-color: var(--a-color-transparent-white-hover)
border-color: var(--a-color-transparent-white-hover)
*
cursor: default
.aurora-icon
width: auto
height: auto
padding: 0
&--blue
color: var(--a-color-blue)
background-color: var(--a-color-transparent-blue)
border-color: var(--a-color-transparent-blue)
&:hover
background-color: var(--a-color-transparent-blue-hover)
border-color: var(--a-color-transparent-blue-hover)
.aurora-icon
color: var(--a-color-blue)
&--green
color: var(--a-color-green)
background-color: var(--a-color-transparent-green)
border-color: var(--a-color-transparent-green)
&:hover
background-color: var(--a-color-transparent-green-hover)
border-color: var(--a-color-transparent-green-hover)
.aurora-icon
color: var(--a-color-green)
&--yellow
color: var(--a-color-yellow)
background-color: var(--a-color-transparent-yellow)
border-color: var(--a-color-transparent-yellow)
&:hover
background-color: var(--a-color-transparent-yellow-hover)
border-color: var(--a-color-transparent-yellow-hover)
.aurora-icon
color: var(--a-color-yellow)
&--red
color: var(--a-color-red)
background-color: var(--a-color-transparent-red)
border-color: var(--a-color-transparent-red)
&:hover
background-color: var(--a-color-transparent-red-hover)
border-color: var(--a-color-transparent-red-hover)
.aurora-icon
color: var(--a-color-red)

View File

@ -0,0 +1,43 @@
import type React from 'react'
import classNames from 'classnames'
import type { IconType } from '../../lib/types'
import { Icon, Flexbox } from '../index'
import './status.sass'
interface Props {
children: React.ReactNode
color?: 'blue' | 'green' | 'red' | 'yellow'
iconName?: string
iconType?: IconType
}
export function Status({
children,
color,
iconName,
iconType = 'line'
}: Props) {
return (
<div
className={classNames('aurora-status', {
[`aurora-status--${color}`]: color
})}
>
{iconName ? (
<Flexbox
alignItems="center"
justifyContent="center"
flexDirection="row"
gap="xs"
>
<Icon name={iconName} type={iconType} size="sm" />
<i>{children}</i>
</Flexbox>
) : (
children
)}
</div>
)
}

View File

@ -0,0 +1 @@
export * from './switch'

View File

@ -0,0 +1,48 @@
@import '../../styles/main.sass'
.aurora-switch
--a-switch-width: 44px
--a-thumb-size: 20px
position: relative
display: flex
align-items: center
gap: var(--a-space-sm)
cursor: pointer
&[data-disabled]
cursor: not-allowed
opacity: var(--a-opacity-disabled)
&:hover:not([data-checked], [data-disabled]) .aurora-switch-control
background-color: var(--a-color-background-surface-secondary-hover)
.aurora-switch-control
position: relative
display: flex
align-items: center
border-radius: var(--a-border-radius-pill)
background-color: var(--a-color-background-surface-secondary)
width: var(--a-switch-width)
height: 22px
transition: background-color var(--a-transition-duration-main) var(--a-transition-timing-main)
&[data-checked]
background-color: var(--a-color-accent)
.aurora-switch-thumb
display: block
position: relative
left: 2px
width: var(--a-thumb-size)
height: var(--a-thumb-size)
border-radius: var(--a-border-radius-circle)
border: 1px solid var(--a-color-input-border)
background-color: var(--a-color-background-surface)
transition: transform var(--a-transition-duration-main) var(--a-transition-timing-main), border-color var(--a-transition-duration-main) var(--a-transition-timing-main)
&[data-checked]
border-color: transparent
transform: translateX(calc(var(--a-switch-width) - var(--a-thumb-size) - 4px))
.aurora-switch-label
color: var(--a-color-text)
font-size: var(--a-font-size-md)
&[data-disabled]
color: inherit

View File

@ -0,0 +1,44 @@
import React, { useState } from 'react'
import {
Switch as ArkSwitch,
SwitchLabel,
SwitchInput,
SwitchControl,
SwitchThumb,
type SwitchProps
} from '@ark-ui/react'
import './switch.sass'
interface Props
extends Pick<SwitchProps, 'value' | 'checked' | 'disabled' | 'onChange'> {
label?: string
}
export function Switch({ label, checked, value, disabled, onChange }: Props) {
const [isChecked, setIsChecked] = useState(checked)
return (
<ArkSwitch
className="aurora-switch"
value={value}
checked={isChecked}
disabled={disabled}
onChange={(e) => {
setIsChecked(e.checked)
if (onChange) {
onChange(e)
}
}}
>
<>
<SwitchInput />
<SwitchControl className="aurora-switch-control">
<SwitchThumb className="aurora-switch-thumb" />
</SwitchControl>
<SwitchLabel className="aurora-switch-label">{label}</SwitchLabel>
</>
</ArkSwitch>
)
}

View File

@ -0,0 +1,4 @@
export * from './tab'
export * from './tab-content'
export * from './tab-group'
export * from './tab-list'

View File

@ -0,0 +1 @@
export * from './tab-content'

View File

@ -0,0 +1,15 @@
import type React from 'react'
import {
TabContent as ArkTabContent,
type TabContentProps
} from '@ark-ui/react'
interface Props extends Pick<TabContentProps, 'children' | 'value'> {}
export function TabContent({ children, value }: Props) {
return (
<ArkTabContent className="aurora-tab-content" value={value}>
{children}
</ArkTabContent>
)
}

View File

@ -0,0 +1 @@
export * from './tab-group'

View File

@ -0,0 +1,38 @@
@import '../../../styles/main.sass'
.aurora-tab-group
.aurora-tab
color: var(--a-color-text)
font-size: var(--a-font-size-md)
cursor: pointer
background-color: transparent
border: none
margin-right: var(--a-space-md)
padding: 0
padding-bottom: var(--a-space-xs)
transition: color var(--a-transition-duration-main) var(--a-transition-timing-main)
&:hover, &[data-selected]
color: var(--a-color-accent)
&[disabled]
opacity: var(--a-opacity-disabled)
cursor: not-allowed
color: inherit
&--sm .aurora-tab
font-size: var(--a-font-size-sm)
&--md .aurora-tab
font-size: var(--a-font-size-md)
&--lg .aurora-tab
font-size: var(--a-font-size-lg)
.aurora-tab-indicator-container
display: grid
.aurora-tab-indicator
justify-self: center
width: 6px
height: 6px
border-radius: var(--a-border-radius-circle)
background-color: var(--a-color-accent)
.aurora-tab-content
margin-top: var(--a-space-md)

View File

@ -0,0 +1,25 @@
import type React from 'react'
import classNames from 'classnames'
import { Tabs, type TabsProps } from '@ark-ui/react'
import './tab-group.sass'
interface Props
extends Pick<TabsProps, 'children' | 'defaultValue' | 'onChange'> {
size?: 'sm' | 'md' | 'lg'
}
export function TabGroup({ children, defaultValue, onChange, size }: Props) {
return (
<Tabs
className={classNames('aurora-tab-group', {
[`aurora-tab-group--${size}`]: size
})}
defaultValue={defaultValue}
onChange={onChange}
orientation="horizontal"
>
{children}
</Tabs>
)
}

View File

@ -0,0 +1 @@
export * from './tab-list'

View File

@ -0,0 +1,19 @@
import type React from 'react'
import {
TabIndicator,
TabList as ArkTabList,
type TabListProps
} from '@ark-ui/react'
interface Props extends Pick<TabListProps, 'children'> {}
export function TabList({ children }: Props) {
return (
<ArkTabList className="aurora-tab-list">
{children}
<TabIndicator className="aurora-tab-indicator-container">
<div className="aurora-tab-indicator" />
</TabIndicator>
</ArkTabList>
)
}

View File

@ -0,0 +1 @@
export * from './tab'

View File

@ -0,0 +1,13 @@
import type React from 'react'
import { TabTrigger, type TabTriggerProps } from '@ark-ui/react'
interface Props
extends Pick<TabTriggerProps, 'children' | 'value' | 'disabled'> {}
export function Tab({ children, value, disabled }: Props) {
return (
<TabTrigger className="aurora-tab" value={value} disabled={disabled}>
{children}
</TabTrigger>
)
}

View File

@ -0,0 +1 @@
export * from './text'

View File

@ -0,0 +1,42 @@
@import '../../styles/main.sass'
.aurora-text
font-size: var(--a-font-size-md)
font-weight: var(--a-font-weight-regular)
line-height: var(--a-line-height-md)
color: var(--a-color-text)
text-align: left
transition: color var(--a-transition-duration-main) var(--a-transition-timing-main)
&--left
text-align: left
&--center
text-align: center
&--right
text-align: right
&--secondary
color: var(--a-color-text-secondary)
&--tertiary
color: var(--a-color-text-tertiary)
&--xs
font-size: var(--a-font-size-xs)
line-height: var(--a-line-height-xs)
&--sm
font-size: var(--a-font-size-sm)
line-height: var(--a-line-height-sm)
&--md
font-size: var(--a-font-size-md)
line-height: var(--a-line-height-md)
&--lg
font-size: var(--a-font-size-lg)
line-height: var(--a-line-height-lg)
&--xl
font-size: var(--a-font-size-xl)
line-height: var(--a-line-height-xl)
&--regular
font-weight: var(--a-font-weight-regular)
&--semi-bold
font-weight: var(--a-font-weight-semi-bold)

View File

@ -0,0 +1,47 @@
import type React from 'react'
import classNames from 'classnames'
import type { Size } from '../../lib/types'
import './text.sass'
/*const FONT_SIZES = {
XS: 'xs',
SM: 'sm',
MD: 'md',
LG: 'lg',
XL: 'xl'
} as const*/
interface Props {
children: React.ReactNode
// fontSize?: typeof FONT_SIZES[keyof typeof FONT_SIZES]
fontSize?: Size
fontWeight?: 'regular' | 'semi-bold'
secondary?: boolean
tertiary?: boolean
textAlign?: 'left' | 'center' | 'right'
}
export function Text({
children,
fontSize,
fontWeight,
secondary,
tertiary,
textAlign
}: Props) {
return (
<p
className={classNames('aurora-text', {
'aurora-text--secondary': secondary,
'aurora-text--tertiary': tertiary,
[`aurora-text--${textAlign}`]: textAlign,
[`aurora-text--${fontSize}`]: fontSize,
[`aurora-text--${fontWeight}`]: fontWeight
})}
>
{children}
</p>
)
}

View File

@ -0,0 +1 @@
export * from './widget-wrapper'

View File

@ -0,0 +1,23 @@
@import '../../styles/main.sass'
.aurora-widget-wrapper
position: relative
display: inline-block
height: auto
border-radius: var(--a-border-radius-md)
padding: var(--a-space-xl) var(--a-space-md)
width: var(--a-widget-width)
background: linear-gradient(var(--a-color-background-surface), var(--a-color-background-surface)) padding-box, linear-gradient(135deg, rgba(28, 117, 219, 0.4) 0%, rgba(237, 41, 122, 0.2) 100%) border-box
border: 1px solid transparent
overflow-x: auto
&--no-padding
padding: 0
&--padding-top
padding-top: var(--a-space-xl)
&--padding-bottom
padding-bottom: var(--a-space-xl)
&--padding-left
padding-left: var(--a-space-md)
&--padding-right
padding-right: var(--a-space-md)

View File

@ -0,0 +1,36 @@
import type React from 'react'
import classNames from 'classnames'
import './widget-wrapper.sass'
interface Props {
children: React.ReactNode
noPadding?: boolean
paddingTop?: boolean
paddingBottom?: boolean
paddingLeft?: boolean
paddingRight?: boolean
}
export function WidgetWrapper({
children,
noPadding,
paddingTop,
paddingBottom,
paddingLeft,
paddingRight
}: Props) {
return (
<div
className={classNames('aurora-widget-wrapper', {
'aurora-widget-wrapper--no-padding': noPadding,
'aurora-widget-wrapper--padding-top': paddingTop,
'aurora-widget-wrapper--padding-bottom': paddingBottom,
'aurora-widget-wrapper--padding-left': paddingLeft,
'aurora-widget-wrapper--padding-right': paddingRight
})}
>
{children}
</div>
)
}

View File

@ -0,0 +1,3 @@
'use client'
export * from './components'

View File

@ -0,0 +1,20 @@
export type Color =
| 'white'
| 'transparent-white'
| 'black'
| 'blue'
| 'secondary-blue'
| 'transparent-blue'
| 'red'
| 'secondary-red'
| 'transparent-red'
| 'green'
| 'secondary-green'
| 'transparent-green'
| 'yellow'
| 'secondary-yellow'
| 'transparent-yellow'
export type Size = 'xs' | 'sm' | 'md' | 'lg' | 'xl'
export type IconType = 'line' | 'fill'

View File

View File

@ -0,0 +1,5 @@
@keyframes aurora-animation-fade-in
0%
opacity: 0
100%
opacity: 1

View File

@ -0,0 +1,139 @@
\:root
/**
* Colors
*/
--a-color-white: #F5F5F7
--a-color-transparent-white: rgba(245, 245, 247, .1)
--a-color-transparent-white-hover: rgba(245, 245, 247, .2)
--a-color-white-secondary: #A7B3C8
--a-color-secondary-grey: #45515E
--a-color-black: #000
--a-color-black-light: #0B0C0B
--a-color-black-lighter-1: #0E0E0E
--a-color-black-lighter-2: #151515
--a-color-grey-blue: #292F36
--a-color-grey-blue-dark: #1B2025
--a-color-blue: #1C75DB
--a-color-secondary-blue: #91BDF0
--a-color-transparent-blue: rgba(28, 117, 219, .2)
--a-color-transparent-blue-hover: rgba(28, 117, 219, .3)
--a-color-pink: #ED297A
--a-color-red: #ac0a0a
--a-color-secondary-red: #F09191
--a-color-transparent-red: rgba(172, 10, 10, .2)
--a-color-transparent-red-hover: rgba(172, 10, 10, .3)
--a-color-green: #168604
--a-color-secondary-green: #91F095
--a-color-transparent-green: rgba(22, 134, 4, .2)
--a-color-transparent-green-hover: rgba(22, 134, 4, .3)
--a-color-yellow: #b08313
--a-color-secondary-yellow: #F0E791
--a-color-transparent-yellow: rgba(176, 131, 19, .2)
--a-color-transparent-yellow-hover: rgba(176, 131, 19, .3)
--a-color-background: var(--a-color-black)
--a-color-background-surface: var(--a-color-black-light)
--a-color-background-surface-secondary: var(--a-color-black-lighter-2)
--a-color-background-surface-hover: var(--a-color-black-lighter-1)
--a-color-background-surface-secondary-hover: #1A1A1A
--a-color-background-danger: var(--a-color-red)
--a-color-accent: var(--a-color-blue)
--a-color-accent-hover: #0060C7
--a-color-danger-hover: #990000
--a-color-text: var(--a-color-white)
--a-color-text-secondary: var(--a-color-white-secondary)
--a-color-text-tertiary: var(--a-color-secondary-grey)
--a-color-text-placeholder: var(--a-color-secondary-grey)
--a-color-text-danger: var(--a-color-text)
--a-color-separator: var(--a-color-grey-blue-dark)
--a-color-input-border: var(--a-color-grey-blue)
--a-color-input-border-hover: var(--a-color-secondary-grey)
--a-color-input-border-focus: var(--a-color-blue)
--a-color-input-background: var(--a-color-black)
--a-color-input-background-hover: var(--a-color-black-light)
/**
* Border radius
*/
--a-border-radius-xs: 4px
--a-border-radius-md: 7px
--a-border-radius-pill: 999px
--a-border-radius-circle: 50%
/**
* Font sizes and line heights
*/
--a-font-size-xs: 12px
--a-line-height-xs: 16px
--a-font-size-sm: 16px
--a-line-height-sm: 20px
--a-font-size-md: 20px
--a-line-height-md: 24px
--a-font-size-lg: 32px
--a-line-height-lg: 36px
--a-font-size-xl: 52px
--a-line-height-xl: 56px
--a-font-size-xxl: 72px
--a-line-height-xxl: 76px
/**
* Font weights
*/
--a-font-weight-regular: 400
--a-font-weight-semi-bold: 600
/**
* Font family
*/
--a-font-family: 'Source Sans Pro', system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji'
/**
* Spacing
*/
--a-space-xs: 4px
--a-space-sm: 8px
--a-space-md: 16px
--a-space-lg: 24px
--a-space-xl: 32px
/**
* Sizing
*/
--a-button-size-md: 42px
--a-input-size-md: 42px
--a-loader-size-md: 40px
/**
* Transitions
*/
--a-transition-duration-main: .15s
--a-transition-timing-main: ease-in-out
/**
* Misc
*/
--a-widget-width: 314px
--a-checkbox-radio-size: 20px
--a-opacity-disabled: .4

View File

@ -0,0 +1,21 @@
@import '_includes/variables'
@import '_includes/animations'
[class^="aurora-"], [class^="aurora-"]:after, [class^="aurora-"]:before
scroll-behavior: smooth
box-sizing: border-box
[class^="aurora-"], [class^="aurora-"] *
font-family: var(--a-font-family)
text-rendering: optimizeLegibility
-webkit-font-smoothing: antialiased
-moz-osx-font-smoothing: grayscale
-webkit-text-size-adjust: 100%
[class^="aurora-"]::selection
background-color: var(--color-blue)
color: var(--color-white)
[class^="aurora-"]::placeholder
color: var(--a-color-text-placeholder)
font-size: var(--a-font-size-md)

View File

@ -2,7 +2,7 @@ import { io } from 'socket.io-client'
import React from 'react'
import { createRoot } from 'react-dom/client'
import { Button } from './aurora/button'
import { Button } from './aurora'
import Chatbot from './chatbot'
import { INIT_MESSAGES } from './constants'

View File

@ -68,56 +68,9 @@
"route": "/api/action/social_communication/mbti/quiz",
"params": []
},
{
"method": "POST",
"route": "/api/action/games/akinator/choose_thematic",
"params": ["thematic"],
"entitiesType": "trim"
},
{
"method": "GET",
"route": "/api/action/games/akinator/setup",
"params": []
},
{
"method": "GET",
"route": "/api/action/games/akinator/guess",
"params": []
},
{
"method": "GET",
"route": "/api/action/games/akinator/retry",
"params": []
},
{
"method": "GET",
"route": "/api/action/games/guess_the_number/setup",
"params": []
},
{
"method": "GET",
"route": "/api/action/games/guess_the_number/guess",
"params": []
},
{
"method": "GET",
"route": "/api/action/games/guess_the_number/replay",
"params": []
},
{
"method": "GET",
"route": "/api/action/games/rochambeau/start",
"params": []
},
{
"method": "POST",
"route": "/api/action/games/rochambeau/play",
"params": ["handsign"],
"entitiesType": "trim"
},
{
"method": "GET",
"route": "/api/action/games/rochambeau/rematch",
"route": "/api/action/unknown/widget-playground/run",
"params": []
},
{
@ -190,6 +143,58 @@
"route": "/api/action/leon/welcome/run",
"params": []
},
{
"method": "POST",
"route": "/api/action/games/akinator/choose_thematic",
"params": ["thematic"],
"entitiesType": "trim"
},
{
"method": "GET",
"route": "/api/action/games/akinator/setup",
"params": []
},
{
"method": "GET",
"route": "/api/action/games/akinator/guess",
"params": []
},
{
"method": "GET",
"route": "/api/action/games/akinator/retry",
"params": []
},
{
"method": "GET",
"route": "/api/action/games/guess_the_number/setup",
"params": []
},
{
"method": "GET",
"route": "/api/action/games/guess_the_number/guess",
"params": []
},
{
"method": "GET",
"route": "/api/action/games/guess_the_number/replay",
"params": []
},
{
"method": "GET",
"route": "/api/action/games/rochambeau/start",
"params": []
},
{
"method": "POST",
"route": "/api/action/games/rochambeau/play",
"params": ["handsign"],
"entitiesType": "trim"
},
{
"method": "GET",
"route": "/api/action/games/rochambeau/rematch",
"params": []
},
{
"method": "GET",
"route": "/api/action/utilities/date_time/current_date_time",

View File

@ -70,6 +70,7 @@
"docker:check": "docker run --rm --interactive leon-ai/leon npm run check"
},
"dependencies": {
"@ark-ui/react": "0.5.0",
"@aws-sdk/client-polly": "3.18.0",
"@fastify/static": "6.9.0",
"@ffmpeg-installer/ffmpeg": "1.1.0",
@ -87,6 +88,7 @@
"archiver": "5.3.1",
"async": "3.2.4",
"axios": "1.1.2",
"classnames": "2.3.2",
"cross-env": "7.0.3",
"dayjs": "1.11.5",
"dotenv": "10.0.0",
@ -141,6 +143,7 @@
"nodemon": "2.0.19",
"prettier": "2.8.7",
"resolve-tspaths": "0.8.8",
"sass": "1.63.6",
"semver": "7.3.5",
"shx": "0.3.3",
"ts-node": "10.9.1",

View File

@ -55,7 +55,7 @@ export const run: ActionFunction = async function () {
* Forecast
*/
const forecast = new Container(
/*const forecast = new Container(
[
new Text({
text: 'Paris',
@ -188,9 +188,9 @@ export const run: ActionFunction = async function () {
}
)
/**
/!**
* Select music provider
*/
*!/
const musicProviderList = new List({
title: {
@ -216,9 +216,9 @@ export const run: ActionFunction = async function () {
await leon.answer({ widget: musicProviderList })
/**
/!**
* Todo list
*/
*!/
const todoList = new List({
title: {
text: 'Shopping List',
@ -245,7 +245,7 @@ export const run: ActionFunction = async function () {
})
await leon.answer({ widget: todoList })
*/
/**
* Random number
*/