Skip to content

Commit

Permalink
feat: rollup config & monorepo
Browse files Browse the repository at this point in the history
  • Loading branch information
Innei committed Dec 10, 2022
1 parent bb332a8 commit 255336c
Show file tree
Hide file tree
Showing 51 changed files with 3,415 additions and 0 deletions.
75 changes: 75 additions & 0 deletions packages/kami-design/components/Banner/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { clsx } from 'clsx'
import type { FC } from 'react'

import {
ClaritySuccessLine,
FluentShieldError20Regular,
FluentWarning28Regular,
IonInformation,
} from '../Icons/status'

const IconMap = {
warning: FluentWarning28Regular,
info: IonInformation,
error: FluentShieldError20Regular,
success: ClaritySuccessLine,
}

const bgColorMap = {
warning: 'bg-amber-50',
info: 'bg-default-blue-50',
success: 'bg-default-green-50',
error: 'bg-default-red-50',
}

const borderColorMap = {
warning: 'border-amber-300',
info: 'border-default-blue-300',

success: 'border-default-green-300',
error: 'border-default-red-300',
}

const iconColorMap = {
warning: 'text-amber-500',
info: 'text-default-blue-500',
success: 'text-default-green-500',
error: 'text-default-red-500',
}

export const Banner: FC<{
type: 'warning' | 'error' | 'success' | 'info'
message?: string | React.ReactNode
className?: string
children?: React.ReactNode
placement?: 'center' | 'left'
showIcon?: boolean
}> = (props) => {
const Icon = IconMap[props.type] || IconMap.info
const { placement = 'center', showIcon = true } = props
return (
<div
className={clsx(
'phone:block p-6 flex items-center space-x-4 rounded-md border text-dark-100 dark:text-[#c4c4c4] dark:bg-transparent ' +
`${bgColorMap[props.type] || bgColorMap.info} ${
borderColorMap[props.type] || borderColorMap.info
}`,
placement == 'center' ? 'justify-center' : 'justify-start',
props.className,
)}
>
{showIcon && (
<Icon
className={`text-3xl self-start flex-shrink-0 ${
iconColorMap[props.type] || iconColorMap.info
} mr-2 phone:float-left phone:-mr-2`}
/>
)}
{props.message ? (
<span className="leading-[1.8]">{props.message}</span>
) : (
props.children
)}
</div>
)
}
18 changes: 18 additions & 0 deletions packages/kami-design/components/CodeBlock/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Mermaid } from '../Mermaid'

export const CodeBlock = (props: {
lang: string | undefined
content: string

HighLighter: React.ComponentType<{
content: string
lang: string | undefined
}>
}) => {
const { HighLighter } = props
if (props.lang === 'mermaid') {
return <Mermaid {...props} />
} else {
return <HighLighter {...props} />
}
}
34 changes: 34 additions & 0 deletions packages/kami-design/components/Divider/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
import { clsx } from 'clsx'
import type { DetailedHTMLProps, FC, HTMLAttributes } from 'react'

export const Divider: FC<
DetailedHTMLProps<HTMLAttributes<HTMLHRElement>, HTMLHRElement>
> = (props) => {
const { className, ...rest } = props
return (
<hr
className={clsx(
'border-0 h-[0.5px] my-4 !bg-opacity-30 bg-black dark:bg-white',
className,
)}
{...rest}
/>
)
}

export const DividerVertical: FC<
DetailedHTMLProps<HTMLAttributes<HTMLSpanElement>, HTMLSpanElement>
> = (props) => {
const { className, ...rest } = props
return (
<span
className={clsx(
'!bg-opacity-30 bg-black dark:bg-white inline-block h-full mx-4 w-[0.5px] text-transparent',
className,
)}
{...rest}
>
w
</span>
)
}
21 changes: 21 additions & 0 deletions packages/kami-design/components/FloatPopover/index.module.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.popover-root {
@apply p-4 relative bg-light-bg rounded-lg overflow-hidden z-2 shadow-out-sm;
}

////
.popover-root,
.headless {
opacity: 0;
transform: translateY(-10px);
transition: opacity 0.2s ease-in-out, transform 0.2s ease-in-out;

@apply delay-100;
}

.show,
.headless.show {
opacity: 1;
transform: translateY(0);

@apply delay-0;
}
221 changes: 221 additions & 0 deletions packages/kami-design/components/FloatPopover/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,221 @@
import { clsx } from 'clsx'
import type { FC } from 'react'
import { memo, useCallback, useEffect, useMemo, useRef, useState } from 'react'
import { useClickAway } from 'react-use'

import type { UseFloatingProps } from '@floating-ui/react-dom'
import { flip, offset, shift, useFloating } from '@floating-ui/react-dom'

