chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:44:08 +08:00
commit 983960e2dd
1244 changed files with 281996 additions and 0 deletions
+61
View File
@@ -0,0 +1,61 @@
@use '../../styles/main.sass' as *
.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)
+114
View File
@@ -0,0 +1,114 @@
import classNames from 'clsx'
import { generateKeyId } from '../../lib/utils'
import { Flexbox, Icon, Loader } from '../..'
import './button.sass'
interface ButtonOnClickData {
name: string | undefined
value: string | number | undefined
}
export interface ButtonProps {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children?: any
// children?: React.ReactNode
type?: 'button' | 'submit'
iconName?: string
iconPosition?: 'left' | 'right'
secondary?: boolean
danger?: boolean
light?: boolean
disabled?: boolean
loading?: boolean
name?: string
value?: string | number | undefined
onClick?: (data: ButtonOnClickData) => void
}
export function Button({
children,
type = 'button',
iconName,
iconPosition = 'left',
secondary,
danger,
light,
disabled,
loading,
name,
value,
onClick
}: ButtonProps) {
let variant = 'primary'
if (secondary) {
variant = 'secondary'
} else if (danger) {
variant = 'danger'
} else if (light) {
variant = 'light'
}
return (
<button
key={`aurora-button_${generateKeyId()}`}
type={type}
name={name}
value={value}
className={classNames('aurora-button', {
'aurora-button--disabled': disabled,
'aurora-button--loading': loading,
[`aurora-button--${variant}`]: variant
})}
disabled={disabled || loading}
onClick={(event) => {
if (type !== 'button') {
return
}
event.preventDefault()
const data = {
name,
value
}
if (onClick) {
onClick(data)
}
}}
>
{loading ? (
<Loader />
) : (
<>
{iconName && iconPosition === 'left' && (
<Flexbox
flexDirection="row"
justifyContent="center"
alignItems="center"
gap="xs"
>
<Icon iconName={iconName} type="line" />
{children}
</Flexbox>
)}
{iconName && iconPosition === 'right' && (
<Flexbox
flexDirection="row"
justifyContent="center"
alignItems="center"
gap="xs"
>
{children}
<Icon iconName={iconName} type="line" />
</Flexbox>
)}
{!iconName && children}
</>
)}
</button>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './button'
+12
View File
@@ -0,0 +1,12 @@
@use '../../styles/main.sass' as *
.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%
+25
View File
@@ -0,0 +1,25 @@
import classNames from 'clsx'
import { generateKeyId } from '../../lib/utils'
import './card.sass'
export interface CardProps {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children: any
// children: React.ReactNode
fullWidth?: boolean
}
export function Card({ children, fullWidth }: CardProps) {
return (
<div
key={`aurora-card_${generateKeyId()}`}
className={classNames('aurora-card', {
'aurora-card--full-width': fullWidth
})}
>
{children}
</div>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './card'
@@ -0,0 +1,39 @@
@use '../../styles/main.sass' as *
.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-state="checked"])
border-color: var(--a-color-input-border-hover)
background-color: var(--a-color-input-background-hover)
&[data-state="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)
@@ -0,0 +1,74 @@
import { useState } from 'react'
import {
Checkbox as ArkCheckbox,
type CheckboxCheckedChangeDetails,
type CheckboxRootProps as ArkCheckboxProps
} from '@ark-ui/react/checkbox'
import { Icon } from '../icon'
import './checkbox.sass'
interface CheckboxOnChangeData {
name: string
value: string | undefined
isChecked: boolean
}
export interface CheckboxProps
extends Pick<
ArkCheckboxProps,
'value' | 'checked' | 'disabled' | 'required'
> {
name: string
label?: string
onChange?: (data: CheckboxOnChangeData) => void
}
export function Checkbox({
name,
label,
checked,
value,
disabled,
required,
onChange
}: CheckboxProps) {
const [isChecked, setIsChecked] = useState(checked)
return (
<ArkCheckbox.Root
className="aurora-checkbox"
name={name}
value={value}
checked={isChecked}
disabled={disabled}
required={required}
onCheckedChange={(event: CheckboxCheckedChangeDetails) => {
setIsChecked(event.checked as boolean)
const data = {
name,
value,
isChecked: !!event.checked
}
if (onChange) {
onChange(data)
}
}}
>
<ArkCheckbox.HiddenInput />
<ArkCheckbox.Control className="aurora-checkbox-control">
{isChecked ? (
<Icon iconName="check" size="sm" animated />
) : (
<div className="aurora-checkbox-placeholder" />
)}
</ArkCheckbox.Control>
<ArkCheckbox.Label className="aurora-checkbox-label">
{label}
</ArkCheckbox.Label>
</ArkCheckbox.Root>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './checkbox'
@@ -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%)
@@ -0,0 +1,41 @@
import classNames from 'clsx'
import { generateKeyId } from '../../lib/utils'
import './circular-progress.sass'
export interface CircularProgressProps {
value: number
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children?: any
// children?: React.ReactNode
size?: 'sm' | 'md' | 'lg'
}
export function CircularProgress({
value,
children,
size = 'md'
}: CircularProgressProps) {
const total = 100
return (
<div
key={`aurora-circular-progress_${generateKeyId()}`}
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>
)
}
@@ -0,0 +1 @@
export * from './circular-progress'
@@ -0,0 +1,92 @@
@use '../../styles/main.sass' as *
.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)
+66
View File
@@ -0,0 +1,66 @@
import classNames from 'clsx'
import { type Size } from '../../lib/types'
import { generateKeyId } from '../../lib/utils'
import './flexbox.sass'
export interface FlexboxProps {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children: any
// 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
}: FlexboxProps) {
return (
<div
key={`aurora-flexbox_${generateKeyId()}`}
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>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './flexbox'
+4
View File
@@ -0,0 +1,4 @@
@use '../../styles/main.sass' as *
.aurora-form
position: relative
+51
View File
@@ -0,0 +1,51 @@
import { generateKeyId } from '../../lib/utils'
import './form.sass'
export interface FormProps {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children?: any
// children?: React.ReactNode
onSubmit: (data: Record<string, unknown>) => void
}
export function Form({ children, onSubmit }: FormProps) {
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
event.preventDefault()
const form = event.currentTarget
const formData = new FormData(form)
const data: Record<string, unknown> = {}
for (const [key, value] of formData.entries()) {
if (data[key] && key.endsWith('[]')) {
if (Array.isArray(data[key])) {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
;(data[key] as []).push(value)
} else {
data[key] = [data[key], value]
}
} else {
if (key.endsWith('[]')) {
data[key] = [value]
} else {
data[key] = value
}
}
}
onSubmit(data)
}
return (
<form
autoComplete="off"
className="aurora-form"
onSubmit={handleSubmit}
key={`aurora-form_${generateKeyId()}`}
>
{children}
</form>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './form'
@@ -0,0 +1,70 @@
@use '../../styles/main.sass' as *
.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)
@@ -0,0 +1,113 @@
import { useState } from 'react'
import classNames from 'clsx'
import { Icon, Loader } from '../..'
import { type IconProps } from '../icon'
import { generateKeyId } from '../../lib/utils'
import './icon-button.sass'
interface IconButtonOnClickData {
name: string | undefined
value: string | number | undefined
isActivated: boolean
}
export interface IconButtonProps {
iconName: string
name?: string
value?: string | number | undefined
type?: 'button' | 'submit'
iconType?: IconProps['type']
size?: IconProps['size']
shape?: IconProps['bgShape']
activated?: boolean
secondary?: boolean
danger?: boolean
light?: boolean
disabled?: boolean
loading?: boolean
onClick?: (data: IconButtonOnClickData) => void
}
export function IconButton({
iconName,
name,
value,
type = 'button',
iconType = 'line',
size,
shape,
activated,
secondary,
danger,
light,
disabled,
loading,
onClick
}: IconButtonProps) {
const [isActivated, setIsActivated] = useState(activated || false)
let variant = 'primary'
if (danger) {
variant = 'danger'
}
return (
<button
key={`aurora-icon-button_${generateKeyId()}`}
type={type}
name={name}
value={value}
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={(event) => {
if (type !== 'button') {
return
}
event.preventDefault()
if (onClick) {
const data = {
name,
value
}
if (typeof activated === 'undefined') {
onClick({
...data,
isActivated: false
})
} else {
const newActivatedState = !isActivated
setIsActivated(newActivatedState)
onClick({
...data,
isActivated: newActivatedState
})
}
}
}}
>
{loading ? (
<Loader />
) : (
<>
<Icon type={iconType} iconName={iconName} size={size} />
</>
)}
</button>
)
}
@@ -0,0 +1 @@
export * from './icon-button'
+115
View File
@@ -0,0 +1,115 @@
@use '../../styles/main.sass' as *
.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)
+75
View File
@@ -0,0 +1,75 @@
import classNames from 'clsx'
import type { Color, Size, IconType } from '../../lib/types'
import { generateKeyId } from '../../lib/utils'
import './icon.sass'
export interface IconProps {
iconName?: string
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
svg?: any
// 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'
}
const REMIX_ICON_TYPE_SUFFIXES = ['-line', '-fill']
/**
* @see https://remixicon.com/
*/
export function Icon({
iconName,
svg,
type = 'line',
color,
size = 'md',
bgShape,
bgColor,
animated
}: IconProps) {
let iconClassName = `ri-${iconName}`
const hasExplicitTypeSuffix = REMIX_ICON_TYPE_SUFFIXES.some((suffix) =>
iconName?.endsWith(suffix)
)
if (type && type !== 'notype' && !hasExplicitTypeSuffix) {
iconClassName = `${iconClassName}-${type}`
}
return (
<span
key={`aurora-icon_${generateKeyId()}`}
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
})}
/>
)}
</span>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './icon'
+76
View File
@@ -0,0 +1,76 @@
@use '../../styles/main.sass' as *
.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)
+54
View File
@@ -0,0 +1,54 @@
import classNames from 'clsx'
import { generateKeyId } from '../../lib/utils'
import './image.sass'
export interface ImageProps {
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
}: ImageProps) {
return (
<div
key={`aurora-image_${generateKeyId()}`}
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})`
}}
/>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './image'
+1
View File
@@ -0,0 +1 @@
export * from './input'
+87
View File
@@ -0,0 +1,87 @@
@use '../../styles/main.sass' as *
.aurora-input-container
--a-icon-container-width: calc(var(--a-input-size-md) + var(--a-space-sm))
position: relative
display: flex
flex-direction: column
.aurora-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)
&::-webkit-calendar-picker-indicator
cursor: pointer
background-color: var(--a-color-grey-blue-dark)
border-radius: var(--a-border-radius-xs)
&:hover
border-color: var(--a-color-input-border-hover)
background-color: var(--a-color-input-background-hover)
&:hover:not([disabled]) ~ .aurora-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-input-icon-container
border-color: var(--a-color-input-border-focus)
i
color: var(--a-color-accent)
&:placeholder-shown ~ .aurora-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-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-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-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-input-hint-container
padding-left: var(--a-space-md)
margin-top: var(--a-space-xs)
+167
View File
@@ -0,0 +1,167 @@
import { useEffect, useState } from 'react'
import classNames from 'clsx'
import { Text, Icon } from '../..'
import type { IconProps } from '../icon'
import './input.sass'
export interface InputProps {
name: string
placeholder: string
required?: boolean
value?: string
type?:
| 'text'
| 'password'
| 'email'
| 'tel'
| 'url'
| 'number'
| 'date'
| 'time'
| 'datetime-local'
| 'month'
| 'week'
| 'color'
iconName?: string
iconSVG?: IconProps['svg']
iconType?: IconProps['type']
iconSize?: IconProps['size']
hint?: string
disabled?: boolean
height?: number | 'auto'
minLength?: number
maxLength?: number
min?: number
max?: number
step?: number
pattern?: string
multiline?: boolean
autofocus?: boolean
onFocus?: () => void
onBlur?: () => void
onKeyDown?: (event: React.KeyboardEvent<HTMLInputElement | HTMLTextAreaElement>) => void
inputRef?: React.Ref<HTMLInputElement | HTMLTextAreaElement>
onChange?: (value: string) => void
}
export function Input({
name,
placeholder,
required = false,
type = 'text',
iconName,
iconSVG,
iconType = 'fill',
iconSize = 'md',
hint,
value,
disabled,
height = 'auto',
minLength,
maxLength,
pattern,
multiline,
autofocus,
onFocus,
onBlur,
onKeyDown,
inputRef,
onChange
}: InputProps) {
const [inputValue, setInputValue] = useState(value || '')
useEffect(() => {
setInputValue(value || '')
}, [value])
if (!multiline) {
if (!maxLength) {
maxLength = 64
}
if (height !== 'auto') {
height = 'auto'
}
}
return (
<div className="aurora-input-container">
{multiline ? (
<textarea
name={name}
placeholder={placeholder}
required={required}
value={inputValue}
disabled={disabled}
autoFocus={autofocus}
minLength={minLength}
maxLength={maxLength}
onFocus={onFocus}
onBlur={onBlur}
onKeyDown={onKeyDown}
ref={inputRef as React.Ref<HTMLTextAreaElement>}
onChange={(e) => {
setInputValue(e.target.value)
if (onChange) {
onChange(e.target.value)
}
}}
style={{ height }}
className={classNames('aurora-input', {
'aurora-input--multiline': true,
'aurora-input--disabled': disabled,
'aurora-input--with-icon': !!iconName || !!iconSVG
})}
/>
) : (
<input
type={type}
name={name}
placeholder={placeholder}
required={required}
value={inputValue}
disabled={disabled}
autoFocus={autofocus}
minLength={minLength}
maxLength={maxLength}
pattern={pattern}
onFocus={onFocus}
onBlur={onBlur}
onKeyDown={onKeyDown}
ref={inputRef as React.Ref<HTMLInputElement>}
onChange={(e) => {
setInputValue(e.target.value)
if (onChange) {
onChange(e.target.value)
}
}}
className={classNames('aurora-input', {
'aurora-input--disabled': disabled,
'aurora-input--with-icon': !!iconName || !!iconSVG
})}
/>
)}
{(iconName || iconSVG) && (
<div className="aurora-input-icon-container">
<Icon
iconName={iconName}
svg={iconSVG}
type={iconType}
size={iconSize}
/>
</div>
)}
{hint && (
<div className="aurora-input-hint-container">
<Text fontSize="xs" tertiary>
{hint}
</Text>
</div>
)}
</div>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './link'
+14
View File
@@ -0,0 +1,14 @@
@use '../../styles/main.sass' as *
.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)
+28
View File
@@ -0,0 +1,28 @@
import classNames from 'clsx'
import { Text } from '../..'
import { type Size } from '../../lib/types'
import { generateKeyId } from '../../lib/utils'
import './link.sass'
export interface LinkProps {
href: string
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children: any
// children: React.ReactNode
fontSize?: Size
}
export function Link({ href, children, fontSize }: LinkProps) {
return (
<a
className={classNames('aurora-link')}
href={href}
target="_blank"
key={`aurora-link_${generateKeyId()}`}
>
<Text fontSize={fontSize}>{children}</Text>
</a>
)
}
+3
View File
@@ -0,0 +1,3 @@
export * from './list'
export * from './list-header'
export * from './list-item'
@@ -0,0 +1 @@
export * from './list-header'
@@ -0,0 +1,24 @@
import classNames from 'clsx'
import { Text } from '../../..'
import { generateKeyId } from '../../../lib/utils'
export interface ListHeaderProps {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children: any
// children: React.ReactNode
align?: 'left' | 'center'
}
export function ListHeader({ children, align }: ListHeaderProps) {
return (
<div
key={`aurora-list-header_${generateKeyId()}`}
className={classNames('aurora-list-header', {
[`aurora-list-header--${align}`]: align
})}
>
<Text fontWeight="semi-bold">{children}</Text>
</div>
)
}
@@ -0,0 +1 @@
export * from './list-item'
@@ -0,0 +1,75 @@
import classNames from 'clsx'
import { generateKeyId } from '../../../lib/utils'
import { Icon } from '../../..'
interface ListItemOnClickData {
name: string | undefined
value: string | number | undefined
}
export interface ListItemProps {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children: any
// children: React.ReactNode
align?: 'left' | 'center'
name?: string
value?: string | number | undefined
selected?: boolean
onClick?: (data: ListItemOnClickData) => void
}
export function ListItem({
children,
align,
name,
value,
selected,
onClick
}: ListItemProps) {
let isClickable = false
if (onClick) {
isClickable = true
}
return (
<li
key={`aurora-list-item_${generateKeyId()}`}
data-aurora-name={name}
value={value}
className={classNames('aurora-list-item', {
'aurora-list-item--clickable': isClickable,
'aurora-list-item--selected': selected,
[`aurora-list-item--${align}`]: align
})}
onClick={(event) => {
if (!isClickable) {
return
}
event.preventDefault()
const data = {
name,
value
}
if (onClick) {
onClick(data)
}
}}
>
{isClickable ? (
<>
{children}
<div className="aurora-list-item-clickable-icon">
<Icon iconName="arrow-right-double" />
</div>
</>
) : (
children
)}
</li>
)
}
@@ -0,0 +1 @@
export * from './list'
@@ -0,0 +1,57 @@
@use '../../../styles/main.sass' as *
.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
font-size: var(--a-font-size-md)
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)
&--selected
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)
+17
View File
@@ -0,0 +1,17 @@
import { generateKeyId } from '../../../lib/utils'
import './list.sass'
export interface ListProps {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children: any
// children: React.ReactNode
}
export function List({ children }: ListProps) {
return (
<ul className="aurora-list" key={`aurora-list_${generateKeyId()}`}>
{children}
</ul>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './loader'
+29
View File
@@ -0,0 +1,29 @@
@use '../../styles/main.sass' as *
.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
+20
View File
@@ -0,0 +1,20 @@
import { generateKeyId } from '../../lib/utils'
import './loader.sass'
// interface Props {
// size?: 'sm' | 'md'
// }
export type LoaderProps = Record<string, never>
export function Loader(): React.JSX.Element {
return (
<span className="aurora-loader" key={`aurora-loader_${generateKeyId()}`} />
/*<span
className={classNames('aurora-loader', {
[`aurora-loader--${size}`]: size
})}
/>*/
)
}
+1
View File
@@ -0,0 +1 @@
export * from './progress'
@@ -0,0 +1,34 @@
@use '../../styles/main.sass' as *
.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)
@@ -0,0 +1,34 @@
import classNames from 'clsx'
import { generateKeyId } from '../../lib/utils'
import './progress.sass'
export interface ProgressProps {
value: number
orientation?: 'horizontal' | 'vertical'
size?: 'sm' | 'md' | 'lg'
}
export function Progress({
value,
orientation = 'horizontal',
size = 'md'
}: ProgressProps) {
return (
<div
key={`aurora-progress_${generateKeyId()}`}
className={classNames('aurora-progress', {
[`aurora-progress--${orientation}`]: orientation,
[`aurora-progress--${size}`]: size
})}
>
<div
className="aurora-progress-value"
style={{
[orientation === 'horizontal' ? 'width' : 'height']: `${value}%`
}}
/>
</div>
)
}
+2
View File
@@ -0,0 +1,2 @@
export * from './radio'
export * from './radio-group'
@@ -0,0 +1 @@
export * from './radio-group'
@@ -0,0 +1,50 @@
@use '../../../styles/main.sass' as *
.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-state="checked"])
border-color: var(--a-color-input-border-hover)
background-color: var(--a-color-input-background-hover)
&[data-state="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
@@ -0,0 +1,53 @@
import {
RadioGroup as ArkRadioGroup,
type RadioGroupRootProps as ArkRadioGroupProps,
type RadioGroupValueChangeDetails
} from '@ark-ui/react/radio-group'
import './radio-group.sass'
interface RadioGroupOnChangeData {
name: string
value: string | number | undefined
}
export interface RadioGroupProps
extends Pick<
ArkRadioGroupProps,
'value' | 'children' | 'defaultValue' | 'disabled'
> {
name: string
onChange?: (data: RadioGroupOnChangeData) => void
}
export function RadioGroup({
name,
value,
children,
defaultValue,
disabled,
onChange
}: RadioGroupProps) {
return (
<ArkRadioGroup.Root
className="aurora-radio-group"
name={name}
defaultValue={defaultValue}
value={value}
disabled={disabled}
onValueChange={(event: RadioGroupValueChangeDetails) => {
const data = {
name,
value: event.value
}
if (onChange) {
onChange(data)
}
}}
orientation="horizontal"
>
{children}
</ArkRadioGroup.Root>
)
}
@@ -0,0 +1 @@
export * from './radio'
@@ -0,0 +1,24 @@
import {
RadioGroup,
type RadioGroupItemProps as ArkRadioProps
} from '@ark-ui/react/radio-group'
export interface RadioProps extends Pick<ArkRadioProps, 'value' | 'disabled'> {
label: string
}
export function Radio({ label, value, disabled }: RadioProps) {
return (
<RadioGroup.Item
className="aurora-radio"
value={value}
disabled={disabled}
>
<RadioGroup.ItemHiddenInput />
<RadioGroup.ItemControl className="aurora-radio-control" />
<RadioGroup.ItemText className="aurora-radio-label">
{label}
</RadioGroup.ItemText>
</RadioGroup.Item>
)
}
@@ -0,0 +1 @@
export * from './range-slider'
@@ -0,0 +1,70 @@
@use '../../styles/main.sass' as *
.aurora-range-slider
--a-track-height: 10px
.aurora-range-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-range-slider-thumb
width: calc(var(--a-track-height) * 2.3)
height: calc(var(--a-track-height) * 2.3)
.aurora-range-slider-track
background-color: var(--a-color-background-surface-secondary-hover)
.aurora-range-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-range-slider-range
background-color: var(--a-color-accent)
border-radius: var(--a-border-radius-pill)
.aurora-range-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-range-slider-thumb
opacity: 1
.aurora-range-slider-thumb
opacity: 0
&[data-orientation="horizontal"]
.aurora-range-slider-control
flex-direction: row
width: 100%
height: var(--a-track-height)
.aurora-range-slider-range
height: var(--a-track-height)
.aurora-range-slider-track
width: 100%
height: var(--a-track-height)
.aurora-range-slider-thumb
margin-top: 1px
&[data-orientation="vertical"]
height: 100%
.aurora-range-slider-control
flex-direction: column
width: var(--a-track-height)
height: 100%
.aurora-range-slider-range
width: var(--a-track-height)
.aurora-range-slider-track
width: var(--a-track-height)
height: 100%
.aurora-range-slider-thumb
margin-left: 1px
@@ -0,0 +1,114 @@
import { useState } from 'react'
import classNames from 'clsx'
import {
Slider,
type SliderRootProps as ArkSliderProps,
type SliderValueChangeDetails
} from '@ark-ui/react/slider'
import './range-slider.sass'
interface RangeSliderOnChangeData {
name: string
value: string | number | undefined
}
export interface RangeSliderProps
extends Pick<
ArkSliderProps,
| 'max'
| 'min'
| 'step'
| 'disabled'
| 'orientation'
> {
name: string
value?: number | number[]
defaultValue?: number | number[]
width?: number | string
height?: number | string
hiddenThumb?: boolean
onChange?: (data: RangeSliderOnChangeData) => void
}
function normalizeValue(value?: number | number[]): number[] | undefined {
if (typeof value === 'undefined') {
return undefined
}
return Array.isArray(value) ? value : [value]
}
export function RangeSlider({
name,
width,
height,
value,
defaultValue,
max = 100,
min = 0,
step = 1,
disabled,
orientation = 'horizontal',
hiddenThumb,
onChange
}: RangeSliderProps) {
const [newValue, setNewValue] = useState(normalizeValue(value ?? defaultValue))
const normalizedValue = normalizeValue(value)
const normalizedDefaultValue = normalizeValue(defaultValue)
const currentValue = normalizedValue ?? newValue ?? normalizedDefaultValue
const currentScalarValue = currentValue?.[0] ?? min
const valueInPercent =
Number((((currentScalarValue - min) / (max - min)) * 100).toFixed(2))
return (
<div
className="aurora-range-slider-container"
style={{
width,
height
}}
>
<Slider.Root
className={classNames('aurora-range-slider', {
'aurora-range-slider--hidden-thumb': hiddenThumb
})}
name={name}
value={normalizedValue}
defaultValue={normalizedDefaultValue}
max={max}
min={min}
step={step}
disabled={disabled}
orientation={orientation}
onValueChange={(event: SliderValueChangeDetails) => {
setNewValue(event.value)
const data = {
name,
value: event.value[0]
}
if (onChange) {
onChange(data)
}
}}
>
<Slider.Control className="aurora-range-slider-control">
<Slider.Track className="aurora-range-slider-track">
<Slider.Range
className="aurora-range-slider-range"
style={{
[orientation === 'horizontal' ? 'width' : 'height']:
`${valueInPercent}%`
}}
/>
</Slider.Track>
<Slider.Thumb className="aurora-range-slider-thumb" index={0}>
<Slider.HiddenInput />
</Slider.Thumb>
</Slider.Control>
</Slider.Root>
</div>
)
}
@@ -0,0 +1 @@
export * from './scroll-container'
@@ -0,0 +1,31 @@
@use '../../styles/main.sass' as *
.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
@@ -0,0 +1,34 @@
import classNames from 'clsx'
import './scroll-container.sass'
export interface ScrollContainerProps {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children: any
orientation?: 'vertical' | 'horizontal'
width?: number | string
height?: number | string
}
export function ScrollContainer({
children,
orientation = 'horizontal',
width,
height
}: ScrollContainerProps) {
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>
)
}
+2
View File
@@ -0,0 +1,2 @@
export * from './select'
export * from './select-option'
@@ -0,0 +1 @@
export * from './select-option'
@@ -0,0 +1,28 @@
import {
Select as ArkSelect
} from '@ark-ui/react/select'
export interface SelectOptionProps {
disabled?: boolean
label: string
value: string
}
export function SelectOption({
label,
value,
disabled = false
}: SelectOptionProps) {
return (
<ArkSelect.Item
className="aurora-select-option"
item={{
label,
value,
disabled
}}
>
<ArkSelect.ItemText>{label}</ArkSelect.ItemText>
</ArkSelect.Item>
)
}
@@ -0,0 +1 @@
export * from './select'
@@ -0,0 +1,77 @@
@use '../../../styles/main.sass' as *
.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
@@ -0,0 +1,124 @@
import { Children, isValidElement, useState, type ReactNode } from 'react'
import { Portal } from '@ark-ui/react/portal'
import {
Select as ArkSelect,
createListCollection
} from '@ark-ui/react/select'
import classNames from 'clsx'
import { Flexbox, Icon } from '../../..'
import { type SelectOptionProps } from '../select-option'
import './select.sass'
interface Option {
label: string
value: string
disabled?: boolean
}
interface SelectOnChangeData {
name: string
value: string | number | undefined
label?: string
}
export interface SelectProps {
name: string
selectedOption?: Option
defaultValue?: string
disabled?: boolean
placeholder: string
children: ReactNode
onChange?: (data: SelectOnChangeData) => void
}
export function Select({
name,
placeholder,
children,
selectedOption,
defaultValue,
disabled,
onChange
}: SelectProps) {
const [currentValue, setCurrentValue] = useState(
selectedOption?.value ?? defaultValue
)
const options = Children.toArray(children).flatMap((child) => {
if (!isValidElement<SelectOptionProps>(child)) {
return []
}
const { label, value, disabled } = child.props
return [
{
label,
value,
disabled
}
]
})
const collection = createListCollection<Option>({
items: options,
itemToString: (item) => item.label,
itemToValue: (item) => item.value,
isItemDisabled: (item) => !!item.disabled
})
const selectedValue = selectedOption?.value
const hasSelectedValue = Boolean(selectedValue ?? currentValue)
return (
<ArkSelect.Root
collection={collection}
closeOnSelect
value={selectedValue ? [selectedValue] : undefined}
defaultValue={defaultValue ? [defaultValue] : undefined}
disabled={disabled}
name={name}
onValueChange={(event) => {
const nextSelectedOption = event.items[0]
setCurrentValue(nextSelectedOption?.value)
const data = {
name,
label: nextSelectedOption?.label,
value: nextSelectedOption?.value
}
if (onChange) {
onChange(data)
}
}}
>
<ArkSelect.HiddenSelect />
<ArkSelect.Trigger
className={classNames('aurora-select-trigger', {
'aurora-select-trigger--selected': hasSelectedValue
})}
>
<Flexbox
flexDirection="row"
alignItems="center"
justifyContent="space-between"
>
<div className="aurora-select-trigger-placeholder-container">
<ArkSelect.ValueText placeholder={placeholder} />
</div>
<div className="aurora-select-trigger-icon-container">
<Icon iconName="arrow-down-s" />
</div>
</Flexbox>
</ArkSelect.Trigger>
<Portal>
<ArkSelect.Positioner>
<ArkSelect.Content className="aurora-select-content">
{children}
</ArkSelect.Content>
</ArkSelect.Positioner>
</Portal>
</ArkSelect.Root>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './status'
+63
View File
@@ -0,0 +1,63 @@
@use '../../styles/main.sass' as *
.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)
i
font-style: normal
*
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)
+45
View File
@@ -0,0 +1,45 @@
import classNames from 'clsx'
import type { IconType } from '../../lib/types'
import { Icon, Flexbox } from '../..'
import { generateKeyId } from '../../lib/utils'
import './status.sass'
export interface StatusProps {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children: any
color?: 'blue' | 'green' | 'red' | 'yellow'
iconName?: string
iconType?: IconType
}
export function Status({
children,
color,
iconName,
iconType = 'line'
}: StatusProps) {
return (
<div
key={`aurora-status_${generateKeyId()}`}
className={classNames('aurora-status', {
[`aurora-status--${color}`]: color
})}
>
{iconName ? (
<Flexbox
alignItems="center"
justifyContent="center"
flexDirection="row"
gap="xs"
>
<Icon iconName={iconName} type={iconType} size="sm" />
<i>{children}</i>
</Flexbox>
) : (
children
)}
</div>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './switch'
+48
View File
@@ -0,0 +1,48 @@
@use '../../styles/main.sass' as *
.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-state="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-state="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-state="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
+63
View File
@@ -0,0 +1,63 @@
import { useState } from 'react'
import {
Switch as ArkSwitch,
type SwitchCheckedChangeDetails,
type SwitchRootProps as ArkSwitchProps
} from '@ark-ui/react/switch'
import './switch.sass'
interface SwitchOnChangeData {
name: string
value: string | number | undefined
isSwitched: boolean
}
export interface SwitchProps
extends Pick<ArkSwitchProps, 'value' | 'checked' | 'disabled' | 'required'> {
name: string
label?: string
onChange?: (data: SwitchOnChangeData) => void
}
export function Switch({
name,
label,
checked,
value,
disabled,
required,
onChange
}: SwitchProps) {
const [isChecked, setIsChecked] = useState(checked)
return (
<ArkSwitch.Root
className="aurora-switch"
name={name}
value={value}
checked={isChecked}
disabled={disabled}
required={required}
onCheckedChange={(event: SwitchCheckedChangeDetails) => {
setIsChecked(event.checked)
const data = {
name,
value,
isSwitched: event.checked
}
if (onChange) {
onChange(data)
}
}}
>
<ArkSwitch.HiddenInput />
<ArkSwitch.Control className="aurora-switch-control">
<ArkSwitch.Thumb className="aurora-switch-thumb" />
</ArkSwitch.Control>
<ArkSwitch.Label className="aurora-switch-label">{label}</ArkSwitch.Label>
</ArkSwitch.Root>
)
}
+4
View File
@@ -0,0 +1,4 @@
export * from './tab'
export * from './tab-content'
export * from './tab-group'
export * from './tab-list'
@@ -0,0 +1 @@
export * from './tab-content'
@@ -0,0 +1,23 @@
import {
Tabs,
type TabContentProps as ArkTabContentProps
} from '@ark-ui/react/tabs'
import { generateKeyId } from '../../../lib/utils'
export type TabContentProps = Pick<ArkTabContentProps, 'children' | 'value'>
export function TabContent({
children,
value
}: TabContentProps): React.JSX.Element {
return (
<Tabs.Content
key={`aurora-tab-content_${generateKeyId()}`}
className="aurora-tab-content"
value={value}
>
{children}
</Tabs.Content>
)
}
@@ -0,0 +1 @@
export * from './tab-group'
@@ -0,0 +1,38 @@
@use '../../../styles/main.sass' as *
.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)
@@ -0,0 +1,37 @@
import classNames from 'clsx'
import {
Tabs,
type TabsRootProps as ArkTabsProps,
type TabsValueChangeDetails
} from '@ark-ui/react/tabs'
import { generateKeyId } from '../../../lib/utils'
import './tab-group.sass'
export interface TabGroupProps
extends Pick<ArkTabsProps, 'children' | 'defaultValue'> {
size?: 'sm' | 'md' | 'lg'
onChange?: (details: TabsValueChangeDetails) => void
}
export function TabGroup({
children,
defaultValue,
onChange,
size
}: TabGroupProps) {
return (
<Tabs.Root
key={`aurora-tab-group_${generateKeyId()}`}
className={classNames('aurora-tab-group', {
[`aurora-tab-group--${size}`]: size
})}
defaultValue={defaultValue}
onValueChange={onChange}
orientation="horizontal"
>
{children}
</Tabs.Root>
)
}
@@ -0,0 +1 @@
export * from './tab-list'
@@ -0,0 +1,22 @@
import {
Tabs,
type TabListProps as ArkTabListProps
} from '@ark-ui/react/tabs'
import { generateKeyId } from '../../../lib/utils'
export type TabListProps = Pick<ArkTabListProps, 'children'>
export function TabList({ children }: TabListProps): React.JSX.Element {
return (
<Tabs.List
key={`aurora-tab-list_${generateKeyId()}`}
className="aurora-tab-list"
>
{children}
<Tabs.Indicator className="aurora-tab-indicator-container">
<div className="aurora-tab-indicator" />
</Tabs.Indicator>
</Tabs.List>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './tab'
+28
View File
@@ -0,0 +1,28 @@
import {
Tabs,
type TabTriggerProps as ArkTabTriggerProps
} from '@ark-ui/react/tabs'
import { generateKeyId } from '../../../lib/utils'
export type TabProps = Pick<
ArkTabTriggerProps,
'children' | 'value' | 'disabled'
>
export function Tab({
children,
value,
disabled
}: TabProps): React.JSX.Element {
return (
<Tabs.Trigger
key={`aurora-tab_${generateKeyId()}`}
className="aurora-tab"
value={value}
disabled={disabled}
>
{children}
</Tabs.Trigger>
)
}
+1
View File
@@ -0,0 +1 @@
export * from './text'
+42
View File
@@ -0,0 +1,42 @@
@use '../../styles/main.sass' as *
.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)
+49
View File
@@ -0,0 +1,49 @@
import classNames from 'clsx'
import type { Size } from '../../lib/types'
import { generateKeyId } from '../../lib/utils'
import './text.sass'
/*const FONT_SIZES = {
XS: 'xs',
SM: 'sm',
MD: 'md',
LG: 'lg',
XL: 'xl'
} as const*/
export interface TextProps {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children: any
// 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
}: TextProps): React.JSX.Element {
return (
<p
key={`aurora-text_${generateKeyId()}`}
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>
)
}
@@ -0,0 +1 @@
export * from './widget-wrapper'
@@ -0,0 +1,23 @@
@use '../../styles/main.sass' as *
.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)
@@ -0,0 +1,39 @@
import classNames from 'clsx'
import { generateKeyId } from '../../lib/utils'
import './widget-wrapper.sass'
export interface WidgetWrapperProps {
/* eslint-disable-next-line @typescript-eslint/no-explicit-any */
children: any
noPadding?: boolean
paddingTop?: boolean
paddingBottom?: boolean
paddingLeft?: boolean
paddingRight?: boolean
}
export function WidgetWrapper({
children,
noPadding,
paddingTop,
paddingBottom,
paddingLeft,
paddingRight
}: WidgetWrapperProps) {
return (
<div
key={`aurora-widget-wrapper_${generateKeyId()}`}
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>
)
}