import { NoSSRWrapper } from '~/utils/no-ssr'

import { RootPortal } from '../Portal'
import styles from './index.module.css'

export const FloatPopover: FC<
{
triggerComponent: FC
headless?: boolean
wrapperClassNames?: string
trigger?: 'click' | 'hover' | 'both'
padding?: number
offset?: number
popoverWrapperClassNames?: string

/**
* 不消失
*/
debug?: boolean
} & UseFloatingProps
> = NoSSRWrapper(
memo((props) => {
const {
headless = false,
wrapperClassNames,
triggerComponent: TriggerComponent,
trigger = 'hover',
padding,
offset: offsetValue,
popoverWrapperClassNames,
debug,
...rest
} = props
const [mounted, setMounted] = useState(false)
const { x, y, reference, floating, strategy, update } = useFloating({
middleware: rest.middleware ?? [
flip({ padding: padding ?? 20 }),
offset(offsetValue ?? 10),
shift(),
],
strategy: rest.strategy,
placement: rest.placement ?? 'bottom-start',
whileElementsMounted: rest.whileElementsMounted,
})
const [currentStatus, setCurrentStatus] = useState(false)
const [open, setOpen] = useState(false)
const updateOnce = useRef(false)
const doPopoverShow = useCallback(() => {
setCurrentStatus(true)
setMounted(true)

if (!updateOnce.current) {
requestAnimationFrame(() => {
update()
updateOnce.current = true
})
}
}, [])

const [containerAnchorRef, setContainerAnchorRef] =
useState<HTMLDivElement | null>()
const containerRef = useRef<HTMLDivElement>(null)

const handleTransition = useCallback(
(status: 'in' | 'out') => {
const nextElementSibling =
containerAnchorRef?.nextElementSibling as HTMLDivElement

if (!nextElementSibling) {
return
}

if (status === 'in') {
nextElementSibling.ontransitionend = null
nextElementSibling?.classList.add(styles.show)
} else {
nextElementSibling?.classList.remove(styles.show)
nextElementSibling!.ontransitionend = () => {
setOpen(false)
setMounted(false)
}
}
},
[containerAnchorRef?.nextElementSibling],
)

useEffect(() => {
if (!containerAnchorRef) {
return
}

if (currentStatus) {
setOpen(true)
requestAnimationFrame(() => {
handleTransition('in')
})
} else {
requestAnimationFrame(() => {
handleTransition('out')
})
}
}, [currentStatus, containerAnchorRef, handleTransition])

useClickAway(containerRef, () => {
if (trigger == 'click' || trigger == 'both') {
doPopoverDisappear()
clickTriggerFlag.current = false
}
})

const doPopoverDisappear = useCallback(() => {
if (debug) {
return
}
setCurrentStatus(false)
}, [debug])

const clickTriggerFlag = useRef(false)
const handleMouseOut = useCallback(() => {
if (clickTriggerFlag.current === true) {
return
}
doPopoverDisappear()
}, [])
const handleClickTrigger = useCallback(() => {
clickTriggerFlag.current = true
doPopoverShow()
}, [])

const listener = useMemo(() => {
const baseListener = {
onFocus: doPopoverShow,
onBlur: doPopoverDisappear,
}
switch (trigger) {
case 'click':
return {
...baseListener,
onClick: doPopoverShow,
}
case 'hover':
return {
...baseListener,
onMouseOver: doPopoverShow,
onMouseOut: doPopoverDisappear,
}
case 'both':
return {
...baseListener,
onClick: handleClickTrigger,
onMouseOver: doPopoverShow,
onMouseOut: handleMouseOut,
}
}
}, [
doPopoverDisappear,
doPopoverShow,
handleClickTrigger,
handleMouseOut,
trigger,
])

const TriggerWrapper = (
<div
role={trigger === 'both' || trigger === 'click' ? 'button' : 'note'}
tabIndex={0}
className={clsx('inline-block', wrapperClassNames)}
ref={reference}
{...listener}
>
<TriggerComponent />
</div>
)

if (!props.children) {
return TriggerWrapper
}

return (
<>
{TriggerWrapper}

{mounted && (
<RootPortal>
<div
className={clsx('float-popover', popoverWrapperClassNames)}
{...(trigger === 'hover' || trigger === 'both' ? listener : {})}
ref={containerRef}
>
<div ref={setContainerAnchorRef} />
{open && (
<div
className={
headless ? styles['headless'] : styles['popover-root']
}
ref={floating}
style={{
position: strategy,
top: y ?? '',
left: x ?? '',
}}
role="dialog"
>
{props.children}
</div>
)}
</div>
</RootPortal>
)}
</>
)
}),
)
Loading

0 comments on commit 255336c

Please sign in to comment.