Merge pull request #9039 from supabase/feat/migrate-supabase-ui

Feat - migrate supabase UI. Move studio to turborepo
This commit is contained in:
Joshen Lim authored and GitHub committed 2022-10-06 11:47:46 +08:00
commit f016160539
1130 files changed
+32572 -14537

No files matched your search

+9
View File
@@ -195,6 +195,15 @@ The monorepo has a set of shared components under `/packages`:
- `/packages/config`: All shared config
- `/packages/spec`: Generates documentation using spec files.
- `/packages/tsconfig`: Shared Typescript settings
- `/packages/ui`: Shared UI components (formerly @supabase/ui)
To use these 'packages', or any of their components from a Next.JS app, you must use `next-transpile-modules` in the `next.config.js` file. This looks like:
```tsx
// next.config.js
const withTM = require('next-transpile-modules')(['ui', 'common'])
module.exports = withTM({})
```
### Installing packages
+4322 -13141
View File
File diff suppressed because it is too large. Load diff
+221
View File
@@ -0,0 +1,221 @@
const deepMerge = require('deepmerge')
const customFormsPlugin = require('@tailwindcss/forms')
const colors = {
transparent: 'transparent',
white: '#ffffff',
black: '#000000',
gray: {
'50': '#f9fafb',
'100': '#f4f5f7',
'200': '#e5e7eb',
'300': '#d5d6d7',
'400': '#9e9e9e',
'500': '#707275',
'600': '#4c4f52',
'700': '#24262d',
'800': '#1a1c23',
'900': '#121317',
// default values from Tailwind UI palette
// '300': '#d2d6dc',
// '400': '#9fa6b2',
// '500': '#6b7280',
// '600': '#4b5563',
// '700': '#374151',
// '800': '#252f3f',
// '900': '#161e2e',
},
'cool-gray': {
'50': '#fbfdfe',
'100': '#f1f5f9',
'200': '#e2e8f0',
'300': '#cfd8e3',
'400': '#97a6ba',
'500': '#64748b',
'600': '#475569',
'700': '#364152',
'800': '#27303f',
'900': '#1a202e',
},
red: {
'50': '#fdf2f2',
'100': '#fde8e8',
'200': '#fbd5d5',
'300': '#f8b4b4',
'400': '#f98080',
'500': '#f05252',
'600': '#e02424',
'700': '#c81e1e',
'800': '#9b1c1c',
'900': '#771d1d',
},
orange: {
'50': '#fff8f1',
'100': '#feecdc',
'200': '#fcd9bd',
'300': '#fdba8c',
'400': '#ff8a4c',
'500': '#ff5a1f',
'600': '#d03801',
'700': '#b43403',
'800': '#8a2c0d',
'900': '#771d1d',
},
yellow: {
'50': '#fdfdea',
'100': '#fdf6b2',
'200': '#fce96a',
'300': '#faca15',
'400': '#e3a008',
'500': '#c27803',
'600': '#9f580a',
'700': '#8e4b10',
'800': '#723b13',
'900': '#633112',
},
green: {
'50': '#f3faf7',
'100': '#def7ec',
'200': '#bcf0da',
'300': '#84e1bc',
'400': '#31c48d',
'500': '#0e9f6e',
'600': '#057a55',
'700': '#046c4e',
'800': '#03543f',
'900': '#014737',
},
teal: {
'50': '#edfafa',
'100': '#d5f5f6',
'200': '#afecef',
'300': '#7edce2',
'400': '#16bdca',
'500': '#0694a2',
'600': '#047481',
'700': '#036672',
'800': '#05505c',
'900': '#014451',
},
blue: {
'50': '#ebf5ff',
'100': '#e1effe',
'200': '#c3ddfd',
'300': '#a4cafe',
'400': '#76a9fa',
'500': '#3f83f8',
'600': '#1c64f2',
'700': '#1a56db',
'800': '#1e429f',
'900': '#233876',
},
indigo: {
'50': '#f0f5ff',
'100': '#e5edff',
'200': '#cddbfe',
'300': '#b4c6fc',
'400': '#8da2fb',
'500': '#6875f5',
'600': '#5850ec',
'700': '#5145cd',
'800': '#42389d',
'900': '#362f78',
},
purple: {
'50': '#f6f5ff',
'100': '#edebfe',
'200': '#dcd7fe',
'300': '#cabffd',
'400': '#ac94fa',
'500': '#9061f9',
'600': '#7e3af2',
'700': '#6c2bd9',
'800': '#5521b5',
'900': '#4a1d96',
},
pink: {
'50': '#fdf2f8',
'100': '#fce8f3',
'200': '#fad1e8',
'300': '#f8b4d9',
'400': '#f17eb8',
'500': '#e74694',
'600': '#d61f69',
'700': '#bf125d',
'800': '#99154b',
'900': '#751a3d',
},
}
const backgroundOpacity = (theme) => ({
'10': '0.1',
...theme('opacity'),
})
const maxHeight = (theme) => ({
'0': '0',
xl: '36rem',
...theme('spacing'),
})
const windmillConfig = {
darkMode: 'class',
purge: {
content: [
'node_modules/@supabase/ui/theme/defaultTheme.js',
// 'node_modules/@supabase/ui/dist/index.js',
],
},
theme: {
colors,
backgroundOpacity,
maxHeight,
},
variants: {
backgroundOpacity: ['responsive', 'hover', 'focus', 'dark'],
backgroundColor: ['responsive', 'hover', 'focus', 'active', 'odd', 'dark'],
display: ['responsive', 'dark'],
textColor: [
'responsive',
'focus',
'focus-within',
'hover',
'active',
'dark',
],
placeholderColor: ['responsive', 'focus', 'dark'],
borderColor: ['responsive', 'hover', 'focus', 'dark'],
divideColor: ['responsive', 'dark'],
boxShadow: ['responsive', 'hover', 'focus', 'dark'],
margin: ['responsive', 'last'],
},
plugins: [customFormsPlugin],
}
function arrayMergeFn(destinationArray, sourceArray) {
return destinationArray.concat(sourceArray).reduce((acc, cur) => {
if (acc.includes(cur)) return acc
return [...acc, cur]
}, [])
}
/**
* Merge Windmill and Tailwind CSS configurations
* @param {object} tailwindConfig - Tailwind config object
* @return {object} new config object
*/
export function wrapper(tailwindConfig) {
let purge
if (Array.isArray(tailwindConfig.purge)) {
purge = {
content: tailwindConfig.purge,
}
} else {
purge = tailwindConfig.purge
}
return deepMerge({ ...tailwindConfig, purge }, windmillConfig, {
arrayMerge: arrayMergeFn,
})
}
// module.exports = wrapper
+90
View File
@@ -0,0 +1,90 @@
module.exports = {
brand: {
brand1: 'hsla(153, 80%, 99%, 1)',
brand2: 'hsla(148, 88%, 97%, 1)',
brand3: 'hsla(148, 76%, 95%, 1)',
brand4: 'hsla(148, 68%, 92%, 1)',
brand5: 'hsla(148, 59%, 88%, 1)',
brand6: 'hsla(149, 43%, 82%, 1)',
brand7: 'hsla(149, 43%, 69%, 1)',
brand8: 'hsla(154, 55%, 45%, 1)',
brand9: 'hsla(153, 60%, 53%, 1)',
brand10: 'hsla(153, 50%, 50%, 1)',
brand11: 'hsla(153, 50%, 34%, 1)',
brand12: 'hsla(153, 40%, 12%, 1)',
},
brandDark: {
brand1: 'hsla(153, 75%, 6%, 1)',
brand2: 'hsla(153, 73%, 7%, 1)',
brand3: 'hsla(154, 69%, 9%, 1)',
brand4: 'hsla(154, 67%, 11%, 1)',
brand5: 'hsla(154, 66%, 13%, 1)',
brand6: 'hsla(154, 64%, 17%, 1)',
brand7: 'hsla(154, 62%, 22%, 1)',
brand8: 'hsla(153, 60%, 28%, 1)',
brand9: 'hsla(153, 60%, 53%, 1)',
brand10: 'hsla(153, 60%, 70%, 1)',
brand11: 'hsla(153, 60%, 50%, 1)',
brand12: 'hsla(153, 60%, 95%, 1)',
},
contrast: {
'brand-hiContrast': 'var(--colors-brand-9)',
'brand-loContrast': 'var(--colors-brand-4)',
},
scale: {
scale1: 'var(--colors-slate1)',
scale2: 'var(--colors-slate2)',
scale3: 'var(--colors-slate3)',
scale4: 'var(--colors-slate4)',
scale5: 'var(--colors-slate5)',
scale6: 'var(--colors-slate6)',
scale7: 'var(--colors-slate7)',
scale8: 'var(--colors-slate8)',
scale9: 'var(--colors-slate9)',
scale10: 'var(--colors-slate10)',
scale11: 'var(--colors-slate11)',
scale12: 'var(--colors-slate12)',
},
scaleA: {
scaleA1: 'var(--colors-slatea1)',
scaleA2: 'var(--colors-slatea2)',
scaleA3: 'var(--colors-slatea3)',
scaleA4: 'var(--colors-slatea4)',
scaleA5: 'var(--colors-slatea5)',
scaleA6: 'var(--colors-slatea6)',
scaleA7: 'var(--colors-slatea7)',
scaleA8: 'var(--colors-slatea8)',
scaleA9: 'var(--colors-slatea9)',
scaleA10: 'var(--colors-slatea10)',
scaleA11: 'var(--colors-slatea11)',
scaleA12: 'var(--colors-slatea12)',
},
scaleDark: {
scale1: 'var(--colors-gray1)',
scale2: 'var(--colors-gray2)',
scale3: 'var(--colors-gray3)',
scale4: 'var(--colors-gray4)',
scale5: 'var(--colors-gray5)',
scale6: 'var(--colors-gray6)',
scale7: 'var(--colors-gray7)',
scale8: 'var(--colors-gray8)',
scale9: 'var(--colors-gray9)',
scale10: 'var(--colors-gray10)',
scale11: 'var(--colors-gray11)',
scale12: 'var(--colors-gray12)',
},
scaleADark: {
scaleA1: 'var(--colors-graya1)',
scaleA2: 'var(--colors-graya2)',
scaleA3: 'var(--colors-graya3)',
scaleA4: 'var(--colors-graya4)',
scaleA5: 'var(--colors-graya5)',
scaleA6: 'var(--colors-graya6)',
scaleA7: 'var(--colors-graya7)',
scaleA8: 'var(--colors-graya8)',
scaleA9: 'var(--colors-graya9)',
scaleA10: 'var(--colors-graya10)',
scaleA11: 'var(--colors-graya11)',
scaleA12: 'var(--colors-graya12)',
},
}
+352
View File
@@ -0,0 +1,352 @@
import * as React from 'react'
// // GENERAL
export * from './src/components/Button'
export * from './src/components/Icon'
export * from './src/components/Icon/IconContext'
// export * from './src/components/Image'
// DISPLAYS
export * from './src/components/Card'
export * from './src/components/Badge'
export * from './src/components/Tabs'
export * from './src/components/Alert'
export * from './src/components/Accordion'
export * from './src/components/Collapsible'
// export * from './src/components/Breadcrumb'
// NAV
export * from './src/components/Menu'
// OVERLAYS
export * from './src/components/Modal'
export * from './src/components/SidePanel'
export * from './src/components/Dropdown'
export * from './src/components/ContextMenu'
export * from './src/components/Popover'
// export * from './src/components/Toast'
// UTILITIES
export * from './src/components/Space'
export * from './src/components/Loading'
export * from './src/components/Divider'
export * from './src/components/ThemeProvider'
// DATA ENTRY
export * from './src/components/Select'
export * from './src/components/Listbox'
export * from './src/components/Checkbox'
export * from './src/components/Input'
export * from './src/components/InputNumber'
export * from './src/components/Radio'
export * from './src/components/Toggle'
export * from './src/components/Upload'
export * from './src/components/Form'
// config
// export { default as Config } from './../ui.config'
// ARCHIVE
// export * from './src/components/Textarea'
// AUTH
// export * from './src/components/Auth'
// ICONS
// export icons
export * from './src/components/Icon/icons/IconActivity'
export * from './src/components/Icon/icons/IconAirplay'
export * from './src/components/Icon/icons/IconAlertCircle'
export * from './src/components/Icon/icons/IconAlertOctagon'
export * from './src/components/Icon/icons/IconAlertTriangle'
export * from './src/components/Icon/icons/IconAlignCenter'
export * from './src/components/Icon/icons/IconAlignJustify'
export * from './src/components/Icon/icons/IconAlignLeft'
export * from './src/components/Icon/icons/IconAlignRight'
export * from './src/components/Icon/icons/IconAnchor'
export * from './src/components/Icon/icons/IconAperture'
export * from './src/components/Icon/icons/IconArchive'
export * from './src/components/Icon/icons/IconArrowDownCircle'
export * from './src/components/Icon/icons/IconArrowDownLeft'
export * from './src/components/Icon/icons/IconArrowDownRight'
export * from './src/components/Icon/icons/IconArrowDown'
export * from './src/components/Icon/icons/IconArrowLeftCircle'
export * from './src/components/Icon/icons/IconArrowLeft'
export * from './src/components/Icon/icons/IconArrowRightCircle'
export * from './src/components/Icon/icons/IconArrowRight'
export * from './src/components/Icon/icons/IconArrowUpCircle'
export * from './src/components/Icon/icons/IconArrowUpLeft'
export * from './src/components/Icon/icons/IconArrowUpRight'
export * from './src/components/Icon/icons/IconArrowUp'
export * from './src/components/Icon/icons/IconAtSign'
export * from './src/components/Icon/icons/IconAward'
export * from './src/components/Icon/icons/IconBarChart2'
export * from './src/components/Icon/icons/IconBarChart'
export * from './src/components/Icon/icons/IconBatteryCharging'
export * from './src/components/Icon/icons/IconBattery'
export * from './src/components/Icon/icons/IconBellOff'
export * from './src/components/Icon/icons/IconBell'
export * from './src/components/Icon/icons/IconBluetooth'
export * from './src/components/Icon/icons/IconBold'
export * from './src/components/Icon/icons/IconBookOpen'
export * from './src/components/Icon/icons/IconBook'
export * from './src/components/Icon/icons/IconBookmark'
export * from './src/components/Icon/icons/IconBox'
export * from './src/components/Icon/icons/IconBriefcase'
export * from './src/components/Icon/icons/IconCalendar'
export * from './src/components/Icon/icons/IconCameraOff'
export * from './src/components/Icon/icons/IconCamera'
export * from './src/components/Icon/icons/IconCast'
export * from './src/components/Icon/icons/IconCheckCircle'
export * from './src/components/Icon/icons/IconCheckSquare'
export * from './src/components/Icon/icons/IconCheck'
export * from './src/components/Icon/icons/IconChevronDown'
export * from './src/components/Icon/icons/IconChevronLeft'
export * from './src/components/Icon/icons/IconChevronRight'
export * from './src/components/Icon/icons/IconChevronUp'
export * from './src/components/Icon/icons/IconChevronsDown'
export * from './src/components/Icon/icons/IconChevronsLeft'
export * from './src/components/Icon/icons/IconChevronsRight'
export * from './src/components/Icon/icons/IconChevronsUp'
export * from './src/components/Icon/icons/IconChrome'
export * from './src/components/Icon/icons/IconCircle'
export * from './src/components/Icon/icons/IconClipboard'
export * from './src/components/Icon/icons/IconClock'
export * from './src/components/Icon/icons/IconCloudDrizzle'
export * from './src/components/Icon/icons/IconCloudLightning'
export * from './src/components/Icon/icons/IconCloudOff'
export * from './src/components/Icon/icons/IconCloudRain'
export * from './src/components/Icon/icons/IconCloudSnow'
export * from './src/components/Icon/icons/IconCloud'
export * from './src/components/Icon/icons/IconCode'
export * from './src/components/Icon/icons/IconCodepen'
export * from './src/components/Icon/icons/IconCodesandbox'
export * from './src/components/Icon/icons/IconCoffee'
export * from './src/components/Icon/icons/IconColumns'
export * from './src/components/Icon/icons/IconCommand'
export * from './src/components/Icon/icons/IconCompass'
export * from './src/components/Icon/icons/IconCopy'
export * from './src/components/Icon/icons/IconCornerDownLeft'
export * from './src/components/Icon/icons/IconCornerDownRight'
export * from './src/components/Icon/icons/IconCornerLeftDown'
export * from './src/components/Icon/icons/IconCornerLeftUp'
export * from './src/components/Icon/icons/IconCornerRightDown'
export * from './src/components/Icon/icons/IconCornerRightUp'
export * from './src/components/Icon/icons/IconCornerUpLeft'
export * from './src/components/Icon/icons/IconCornerUpRight'
export * from './src/components/Icon/icons/IconCpu'
export * from './src/components/Icon/icons/IconCreditCard'
export * from './src/components/Icon/icons/IconCrop'
export * from './src/components/Icon/icons/IconCrosshair'
export * from './src/components/Icon/icons/IconDatabase'
export * from './src/components/Icon/icons/IconDelete'
export * from './src/components/Icon/icons/IconDisc'
export * from './src/components/Icon/icons/IconDivideCircle'
export * from './src/components/Icon/icons/IconDivideSquare'
export * from './src/components/Icon/icons/IconDivide'
export * from './src/components/Icon/icons/IconDollarSign'
export * from './src/components/Icon/icons/IconDownloadCloud'
export * from './src/components/Icon/icons/IconDownload'
export * from './src/components/Icon/icons/IconDribbble'
export * from './src/components/Icon/icons/IconDroplet'
export * from './src/components/Icon/icons/IconEdit2'
export * from './src/components/Icon/icons/IconEdit3'
export * from './src/components/Icon/icons/IconEdit'
export * from './src/components/Icon/icons/IconExternalLink'
export * from './src/components/Icon/icons/IconEyeOff'
export * from './src/components/Icon/icons/IconEye'
export * from './src/components/Icon/icons/IconFacebook'
export * from './src/components/Icon/icons/IconFastForward'
export * from './src/components/Icon/icons/IconFeather'
export * from './src/components/Icon/icons/IconFigma'
export * from './src/components/Icon/icons/IconFileMinus'
export * from './src/components/Icon/icons/IconFilePlus'
export * from './src/components/Icon/icons/IconFileText'
export * from './src/components/Icon/icons/IconFile'
export * from './src/components/Icon/icons/IconFilm'
export * from './src/components/Icon/icons/IconFilter'
export * from './src/components/Icon/icons/IconFlag'
export * from './src/components/Icon/icons/IconFolderMinus'
export * from './src/components/Icon/icons/IconFolderPlus'
export * from './src/components/Icon/icons/IconFolder'
export * from './src/components/Icon/icons/IconFramer'
export * from './src/components/Icon/icons/IconFrown'
export * from './src/components/Icon/icons/IconGift'
export * from './src/components/Icon/icons/IconGitBranch'
export * from './src/components/Icon/icons/IconGitCommit'
export * from './src/components/Icon/icons/IconGitMerge'
export * from './src/components/Icon/icons/IconGitPullRequest'
export * from './src/components/Icon/icons/IconGitHub'
export * from './src/components/Icon/icons/IconGitlab'
export * from './src/components/Icon/icons/IconGlobe'
export * from './src/components/Icon/icons/IconGrid'
export * from './src/components/Icon/icons/IconHardDrive'
export * from './src/components/Icon/icons/IconHash'
export * from './src/components/Icon/icons/IconHeadphones'
export * from './src/components/Icon/icons/IconHeart'
export * from './src/components/Icon/icons/IconHelpCircle'
export * from './src/components/Icon/icons/IconHexagon'
export * from './src/components/Icon/icons/IconHome'
export * from './src/components/Icon/icons/IconImage'
export * from './src/components/Icon/icons/IconInbox'
export * from './src/components/Icon/icons/IconInfo'
export * from './src/components/Icon/icons/IconInstagram'
export * from './src/components/Icon/icons/IconItalic'
export * from './src/components/Icon/icons/IconKey'
export * from './src/components/Icon/icons/IconLayers'
export * from './src/components/Icon/icons/IconLayout'
export * from './src/components/Icon/icons/IconLifeBuoy'
export * from './src/components/Icon/icons/IconLink2'
export * from './src/components/Icon/icons/IconLink'
export * from './src/components/Icon/icons/IconLinkedin'
export * from './src/components/Icon/icons/IconList'
export * from './src/components/Icon/icons/IconLoader'
export * from './src/components/Icon/icons/IconLock'
export * from './src/components/Icon/icons/IconLogIn'
export * from './src/components/Icon/icons/IconLogOut'
export * from './src/components/Icon/icons/IconMail'
export * from './src/components/Icon/icons/IconMapPin'
export * from './src/components/Icon/icons/IconMap'
export * from './src/components/Icon/icons/IconMaximize2'
export * from './src/components/Icon/icons/IconMaximize'
export * from './src/components/Icon/icons/IconMeh'
export * from './src/components/Icon/icons/IconMenu'
export * from './src/components/Icon/icons/IconMessageCircle'
export * from './src/components/Icon/icons/IconMessageSquare'
export * from './src/components/Icon/icons/IconMicOff'
export * from './src/components/Icon/icons/IconMic'
export * from './src/components/Icon/icons/IconMinimize2'
export * from './src/components/Icon/icons/IconMinimize'
export * from './src/components/Icon/icons/IconMinusCircle'
export * from './src/components/Icon/icons/IconMinusSquare'
export * from './src/components/Icon/icons/IconMinus'
export * from './src/components/Icon/icons/IconMonitor'
export * from './src/components/Icon/icons/IconMoon'
export * from './src/components/Icon/icons/IconMoreHorizontal'
export * from './src/components/Icon/icons/IconMoreVertical'
export * from './src/components/Icon/icons/IconMousePointer'
export * from './src/components/Icon/icons/IconMove'
export * from './src/components/Icon/icons/IconMusic'
export * from './src/components/Icon/icons/IconNavigation2'
export * from './src/components/Icon/icons/IconNavigation'
export * from './src/components/Icon/icons/IconOctagon'
export * from './src/components/Icon/icons/IconPackage'
export * from './src/components/Icon/icons/IconPaperclip'
export * from './src/components/Icon/icons/IconPauseCircle'
export * from './src/components/Icon/icons/IconPause'
export * from './src/components/Icon/icons/IconPenTool'
export * from './src/components/Icon/icons/IconPercent'
export * from './src/components/Icon/icons/IconPhoneCall'
export * from './src/components/Icon/icons/IconPhoneForwarded'
export * from './src/components/Icon/icons/IconPhoneIncoming'
export * from './src/components/Icon/icons/IconPhoneMissed'
export * from './src/components/Icon/icons/IconPhoneOff'
export * from './src/components/Icon/icons/IconPhoneOutgoing'
export * from './src/components/Icon/icons/IconPhone'
export * from './src/components/Icon/icons/IconPieChart'
export * from './src/components/Icon/icons/IconPlayCircle'
export * from './src/components/Icon/icons/IconPlay'
export * from './src/components/Icon/icons/IconPlusCircle'
export * from './src/components/Icon/icons/IconPlusSquare'
export * from './src/components/Icon/icons/IconPlus'
export * from './src/components/Icon/icons/IconPocket'
export * from './src/components/Icon/icons/IconPower'
export * from './src/components/Icon/icons/IconPrinter'
export * from './src/components/Icon/icons/IconRadio'
export * from './src/components/Icon/icons/IconRefreshCcw'
export * from './src/components/Icon/icons/IconRefreshCw'
export * from './src/components/Icon/icons/IconRepeat'
export * from './src/components/Icon/icons/IconRewind'
export * from './src/components/Icon/icons/IconRotateCcw'
export * from './src/components/Icon/icons/IconRotateCw'
export * from './src/components/Icon/icons/IconRss'
export * from './src/components/Icon/icons/IconSave'
export * from './src/components/Icon/icons/IconScissors'
export * from './src/components/Icon/icons/IconSearch'
export * from './src/components/Icon/icons/IconSend'
export * from './src/components/Icon/icons/IconServer'
export * from './src/components/Icon/icons/IconSettings'
export * from './src/components/Icon/icons/IconShare2'
export * from './src/components/Icon/icons/IconShare'
export * from './src/components/Icon/icons/IconShieldOff'
export * from './src/components/Icon/icons/IconShield'
export * from './src/components/Icon/icons/IconShoppingBag'
export * from './src/components/Icon/icons/IconShoppingCart'
export * from './src/components/Icon/icons/IconShuffle'
export * from './src/components/Icon/icons/IconSidebar'
export * from './src/components/Icon/icons/IconSkipBack'
export * from './src/components/Icon/icons/IconSkipForward'
export * from './src/components/Icon/icons/IconSlack'
export * from './src/components/Icon/icons/IconSlash'
export * from './src/components/Icon/icons/IconSliders'
export * from './src/components/Icon/icons/IconSmartphone'
export * from './src/components/Icon/icons/IconSmile'
export * from './src/components/Icon/icons/IconSpeaker'
export * from './src/components/Icon/icons/IconSquare'
export * from './src/components/Icon/icons/IconStar'
export * from './src/components/Icon/icons/IconStopCircle'
export * from './src/components/Icon/icons/IconSun'
export * from './src/components/Icon/icons/IconSunrise'
export * from './src/components/Icon/icons/IconSunset'
export * from './src/components/Icon/icons/IconTablet'
export * from './src/components/Icon/icons/IconTag'
export * from './src/components/Icon/icons/IconTarget'
export * from './src/components/Icon/icons/IconTerminal'
export * from './src/components/Icon/icons/IconThermometer'
export * from './src/components/Icon/icons/IconThumbsDown'
export * from './src/components/Icon/icons/IconThumbsUp'
export * from './src/components/Icon/icons/IconToggleLeft'
export * from './src/components/Icon/icons/IconToggleRight'
export * from './src/components/Icon/icons/IconTool'
export * from './src/components/Icon/icons/IconTrash2'
export * from './src/components/Icon/icons/IconTrash'
export * from './src/components/Icon/icons/IconTrello'
export * from './src/components/Icon/icons/IconTrendingDown'
export * from './src/components/Icon/icons/IconTrendingUp'
export * from './src/components/Icon/icons/IconTriangle'
export * from './src/components/Icon/icons/IconTruck'
export * from './src/components/Icon/icons/IconTv'
export * from './src/components/Icon/icons/IconTwitch'
export * from './src/components/Icon/icons/IconTwitter'
export * from './src/components/Icon/icons/IconType'
export * from './src/components/Icon/icons/IconUmbrella'
export * from './src/components/Icon/icons/IconUnderline'
export * from './src/components/Icon/icons/IconUnlock'
export * from './src/components/Icon/icons/IconUploadCloud'
export * from './src/components/Icon/icons/IconUpload'
export * from './src/components/Icon/icons/IconUserCheck'
export * from './src/components/Icon/icons/IconUserMinus'
export * from './src/components/Icon/icons/IconUserPlus'
export * from './src/components/Icon/icons/IconUserX'
export * from './src/components/Icon/icons/IconUser'
export * from './src/components/Icon/icons/IconUsers'
export * from './src/components/Icon/icons/IconVideoOff'
export * from './src/components/Icon/icons/IconVideo'
export * from './src/components/Icon/icons/IconVoicemail'
export * from './src/components/Icon/icons/IconVolume1'
export * from './src/components/Icon/icons/IconVolume2'
export * from './src/components/Icon/icons/IconVolumeX'
export * from './src/components/Icon/icons/IconVolume'
export * from './src/components/Icon/icons/IconWatch'
export * from './src/components/Icon/icons/IconWifiOff'
export * from './src/components/Icon/icons/IconWifi'
export * from './src/components/Icon/icons/IconWind'
export * from './src/components/Icon/icons/IconXCircle'
export * from './src/components/Icon/icons/IconXOctagon'
export * from './src/components/Icon/icons/IconXSquare'
export * from './src/components/Icon/icons/IconX'
export * from './src/components/Icon/icons/IconYoutube'
export * from './src/components/Icon/icons/IconZapOff'
export * from './src/components/Icon/icons/IconZap'
export * from './src/components/Icon/icons/IconZoomIn'
export * from './src/components/Icon/icons/IconZoomOut'
+288
View File
@@ -0,0 +1,288 @@
export default {
IconActivity: 'src/components/Icon/icons/IconActivity/index.tsx',
IconAirplay: 'src/components/Icon/icons/IconAirplay/index.tsx',
IconAlertCircle: 'src/components/Icon/icons/IconAlertCircle/index.tsx',
IconAlertOctagon: 'src/components/Icon/icons/IconAlertOctagon/index.tsx',
IconAlertTriangle: 'src/components/Icon/icons/IconAlertTriangle/index.tsx',
IconAlignCenter: 'src/components/Icon/icons/IconAlignCenter/index.tsx',
IconAlignJustify: 'src/components/Icon/icons/IconAlignJustify/index.tsx',
IconAlignLeft: 'src/components/Icon/icons/IconAlignLeft/index.tsx',
IconAlignRight: 'src/components/Icon/icons/IconAlignRight/index.tsx',
IconAnchor: 'src/components/Icon/icons/IconAnchor/index.tsx',
IconAperture: 'src/components/Icon/icons/IconAperture/index.tsx',
IconArchive: 'src/components/Icon/icons/IconArchive/index.tsx',
IconArrowDownCircle: 'src/components/Icon/icons/IconArrowDownCircle/index.tsx',
IconArrowDownLeft: 'src/components/Icon/icons/IconArrowDownLeft/index.tsx',
IconArrowDownRight: 'src/components/Icon/icons/IconArrowDownRight/index.tsx',
IconArrowDown: 'src/components/Icon/icons/IconArrowDown/index.tsx',
IconArrowLeftCircle: 'src/components/Icon/icons/IconArrowLeftCircle/index.tsx',
IconArrowLeft: 'src/components/Icon/icons/IconArrowLeft/index.tsx',
IconArrowRightCircle: 'src/components/Icon/icons/IconArrowRightCircle/index.tsx',
IconArrowRight: 'src/components/Icon/icons/IconArrowRight/index.tsx',
IconArrowUpCircle: 'src/components/Icon/icons/IconArrowUpCircle/index.tsx',
IconArrowUpLeft: 'src/components/Icon/icons/IconArrowUpLeft/index.tsx',
IconArrowUpRight: 'src/components/Icon/icons/IconArrowUpRight/index.tsx',
IconArrowUp: 'src/components/Icon/icons/IconArrowUp/index.tsx',
IconAtSign: 'src/components/Icon/icons/IconAtSign/index.tsx',
IconAward: 'src/components/Icon/icons/IconAward/index.tsx',
IconBarChart2: 'src/components/Icon/icons/IconBarChart2/index.tsx',
IconBarChart: 'src/components/Icon/icons/IconBarChart/index.tsx',
IconBatteryCharging: 'src/components/Icon/icons/IconBatteryCharging/index.tsx',
IconBattery: 'src/components/Icon/icons/IconBattery/index.tsx',
IconBellOff: 'src/components/Icon/icons/IconBellOff/index.tsx',
IconBell: 'src/components/Icon/icons/IconBell/index.tsx',
IconBluetooth: 'src/components/Icon/icons/IconBluetooth/index.tsx',
IconBold: 'src/components/Icon/icons/IconBold/index.tsx',
IconBookOpen: 'src/components/Icon/icons/IconBookOpen/index.tsx',
IconBook: 'src/components/Icon/icons/IconBook/index.tsx',
IconBookmark: 'src/components/Icon/icons/IconBookmark/index.tsx',
IconBox: 'src/components/Icon/icons/IconBox/index.tsx',
IconBriefcase: 'src/components/Icon/icons/IconBriefcase/index.tsx',
IconCalendar: 'src/components/Icon/icons/IconCalendar/index.tsx',
IconCameraOff: 'src/components/Icon/icons/IconCameraOff/index.tsx',
IconCamera: 'src/components/Icon/icons/IconCamera/index.tsx',
IconCast: 'src/components/Icon/icons/IconCast/index.tsx',
IconCheckCircle: 'src/components/Icon/icons/IconCheckCircle/index.tsx',
IconCheckSquare: 'src/components/Icon/icons/IconCheckSquare/index.tsx',
IconCheck: 'src/components/Icon/icons/IconCheck/index.tsx',
IconChevronDown: 'src/components/Icon/icons/IconChevronDown/index.tsx',
IconChevronLeft: 'src/components/Icon/icons/IconChevronLeft/index.tsx',
IconChevronRight: 'src/components/Icon/icons/IconChevronRight/index.tsx',
IconChevronUp: 'src/components/Icon/icons/IconChevronUp/index.tsx',
IconChevronsDown: 'src/components/Icon/icons/IconChevronsDown/index.tsx',
IconChevronsLeft: 'src/components/Icon/icons/IconChevronsLeft/index.tsx',
IconChevronsRight: 'src/components/Icon/icons/IconChevronsRight/index.tsx',
IconChevronsUp: 'src/components/Icon/icons/IconChevronsUp/index.tsx',
IconChrome: 'src/components/Icon/icons/IconChrome/index.tsx',
IconCircle: 'src/components/Icon/icons/IconCircle/index.tsx',
IconClipboard: 'src/components/Icon/icons/IconClipboard/index.tsx',
IconClock: 'src/components/Icon/icons/IconClock/index.tsx',
IconCloudDrizzle: 'src/components/Icon/icons/IconCloudDrizzle/index.tsx',
IconCloudLightning: 'src/components/Icon/icons/IconCloudLightning/index.tsx',
IconCloudOff: 'src/components/Icon/icons/IconCloudOff/index.tsx',
IconCloudRain: 'src/components/Icon/icons/IconCloudRain/index.tsx',
IconCloudSnow: 'src/components/Icon/icons/IconCloudSnow/index.tsx',
IconCloud: 'src/components/Icon/icons/IconCloud/index.tsx',
IconCode: 'src/components/Icon/icons/IconCode/index.tsx',
IconCodepen: 'src/components/Icon/icons/IconCodepen/index.tsx',
IconCodesandbox: 'src/components/Icon/icons/IconCodesandbox/index.tsx',
IconCoffee: 'src/components/Icon/icons/IconCoffee/index.tsx',
IconColumns: 'src/components/Icon/icons/IconColumns/index.tsx',
IconCommand: 'src/components/Icon/icons/IconCommand/index.tsx',
IconCompass: 'src/components/Icon/icons/IconCompass/index.tsx',
IconCopy: 'src/components/Icon/icons/IconCopy/index.tsx',
IconCornerDownLeft: 'src/components/Icon/icons/IconCornerDownLeft/index.tsx',
IconCornerDownRight: 'src/components/Icon/icons/IconCornerDownRight/index.tsx',
IconCornerLeftDown: 'src/components/Icon/icons/IconCornerLeftDown/index.tsx',
IconCornerLeftUp: 'src/components/Icon/icons/IconCornerLeftUp/index.tsx',
IconCornerRightDown: 'src/components/Icon/icons/IconCornerRightDown/index.tsx',
IconCornerRightUp: 'src/components/Icon/icons/IconCornerRightUp/index.tsx',
IconCornerUpLeft: 'src/components/Icon/icons/IconCornerUpLeft/index.tsx',
IconCornerUpRight: 'src/components/Icon/icons/IconCornerUpRight/index.tsx',
IconCpu: 'src/components/Icon/icons/IconCpu/index.tsx',
IconCreditCard: 'src/components/Icon/icons/IconCreditCard/index.tsx',
IconCrop: 'src/components/Icon/icons/IconCrop/index.tsx',
IconCrosshair: 'src/components/Icon/icons/IconCrosshair/index.tsx',
IconDatabase: 'src/components/Icon/icons/IconDatabase/index.tsx',
IconDelete: 'src/components/Icon/icons/IconDelete/index.tsx',
IconDisc: 'src/components/Icon/icons/IconDisc/index.tsx',
IconDivideCircle: 'src/components/Icon/icons/IconDivideCircle/index.tsx',
IconDivideSquare: 'src/components/Icon/icons/IconDivideSquare/index.tsx',
IconDivide: 'src/components/Icon/icons/IconDivide/index.tsx',
IconDollarSign: 'src/components/Icon/icons/IconDollarSign/index.tsx',
IconDownloadCloud: 'src/components/Icon/icons/IconDownloadCloud/index.tsx',
IconDownload: 'src/components/Icon/icons/IconDownload/index.tsx',
IconDribbble: 'src/components/Icon/icons/IconDribbble/index.tsx',
IconDroplet: 'src/components/Icon/icons/IconDroplet/index.tsx',
IconEdit2: 'src/components/Icon/icons/IconEdit2/index.tsx',
IconEdit3: 'src/components/Icon/icons/IconEdit3/index.tsx',
IconEdit: 'src/components/Icon/icons/IconEdit/index.tsx',
IconExternalLink: 'src/components/Icon/icons/IconExternalLink/index.tsx',
IconEyeOff: 'src/components/Icon/icons/IconEyeOff/index.tsx',
IconEye: 'src/components/Icon/icons/IconEye/index.tsx',
IconFacebook: 'src/components/Icon/icons/IconFacebook/index.tsx',
IconFastForward: 'src/components/Icon/icons/IconFastForward/index.tsx',
IconFeather: 'src/components/Icon/icons/IconFeather/index.tsx',
IconFigma: 'src/components/Icon/icons/IconFigma/index.tsx',
IconFileMinus: 'src/components/Icon/icons/IconFileMinus/index.tsx',
IconFilePlus: 'src/components/Icon/icons/IconFilePlus/index.tsx',
IconFileText: 'src/components/Icon/icons/IconFileText/index.tsx',
IconFile: 'src/components/Icon/icons/IconFile/index.tsx',
IconFilm: 'src/components/Icon/icons/IconFilm/index.tsx',
IconFilter: 'src/components/Icon/icons/IconFilter/index.tsx',
IconFlag: 'src/components/Icon/icons/IconFlag/index.tsx',
IconFolderMinus: 'src/components/Icon/icons/IconFolderMinus/index.tsx',
IconFolderPlus: 'src/components/Icon/icons/IconFolderPlus/index.tsx',
IconFolder: 'src/components/Icon/icons/IconFolder/index.tsx',
IconFramer: 'src/components/Icon/icons/IconFramer/index.tsx',
IconFrown: 'src/components/Icon/icons/IconFrown/index.tsx',
IconGift: 'src/components/Icon/icons/IconGift/index.tsx',
IconGitBranch: 'src/components/Icon/icons/IconGitBranch/index.tsx',
IconGitCommit: 'src/components/Icon/icons/IconGitCommit/index.tsx',
IconGitMerge: 'src/components/Icon/icons/IconGitMerge/index.tsx',
IconGitPullRequest: 'src/components/Icon/icons/IconGitPullRequest/index.tsx',
IconGitHub: 'src/components/Icon/icons/IconGitHub/index.tsx',
IconGitlab: 'src/components/Icon/icons/IconGitlab/index.tsx',
IconGlobe: 'src/components/Icon/icons/IconGlobe/index.tsx',
IconGrid: 'src/components/Icon/icons/IconGrid/index.tsx',
IconHardDrive: 'src/components/Icon/icons/IconHardDrive/index.tsx',
IconHash: 'src/components/Icon/icons/IconHash/index.tsx',
IconHeadphones: 'src/components/Icon/icons/IconHeadphones/index.tsx',
IconHeart: 'src/components/Icon/icons/IconHeart/index.tsx',
IconHelpCircle: 'src/components/Icon/icons/IconHelpCircle/index.tsx',
IconHexagon: 'src/components/Icon/icons/IconHexagon/index.tsx',
IconHome: 'src/components/Icon/icons/IconHome/index.tsx',
IconImage: 'src/components/Icon/icons/IconImage/index.tsx',
IconInbox: 'src/components/Icon/icons/IconInbox/index.tsx',
IconInfo: 'src/components/Icon/icons/IconInfo/index.tsx',
IconInstagram: 'src/components/Icon/icons/IconInstagram/index.tsx',
IconItalic: 'src/components/Icon/icons/IconItalic/index.tsx',
IconKey: 'src/components/Icon/icons/IconKey/index.tsx',
IconLayers: 'src/components/Icon/icons/IconLayers/index.tsx',
IconLayout: 'src/components/Icon/icons/IconLayout/index.tsx',
IconLifeBuoy: 'src/components/Icon/icons/IconLifeBuoy/index.tsx',
IconLink2: 'src/components/Icon/icons/IconLink2/index.tsx',
IconLink: 'src/components/Icon/icons/IconLink/index.tsx',
IconLinkedin: 'src/components/Icon/icons/IconLinkedin/index.tsx',
IconList: 'src/components/Icon/icons/IconList/index.tsx',
IconLoader: 'src/components/Icon/icons/IconLoader/index.tsx',
IconLock: 'src/components/Icon/icons/IconLock/index.tsx',
IconLogIn: 'src/components/Icon/icons/IconLogIn/index.tsx',
IconLogOut: 'src/components/Icon/icons/IconLogOut/index.tsx',
IconMail: 'src/components/Icon/icons/IconMail/index.tsx',
IconMapPin: 'src/components/Icon/icons/IconMapPin/index.tsx',
IconMap: 'src/components/Icon/icons/IconMap/index.tsx',
IconMaximize2: 'src/components/Icon/icons/IconMaximize2/index.tsx',
IconMaximize: 'src/components/Icon/icons/IconMaximize/index.tsx',
IconMeh: 'src/components/Icon/icons/IconMeh/index.tsx',
IconMenu: 'src/components/Icon/icons/IconMenu/index.tsx',
IconMessageCircle: 'src/components/Icon/icons/IconMessageCircle/index.tsx',
IconMessageSquare: 'src/components/Icon/icons/IconMessageSquare/index.tsx',
IconMicOff: 'src/components/Icon/icons/IconMicOff/index.tsx',
IconMic: 'src/components/Icon/icons/IconMic/index.tsx',
IconMinimize2: 'src/components/Icon/icons/IconMinimize2/index.tsx',
IconMinimize: 'src/components/Icon/icons/IconMinimize/index.tsx',
IconMinusCircle: 'src/components/Icon/icons/IconMinusCircle/index.tsx',
IconMinusSquare: 'src/components/Icon/icons/IconMinusSquare/index.tsx',
IconMinus: 'src/components/Icon/icons/IconMinus/index.tsx',
IconMonitor: 'src/components/Icon/icons/IconMonitor/index.tsx',
IconMoon: 'src/components/Icon/icons/IconMoon/index.tsx',
IconMoreHorizontal: 'src/components/Icon/icons/IconMoreHorizontal/index.tsx',
IconMoreVertical: 'src/components/Icon/icons/IconMoreVertical/index.tsx',
IconMousePointer: 'src/components/Icon/icons/IconMousePointer/index.tsx',
IconMove: 'src/components/Icon/icons/IconMove/index.tsx',
IconMusic: 'src/components/Icon/icons/IconMusic/index.tsx',
IconNavigation2: 'src/components/Icon/icons/IconNavigation2/index.tsx',
IconNavigation: 'src/components/Icon/icons/IconNavigation/index.tsx',
IconOctagon: 'src/components/Icon/icons/IconOctagon/index.tsx',
IconPackage: 'src/components/Icon/icons/IconPackage/index.tsx',
IconPaperclip: 'src/components/Icon/icons/IconPaperclip/index.tsx',
IconPauseCircle: 'src/components/Icon/icons/IconPauseCircle/index.tsx',
IconPause: 'src/components/Icon/icons/IconPause/index.tsx',
IconPenTool: 'src/components/Icon/icons/IconPenTool/index.tsx',
IconPercent: 'src/components/Icon/icons/IconPercent/index.tsx',
IconPhoneCall: 'src/components/Icon/icons/IconPhoneCall/index.tsx',
IconPhoneForwarded: 'src/components/Icon/icons/IconPhoneForwarded/index.tsx',
IconPhoneIncoming: 'src/components/Icon/icons/IconPhoneIncoming/index.tsx',
IconPhoneMissed: 'src/components/Icon/icons/IconPhoneMissed/index.tsx',
IconPhoneOff: 'src/components/Icon/icons/IconPhoneOff/index.tsx',
IconPhoneOutgoing: 'src/components/Icon/icons/IconPhoneOutgoing/index.tsx',
IconPhone: 'src/components/Icon/icons/IconPhone/index.tsx',
IconPieChart: 'src/components/Icon/icons/IconPieChart/index.tsx',
IconPlayCircle: 'src/components/Icon/icons/IconPlayCircle/index.tsx',
IconPlay: 'src/components/Icon/icons/IconPlay/index.tsx',
IconPlusCircle: 'src/components/Icon/icons/IconPlusCircle/index.tsx',
IconPlusSquare: 'src/components/Icon/icons/IconPlusSquare/index.tsx',
IconPlus: 'src/components/Icon/icons/IconPlus/index.tsx',
IconPocket: 'src/components/Icon/icons/IconPocket/index.tsx',
IconPower: 'src/components/Icon/icons/IconPower/index.tsx',
IconPrinter: 'src/components/Icon/icons/IconPrinter/index.tsx',
IconRadio: 'src/components/Icon/icons/IconRadio/index.tsx',
IconRefreshCcw: 'src/components/Icon/icons/IconRefreshCcw/index.tsx',
IconRefreshCw: 'src/components/Icon/icons/IconRefreshCw/index.tsx',
IconRepeat: 'src/components/Icon/icons/IconRepeat/index.tsx',
IconRewind: 'src/components/Icon/icons/IconRewind/index.tsx',
IconRotateCcw: 'src/components/Icon/icons/IconRotateCcw/index.tsx',
IconRotateCw: 'src/components/Icon/icons/IconRotateCw/index.tsx',
IconRss: 'src/components/Icon/icons/IconRss/index.tsx',
IconSave: 'src/components/Icon/icons/IconSave/index.tsx',
IconScissors: 'src/components/Icon/icons/IconScissors/index.tsx',
IconSearch: 'src/components/Icon/icons/IconSearch/index.tsx',
IconSend: 'src/components/Icon/icons/IconSend/index.tsx',
IconServer: 'src/components/Icon/icons/IconServer/index.tsx',
IconSettings: 'src/components/Icon/icons/IconSettings/index.tsx',
IconShare2: 'src/components/Icon/icons/IconShare2/index.tsx',
IconShare: 'src/components/Icon/icons/IconShare/index.tsx',
IconShieldOff: 'src/components/Icon/icons/IconShieldOff/index.tsx',
IconShield: 'src/components/Icon/icons/IconShield/index.tsx',
IconShoppingBag: 'src/components/Icon/icons/IconShoppingBag/index.tsx',
IconShoppingCart: 'src/components/Icon/icons/IconShoppingCart/index.tsx',
IconShuffle: 'src/components/Icon/icons/IconShuffle/index.tsx',
IconSidebar: 'src/components/Icon/icons/IconSidebar/index.tsx',
IconSkipBack: 'src/components/Icon/icons/IconSkipBack/index.tsx',
IconSkipForward: 'src/components/Icon/icons/IconSkipForward/index.tsx',
IconSlack: 'src/components/Icon/icons/IconSlack/index.tsx',
IconSlash: 'src/components/Icon/icons/IconSlash/index.tsx',
IconSliders: 'src/components/Icon/icons/IconSliders/index.tsx',
IconSmartphone: 'src/components/Icon/icons/IconSmartphone/index.tsx',
IconSmile: 'src/components/Icon/icons/IconSmile/index.tsx',
IconSpeaker: 'src/components/Icon/icons/IconSpeaker/index.tsx',
IconSquare: 'src/components/Icon/icons/IconSquare/index.tsx',
IconStar: 'src/components/Icon/icons/IconStar/index.tsx',
IconStopCircle: 'src/components/Icon/icons/IconStopCircle/index.tsx',
IconSun: 'src/components/Icon/icons/IconSun/index.tsx',
IconSunrise: 'src/components/Icon/icons/IconSunrise/index.tsx',
IconSunset: 'src/components/Icon/icons/IconSunset/index.tsx',
IconTablet: 'src/components/Icon/icons/IconTablet/index.tsx',
IconTag: 'src/components/Icon/icons/IconTag/index.tsx',
IconTarget: 'src/components/Icon/icons/IconTarget/index.tsx',
IconTerminal: 'src/components/Icon/icons/IconTerminal/index.tsx',
IconThermometer: 'src/components/Icon/icons/IconThermometer/index.tsx',
IconThumbsDown: 'src/components/Icon/icons/IconThumbsDown/index.tsx',
IconThumbsUp: 'src/components/Icon/icons/IconThumbsUp/index.tsx',
IconToggleLeft: 'src/components/Icon/icons/IconToggleLeft/index.tsx',
IconToggleRight: 'src/components/Icon/icons/IconToggleRight/index.tsx',
IconTool: 'src/components/Icon/icons/IconTool/index.tsx',
IconTrash2: 'src/components/Icon/icons/IconTrash2/index.tsx',
IconTrash: 'src/components/Icon/icons/IconTrash/index.tsx',
IconTrello: 'src/components/Icon/icons/IconTrello/index.tsx',
IconTrendingDown: 'src/components/Icon/icons/IconTrendingDown/index.tsx',
IconTrendingUp: 'src/components/Icon/icons/IconTrendingUp/index.tsx',
IconTriangle: 'src/components/Icon/icons/IconTriangle/index.tsx',
IconTruck: 'src/components/Icon/icons/IconTruck/index.tsx',
IconTv: 'src/components/Icon/icons/IconTv/index.tsx',
IconTwitch: 'src/components/Icon/icons/IconTwitch/index.tsx',
IconTwitter: 'src/components/Icon/icons/IconTwitter/index.tsx',
IconType: 'src/components/Icon/icons/IconType/index.tsx',
IconUmbrella: 'src/components/Icon/icons/IconUmbrella/index.tsx',
IconUnderline: 'src/components/Icon/icons/IconUnderline/index.tsx',
IconUnlock: 'src/components/Icon/icons/IconUnlock/index.tsx',
IconUploadCloud: 'src/components/Icon/icons/IconUploadCloud/index.tsx',
IconUpload: 'src/components/Icon/icons/IconUpload/index.tsx',
IconUserCheck: 'src/components/Icon/icons/IconUserCheck/index.tsx',
IconUserMinus: 'src/components/Icon/icons/IconUserMinus/index.tsx',
IconUserPlus: 'src/components/Icon/icons/IconUserPlus/index.tsx',
IconUserX: 'src/components/Icon/icons/IconUserX/index.tsx',
IconUser: 'src/components/Icon/icons/IconUser/index.tsx',
IconUsers: 'src/components/Icon/icons/IconUsers/index.tsx',
IconVideoOff: 'src/components/Icon/icons/IconVideoOff/index.tsx',
IconVideo: 'src/components/Icon/icons/IconVideo/index.tsx',
IconVoicemail: 'src/components/Icon/icons/IconVoicemail/index.tsx',
IconVolume1: 'src/components/Icon/icons/IconVolume1/index.tsx',
IconVolume2: 'src/components/Icon/icons/IconVolume2/index.tsx',
IconVolumeX: 'src/components/Icon/icons/IconVolumeX/index.tsx',
IconVolume: 'src/components/Icon/icons/IconVolume/index.tsx',
IconWatch: 'src/components/Icon/icons/IconWatch/index.tsx',
IconWifiOff: 'src/components/Icon/icons/IconWifiOff/index.tsx',
IconWifi: 'src/components/Icon/icons/IconWifi/index.tsx',
IconWind: 'src/components/Icon/icons/IconWind/index.tsx',
IconXCircle: 'src/components/Icon/icons/IconXCircle/index.tsx',
IconXOctagon: 'src/components/Icon/icons/IconXOctagon/index.tsx',
IconXSquare: 'src/components/Icon/icons/IconXSquare/index.tsx',
IconX: 'src/components/Icon/icons/IconX/index.tsx',
IconYoutube: 'src/components/Icon/icons/IconYoutube/index.tsx',
IconZapOff: 'src/components/Icon/icons/IconZapOff/index.tsx',
IconZap: 'src/components/Icon/icons/IconZap/index.tsx',
IconZoomIn: 'src/components/Icon/icons/IconZoomIn/index.tsx',
IconZoomOut: 'src/components/Icon/icons/IconZoomOut/index.tsx'
}
File diff suppressed because it is too large. Load diff
+77
View File
@@ -0,0 +1,77 @@
const fs = require('fs')
const util = require('util')
var icons = require('./icons.json') //with path
let iconList = {}
let importList = []
//
// create icon .tsx files
//
Object.values(icons).map((icon) => {
iconList[`Icon${icon.name}`] = `src/components/Icon/icons/Icon${icon.name}/index.tsx`
importList.push(`export * as Icon${icon.name} from './Icon${icon.name}'`)
var dir = `src/components/Icon/icons/Icon${icon.name}`
fs.mkdir(dir, { recursive: true }, (err) => {
if (err) throw err
})
fs.writeFile(
`${dir}/index.tsx`,
`export { default as Icon${icon.name} } from './Icon${icon.name}'`,
function (err) {
if (err) return console.log(err)
}
)
fs.writeFile(
`${dir}/Icon${icon.name}.tsx`,
`// DO NOT EDIT
// this file is generated by /internals/populate-icons script
import * as React from 'react'
// @ts-ignore
import { ${icon.name} } from 'react-feather'
import IconBase from './../../IconBase'
function Icon${icon.name}(props: any) {
return <IconBase icon={${icon.name}} {...props} />
}
export default Icon${icon.name}
`,
function (err) {
if (err) return console.log(err)
// console.log(`${icon.name} > ${icon.path}`)
}
)
})
//
// create export file for icons
//
fs.writeFile(
`src/components/Icon/icons/index.tsx`,
`// export icons
${importList
.map((icon) => {
return `${icon}\n`
})
.join('')}`,
function (err) {
if (err) return console.log(err)
// console.log(`wrote file for rollup`)
}
)
//
// create input destinations for rollup
//
fs.writeFile(`internals/icons.js`, `export default ${util.inspect(iconList)}`, function (err) {
if (err) return console.log(err)
// console.log(`wrote file for rollup`)
})
+39
View File
@@ -0,0 +1,39 @@
{
"name": "ui",
"version": "0.0.0",
"main": "./index.tsx",
"types": "./index.tsx",
"license": "MIT",
"scripts": {
"build:icons": "node --experimental-modules internals/populate-icons.js"
},
"dependencies": {
"@headlessui/react": "^1.0.0",
"@mertasan/tailwindcss-variables": "^2.0.1",
"@radix-ui/colors": "^0.1.8",
"@radix-ui/react-accordion": "^0.1.5",
"@radix-ui/react-collapsible": "^0.1.5",
"@radix-ui/react-context-menu": "^0.1.0",
"@radix-ui/react-dialog": "^0.1.5",
"@radix-ui/react-dropdown-menu": "^0.1.4",
"@radix-ui/react-popover": "^0.1.0",
"@radix-ui/react-portal": "^0.1.3",
"@radix-ui/react-tabs": "^0.1.0",
"@tailwindcss/forms": "^0.4.0",
"@tailwindcss/typography": "^0.5.0",
"autoprefixer": "^10.4.2",
"deepmerge": "^4.2.2",
"formik": "^2.2.9",
"lodash": "^4.17.20",
"postcss": "^8.4.5",
"prop-types": "^15.7.2",
"react-feather": "^2.0.10",
"tailwindcss": "^3.0.15",
"tailwindcss-radix": "^1.6.0"
},
"devDependencies": {
"@types/react": "^17.0.37",
"@types/react-dom": "^17.0.11",
"typescript": "4.3.4"
}
}
+1
View File
@@ -0,0 +1 @@
module.exports = require('config/postcss.config')
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,72 @@
/* .sbui-accordion-container {
@apply flex flex-col rounded-md;
}
.sbui-accordion-container--bordered {
@apply border border-solid;
@apply bg-white border-gray-200;
@apply dark:bg-dark-700 dark:border-darkmode;
} */
/* .sbui-accordion-item {
@apply w-full;
} */
/* .sbui-accordion-item__button {
@apply flex justify-between w-full text-left cursor-pointer px-6 py-4 border-0 border-solid font-medium text-base rounded-t-md bg-transparent;
@apply border-gray-200 text-gray-500 hover:text-gray-600;
@apply dark:border-darkmode dark:text-dark-200 dark:hover:text-white;
font-family: inherit;
font-weight: inherit;
} */
/* .sbui-accordion-item__button .sbui-typography-text {
@apply w-full max-w-none;
} */
/* .sbui-accordion-item__button .sbui-typography-text:last-child {
@apply pl-2;
} */
/* .sbui-accordion-item__button .sbui-icon {
@apply mt-px;
} */
/* .sbui-accordion-item__button--open .sbui-icon {
@apply transform rotate-180;
} */
/*
.sbui-accordion-container--bordered
.sbui-accordion-item__button:not(:first-child) {
@apply rounded-none border-t border-gray-200 dark:border-darkmode;
} */
/* .sbui-accordion-item__panel {
@apply px-6 py-4;
} */
/* .sbui-accordion-item__panel--enter {
@apply transition-max-height ease-in-out duration-700 overflow-hidden;
}
.sbui-accordion-item__panel--enterFrom {
@apply max-h-0;
}
.sbui-accordion-item__panel--enterTo {
@apply max-h-screen;
}
.sbui-accordion-item__panel--leave {
@apply transition-max-height ease-in-out duration-300 overflow-hidden;
}
.sbui-accordion-item__panel--leaveFrom {
@apply max-h-screen;
}
.sbui-accordion-item__panel--leaveTo {
@apply max-h-0;
} */
@@ -0,0 +1,201 @@
import React from 'react'
import { Accordion } from '.'
import { Typography } from '../Typography'
import { IconArrowUp } from '../Icon/icons/IconArrowUp'
import { Badge } from '../Badge'
export default {
title: 'Displays/Accordion',
component: Accordion,
}
export const OneItem = (args: any) => (
<Accordion {...args} justified={false}>
<Accordion.Item
header={
<>
<span className="text-scale-900 group-hover:text-scale-1200">
Title of the thing
</span>
<Badge>Test badge</Badge>
</>
}
id="first"
>
<span className="text-scale-900">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
amet labore.
</span>
</Accordion.Item>
</Accordion>
)
export const MultipleItems = (args: any) => (
<Accordion {...args} openBehaviour="multiple">
<Accordion.Item
header={
<span className="text-scale-900 group-hover:text-scale-1200">
Title of the thing
</span>
}
id={'1'}
>
<span className="text-scale-900">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
amet labore.
</span>
</Accordion.Item>
<Accordion.Item
header={
<span className="text-scale-900 group-hover:text-scale-1200">
Title of the thing
</span>
}
id={'2'}
>
<span className="text-scale-900">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
amet labore.
</span>
</Accordion.Item>
<Accordion.Item
header={
<span className="text-scale-900 group-hover:text-scale-1200">
Title of the thing
</span>
}
id={'3'}
>
<span className="text-scale-900">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
amet labore.
</span>
</Accordion.Item>
<Accordion.Item
header={
<span className="text-scale-900 group-hover:text-scale-1200">
Title of the thing
</span>
}
id={'4'}
>
<span className="text-scale-900">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
amet labore.
</span>
</Accordion.Item>
</Accordion>
)
export const Bordered = (args: any) => (
<Accordion {...args}>
<Accordion.Item
header={
<span className="text-scale-900 group-hover:text-scale-1200">
Title of the thing
</span>
}
id={'1'}
>
<span className="text-scale-900">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
amet labore.
</span>
</Accordion.Item>
<Accordion.Item
header={
<span className="text-scale-900 group-hover:text-scale-1200">
Title of the thing
</span>
}
id={'2'}
>
<span className="text-scale-900">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
amet labore.
</span>
</Accordion.Item>
<Accordion.Item
header={
<span className="text-scale-900 group-hover:text-scale-1200">
Title of the thing
</span>
}
id={'3'}
>
<span className="text-scale-900">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
amet labore.
</span>
</Accordion.Item>
<Accordion.Item
header={
<span className="text-scale-900 group-hover:text-scale-1200">
Title of the thing
</span>
}
id={'4'}
>
<span className="text-scale-900">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
amet labore.
</span>
</Accordion.Item>
</Accordion>
)
Bordered.args = {
type: 'bordered',
}
export const LeftAlignedChevron = (args: any) => (
<Accordion {...args} justified={false} chevronAlign="left">
<Accordion.Item
header={
<>
<span className="text-scale-900 group-hover:text-scale-1200">
First item
</span>
<Badge>Test badge</Badge>
</>
}
id="first"
>
<span className="text-scale-900">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
amet labore.
</span>
</Accordion.Item>
<Accordion.Item
header={
<>
<span className="text-scale-900 group-hover:text-scale-1200">
Second item
</span>
</>
}
id="second"
>
<span className="text-scale-900">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur
amet labore.
</span>
</Accordion.Item>
</Accordion>
)
// export const withDefaultActive = Multiple.bind({})
// withDefaultActive.args = {
// defaultActiveId: [1],
// }
// export const withIconLeft = Multiple.bind({})
// withIconLeft.args = {
// iconPosition: 'left',
// }
// export const withCustomIcon = Multiple.bind({})
// withCustomIcon.args = {
// icon: <IconArrowUp />,
// }
@@ -0,0 +1,152 @@
import React, { createContext, useContext, useState } from 'react'
import { IconChevronUp } from '../Icon/icons/IconChevronUp'
import styleHandler from '../../lib/theme/styleHandler'
import * as RadixAccordion from '@radix-ui/react-accordion'
import { IconChevronDown } from '../Icon/icons/IconChevronDown'
import { Transition } from '@headlessui/react'
// type ContextValue = Required<
// Pick<AccordionProps, 'defaultActiveId' | 'icon' | 'iconPosition'>
// > &
// Pick<AccordionProps, 'onChange'>
type Type = 'default' | 'bordered'
type Size = 'tiny' | 'small' | 'medium' | 'large' | 'xlarge'
type Align = 'left' | 'right'
interface ContextValue {
bordered?: boolean
type: Type
justified: Boolean
chevronAlign: Align
// currentItems: string[]
}
const AccordionContext = createContext<ContextValue>({
chevronAlign: 'left',
justified: true,
type: 'default',
// currentItems: [],
})
interface AccordionProps {
children?: React.ReactNode
className?: string
defaultActiveId?: (string | number)[]
icon?: React.ReactNode
iconPosition?: Align
bordered: boolean
onChange?: (item: string | string[]) => void
openBehaviour: 'single' | 'multiple'
type: Type
size: Size
defaultValue?: string | string[] | undefined
justified: Boolean
chevronAlign: Align
}
function Accordion({
children,
className,
defaultActiveId = [],
icon = <IconChevronUp strokeWidth={2} />,
iconPosition = 'right',
onChange,
openBehaviour = 'multiple',
type = 'default',
// size, // TO DO
defaultValue = undefined,
justified = true,
chevronAlign,
}: AccordionProps) {
// const [currentItems, setCurrentItems] = useState(defaultValue || [])
const __styles = styleHandler('accordion')
let containerClasses = [__styles.variants[type].base]
if (className) {
containerClasses.push(className)
}
// let currentItems = defaultValue || []
const contextValue = {
chevronAlign,
justified,
type,
defaultValue,
}
function handleOnChange(e: string | string[]) {
if (onChange) onChange(e)
const value = e == typeof String ? e.split(' ') : e
// setCurrentItems(e)
console.log('about to change state')
// currentItems = e
// console.log('currentItems', currentItems)
}
return (
<>
{/* @ts-ignore */}
<RadixAccordion.Root
type={openBehaviour}
onValueChange={handleOnChange}
defaultValue={defaultValue}
className={containerClasses.join(' ')}
children={
<AccordionContext.Provider value={{ ...contextValue }}>
<div className={containerClasses.join(' ')}>{children}</div>
</AccordionContext.Provider>
}
></RadixAccordion.Root>
</>
)
}
interface ItemProps {
children?: React.ReactNode
className?: string
header: React.ReactNode
id: string
icon?: React.ReactNode
}
export function Item({ children, className, header, id, icon }: ItemProps) {
const __styles = styleHandler('accordion')
// const [open, setOpen] = useState(false)
const {
type,
justified,
chevronAlign,
// currentItems,
// defaultActiveId, iconPosition, onChange
} = useContext(AccordionContext)
let triggerClasses = [__styles.variants[type].trigger]
if (justified) triggerClasses.push(__styles.justified)
if (className) triggerClasses.push(className)
let chevronClasses = [__styles.chevron.base, __styles.chevron.align[chevronAlign]]
// console.log('currentItems', currentItems)
return (
<RadixAccordion.Item value={id} className={__styles.variants[type].container}>
<RadixAccordion.Trigger className={triggerClasses.join(' ')}>
{header}
<IconChevronDown aria-hidden className={chevronClasses.join(' ')} strokeWidth={2} />
</RadixAccordion.Trigger>
<RadixAccordion.Content className={__styles.variants[type].content}>
<div className={__styles.variants[type].panel}>{children}</div>
</RadixAccordion.Content>
</RadixAccordion.Item>
)
}
Accordion.Item = Item
export default Accordion
@@ -0,0 +1 @@
export { default as Accordion } from './Accordion'
@@ -0,0 +1,63 @@
/* .sbui-alert-container {
@apply rounded-md p-4;
}
.sbui-alert-container--danger {
@apply bg-red-600 bg-opacity-10 text-red-600;
}
.sbui-alert-container--warning {
@apply bg-yellow-600 bg-opacity-10 text-yellow-600;
}
.sbui-alert-container--info {
@apply bg-blue-600 bg-opacity-10 text-blue-600;
}
.sbui-alert-container--success {
@apply bg-green-600 bg-opacity-10 text-green-600;
} */
/* .sbui-alert-title {
@apply m-0 text-sm font-medium;
}
.sbui-alert-description {
@apply mt-2 text-sm;
}
.sbui-alert-description--danger {
@apply text-red-500;
}
.sbui-alert-description--warning {
@apply text-yellow-500;
}
.sbui-alert-description--info {
@apply text-blue-500;
}
.sbui-alert-description--success {
@apply text-green-500;
}
.sbui-close-button {
@apply cursor-pointer inline-flex transition ease-in-out duration-200 bg-transparent border-transparent rounded-md p-1.5 focus:outline-none;
}
.sbui-close-button--success {
@apply text-green-500 hover:bg-green-600 hover:bg-opacity-10;
}
.sbui-close-button--danger {
@apply text-red-500 hover:bg-red-600 hover:bg-opacity-10;
}
.sbui-close-button--warning {
@apply text-yellow-500 hover:bg-yellow-600 hover:bg-opacity-10;
}
.sbui-close-button--info {
@apply text-blue-500 hover:bg-blue-600 hover:bg-opacity-10;
} */
@@ -0,0 +1,137 @@
import React from 'react'
import { Alert } from './../../../'
// import ThemeProvider from '../../theme/themeContext'
export default {
title: 'Displays/Alerts',
component: Alert,
}
export const Neutral = (args: any) => (
<Alert {...args}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur amet labore.
</Alert>
)
export const Success = (args: any) => (
<Alert {...args}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur amet labore.
</Alert>
)
export const SuccessWithIcon = (args: any) => (
<Alert {...args}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur amet labore.
</Alert>
)
export const Danger = (args: any) => (
<Alert {...args}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur amet labore.
</Alert>
)
export const DangerWithIcon = (args: any) => (
<Alert {...args}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur amet labore.
</Alert>
)
export const Info = (args: any) => (
<Alert {...args}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur amet labore.
</Alert>
)
export const InfoWithIcon = (args: any) => (
<Alert {...args}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur amet labore.
</Alert>
)
export const Warning = (args: any) => (
<Alert {...args}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur amet labore.
</Alert>
)
export const WarningWithIcon = (args: any) => (
<Alert {...args}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur amet labore.
</Alert>
)
export const Closable = (args: any) => (
<Alert {...args}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur amet labore.
</Alert>
)
export const WithAction = (args: any) => (
<Alert {...args}>
Lorem ipsum dolor sit amet consectetur adipisicing elit. Consequatur amet labore.
</Alert>
)
Neutral.args = {
title: 'Success alert with icon',
withIcon: true,
}
Success.args = {
title: 'Success alert',
variant: 'success',
}
SuccessWithIcon.args = {
title: 'Success alert with icon',
variant: 'success',
withIcon: true,
}
Danger.args = {
title: 'Danger alert',
variant: 'danger',
}
DangerWithIcon.args = {
title: 'Danger alert with icon',
variant: 'danger',
withIcon: true,
}
Info.args = {
title: 'Info alert',
variant: 'info',
}
InfoWithIcon.args = {
title: 'Info alert with icon',
variant: 'info',
withIcon: true,
}
Warning.args = {
title: 'Warning alert',
variant: 'warning',
}
WarningWithIcon.args = {
title: 'Warning alert with icon',
variant: 'warning',
withIcon: true,
}
Closable.args = {
title: 'Closable alert',
closable: true,
}
WithAction.args = {
title: 'Alert with action',
variant: 'warning',
withIcon: true,
actions: <div>Hello</div>,
}
@@ -0,0 +1,67 @@
import { fireEvent, render, screen } from '@testing-library/react'
import Alert from './Alert'
const VARIANTS = ['success', 'danger', 'warning', 'info']
describe('#Alert', () => {
it('should render elements correctly', () => {
render(<Alert title="Required Title">{'Description'}</Alert>)
expect(screen.queryByText('Required Title')).toBeInTheDocument()
expect(screen.queryByText('Description')).toBeInTheDocument()
})
it('should add custom classes to container div', () => {
const { container } = render(
<Alert title="Required Title" className={'custom classes'}>
{'Description'}
</Alert>
)
expect(container.querySelector('div')).toHaveClass(
`sbui-alert-container sbui-alert-container--success custom classes`
)
})
it('should close alert when close button clicked', () => {
render(
<Alert title="Required Title" closable>
{'Description'}
</Alert>
)
const closeButton = screen.getByRole('button')
fireEvent.click(closeButton)
expect(screen.queryByText('Description')).not.toBeInTheDocument()
})
it('should render an icon when passed withIcon', () => {
const { container } = render(
<Alert title="Required Title" withIcon>
{'Description'}
</Alert>
)
expect(
container.querySelector('div.flex-shrink-0 > svg')
).toBeInTheDocument()
})
it.each(VARIANTS)(
'should have "sbui-alert-[container|description]--%s" class',
(variant) => {
const { container } = render(
<Alert title="Required Title" variant={variant}>
{'Description'}
</Alert>
)
expect(container.querySelector('div')).toHaveClass(
`sbui-alert-container sbui-alert-container--${variant}`
)
expect(screen.queryByText('Description')).toHaveClass(
`sbui-alert-description sbui-alert-description--${variant}`
)
}
)
})
@@ -0,0 +1,99 @@
import React, { useState } from 'react'
import { IconAlertTriangle } from '../Icon/icons/IconAlertTriangle'
import { IconInfo } from '../Icon/icons/IconInfo'
import { IconX } from '../Icon/icons/IconX'
// @ts-ignore
// import AlertStyles from './Alert.module.css'
import styleHandler from '../../lib/theme/styleHandler'
import { IconAlertOctagon } from '../Icon/icons/IconAlertOctagon'
import { IconCheckCircle } from '../Icon/icons/IconCheckCircle'
interface Props {
variant?: 'success' | 'danger' | 'warning' | 'info' | 'neutral'
className?: string
title: string
withIcon?: boolean
closable?: boolean
children?: React.ReactNode
icon?: React.ReactNode
actions?: React.ReactNode
}
const icons: Record<
'success' | 'danger' | 'warning' | 'info' | 'neutral',
React.ReactElement
> = {
danger: <IconAlertOctagon strokeWidth={1.5} size={18} />,
success: <IconCheckCircle strokeWidth={1.5} size={18} />,
warning: <IconAlertTriangle strokeWidth={1.5} size={18} />,
info: <IconInfo strokeWidth={1.5} size={18} />,
neutral: <></>,
}
function Alert({
variant = 'neutral',
className,
title,
withIcon,
closable,
children,
icon,
actions,
}: Props) {
let __styles = styleHandler('alert')
const [visible, setVisible] = useState(true)
let containerClasses = [__styles.base]
containerClasses.push(__styles.variant[variant].base)
if (className) containerClasses.push(className)
let descriptionClasses = [
__styles.description,
__styles.variant[variant].description,
]
let closeButtonClasses = [__styles.close]
return (
<>
{visible && (
<div className={containerClasses.join(' ')}>
{withIcon ? (
<div className={__styles.variant[variant].icon}>
{withIcon && icons[variant]}
</div>
) : null}
{icon && icon}
<div className="flex flex-1 items-center justify-between">
<div>
<h3
className={[
__styles.variant[variant].header,
__styles.header,
].join(' ')}
>
{title}
</h3>
<div className={descriptionClasses.join(' ')}>{children}</div>
</div>
{actions}
</div>
{closable && (
<button
aria-label="Close alert"
onClick={() => setVisible(false)}
className={closeButtonClasses.join(' ')}
>
<IconX strokeWidth={2} size={16} />
</button>
)}
</div>
)}
</>
)
}
export default Alert
@@ -0,0 +1 @@
export { default as Alert } from './Alert'
@@ -0,0 +1,65 @@
.sbui-avatar {
@apply rounded-full;
}
.sbui-avatar-type-rounded {
border-radius: 10%;
}
.sbui-avatar-type-square {
border-radius: 0;
}
.sbui-avatar-image {
object-fit: 'contain';
border-radius: '50%';
height: 3rem;
width: 3rem;
}
.sbui-avatar-children {
@apply flex;
@apply justify-center;
@apply items-center
}
.sbui-avatar-icon {
@apply flex;
@apply justify-center;
@apply items-center;
background-color: cadetblue;
height: 3rem;
width: 3rem;
}
.sbui-avatar-text {
@apply flex;
@apply justify-center;
@apply items-center;
background-color: cadetblue;
float: left;
height: 3rem;
width: 3rem;
}
.sbui-avatar-fallback {
@apply flex;
@apply justify-center;
@apply items-center;
background-color: cadetblue;
height: 3rem;
width: 3rem;
}
.sbui-avatar-single {
}
.sbui-avatar-multiple {
}
.sbui-image-responsive {
width: 100%;
height: auto;
}
@@ -0,0 +1,60 @@
import React from 'react'
import { IconAirplay } from '../Icon/icons/IconAirplay'
import Avatar from './Avatar'
export default {
title: 'General/Avatar',
component: Avatar,
}
export const Image = (args: any) => {
return (
<>
<Avatar {...args} />
</>
)
}
export const Text = (args: any) => {
return (
<>
<Avatar {...args} />
</>
)
}
export const Icon = (args: any) => {
return (
<>
<Avatar {...args} />
</>
)
}
export const Fallback = (args: any) => {
return (
<>
<Avatar {...args} />
</>
)
}
Image.args = {
active: true,
src: 'https://via.placeholder.com/150',
}
Text.args = {
active: true,
text: 'Shoury',
}
Icon.args = {
active: true,
Icon: IconAirplay,
}
Fallback.args = {
active: true,
}
@@ -0,0 +1,104 @@
import React from 'react'
import { Icon } from '../Icon/IconImportHandler'
import { IconUser } from '../Icon/icons/IconUser'
// @ts-ignore
import AvatarStyles from './Avatar.module.css'
interface Props {
children?: React.ReactNode
src?: string | undefined
style?: React.CSSProperties
className?: string
alt?: string
responsive?: boolean
text?: string
variant?: 'circle' | 'square'
AvatarIcon?: Icon
size: number
}
export default function Avatar({
src,
style,
className,
alt,
responsive,
text,
variant,
AvatarIcon,
size,
children,
}: Props) {
const classes = [AvatarStyles['sbui-avatar']]
classes.push(className)
let objectToRender
const imageExist = () => {
const img = new Image()
img.src = src
if (img.complete) {
return true
} else {
img.onload = () => {
return true
}
img.onerror = () => {
return false
}
}
}
if (imageExist && src) {
classes.push(AvatarStyles['sbui-avatar-image'])
objectToRender = (
<img
className={classes.join(' ')}
src={src}
alt={alt}
style={{ height: size, width: size, ...style }}
/>
)
} else if (AvatarIcon) {
classes.push(AvatarStyles['sbui-avatar-icon'])
objectToRender = (
<div
className={classes.join(' ')}
style={{ height: size, width: size, ...style }}
>
<AvatarIcon />
</div>
)
} else if (text) {
classes.push(AvatarStyles['sbui-avatar-text'])
objectToRender = (
<div
className={classes.join(' ')}
style={{ height: size, width: size, ...style }}
>
<p>{text[0]}</p>
</div>
)
} else if (children) {
classes.push(AvatarStyles['sbui-avatar-children'])
objectToRender = (
<div
className={classes.join(' ')}
style={{ height: size, width: size, ...style }}
>
{children}
</div>
)
} else {
classes.push(AvatarStyles['sbui-avatar-fallback'])
objectToRender = (
<div
className={classes.join(' ')}
style={{ height: size, width: size, ...style }}
>
<IconUser />
</div>
)
}
return <>{objectToRender}</>
}
@@ -0,0 +1 @@
export { default as Image } from './Avatar'
@@ -0,0 +1,43 @@
/* .sbui-badge {
@apply inline-flex items-center px-2.5 py-0.5 rounded-full text-xs font-medium bg-green-500 bg-opacity-10 text-brand-800;
}
.sbui-badge--large {
@apply px-3 py-0.5 rounded-full text-sm;
}
.sbui-badge-dot {
@apply -ml-0.5 mr-1.5 h-2 w-2;
}
.sbui-badge--gray {
@apply bg-gray-600 bg-opacity-10 text-gray-500;
}
.sbui-badge--red {
@apply bg-red-600 bg-opacity-10 text-red-500;
}
.sbui-badge--yellow {
@apply bg-yellow-600 bg-opacity-10 text-yellow-500;
}
.sbui-badge--green {
@apply bg-green-600 bg-opacity-10 text-green-500;
}
.sbui-badge--blue {
@apply bg-blue-600 bg-opacity-10 text-blue-500;
}
.sbui-badge--indigo {
@apply bg-indigo-600 bg-opacity-10 text-indigo-500;
}
.sbui-badge--purple {
@apply bg-purple-600 bg-opacity-10 text-purple-500;
}
.sbui-badge--pink {
@apply bg-pink-600 bg-opacity-10 text-pink-500;
} */
@@ -0,0 +1,98 @@
import { Badge } from './'
export default {
title: 'Displays/Badge',
component: Badge,
}
const colors = [
'brand',
'scale',
'tomato',
'red',
'crimson',
'pink',
'plum',
'purple',
'violet',
'indigo',
'blue',
'cyan',
'teal',
'green',
'grass',
'brown',
'orange',
'sky',
'mint',
'lime',
'yellow',
'amber',
'gold',
'bronze',
'gray',
'mauve',
'slate',
'sage',
'olive',
'sand',
]
const sizes: string[] = ['small', 'large']
export const Default = (args: any) => <Badge {...args}>Hello world</Badge>
export const withColor = (args: any) => <Badge {...args}>Hello world</Badge>
export const withDot = (args: any) => <Badge {...args}>Hello world</Badge>
export const large = (args: any) => <Badge {...args}>Hello world</Badge>
export const withDotLarge = (args: any) => <Badge {...args}>Hello world</Badge>
export const withCustomClassNames = (args: any) => (
<Badge {...args}>Hello world</Badge>
)
export const allBadges = () => (
<>
<div className="flex flex-row gap-6 mx-auto my-4">
{sizes.map((size, sizeIndex) => (
<>
<h3 className="text-scale-900">{size}</h3>
<div className="flex flex-col gap-2">
{colors.map((x, colorIndex) => (
// @ts-ignore
<Badge size={sizes[sizeIndex]} color={colors[colorIndex]}>
Supabase
</Badge>
))}
</div>
</>
))}
</div>
</>
)
Default.args = {}
withColor.args = {
color: 'red',
}
withDot.args = {
dot: true,
}
large.args = {
size: 'large',
}
withDotLarge.args = {
size: 'large',
dot: true,
}
withCustomClassNames.args = {
className: 'border-teal-100 border-2'
}
@@ -0,0 +1,55 @@
import React from 'react'
import { render, screen } from '@testing-library/react'
import Badge from './Badge'
const SIZES = ['small', 'large']
const COLORS = [
'gray',
'red',
'yellow',
'green',
'blue',
'indigo',
'purple',
'pink'
]
describe('#Badge', () => {
it('should render component correctly', () => {
const wrapper = render(<Badge>Badge</Badge>)
expect(screen.getByText('Badge')).toBeInTheDocument()
expect(() => wrapper.unmount()).not.toThrow()
})
it('should render different text', () => {
const wrapper = render(<Badge>Badge</Badge>)
expect(screen.getByText('Badge')).toBeInTheDocument()
wrapper.rerender(<Badge>徽章</Badge>)
expect(screen.getByText('徽章')).toBeInTheDocument()
})
it('should render with dot', () => {
const wrapper = render(<Badge dot={true}>Badge</Badge>)
expect(screen.getByText('Badge')).toBeInTheDocument()
expect(() => wrapper.unmount()).not.toThrow()
})
it.each(COLORS)('should have %s color', (color) => {
render(<Badge color={color}>{color}</Badge>)
expect(screen.getByText(color)).toHaveClass(
`sbui-badge sbui-badge--${color}`
)
})
it.each(SIZES)('should render with %s size', (size) => {
render(<Badge size={size}>{size}</Badge>)
expect(screen.getByText(size)).toHaveClass(
`sbui-badge ${size === 'large' ? 'sbui-badge--large' : ''}`
)
})
it('should render with Classes',()=>{
render(<Badge className='border-2'>Badge</Badge>)
expect(screen.getByText('Badge')).toHaveClass('border-2')
})
})
@@ -0,0 +1,71 @@
import styleHandler from '../../lib/theme/styleHandler'
interface Props {
color?:
| 'brand'
| 'scale'
| 'tomato'
| 'red'
| 'crimson'
| 'pink'
| 'plum'
| 'purple'
| 'violet'
| 'indigo'
| 'blue'
| 'cyan'
| 'teal'
| 'green'
| 'grass'
| 'brown'
| 'orange'
| 'sky'
| 'mint'
| 'lime'
| 'yellow'
| 'amber'
| 'gold'
| 'bronze'
| 'gray'
| 'mauve'
| 'slate'
| 'sage'
| 'olive'
| 'sand'
children: string | React.ReactNode
size?: 'large' | 'small'
dot?: boolean
className?: string
}
function Badge({ color = 'brand', children, size, dot, className }: Props) {
const __styles = styleHandler('badge')
let classes = [__styles.base]
if (color) {
classes.push(__styles.color[color])
}
if (size === 'large') {
classes.push(__styles.size.large)
}
if (className) {
classes.push(className)
}
return (
<span className={classes.join(' ')}>
{dot && (
<svg
className={`${__styles.dot} ${__styles.color[color]}`}
fill="currentColor"
viewBox="0 0 8 8"
>
<circle cx="4" cy="4" r="3" />
</svg>
)}
{children}
</span>
)
}
export default Badge
@@ -0,0 +1 @@
export { default as Badge } from './Badge'
@@ -0,0 +1,34 @@
.sbui-breadcrumb--container {
@apply flex flex-row items-center;
@apply p-0 my-0;
}
.sbui-breadcrumb--item-container {
@apply flex items-center;
}
.sbui-breadcrumb--item {
@apply text-gray-500 hover:text-gray-600;
@apply cursor-pointer;
@apply dark:text-dark-200 dark:hover:text-brand-700;
}
.sbui-breadcrumb--item__active {
@apply text-brand-700 dark:text-brand-700;
}
.sbui-breadcrumb--separator {
@apply mx-2;
@apply text-gray-500 hover:text-gray-600;
@apply dark:text-dark-200 dark:hover:text-white;
}
.sbui-breadcrumb--separator-small {
@apply mx-2;
}
.sbui-breadcrumb--separator-medium {
@apply mx-4;
}
.sbui-breadcrumb--separator-large {
@apply mx-6;
}
@@ -0,0 +1,18 @@
import React from 'react'
import { Breadcrumb } from './../../../'
export default {
title: 'Navigation/Breadcrumb',
component: Breadcrumb,
}
export const Default = ({ children, ...args }: any) => <Breadcrumb {...args}>{children}</Breadcrumb>
Default.args = {
children: [
<Breadcrumb.Item>Brothers</Breadcrumb.Item>,
<Breadcrumb.Item>Grimm</Breadcrumb.Item>,
<Breadcrumb.Item active>Hansel</Breadcrumb.Item>,
<Breadcrumb.Item>Gretel</Breadcrumb.Item>,
],
}
@@ -0,0 +1,25 @@
import React from from 'react';
import { render, screen } from '@testing-library/react';
import Breadcrumb from './Breadcrumb';
describe('#Breadcrumb', () => {
it('should render breadcrumb correctly', async () => {
render(
<Breadcrumb data-testid="breadcrumb">
<p> Item 1 </p>
<p> Item 2 </p>
</Breadcrumb>
)
expect(screen.queryByTestId('breadcrumb')).toBeInTheDocument()
})
it('should have "breadcrumb--item" class', () => {
render(
<Breadcrumb data-testid="breadcrumb">
<p> Item 1 </p>
<p> Item 2 </p>
</Breadcrumb>
)
expect(screen.queryByTestId('breadcrumb')).toHaveClass('.sbui-breadcrumb--item ')
})
})
@@ -0,0 +1,62 @@
import { IconChevronRight } from '../Icon/icons/IconChevronRight'
// @ts-ignore
import BreadcrumbStyle from './Breadcrumb.module.css'
interface Props {
children?: [React.ReactNode]
className?: string
style?: React.CSSProperties
spacing?: 'small' | 'medium' | 'large'
}
const Breadcrumb = ({ className, style, children, spacing = 'small' }: Props) => {
let classes = [BreadcrumbStyle['sbui-breadcrumb--container']]
let seperatorClasses = [BreadcrumbStyle['sbui-breadcrumb--separator']]
if (className) {
classes.push(className)
}
if (spacing) {
seperatorClasses.push(`sbui-breadcrumb--separator-${spacing}`)
}
return (
<ol className={classes.join(' ')} style={style} aria-label="Breadcrumb">
{children!.map((child: React.ReactNode, idx: number) => (
<li className={BreadcrumbStyle['sbui-breadcrumb--item-container']}>
{child}
{idx + 1 < children!.length && (
<IconChevronRight size={12} className={seperatorClasses.join(' ')} aria-hidden="true" />
)}
</li>
))}
</ol>
)
}
interface ItemProps {
children: React.ReactNode
active?: boolean
onClick?: any
style?: React.CSSProperties
}
export function Item({ children, active, onClick, style }: ItemProps) {
let classes = [BreadcrumbStyle['sbui-breadcrumb--item']]
if (active) classes.push(BreadcrumbStyle['sbui-breadcrumb--item__active'])
return (
<span
className={classes.join(' ')}
onClick={onClick}
style={style}
aria-current={active ? 'page' : false}
>
{children}
</span>
)
}
Breadcrumb.Item = Item
export default Breadcrumb
@@ -0,0 +1 @@
export { default as Breadcrumb } from './Breadcrumb'
@@ -0,0 +1,156 @@
/* .sbui-btn-container {
@apply inline-flex font-medium;
} */
/* .sbui-btn {
@apply relative cursor-pointer inline-flex items-center space-x-2 text-center border border-solid border-transparent transition ease-out duration-200 outline-none;
@apply rounded;
font-family: inherit;
font-weight: inherit;
} */
/* .sbui-btn:focus {
@apply outline-none;
} */
/* .sbui-btn-container--shadow {
box-shadow: 0 2px 0 rgba(0, 0, 0, 0.045);
} */
/* .sbui-btn--w-full {
@apply w-full flex items-center justify-center;
} */
/* .sbui-btn:disabled {
@apply opacity-75 cursor-not-allowed;
pointer-events: none;
} */
/*
Button sizes
*/
.sbui-btn--tiny {
@apply px-2.5 py-1.5 text-xs;
}
.sbui-btn--small {
@apply px-3 py-2 text-sm leading-4;
}
.sbui-btn--medium {
@apply px-4 py-2 text-sm;
}
.sbui-btn--large {
@apply px-4 py-2 text-base;
}
.sbui-btn--xlarge {
@apply px-6 py-3 text-base;
}
/*
Button varients
*/
/* .sbui-btn-primary {
@apply text-white bg-brand-800 hover:bg-brand-600;
@apply dark:hover:bg-brand-900;
} */
.dark .sbui-btn-primary {
text-shadow: 0px 0px 4px rgba(38 111 78 / 50%);
}
/* .sbui-btn-default {
@apply text-gray-500 bg-white border-gray-200 hover:text-gray-600;
@apply hover:bg-white hover:border-gray-200;
@apply dark:border-gray-600 dark:bg-gray-600 dark:text-dark-200;
@apply dark:hover:bg-gray-700;
} */
.dark .sbui-btn-default {
text-shadow: 0px 0px 4px rgba(31 31 31 / 50%);
}
/*
.sbui-btn-secondary {
@apply text-gray-600 bg-gray-200;
@apply hover:text-gray-700 hover:bg-gray-300;
@apply dark:text-gray-300 dark:bg-gray-500;
@apply dark:hover:bg-gray-600;
} */
.dark .sbui-btn-secondary {
text-shadow: 0px 0px 4px rgba(42 42 42 / 50%);
}
/* .sbui-btn-outline {
@apply border text-gray-500 bg-transparent border-gray-200 border-solid hover:bg-white hover:text-gray-600 hover:border-gray-600 dark:text-white dark:border-dark-400 dark:hover:text-dark-600 dark:hover:border-white;
} */
/* .sbui-btn-dashed {
@apply border text-gray-500 bg-transparent border-gray-200 border-dashed hover:text-gray-600 hover:border-gray-600;
@apply dark:text-white dark:border-dark-400 dark:hover:text-white dark:hover:border-white;
} */
/* .sbui-btn-link {
@apply bg-transparent text-brand-800 border-none hover:bg-brand-900 hover:bg-opacity-25;
box-shadow: none;
} */
/* .sbui-btn-text {
@apply text-gray-400 bg-transparent border-none hover:bg-gray-200 hover:bg-opacity-25;
@apply dark:text-dark-300 dark:hover:bg-dark-600;
box-shadow: none;
} */
/* .sbui-btn--danger {
@apply border-red-500 text-red-500;
@apply dark:border-red-500 dark:text-red-500;
} */
/* .dark .sbui-btn--danger {
text-shadow: 0px 0px 4px rgba(229, 62, 62 / 50%);
}
.sbui-btn-primary.sbui-btn--danger {
@apply bg-red-500 text-white;
@apply hover:bg-red-600 hover:border-red-600;
}
.sbui-btn-default.sbui-btn--danger,
.sbui-btn-secondary.sbui-btn--danger,
.sbui-btn-outline.sbui-btn--danger,
.sbui-btn-dashed.sbui-btn--danger,
.sbui-btn-link.sbui-btn--danger,
.sbui-btn-text.sbui-btn--danger {
@apply hover:bg-red-600 hover:text-white hover:border-red-600;
} */
/* {
@apply hover:bg-red-600 hover:text-white hover:border-red-600;
} */
/*
Animation for icon
*/
/* .sbui-btn--anim--spin {
@apply animate-spin;
} */
/* @keyframes spin {
from {
transform: rotate(0deg);
}
to {
transform: rotate(360deg);
}
} */
/* .sbui-btn-loader--center {
position: absolute;
top: 50%;
left: 50%;
right: 50%;
bottom: 50%;
transform: translate(-50%, -50%);
margin: auto 0;
width: inherit;
height: inherit;
}
.sbui-btn--text-fade-out span {
@apply opacity-0;
} */
@@ -0,0 +1,260 @@
// import React, { useRef, useState } from 'react'
// import defaultTheme from '../../theme/defaultTheme'
// import { ThemeProvider } from './../ThemeProvider'
// import customThemeExample from '../../lib/theme/customThemeExample'
import { useRef, useState } from 'react'
import { Button, IconPackage, IconChevronRight } from './../../index'
export default {
title: 'General/Button',
component: Button,
}
export const Default = (args: any) => <Button {...args}>Button text</Button>
export const withStyles = (args: any) => <Button {...args}>Button text</Button>
export const withIcon = (args: any) => <Button {...args}>Button text</Button>
export const withIconRight = (args: any) => (
<Button {...args}>Button text</Button>
)
export const withBlock = (args: any) => <Button {...args}>Button text</Button>
export const withOnlyIcon = (args: any) => <Button {...args} />
export const withOnlyLoading = (args: any) => <Button {...args} />
export const withLoadingCentered = (args: any) => (
<Button {...args}>Loading icon is centered</Button>
)
export const withRef = () => {
const buttonRef = useRef(null)
const [msg, setMsg] = useState('Click button to console.log Ref')
function onClick() {
const message = `button:${buttonRef?.current} `
setMsg(message)
// console.log(message)
}
return (
<>
<Button ref={buttonRef} onClick={onClick}>
Button with forwardRef
</Button>
<p style={{ color: '#666666' }}>{msg}</p>
</>
)
}
export const allButtons = (args: any) => (
<>
<div className="flex flex-col space-y-4">
<div className="flex space-x-4">
<Button {...args} size="tiny">
Button text
</Button>
<Button {...args} size="tiny" type="default">
Button text
</Button>
<Button {...args} size="tiny" type="secondary">
Button text
</Button>
<Button {...args} size="tiny" type="alternative">
Button text
</Button>
<Button {...args} size="tiny" type="link">
Button text
</Button>
<Button {...args} size="tiny" type="text">
Button text
</Button>
<Button {...args} size="tiny" type="dashed">
Button text
</Button>
<Button {...args} size="tiny" type="outline">
Button text
</Button>
<Button {...args} size="tiny" type="danger">
Button text
</Button>
<Button {...args} size="tiny" type="warning">
Button text
</Button>
</div>
<div className="flex space-x-4">
<Button {...args} size="small">
Button text
</Button>
<Button {...args} size="small" type="default">
Button text
</Button>
<Button {...args} size="small" type="secondary">
Button text
</Button>
<Button {...args} size="small" type="alternative">
Button text
</Button>
<Button {...args} size="small" type="link">
Button text
</Button>
<Button {...args} size="small" type="text">
Button text
</Button>
<Button {...args} size="small" type="dashed">
Button text
</Button>
<Button {...args} size="small" type="outline">
Button text
</Button>
<Button {...args} size="small" type="danger">
Button text
</Button>
<Button {...args} size="small" type="warning">
Button text
</Button>
</div>
<div className="flex space-x-4">
<Button {...args} size="medium">
Button text
</Button>
<Button {...args} size="medium" type="default">
Button text
</Button>
<Button {...args} size="medium" type="secondary">
Button text
</Button>
<Button {...args} size="medium" type="alternative">
Button text
</Button>
<Button {...args} size="medium" type="link">
Button text
</Button>
<Button {...args} size="medium" type="text">
Button text
</Button>
<Button {...args} size="medium" type="dashed">
Button text
</Button>
<Button {...args} size="medium" type="outline">
Button text
</Button>
<Button {...args} size="medium" type="danger">
Button text
</Button>
<Button {...args} size="medium" type="warning">
Button text
</Button>
</div>
<div className="flex space-x-4">
<Button {...args} size="large">
Button text
</Button>
<Button {...args} size="large" type="default">
Button text
</Button>
<Button {...args} size="large" type="secondary">
Button text
</Button>
<Button {...args} size="large" type="alternative">
Button text
</Button>
<Button {...args} size="large" type="link">
Button text
</Button>
<Button {...args} size="large" type="text">
Button text
</Button>
<Button {...args} size="large" type="dashed">
Button text
</Button>
<Button {...args} size="large" type="outline">
Button text
</Button>
<Button {...args} size="large" type="danger">
Button text
</Button>
<Button {...args} size="large" type="warning">
Button text
</Button>
</div>
<div className="flex space-x-4">
<Button {...args} size="xlarge">
Button text
</Button>
<Button {...args} size="xlarge" type="default">
Button text
</Button>
<Button {...args} size="xlarge" type="secondary">
Button text
</Button>
<Button {...args} size="xlarge" type="alternative">
Button text
</Button>
<Button {...args} size="xlarge" type="link">
Button text
</Button>
<Button {...args} size="xlarge" type="text">
Button text
</Button>
<Button {...args} size="xlarge" type="dashed">
Button text
</Button>
<Button {...args} size="xlarge" type="outline">
Button text
</Button>
<Button {...args} size="xlarge" type="danger">
Button text
</Button>
<Button {...args} size="xlarge" type="warning">
Button text
</Button>
</div>
</div>
</>
)
export const withCustomTag = (args: any) => (
<Button {...args}>Button text</Button>
)
const icon = <IconPackage />
withIcon.args = {
type: 'primary',
icon: icon,
}
withIconRight.args = {
type: 'primary',
iconRight: <IconChevronRight strokeWidth={2} />,
}
withStyles.args = {
type: 'primary',
style: { backgroundColor: 'red', color: 'yellow' },
}
withBlock.args = {
type: 'primary',
block: true,
}
withOnlyIcon.args = {
icon: icon,
}
withOnlyLoading.args = {
loading: true,
}
withLoadingCentered.args = {
loading: true,
loadingCentered: true,
}
allButtons.args = {
loading: false,
danger: false,
}
withCustomTag.args = {
as: 'span',
}
@@ -0,0 +1,87 @@
import React from 'react'
import { render, screen, fireEvent } from '@testing-library/react'
import Button from './Button'
const SIZES = ['tiny', 'small', 'medium', 'large', 'xlarge']
const TYPES = [
'primary',
'default',
'secondary',
'outline',
'dashed',
'link',
'text',
]
describe('#Button', () => {
it('should render button correctly', () => {
const wrapper = render(<Button>Button</Button>)
expect(wrapper.getByText('Button')).toBeInTheDocument()
expect(() => wrapper.unmount()).not.toThrow()
})
it('should render different text', () => {
const wrapper = render(<Button>Button</Button>)
expect(screen.getByText('Button')).toBeInTheDocument()
wrapper.rerender(<Button>按钮</Button>)
expect(screen.getByText('按钮')).toBeInTheDocument()
})
it('should ignore events when disabled', () => {
const WrapperButton = () => {
const [state, setState] = React.useState('state1')
return (
<Button disabled onClick={() => setState('state2')}>
{state}
</Button>
)
}
render(<WrapperButton />)
expect(screen.getByText('state1')).toBeInTheDocument()
fireEvent.click(screen.getByText('state1'))
expect(screen.getByText('state1')).toBeInTheDocument()
expect(screen.queryByText('state2')).not.toBeInTheDocument()
})
it('should ignore events when loading', () => {
const WrapperButton = () => {
const [state, setState] = React.useState('state1')
return (
<Button loading onClick={() => setState('state2')}>
{state}
</Button>
)
}
render(<WrapperButton />)
fireEvent.click(screen.getByText('state1'))
expect(screen.queryByText('state2')).not.toBeInTheDocument()
})
it('should have "w-full" class', async () => {
render(<Button block>Button Block</Button>)
expect(screen.queryByRole('button')).toHaveClass(
'sbui-btn sbui-btn-primary sbui-btn--w-full sbui-btn-container--shadow sbui-btn--tiny'
)
})
it.each(TYPES)('should have "btn--%s" class', (type) => {
render(<Button type={type}>Button Variant</Button>)
if (type !== 'text' && type !== 'link') {
expect(screen.queryByRole('button')).toHaveClass(
`sbui-btn sbui-btn-${type} sbui-btn-container--shadow sbui-btn--tiny`
)
} else {
expect(screen.queryByRole('button')).toHaveClass(
`sbui-btn sbui-btn-${type} sbui-btn--tiny`
)
}
})
it.each(SIZES)('should have "btn--%s" class', (size) => {
render(<Button size={size}>Button</Button>)
expect(screen.queryByRole('button')).toHaveClass(
`sbui-btn sbui-btn-primary sbui-btn-container--shadow sbui-btn--${size}`
)
})
})
@@ -0,0 +1,171 @@
import React, { forwardRef, useRef, useImperativeHandle } from 'react'
import { IconContext } from './../Icon/IconContext'
import { IconLoader } from './../Icon/icons/IconLoader'
import styleHandler from '../../lib/theme/styleHandler'
export interface ButtonProps extends React.HTMLAttributes<HTMLButtonElement> {
block?: boolean
className?: string
children?: React.ReactNode
disabled?: boolean
onClick?: React.MouseEventHandler<HTMLButtonElement>
icon?: React.ReactNode
iconRight?: React.ReactNode
loading?: boolean
loadingCentered?: boolean
shadow?: boolean
size?: 'tiny' | 'small' | 'medium' | 'large' | 'xlarge'
style?: React.CSSProperties
type?:
| 'primary'
| 'default'
| 'secondary'
| 'alternative'
| 'outline'
| 'dashed'
| 'link'
| 'text'
| 'danger'
| 'warning'
danger?: boolean
htmlType?: 'button' | 'submit' | 'reset'
ref?: any
ariaSelected?: boolean
ariaControls?: string
tabIndex?: 0 | -1
role?: string
textAlign?: 'left' | 'center' | 'right'
as?: keyof JSX.IntrinsicElements
form?: string
}
interface CustomButtonProps extends React.HTMLAttributes<HTMLButtonElement> {}
interface RefHandle {
// container: () => HTMLElement | null
button: () => HTMLButtonElement | null
}
export const Button = forwardRef<RefHandle, ButtonProps>(
(
{
block,
className,
children,
danger,
disabled = false,
onClick,
icon,
iconRight,
loading = false,
loadingCentered = false,
shadow = true,
size = 'tiny',
style,
type = 'primary',
htmlType = 'button',
ariaSelected,
ariaControls,
tabIndex,
role,
as,
textAlign = 'center',
...props
}: ButtonProps,
ref
) => {
// button ref
// const containerRef = useRef<HTMLElement>(null)
const buttonRef = useRef<HTMLButtonElement>(null)
useImperativeHandle(ref, () => ({
button: () => {
return buttonRef.current
},
}))
let __styles = styleHandler('button')
// styles
const showIcon = loading || icon
let classes = [__styles.base]
let containerClasses = [__styles.container]
classes.push(__styles.type[type])
if (block) {
containerClasses.push(__styles.block)
classes.push(__styles.block)
}
if (shadow && type !== 'link' && type !== 'text') {
classes.push(__styles.shadow)
}
if (size) {
classes.push(__styles.size[size])
}
if (className) {
classes.push(className)
}
if (disabled) {
classes.push(__styles.disabled)
}
const iconLoaderClasses = [__styles.loading]
// custom button tag
const CustomButton = ({ ...props }) => {
const Tag = as as keyof JSX.IntrinsicElements
return <Tag {...props} />
}
const buttonContent = (
<>
{showIcon &&
(loading ? (
<IconLoader size={size} className={iconLoaderClasses.join(' ')} />
) : icon ? (
<IconContext.Provider value={{ contextSize: size }}>{icon}</IconContext.Provider>
) : null)}
{children && <span className={__styles.label}>{children}</span>}
{iconRight && !loading && (
<IconContext.Provider value={{ contextSize: size }}>{iconRight}</IconContext.Provider>
)}
</>
)
if (as) {
return (
<CustomButton {...props} className={classes.join(' ')} onClick={onClick} style={style}>
{buttonContent}
</CustomButton>
)
} else {
return (
// <span ref={containerRef} className={containerClasses.join(' ')}>
<button
{...props}
ref={buttonRef}
className={classes.join(' ')}
disabled={loading || (disabled && true)}
onClick={onClick}
style={style}
type={htmlType}
aria-selected={ariaSelected}
aria-controls={ariaControls}
tabIndex={tabIndex}
role={role}
form={props.form}
>
{buttonContent}
</button>
// </span>
)
}
}
)
@@ -0,0 +1 @@
export * from './Button'
@@ -0,0 +1,27 @@
.sbui-card {
@apply flex flex-col bg-white dark:bg-dark-700 rounded-md shadow-lg overflow-hidden relative;
border: 1px solid #e0e0e0;
}
.sbui-card--hoverable {
@apply transition transform hover:-translate-y-1 hover:shadow-2xl;
}
.dark .sbui-card {
border: 1px solid #2a2a2a;
}
.sbui-card-head {
@apply px-8 py-6 flex justify-between;
border-bottom: 1px solid #e0e0e0;
}
.dark .sbui-card-head {
border-bottom: 1px solid #2a2a2a;
}
.sbui-card-content {
@apply p-8;
}
@@ -0,0 +1,61 @@
import React from 'react'
import Typography from '../Typography'
// import { AutoForm } from 'uniforms'
import { Card } from './'
export default {
title: 'Displays/Card',
component: Card,
}
export const Default = (args: any) => (
<Card {...args}>
<Typography.Title level={5}>Card content</Typography.Title>
<Typography.Title level={5}>Card content</Typography.Title>
<Typography.Title level={5}>Card content</Typography.Title>
</Card>
)
export const withCover = (args: any) => (
<Card {...args}>
<Typography.Text type="secondary">Sub title here</Typography.Text>
<Typography.Title level={3}>To Do List with Vue.JS</Typography.Title>
</Card>
)
export const withMeta = (args: any) => (
<Card {...args}>
<Card.Meta title={'To Do List with Vue.JS'} description={'To Do List with Vue.JS'}/>
</Card>
)
export const withHover = (args: any) => (
<Card {...args}>
<Card.Meta title={'To Do List with Vue.JS'} description={'To Do List with Vue.JS'}/>
</Card>
)
Default.args = {
title: 'I am a title',
titleExtra: <Typography.Link>Learn more</Typography.Link>,
}
withCover.args = {
cover: (
<img
className="h-64 w-full object-cover"
src={'https://supabase.io/new/images/case-study-monitoro.jpg'}
alt={'title'}
/>
),
}
withMeta.args = {
title: 'title is here'
}
withHover.args = {
title: 'This card can hover',
hoverable: true
}
+69
View File
@@ -0,0 +1,69 @@
import React from 'react'
import Typography from '../Typography'
// @ts-ignore
import CardStyles from './Card.module.css'
import styleHandler from '../../lib/theme/styleHandler'
interface CardProps {
children?: React.ReactNode
className?: string
cover?: React.ReactNode
description?: string
hoverable?: boolean
style?: React.CSSProperties
title?: string
titleExtra?: React.ReactNode
}
function Card({
children,
className,
cover,
hoverable,
style,
title,
titleExtra,
}: CardProps) {
let __styles = styleHandler('card')
let classes = [__styles.base]
if (hoverable) classes.push(__styles.hoverable)
if (className) classes.push(className)
return (
<div className={classes.join(' ')} style={style}>
{title && (
<div className={__styles.head}>
<Typography.Text style={{ margin: 0 }}>{title}</Typography.Text>
<Typography.Link style={{ margin: 0 }}>{titleExtra}</Typography.Link>
</div>
)}
{cover}
<div className={__styles.content}>{children}</div>
</div>
)
}
interface MetaProps {
title?: string
description?: string
style?: React.CSSProperties
className?: string
}
function Meta({ title, description, style, className }: MetaProps) {
return (
<div style={style} className={className}>
<Typography.Title style={{ margin: '0' }} level={5}>
{title}
</Typography.Title>
<div>
<Typography.Text type="secondary">{description}</Typography.Text>
</div>
</div>
)
}
Card.Meta = Meta
export default Card
@@ -0,0 +1 @@
export { default as Card } from './Card'
@@ -0,0 +1,127 @@
/* clear native styling */
/* .sbui-checkbox[type='checkbox'] {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
padding: 0;
-webkit-print-color-adjust: exact;
color-adjust: exact;
display: inline-block;
vertical-align: middle;
background-origin: border-box;
-webkit-user-select: none;
-moz-user-select: none;
-ms-user-select: none;
user-select: none;
flex-shrink: 0;
height: 1rem;
width: 1rem;
color: #2563eb;
background-color: #fff;
border-color: #6b7280;
border-width: 1px;
} */
/* .sbui-checkbox[type='checkbox']:checked {
background-image: url("data:image/svg+xml,%3csvg viewBox='0 0 16 16' fill='white' xmlns='http://www.w3.org/2000/svg'%3e%3cpath d='M12.207 4.793a1 1 0 010 1.414l-5 5a1 1 0 01-1.414 0l-2-2a1 1 0 011.414-1.414L6.5 9.086l4.293-4.293a1 1 0 011.414 0z'/%3e%3c/svg%3e");
}
.sbui-checkbox[type='checkbox']:checked {
@apply dark:bg-brand-700;
@apply bg-brand-700;
border-color: transparent;
background-size: 100% 100%;
background-position: center;
background-repeat: no-repeat;
} */
/* .sbui-checkbox {
@apply border border-solid rounded;
@apply text-brand-700 border-gray-300 transition-all;
@apply hover:border-brand-500 focus:ring-brand-500 focus:outline-none;
@apply dark:bg-transparent dark:border-dark-400 dark:text-white;
@apply dark:hover:border-brand-500;
margin-top: 2px;
} */
/*
.sbui-checkbox-container {
@apply flex cursor-pointer;
} */
/* .sbui-checkbox__label-container {
@apply leading-none;
} */
/* .sbui-checkbox__label-container__label {
@apply text-gray-700 dark:text-white cursor-pointer mt-0;
}
.sbui-checkbox__label-container__label__span {
@apply font-medium;
}
.sbui-checkbox__label-container__label__span .sbui-checkbox__label-text-before,
.sbui-checkbox__label-container__label__span .sbui-checkbox__label-text-after {
@apply text-gray-400 dark:text-gray-300;
}
.sbui-checkbox__label-container__label__p {
@apply mt-0 text-gray-400 dark:text-gray-300;
} */
/*
Label sizes
*/
/* .sbui-checkbox-container--tiny .sbui-checkbox__label-container__label,
.sbui-checkbox-container--tiny .sbui-checkbox__label-container__label__span,
.sbui-checkbox-container--tiny .sbui-checkbox__label-container__label__p {
@apply text-xs;
}
.sbui-checkbox-container--small .sbui-checkbox__label-container__label,
.sbui-checkbox-container--small .sbui-checkbox__label-container__label__span,
.sbui-checkbox-container--small .sbui-checkbox__label-container__label__p {
@apply text-sm;
}
.sbui-checkbox-container--medium .sbui-checkbox__label-container__label,
.sbui-checkbox-container--medium .sbui-checkbox__label-container__label__span,
.sbui-checkbox-container--medium .sbui-checkbox__label-container__label__p {
@apply text-sm;
}
.sbui-checkbox-container--large .sbui-checkbox__label-container__label,
.sbui-checkbox-container--large .sbui-checkbox__label-container__label__span,
.sbui-checkbox-container--large .sbui-checkbox__label-container__label__p {
@apply text-base;
}
.sbui-checkbox-container--xlarge .sbui-checkbox__label-container__label,
.sbui-checkbox-container--xlarge .sbui-checkbox__label-container__label__span,
.sbui-checkbox-container--xlarge .sbui-checkbox__label-container__label__p {
@apply text-base;
} */
/*
Checkbox sizes
*/
/* .sbui-checkbox-container--tiny .sbui-checkbox {
@apply h-3 w-3 mt-1 mr-3;
}
.sbui-checkbox-container--small .sbui-checkbox {
@apply h-3.5 w-3.5 mt-0.5 mr-3.5;
}
.sbui-checkbox-container--medium .sbui-checkbox {
@apply h-4 w-4 mt-0.5 mr-3.5;
}
.sbui-checkbox-container--large .sbui-checkbox {
@apply h-5 w-5 mt-0.5 mr-4;
}
.sbui-checkbox-container--xlarge .sbui-checkbox {
@apply h-5 w-5 mt-0.5 mr-4;
} */
@@ -0,0 +1,133 @@
import React from 'react'
import { Checkbox } from '.'
export default {
title: 'Data Input/Checkbox',
component: Checkbox,
}
export const Default = (args: any) => <Checkbox {...args} />
export const withGroup = (args: any) => (
<Checkbox.Group {...args}>
<Checkbox
id="checkbox1"
name="checkbox1"
label="JavaScript"
description="JavaScript, often abbreviated as JS, is a programming language that conforms to the ECMAScript specification."
/>
<Checkbox
id="checkbox2"
name="checkbox2"
label="Typescript"
description="TypeScript is a programming language developed and maintained by Microsoft. It is a strict syntactical superset of JavaScript and adds optional static typing to the language. "
/>
<Checkbox
id="checkbox3"
name="checkbox3"
label="React"
description="React is an open-source, front end, JavaScript library for building user interfaces or UI components. It is maintained by Facebook and a community of individual developers and companies."
/>
</Checkbox.Group>
)
export const withGroupHorizontal = (args: any) => (
<Checkbox.Group {...args}>
<Checkbox
id="checkbox1"
name="checkbox1"
label="JavaScript"
description="JavaScript, often abbreviated as JS, is a programming language that conforms to the ECMAScript specification."
/>
<Checkbox
id="checkbox2"
name="checkbox2"
label="Typescript"
description="TypeScript is a programming language developed and maintained by Microsoft. It is a strict syntactical superset of JavaScript and adds optional static typing to the language. "
/>
<Checkbox
id="checkbox3"
name="checkbox3"
label="React"
description="React is an open-source, front end, JavaScript library for building user interfaces or UI components. It is maintained by Facebook and a community of individual developers and companies."
/>
</Checkbox.Group>
)
export const size = (args: any) => (
<Checkbox.Group {...args}>
<Checkbox
id="checkbox1"
name="checkbox1"
label="JavaScript"
description="JavaScript, often abbreviated as JS, is a programming language that conforms to the ECMAScript specification."
/>
<Checkbox
id="checkbox2"
name="checkbox2"
label="Typescript"
description="TypeScript is a programming language developed and maintained by Microsoft. It is a strict syntactical superset of JavaScript and adds optional static typing to the language. "
/>
<Checkbox
id="checkbox3"
name="checkbox3"
label="React"
description="React is an open-source, front end, JavaScript library for building user interfaces or UI components. It is maintained by Facebook and a community of individual developers and companies."
/>
</Checkbox.Group>
)
export const withBeforeAndAfterLabels = (args: any) => (
<Checkbox.Group {...args} />
)
Default.args = {
label: 'This is the label',
description: 'This is the description',
}
withGroup.args = {
id: 'checkobox-q',
label: 'This is the label',
description: 'This is the description',
disabled: false,
size: 'medium',
className: 'font-sans',
layout: 'vertical',
}
withGroupHorizontal.args = {
id: 'checkobox-q',
label: 'This is the label',
description: 'This is the description',
disabled: false,
className: 'font-sans',
layout: 'horizontal',
}
size.args = {
id: 'checkobox-q',
label: 'Control the size of the checkboxes',
description:
'You can add a size just the Group component and it will affect the children',
disabled: false,
className: 'font-sans',
layout: 'horizontal',
size: 'tiny',
}
withBeforeAndAfterLabels.args = {
label: 'Label',
beforeLabel: 'Before : ',
afterLabel: ' : After',
options: [
{
label: 'Label',
beforeLabel: 'Before : ',
afterLabel: ' : After',
description: 'Description',
},
],
className: 'font-sans',
}
@@ -0,0 +1,15 @@
import React from 'react'
import { render, screen } from '@testing-library/react'
import Checkbox from './Checkbox'
describe('#Checkbox', () => {
it('should render checkbox correctly', () => {
render(<Checkbox data-testid="form-checkbox" label="labelIsRequired" />)
expect(screen.queryByTestId('form-checkbox')).toBeInTheDocument()
})
it('should show label', () => {
render(<Checkbox data-testid="form-checkbox" label="JavaScript" />)
expect(screen.queryByText('JavaScript')).toBeInTheDocument()
})
})
@@ -0,0 +1,216 @@
import React, { useEffect, useState } from 'react'
import { FormLayout } from '../../lib/Layout/FormLayout'
import { CheckboxContext } from './CheckboxContext'
// @ts-ignore
import CheckboxStyles from './Checkbox.module.css'
import defaultTheme from '../../lib/theme/defaultTheme'
import { useFormContext } from '../Form/FormContext'
import styleHandler from '../../lib/theme/styleHandler'
export interface InputProps extends Omit<React.InputHTMLAttributes<HTMLInputElement>, 'size'> {
afterLabel?: string
beforeLabel?: string
description?: string
label?: string
size?: 'tiny' | 'small' | 'medium' | 'large' | 'xlarge'
}
interface GroupProps {
id?: string
layout?: 'horizontal' | 'vertical'
error?: any
descriptionText?: any
label?: any
afterLabel?: string
beforeLabel?: string
labelOptional?: any
name?: any
value?: any
className?: string
children?: React.ReactNode
options?: Array<InputProps>
defaultValue?: string
onChange?(x: React.ChangeEvent<HTMLInputElement>): void
size?: 'tiny' | 'small' | 'medium' | 'large' | 'xlarge'
}
function Group({
id,
layout = 'vertical',
error,
descriptionText,
label,
afterLabel,
beforeLabel,
labelOptional,
children,
className,
options,
onChange,
size = 'medium',
}: GroupProps) {
const parentCallback = (e: React.ChangeEvent<HTMLInputElement>) => {
if (onChange) onChange(e)
}
const __styles = styleHandler('checkbox')
return (
<FormLayout
label={label}
afterLabel={afterLabel}
beforeLabel={beforeLabel}
labelOptional={labelOptional}
layout={layout}
id={id}
error={error}
descriptionText={descriptionText}
className={className}
size={size}
>
<CheckboxContext.Provider value={{ parentCallback, parentSize: size }}>
<div className={__styles.group}>
{options
? options.map((option: InputProps) => {
return (
<Checkbox
id={option.id}
value={option.value}
label={option.label}
beforeLabel={option.beforeLabel}
afterLabel={option.afterLabel}
checked={option.checked}
name={option.name}
description={option.description}
/>
)
})
: children}
</div>
</CheckboxContext.Provider>
</FormLayout>
)
}
export function Checkbox({
className,
id = '',
name = '',
label,
afterLabel,
beforeLabel,
description,
checked,
value,
onChange,
onBlur,
size = 'medium',
disabled = false,
...props
}: InputProps) {
const { formContextOnChange, values, handleBlur } = useFormContext()
const __styles = styleHandler('checkbox')
return (
<CheckboxContext.Consumer>
{({ parentCallback, parentSize }) => {
// if id does not exist, use label
const markupId = id
? id
: name
? name
: label
? label
.toLowerCase()
.replace(/^[^A-Z0-9]+/gi, '')
.replace(/ /g, '-')
: undefined
// @ts-ignore
size = parentSize ? parentSize : size
// if name does not exist on Radio then use Context Name from Radio.Group
// if that fails, use the id
const markupName = name ? name : markupId
// check if checkbox checked is true or false
// if neither true or false the checkbox will rely on native control
let active = checked ?? undefined
// if (values && !value) value = values[id || name]
let containerClasses = [__styles.container]
function onInputChange(e: React.ChangeEvent<HTMLInputElement>) {
// '`onChange` callback for parent component
if (parentCallback) parentCallback(e)
// '`onChange` callback for this component
if (onChange) onChange(e)
// update form
if (formContextOnChange) formContextOnChange(e)
}
if (className) containerClasses.push(className)
if (values && checked === undefined) active = values[id || name]
function handleBlurEvent(e: React.FocusEvent<HTMLInputElement>) {
if (handleBlur) handleBlur(e)
if (onBlur) onBlur(e)
}
return (
<div className={containerClasses.join(' ')}>
<input
id={markupId}
name={markupName}
type="checkbox"
className={[__styles.base, __styles.size[size]].join(' ')}
onChange={onInputChange}
onBlur={handleBlurEvent}
checked={active}
value={value ? value : markupId}
disabled={disabled}
{...props}
/>
<label
className={[__styles.label.base, __styles.label[size]].join(' ')}
htmlFor={markupId}
>
<span>
{beforeLabel && (
<span
className={[__styles.label_before.base, __styles.label_before[size]].join(' ')}
>
{beforeLabel}
</span>
)}
{label}
{afterLabel && (
<span
className={[__styles.label_after.base, __styles.label_after[size]].join(' ')}
>
{afterLabel}
</span>
)}
</span>
{description && (
<p className={[__styles.description.base, __styles.description[size]].join(' ')}>
{description}
</p>
)}
</label>
</div>
)
}}
</CheckboxContext.Consumer>
)
}
Checkbox.Group = Group
export default Checkbox
@@ -0,0 +1,8 @@
import { createContext } from 'react'
// Make sure the shape of the default value passed to
// createContext matches the shape that the consumers expect!
export const CheckboxContext = createContext({
parentCallback: (e: any) => {},
parentSize: '',
})
@@ -0,0 +1,3 @@
import Checkbox from './Checkbox'
export default Checkbox
export { default as Checkbox } from './Checkbox'
@@ -0,0 +1,67 @@
import React from 'react'
// import { AutoForm } from 'uniforms'
import { Collapsible } from '.'
import { IconChevronUp } from '../..'
import { Button } from '../Button'
export default {
title: 'Displays/Collapsible',
component: Collapsible,
}
export const Default = (args: any) => {
return (
<>
hello all
<Collapsible className="-space-y-px">
<Collapsible.Trigger asChild>
<button
type="button"
className="group text-scale-1200 flex justify-between items-center w-full bg-scale-300 rounded border border-scale-500 p-3"
>
Hello
<div className="flex gap-2 items-center">
<IconChevronUp className="transition data-open-parent:rotate-0 data-closed-parent:rotate-180" />
<Button
onClick={(e) => {
e.stopPropagation()
}}
>
Turn it on
</Button>
</div>
</button>
</Collapsible.Trigger>
<Collapsible.Content>
<div className="group text-scale-1200 flex justify-between items-center w-full bg-scale-300 rounded border border-scale-500 p-3">
<h3 className="text-tomato-900">I am content</h3>
<h3 className="text-tomato-900">I am content</h3>
<h3 className="text-tomato-900">I am content</h3>
<h3 className="text-tomato-900">I am content</h3>
</div>
</Collapsible.Content>
</Collapsible>
<Collapsible>
<Collapsible.Trigger asChild>
<button type="button">Hello</button>
</Collapsible.Trigger>
<Collapsible.Content>
<div>
<h3 className="text-tomato-900">I am content</h3>
<h3 className="text-tomato-900">I am content</h3>
<h3 className="text-tomato-900">I am content</h3>
<h3 className="text-tomato-900">I am content</h3>
</div>
</Collapsible.Content>
</Collapsible>
</>
)
}
Default.args = {
placeholder: 'Type text here ...',
disabled: false,
label: 'Name',
layout: 'vertical',
}
@@ -0,0 +1,56 @@
import * as RadixCollapsible from '@radix-ui/react-collapsible'
import React from 'react'
import styleHandler from '../../lib/theme/styleHandler'
export interface CollapsibleProps extends RadixCollapsible.CollapsibleProps {
children: React.ReactNode
// onChange?: (e: boolean) => void
}
export const Collapsible = ({
open = undefined,
children,
className,
...props
}: CollapsibleProps) => {
// const [_open, setOpen] = React.useState(open)
// function handleOpenChange(e: boolean) {
// console.log(e)
// if (onChange) onChange(e)
// }
return (
<RadixCollapsible.Root
defaultOpen={props.defaultOpen}
open={open}
onOpenChange={props.onOpenChange}
disabled={props.disabled}
className={className}
>
{children}
</RadixCollapsible.Root>
)
}
export function Trigger({ children, asChild }: { children: React.ReactNode; asChild?: boolean }) {
return <RadixCollapsible.Trigger asChild={asChild}>{children}</RadixCollapsible.Trigger>
}
export function Content({
children,
className,
}: {
children: React.ReactNode
className?: string
}) {
const __styles = styleHandler('collapsible')
return (
<RadixCollapsible.Content className={[__styles.content, className].join(' ')}>
{children}
</RadixCollapsible.Content>
)
}
Collapsible.Trigger = Trigger
Collapsible.Content = Content
export default Collapsible
@@ -0,0 +1 @@
export { default as Collapsible } from './Collapsible'
@@ -0,0 +1,65 @@
.sbui-contextmenu-item {
@apply text-xs;
@apply text-typography-body-light dark:text-typography-body-dark;
@apply px-4 py-1.5 flex items-center space-x-2;
@apply cursor-pointer;
@apply focus:bg-bg-secondary-light dark:focus:bg-bg-primary-dark border-none;
cursor: 'default';
}
.sbui-contextmenu-item svg {
/* @apply text-typography-body-secondary-light dark:text-typography-body-secondary-dark; */
}
.sbui-contextmenu-label {
/* @apply text-typography-body-secondary-light dark:text-typography-body-secondary-dark; */
/* @apply px-4 py-1.5 flex items-center space-x-2; */
/* font-size: 0.65rem; */
}
.sbui-contextmenu-misc {
/* @apply px-4 py-1.5; */
}
.sbui-contextmenu-item:focus-visible {
/* border: none; */
/* outline: none; */
}
.sbui-contextmenu-input {
/* @apply flex items-center space-x-2; */
}
.sbui-contextmenu-input__check {
/* @apply flex items-center; */
}
.sbui-contextmenu__content {
/* @apply bg-bg-primary-light dark:bg-bg-secondary-dark p-0; */
/* @apply rounded; */
/* @apply border; */
/* @apply shadow; */
/* overflow: visible; */
/* border-style: solid; */
/* border-width: 1px; */
}
@keyframes transition {
/* 0% { */
/* opacity: 0; */
/* transform: scale(0.95); */
/* } */
/* 100% { */
/* opacity: 1; */
/* transform: scale(1); */
/* } */
}
.sbui-contextmenu__content {
/* transform-origin: var(--radix-dropdown-menu-content-transform-origin); */
/* animation: transition 0.1s ease-out; */
}
.sbui-contextmenu__trigger {
/* @apply border-none bg-transparent p-0 focus:ring-0; */
}
@@ -0,0 +1,168 @@
import React, { useState } from 'react'
import { Button } from '../Button'
import { Divider } from '../Divider'
import { IconSettings, IconLogOut } from '../../index'
import Typography from '../Typography'
import { ContextMenu } from '.'
import { IconLogIn } from '../Icon/icons/IconLogIn'
export default {
title: 'Navigation/ContextMenu',
component: ContextMenu,
}
const triggerArea = (
<div
style={{
background: 'gray',
width: '280px',
height: '180px',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
}}
>
<span>Right click this area</span>
</div>
)
export const Default = (args: any) => (
<div style={{ margin: '0 auto', minHeight: '420px', marginTop: '220px' }}>
<ContextMenu
{...args}
overlay={[
<ContextMenu.Misc>
<div>
<Typography.Text small className="block">
Signed in as{' '}
</Typography.Text>
<Typography.Text small strong>
tom@example.com{' '}
</Typography.Text>
</div>
</ContextMenu.Misc>,
<Divider light />,
<ContextMenu.Label>Group label</ContextMenu.Label>,
<ContextMenu.Item onClick={() => console.log('clicked')}>
Account
</ContextMenu.Item>,
<ContextMenu.Item>Settings</ContextMenu.Item>,
<Divider light />,
<ContextMenu.Item icon={<IconLogIn size="tiny" />}>
Log out
</ContextMenu.Item>,
]}
>
{triggerArea}
</ContextMenu>
</div>
)
Default.args = {}
export const doNotcloseOverlay = (args: any) => (
<div style={{ margin: '0 auto', minHeight: '420px', marginTop: '220px' }}>
<ContextMenu
{...args}
overlay={[
<ContextMenu.Misc>
<Typography.Text>Signed in as </Typography.Text>
<Typography.Text strong>tom@example.com </Typography.Text>
</ContextMenu.Misc>,
<Divider light />,
<ContextMenu.Item>Account</ContextMenu.Item>,
<ContextMenu.Item>Settings</ContextMenu.Item>,
<ContextMenu.Item>
<Button icon={<IconLogOut />}>Log out</Button>
</ContextMenu.Item>,
]}
>
{triggerArea}
</ContextMenu>
</div>
)
doNotcloseOverlay.args = {}
export const withCustomStyles = (args: any) => (
<div
style={{
margin: '0 auto',
minHeight: '420px',
marginTop: '220px',
marginLeft: '400px',
}}
>
<ContextMenu
overlayStyle={{ minWidth: '500px' }}
placement="bottomRight"
{...args}
overlay={[
<ContextMenu.Item>
<Typography.Text>Signed in as </Typography.Text>
<Typography.Text strong>tom@example.com </Typography.Text>
</ContextMenu.Item>,
<Divider light />,
<ContextMenu.Item>Account</ContextMenu.Item>,
<ContextMenu.Item>Settings</ContextMenu.Item>,
<Divider light />,
<ContextMenu.Item>
<Button type="default" icon={<IconLogOut />}>
Log out
</Button>
</ContextMenu.Item>,
]}
>
{triggerArea}
</ContextMenu>
</div>
)
withCustomStyles.args = {}
export const Checkbox = (args: any) => {
const [checked, setChecked] = useState(false)
return (
<div style={{ margin: '0 auto', minHeight: '420px', marginTop: '220px' }}>
<ContextMenu
{...args}
overlay={[
<ContextMenu.Item icon={<IconSettings size="small" />}>
Account
</ContextMenu.Item>,
<ContextMenu.Item>Settings</ContextMenu.Item>,
<Divider light />,
<ContextMenu.Checkbox checked={checked} onChange={setChecked}>
Show subtitles
</ContextMenu.Checkbox>,
]}
>
{triggerArea}
</ContextMenu>
</div>
)
}
export const Radio = (args: any) => {
const [value, setValue] = useState('red')
return (
<div style={{ margin: '0 auto', minHeight: '420px', marginTop: '220px' }}>
<ContextMenu
{...args}
overlay={[
<ContextMenu.RadioGroup value={value} onChange={setValue}>
<ContextMenu.Radio value={'red'}>Red</ContextMenu.Radio>
<ContextMenu.Radio value={'blue'}>Blue</ContextMenu.Radio>
<ContextMenu.Radio value={'green'}>Green</ContextMenu.Radio>
</ContextMenu.RadioGroup>,
]}
>
{triggerArea}
</ContextMenu>
</div>
)
}
@@ -0,0 +1,194 @@
import React, { useState } from 'react'
// import * as RadixContextMenu from '@radix-ui/react-dropdown-menu'
import { IconCheck } from '../Icon/icons/IconCheck'
// @ts-ignore
// import ContextMenuStyles from './ContextMenu.module.css'
import type * as RadixContextMenuTypes from '@radix-ui/react-context-menu/'
import * as RadixContextMenu from '@radix-ui/react-context-menu'
const ContextMenuStyles = {}
interface RootProps {
onOpenChange?(x: boolean): void
alignOffset?: RadixContextMenuTypes.ContextMenuContentProps['alignOffset']
overlay?: React.ReactNode
children?: React.ReactNode
className?: string
style?: React.CSSProperties
}
function ContextMenu({
onOpenChange,
alignOffset = 6,
overlay,
children,
className,
style,
}: RootProps) {
// let classes = [ContextMenuStyles['sbui-contextmenu__content']]
// if (className) {
// classes.push(className)
// }
return (
<RadixContextMenu.Root onOpenChange={onOpenChange}>
<RadixContextMenu.Trigger
// className={ContextMenuStyles['sbui-contextmenu__trigger']}
>
{children}
</RadixContextMenu.Trigger>
<RadixContextMenu.Content
sideOffset={alignOffset}
// className={classes.join(' ')}
style={style}
>
{overlay}
</RadixContextMenu.Content>
</RadixContextMenu.Root>
)
}
interface ItemProps {
children: React.ReactNode
icon?: React.ReactNode
disabled?: boolean
onClick?: (event: Event) => void
}
export function Item({ children, icon, disabled, onClick }: ItemProps) {
return (
<RadixContextMenu.Item
// className={ContextMenuStyles['sbui-contextmenu-item']}
disabled={disabled}
onSelect={onClick}
>
{icon && icon}
<span>{children}</span>
</RadixContextMenu.Item>
)
}
export function Misc({ children, icon }: ItemProps) {
return (
<div
// className={ContextMenuStyles['sbui-contextmenu-misc']}
>
{icon && icon}
{children}
</div>
)
}
interface CheckboxProps {
children: React.ReactNode
checked?: boolean
onChange?(x: boolean): void
disabled?: boolean
ItemIndicator?: React.ReactNode
}
export function Checkbox({
children,
checked: propsChecked,
onChange,
disabled,
ItemIndicator,
}: CheckboxProps) {
const [checked, setChecked] = useState(propsChecked ? propsChecked : false)
const handleChange = (e: boolean) => {
if (onChange) onChange(e)
setChecked(e)
}
return (
<RadixContextMenu.CheckboxItem
checked={checked}
onCheckedChange={handleChange}
// className={`${ContextMenuStyles['sbui-contextmenu-item']} ${ContextMenuStyles['sbui-contextmenu-input']}`}
disabled={disabled}
>
<RadixContextMenu.ItemIndicator
// className={ContextMenuStyles['sbui-contextmenu-input__check']}
>
{ItemIndicator ? ItemIndicator : <IconCheck size="tiny" />}
<RadixContextMenu.CheckboxItem />
</RadixContextMenu.ItemIndicator>
<span>{children}</span>
</RadixContextMenu.CheckboxItem>
)
}
interface RadioProps {
children: React.ReactNode
value: string
ItemIndicator?: React.ReactNode
}
export function Radio({ children, value, ItemIndicator }: RadioProps) {
return (
<RadixContextMenu.RadioItem
value={value}
// className={`${ContextMenuStyles['sbui-contextmenu-item']} ${ContextMenuStyles['sbui-contextmenu-input']}`}
>
<RadixContextMenu.ItemIndicator
// className={ContextMenuStyles['sbui-contextmenu-input__check']}
>
{ItemIndicator ? ItemIndicator : <IconCheck size="tiny" />}
</RadixContextMenu.ItemIndicator>
<span>{children}</span>
</RadixContextMenu.RadioItem>
)
}
interface RadioGroupProps {
children: React.ReactNode
value: string
onChange?(x: string): void
}
export function RadioGroup({
children,
value: propsValue,
onChange,
}: RadioGroupProps) {
const [value, setValue] = useState(propsValue ? propsValue : '')
const handleChange = (e: string) => {
if (onChange) onChange(e)
setValue(e)
}
return (
<RadixContextMenu.RadioGroup value={value} onValueChange={handleChange}>
{children}
</RadixContextMenu.RadioGroup>
)
}
interface LabelProps {
children: React.ReactNode
}
export function Label({ children }: LabelProps) {
return (
<RadixContextMenu.Label
// className={ContextMenuStyles['sbui-contextmenu-label']}
>
{children}
</RadixContextMenu.Label>
)
}
ContextMenu.Item = Item
ContextMenu.Misc = Misc
ContextMenu.Checkbox = Checkbox
ContextMenu.Radio = Radio
ContextMenu.RadioGroup = RadioGroup
ContextMenu.Label = Label
export default ContextMenu
@@ -0,0 +1 @@
export { default as ContextMenu } from './ContextMenu'
@@ -0,0 +1,101 @@
.sbui-divider {
width: 100%;
display: flex;
align-items: center;
white-space: nowrap;
}
.sbui-divider-vertical {
@apply bg-gray-200 dark:bg-dark-500;
width: 1px;
height: inherit;
}
.sbui-divider-vertical.sbui-divider--light {
@apply bg-gray-100 dark:bg-dark-600;
}
.sbui-divider--no-text {
@apply border-gray-200 dark:border-dark-500;
border-bottom-style: solid;
border-bottom-width: 1px;
}
.sbui-divider > span {
@apply text-sm;
@apply text-gray-300;
@apply dark:text-dark-400;
display: inline-block;
padding: 0 1em;
}
.sbui-divider--left:before {
@apply border-gray-200 dark:border-dark-500;
border-bottom-style: solid;
border-bottom-width: 1px;
top: 50%;
content: '';
position: relative;
display: inline-block;
width: 5%;
}
.sbui-divider--left:after {
@apply border-gray-200 dark:border-dark-500;
border-bottom-style: solid;
border-bottom-width: 1px;
top: 50%;
content: '';
position: relative;
display: inline-block;
width: 95%;
}
.sbui-divider--right:before {
@apply border-gray-200 dark:border-dark-500;
border-bottom-style: solid;
border-bottom-width: 1px;
top: 50%;
content: '';
position: relative;
display: inline-block;
width: 95%;
}
.sbui-divider--right:after {
@apply border-gray-200 dark:border-dark-500;
border-bottom-style: solid;
border-bottom-width: 1px;
top: 50%;
content: '';
position: relative;
display: inline-block;
width: 5%;
}
.sbui-divider--center:before,
.sbui-divider--center:after {
@apply border-gray-200 dark:border-dark-500;
border-bottom-style: solid;
border-bottom-width: 1px;
top: 50%;
content: '';
position: relative;
display: inline-block;
width: 50%;
}
.sbui-divider--light.sbui-divider--left:before,
.sbui-divider--light.sbui-divider--left:after,
.sbui-divider--light.sbui-divider--right:before,
.sbui-divider--light.sbui-divider--right:after,
.sbui-divider--light.sbui-divider--center:before,
.sbui-divider--light.sbui-divider--center:after,
.sbui-divider--light.sbui-divider--no-text {
@apply border-gray-100 dark:border-dark-600;
}
.sbui-divider--light.sbui-divider > span {
@apply text-gray-200;
@apply dark:text-dark-800;
}
@@ -0,0 +1,60 @@
import React from 'react'
import { Button } from '../Button'
import Typography from '../Typography'
import { Divider } from './'
export default {
title: 'Utilities/Divider',
component: Divider,
}
export const Default = (args: any) => <Divider {...args} />
export const withCenterText = (args: any) => (
<Divider {...args}>Hello world</Divider>
)
export const withLeftText = (args: any) => (
<Divider {...args}>Hello world</Divider>
)
export const withRightText = (args: any) => (
<Divider {...args}>Hello world</Divider>
)
export const lighterColor = (args: any) => <Divider {...args} />
export const vertical = (args: any) => (
<div style={{ height: '32px' }}>
<div className="space-x-3 w-full">
<Divider {...args} />
<Button>Button one</Button>
<Divider {...args} />
<Button>Button two</Button>
<Divider {...args} />
<Typography.Text>Some text</Typography.Text>
<Divider {...args} />
<Button>Button three</Button>
</div>
</div>
)
Default.args = {}
withCenterText.args = {}
withLeftText.args = {
orientation: 'left',
}
withRightText.args = {
orientation: 'right',
}
lighterColor.args = {
light: true,
}
vertical.args = {
type: 'vertical',
}
@@ -0,0 +1,52 @@
import React from 'react'
// @ts-ignore
// import DividerStyles from './Divider.module.css'
interface Props {
children?: React.ReactNode
className?: string
light?: boolean
orientation?: 'left' | 'right' | 'center'
style?: React.CSSProperties
type?: 'vertical' | 'horizontal'
}
export default function Divider({
children,
className,
light = false,
orientation = 'center',
style,
type = 'horizontal',
}: Props) {
// let classes = [
// type === 'horizontal'
// ? DividerStyles['sbui-divider']
// : DividerStyles['sbui-divider-vertical'],
// ]
// if (light) classes.push(DividerStyles['sbui-divider--light'])
// if (children) {
// classes.push(DividerStyles[`sbui-divider--${orientation}`])
// } else if (!children && type === 'horizontal') {
// classes.push(DividerStyles[`sbui-divider--no-text`])
// }
// if (className) classes.push(className)
return (
<div
// className={classes.join(' ')}
role="seperator"
style={style}
>
{children && (
<span
// className={DividerStyles['sbui-divider__content']}
>
{children}
</span>
)}
</div>
)
}
@@ -0,0 +1 @@
export { default as Divider } from './Divider'
@@ -0,0 +1,112 @@
/* .sbui-dropdown-item {
@apply text-xs;
@apply text-typography-body-light dark:text-typography-body-dark;
@apply px-4 py-1.5 flex items-center space-x-2;
@apply cursor-pointer;
@apply focus:bg-bg-secondary-light dark:focus:bg-bg-primary-dark border-none;
cursor: 'default';
user-select: none;
}
/* .sbui-dropdown-item svg {
@apply text-typography-body-secondary-light dark:text-typography-body-secondary-dark;
} */
/* .sbui-dropdown-label {
@apply text-typography-body-secondary-light dark:text-typography-body-secondary-dark;
@apply px-4 py-1.5 flex items-center space-x-2;
font-size: 0.65rem;
}
.sbui-dropdown-misc {
@apply px-4 py-1.5;
}
.sbui-dropdown-item:focus-visible {
border: none;
outline: none;
}
.sbui-dropdown-input {
@apply flex items-center space-x-0 pl-8 pr-4;
}
.sbui-dropdown-input__check {
@apply absolute left-2;
@apply flex items-center;
} */
/* .sbui-dropdown__content {
@apply bg-bg-primary-light dark:bg-bg-secondary-dark p-0;
@apply border border-lightmode dark:border-darkmode;
@apply rounded;
@apply shadow;
border-style: solid;
border-width: 1px;
} */
/* @keyframes fadeIn {
from {
transform: scale(0.95);
opacity: 0;
}
to {
transform: scale(1);
opacity: 1;
}
}
@keyframes fadeOut {
from {
transform: scale(1);
opacity: 1;
}
to {
transform: scale(0.95);
opacity: 0;
}
} */
/* .sbui-dropdown__content {
transform-origin: 'var(--radix-dropdown-menu-content-transform-origin)';
} */
/* .sbui-dropdown__content[data-state='open'] {
animation: fadeIn 50ms ease-out;
}
.sbui-dropdown__content[data-state='closed'] {
animation: fadeOut 50ms ease-in;
} */
/* .sbui-dropdown__trigger {
@apply border-none bg-transparent p-0 focus:ring-0;
} */
/* .sbui-dropdown__arrow {
@apply fill-current text-bg-primary-light dark:text-bg-secondary-dark;
@apply border-0 border-t;
border-style: solid;
}
.sbui-dropdown-item-trigger {
@apply text-xs;
@apply text-typography-body-light dark:text-typography-body-dark;
@apply px-4 py-1.5 flex items-center space-x-2;
@apply cursor-pointer;
cursor: 'default';
}
.sbui-dropdown-item-trigger svg {
@apply text-typography-body-secondary-light dark:text-typography-body-secondary-dark;
}
.sbui-dropdown-item-trigger:focus-visible {
border: none;
outline: none;
} */
/* .sbui-dropdown__trigger-item[data-state='open'] {
@apply bg-bg-secondary-light dark:bg-bg-primary-dark border-none;
} */
@@ -0,0 +1,347 @@
import React, { useState } from 'react'
import { Button } from '../Button'
import { Divider } from '../Divider'
import {
IconSettings,
IconLogOut,
IconChevronDown,
IconChevronRight,
IconHardDrive,
} from './../../index'
import Typography from '../Typography'
import { Dropdown } from './'
import { IconLogIn } from '../Icon/icons/IconLogIn'
import { Input } from '../Input'
import { IconSearch } from '../Icon/icons/IconSearch'
export default {
title: 'Navigation/Dropdown',
component: Dropdown,
}
const DemoContainer = ({ children }: { children: React.ReactNode }) => (
<div
className="
flex justify-center items-center
w-screen h-screen
"
>
<div
className="
p-3 px-5
bg-scale-300 border border-scale-600 rounded flex gap-4
justify-between
items-center
w-3/4
"
>
<div>
<h4 className="text-scale-1200 text-base">
Shall we nest some components?
</h4>
<p className="text-scale-1100 text-sm">yea sure, go on then.</p>
</div>
<div className="relative">{children}</div>
</div>
</div>
)
export const DefaultFull = (args: any) => {
const [checked, setChecked] = useState(false)
const [value, setValue] = useState('red')
return (
<DemoContainer>
<Dropdown
side="bottom"
align="end"
overlay={[
<Dropdown.Misc>
<div>
<Typography.Text small className="block">
Signed in as{' '}
</Typography.Text>
<Typography.Text small strong>
tom@example.com{' '}
</Typography.Text>
</div>
</Dropdown.Misc>,
<Dropdown.Seperator />,
<Dropdown.Label>Group label</Dropdown.Label>,
<Dropdown.Item onClick={() => console.log('clicked')}>
Account
</Dropdown.Item>,
<Dropdown.Item>
Settings <Dropdown.RightSlot>⌘+T</Dropdown.RightSlot>
</Dropdown.Item>,
<Dropdown.Seperator />,
<Dropdown.Checkbox checked={checked} onChange={setChecked}>
Show subtitles
</Dropdown.Checkbox>,
<Dropdown.Seperator />,
<Dropdown.RadioGroup value={value} onChange={setValue}>
<Dropdown.Radio value={'red'}>Red</Dropdown.Radio>
<Dropdown.Radio value={'blue'}>Blue</Dropdown.Radio>
<Dropdown.Radio value={'green'}>Green</Dropdown.Radio>
</Dropdown.RadioGroup>,
<Dropdown.Seperator />,
<Dropdown
isNested
overlay={[
<Dropdown.RadioGroup value={value} onChange={setValue}>
<Dropdown.Radio value={'red'}>Red</Dropdown.Radio>
<Dropdown.Radio value={'blue'}>Blue</Dropdown.Radio>
<Dropdown.Radio value={'green'}>Green</Dropdown.Radio>
</Dropdown.RadioGroup>,
<Dropdown.Seperator />,
<Dropdown.Label>Group label</Dropdown.Label>,
<Dropdown.Item onClick={() => console.log('clicked')}>
Account
</Dropdown.Item>,
<Dropdown.Item>
Settings <Dropdown.RightSlot>⌘+T</Dropdown.RightSlot>
</Dropdown.Item>,
]}
>
<Dropdown.TriggerItem icon={<IconHardDrive />}>
Open sub menu{' '}
<Dropdown.RightSlot>
<IconChevronRight size={14} />
</Dropdown.RightSlot>
</Dropdown.TriggerItem>
</Dropdown>,
<Dropdown.Seperator />,
<Dropdown.Item icon={<IconLogIn size="tiny" />}>
Log out
</Dropdown.Item>,
]}
>
<Button as="span" type="default" iconRight={<IconChevronDown />}>
Click for dropdown
</Button>
</Dropdown>
</DemoContainer>
)
}
export const Default = (args: any) => (
<div style={{ margin: '0 auto', minHeight: '420px', marginTop: '220px' }}>
<Dropdown
{...args}
overlay={[
<Dropdown.Misc>
<div>
<Typography.Text small className="block">
Signed in as{' '}
</Typography.Text>
<Typography.Text small strong>
tom@example.com{' '}
</Typography.Text>
</div>
</Dropdown.Misc>,
<Dropdown.Seperator />,
<Dropdown.Label>Group label</Dropdown.Label>,
<Dropdown.Item onClick={() => console.log('clicked')}>
Account
</Dropdown.Item>,
<Dropdown.Item>
Settings <Dropdown.RightSlot>⌘+T</Dropdown.RightSlot>
</Dropdown.Item>,
<Dropdown.Seperator />,
<Dropdown.Item icon={<IconLogIn size="tiny" />}>Log out</Dropdown.Item>,
]}
>
<Button as="span" type="secondary" iconRight={<IconChevronDown />}>
Click for dropdown
</Button>
</Dropdown>
</div>
)
Default.args = {}
export const doNotcloseOverlay = (args: any) => (
<div style={{ margin: '0 auto', minHeight: '420px', marginTop: '220px' }}>
<Dropdown
{...args}
overlay={[
<Dropdown.Misc>
<Typography.Text>Signed in as </Typography.Text>
<Typography.Text strong>tom@example.com </Typography.Text>
</Dropdown.Misc>,
<Dropdown.Seperator />,
<Dropdown.Item>Account</Dropdown.Item>,
<Dropdown.Item>Settings</Dropdown.Item>,
<Dropdown.Item>
<Button icon={<IconLogOut />}>Log out</Button>
</Dropdown.Item>,
]}
>
<Button as="span" type="outline" iconRight={<IconChevronDown />}>
Click for dropdown
</Button>
</Dropdown>
</div>
)
doNotcloseOverlay.args = {}
export const withCustomStyles = (args: any) => (
<div
style={{
margin: '0 auto',
minHeight: '420px',
marginTop: '220px',
marginLeft: '400px',
}}
>
<Dropdown
overlayStyle={{ minWidth: '500px' }}
placement="bottomRight"
{...args}
overlay={[
<Dropdown.Item>
<Typography.Text>Signed in as </Typography.Text>
<Typography.Text strong>tom@example.com </Typography.Text>
</Dropdown.Item>,
<Dropdown.Seperator />,
<Dropdown.Item>Account</Dropdown.Item>,
<Dropdown.Item>Settings</Dropdown.Item>,
<Dropdown.Seperator />,
<Dropdown.Item>
<Button type="default" icon={<IconLogOut />}>
Log out
</Button>
</Dropdown.Item>,
]}
>
<Button as="span" type="outline" iconRight={<IconChevronDown />}>
Click for dropdown
</Button>
</Dropdown>
</div>
)
withCustomStyles.args = {}
export const SearchList = (args: any) => (
<div style={{ margin: '0 auto', minHeight: '420px', marginTop: '220px' }}>
<Dropdown
{...args}
overlay={[
<Dropdown.Item>
<Input size="tiny" icon={<IconSearch />} autofocus={false} />
</Dropdown.Item>,
<Dropdown.Item>
<Typography.Text>Signed in as </Typography.Text>
<Typography.Text strong>tom@example.com </Typography.Text>
</Dropdown.Item>,
<Dropdown.Item>
<Typography.Text>Signed in as </Typography.Text>
<Typography.Text strong>tom@example.com </Typography.Text>
</Dropdown.Item>,
<Dropdown.Seperator />,
<Dropdown.Item icon={<IconLogIn />}>
<Typography.Text>Log out</Typography.Text>
</Dropdown.Item>,
]}
>
<Button as="span" type="outline" iconRight={<IconChevronDown />}>
Click for dropdown
</Button>
</Dropdown>
</div>
)
SearchList.args = {}
export const Checkbox = (args: any) => {
const [checked, setChecked] = useState(false)
return (
<div style={{ margin: '0 auto', minHeight: '420px', marginTop: '220px' }}>
<Dropdown
{...args}
overlay={[
<Dropdown.Item icon={<IconSettings size="small" />}>
Account
</Dropdown.Item>,
<Dropdown.Item>Settings</Dropdown.Item>,
<Dropdown.Seperator />,
<Dropdown.Checkbox checked={checked} onChange={setChecked}>
Show subtitles
</Dropdown.Checkbox>,
]}
>
<Button as="span" type="outline" iconRight={<IconChevronDown />}>
Click for dropdown
</Button>
</Dropdown>
</div>
)
}
export const Radio = (args: any) => {
const [value, setValue] = useState('red')
return (
<div style={{ margin: '0 auto', minHeight: '420px', marginTop: '220px' }}>
<Dropdown
{...args}
overlay={[
<Dropdown.RadioGroup value={value} onChange={setValue}>
<Dropdown.Radio value={'red'}>Red</Dropdown.Radio>
<Dropdown.Radio value={'blue'}>Blue</Dropdown.Radio>
<Dropdown.Radio value={'green'}>Green</Dropdown.Radio>
</Dropdown.RadioGroup>,
]}
>
<Button as="span" type="outline" iconRight={<IconChevronDown />}>
Click for dropdown
</Button>
</Dropdown>
</div>
)
}
export const Nested = (args: any) => {
const [value, setValue] = useState('red')
return (
<div style={{ margin: '0 auto', minHeight: '420px', marginTop: '220px' }}>
<Dropdown
{...args}
overlay={
<>
<Dropdown.RadioGroup value={value} onChange={setValue}>
<Dropdown.Radio value={'red'}>Red</Dropdown.Radio>
<Dropdown.Radio value={'blue'}>Blue</Dropdown.Radio>
<Dropdown.Radio value={'green'}>Green</Dropdown.Radio>
</Dropdown.RadioGroup>
<Dropdown
isNested
overlay={[
<Dropdown.RadioGroup value={value} onChange={setValue}>
<Dropdown.Radio value={'red'}>Red</Dropdown.Radio>
<Dropdown.Radio value={'blue'}>Blue</Dropdown.Radio>
<Dropdown.Radio value={'green'}>Green</Dropdown.Radio>
</Dropdown.RadioGroup>,
]}
>
<Dropdown.TriggerItem>Open sub menu</Dropdown.TriggerItem>
</Dropdown>
<Dropdown.Item>hello</Dropdown.Item>
</>
}
>
<Button as="span" type="outline" iconRight={<IconChevronDown />}>
Click for dropdown
</Button>
</Dropdown>
</div>
)
}
@@ -0,0 +1,226 @@
import React, { useState } from 'react'
import * as RadixDropdown from '@radix-ui/react-dropdown-menu'
import { IconCheck } from '../Icon/icons/IconCheck'
// @ts-ignore
// import DropdownStyles from './Dropdown.module.css'
import type * as RadixDropdownTypes from '@radix-ui/react-dropdown-menu/'
import styleHandler from '../../lib/theme/styleHandler'
import { IconTarget } from '../Icon/icons/IconTarget'
interface RootProps {
open?: boolean
arrow?: boolean
onOpenChange?: RadixDropdownTypes.DropdownMenuProps['onOpenChange'] // DropdownMenu['onOpenChange']
side?: RadixDropdownTypes.DropdownMenuContentProps['side']
align?: RadixDropdownTypes.DropdownMenuContentProps['align']
sideOffset?: RadixDropdownTypes.DropdownMenuContentProps['sideOffset']
overlay?: React.ReactNode
children?: React.ReactNode
size?: 'tiny' | 'small' | 'medium' | 'large' | 'xlarge' | 'content'
className?: string
style?: React.CSSProperties
isNested?: Boolean
}
function Dropdown({
open,
onOpenChange,
align = 'center', //Default value
side = 'bottom', //Default value
sideOffset = 6,
overlay,
children,
size = 'medium',
className,
style,
arrow,
isNested,
}: RootProps) {
let __styles = styleHandler('dropdown')
let classes = [__styles.content, __styles.size[size]]
if (className) {
classes.push(className)
}
return (
<RadixDropdown.Root onOpenChange={onOpenChange} open={open}>
{isNested ? (
<RadixDropdown.TriggerItem className={[__styles.item_nested].join(' ')}>
{children}
</RadixDropdown.TriggerItem>
) : (
<RadixDropdown.Trigger className={__styles.trigger}>{children}</RadixDropdown.Trigger>
)}
<RadixDropdown.Content
portalled={true}
sideOffset={sideOffset}
side={side}
align={align}
className={classes.join(' ')}
style={style}
>
{arrow && (
<RadixDropdown.Arrow className={__styles.arrow} offset={10}></RadixDropdown.Arrow>
)}
{overlay}
</RadixDropdown.Content>
</RadixDropdown.Root>
)
}
export function RightSlot({ children }: any) {
let __styles = styleHandler('dropdown')
return <div className={__styles.right_slot}>{children}</div>
}
interface ItemProps {
children: React.ReactNode
icon?: React.ReactNode
disabled?: boolean
onClick?: (event: Event) => void
rightSlot?: React.ReactNode
}
export function Item({ children, icon, disabled, onClick, rightSlot }: ItemProps) {
let __styles = styleHandler('dropdown')
return (
<RadixDropdown.Item className={__styles.item} disabled={disabled} onSelect={onClick}>
{icon && icon}
<span>{children}</span>
</RadixDropdown.Item>
)
}
export function TriggerItem({ children, icon, disabled }: ItemProps) {
let __styles = styleHandler('dropdown')
return (
<div className={__styles.item}>
{icon && icon}
<span>{children}</span>
</div>
)
}
export function Misc({ children, icon }: ItemProps) {
let __styles = styleHandler('dropdown')
return (
<div className={__styles.misc}>
{icon && icon}
{children}
</div>
)
}
interface CheckboxProps {
children: React.ReactNode
checked?: boolean
onChange?(x: boolean): void
disabled?: boolean
ItemIndicator?: React.ReactNode
}
export function Seperator() {
let __styles = styleHandler('dropdown')
return <RadixDropdown.Separator className={__styles.seperator} />
}
export function Checkbox({
children,
checked: propsChecked,
onChange,
disabled,
ItemIndicator,
}: CheckboxProps) {
const [checked, setChecked] = useState(propsChecked ? propsChecked : false)
let __styles = styleHandler('dropdown')
const handleChange = (e: boolean) => {
if (onChange) onChange(e)
setChecked(e)
}
return (
<RadixDropdown.CheckboxItem
checked={checked}
onCheckedChange={handleChange}
className={`${__styles.item} ${__styles.input}`}
disabled={disabled}
>
<RadixDropdown.ItemIndicator className={__styles.check}>
{ItemIndicator ? ItemIndicator : <IconCheck size="tiny" strokeWidth={3} />}
<RadixDropdown.CheckboxItem />
</RadixDropdown.ItemIndicator>
<span>{children}</span>
</RadixDropdown.CheckboxItem>
)
}
interface RadioProps {
children: React.ReactNode
value: string
ItemIndicator?: React.ReactNode
}
export function Radio({ children, value, ItemIndicator }: RadioProps) {
let __styles = styleHandler('dropdown')
return (
<RadixDropdown.RadioItem value={value} className={`${__styles.item} ${__styles.input}`}>
<RadixDropdown.ItemIndicator className={__styles.check}>
{ItemIndicator ? ItemIndicator : <IconTarget strokeWidth={6} size={10} />}
</RadixDropdown.ItemIndicator>
<span>{children}</span>
</RadixDropdown.RadioItem>
)
}
interface RadioGroupProps {
children: React.ReactNode
value: string
onChange?(x: string): void
}
export function RadioGroup({ children, value: propsValue, onChange }: RadioGroupProps) {
const [value, setValue] = useState(propsValue ? propsValue : '')
const handleChange = (e: string) => {
if (onChange) onChange(e)
setValue(e)
}
return (
<RadixDropdown.RadioGroup value={value} onValueChange={handleChange}>
{children}
</RadixDropdown.RadioGroup>
)
}
interface LabelProps {
children: React.ReactNode
}
export function Label({ children }: LabelProps) {
let __styles = styleHandler('dropdown')
return <RadixDropdown.Label className={__styles.label}>{children}</RadixDropdown.Label>
}
Dropdown.Item = Item
Dropdown.Misc = Misc
Dropdown.Checkbox = Checkbox
Dropdown.Radio = Radio
Dropdown.RadioGroup = RadioGroup
Dropdown.Label = Label
Dropdown.Seperator = Seperator
Dropdown.RightSlot = RightSlot
Dropdown.TriggerItem = TriggerItem
export default Dropdown
@@ -0,0 +1 @@
export { default as Dropdown } from './Dropdown'
Whitespace-only changes.
@@ -0,0 +1,569 @@
import { Form } from '.'
import {
Input,
Button,
InputNumber,
Toggle,
Checkbox,
Radio,
Select,
Listbox,
} from '../../index'
import * as Yup from 'yup'
import { User } from '../Icon/IconImportHandler'
import React from 'react'
export default {
title: 'Data Input/Form',
component: Form,
}
interface Values {
email: string
last_name: string
profession: string
number: number | undefined
// remember_me: boolean
checkbox_alone: boolean
favorite_food: string
check_3: boolean
check_2: boolean
check_1: boolean
textarea: string
toggle: boolean
people: number | undefined
}
const INITIAL_VALUES: Values = {
email: '',
last_name: '',
profession: '',
number: undefined,
checkbox_alone: false,
// remember_me: false,
favorite_food: '',
check_3: false,
check_2: true,
check_1: false,
textarea: '',
toggle: true,
people: undefined,
}
export const InputLevelValidation = () => {
function validateEmail(value: string) {
console.log('validateEmail running')
let error
if (!value) {
error = 'Required'
} else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(value)) {
error = 'Invalid email address'
}
return error
}
return (
<Form
initialValues={{
email: '',
firstname: '',
}}
validateOnBlur
onSubmit={(values: any, { setSubmitting }: any) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2))
setSubmitting(false)
}, 400)
}}
>
{({ isSubmitting }: { isSubmitting: boolean }) => (
<div className="space-y-4">
<Input
id="email"
label="email"
placeholder="something in here"
labelOptional="This is a required field"
validation={validateEmail}
/>
{/* <Input
id="firstname"
label="firstname"
placeholder="something in here"
/> */}
<Button loading={isSubmitting} type="primary" htmlType="submit">
Submit
</Button>
</div>
)}
</Form>
)
}
export const InputLevelValidationYip = () => {
// validation schema
const SignupSchema = Yup.object().shape({
firstname: Yup.string()
.min(2, 'Too Short!')
.max(50, 'Too Long!')
.required('Required'),
lastname: Yup.string()
.min(2, 'Too Short!')
.max(50, 'Too Long!')
.required('Required'),
email: Yup.string().email('Invalid email').required('Required'),
})
return (
<Form
initialValues={{
firstname: '',
lastname: '',
email: '',
}}
validationSchema={SignupSchema}
onSubmit={(values: any, { setSubmitting }: any) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2))
setSubmitting(false)
}, 400)
}}
>
{({ isSubmitting }: any) => (
<div className="space-y-4">
<Input
id="firstname"
name="firstname"
label="firstname"
placeholder="firstname"
/>
<Input
id="lastname"
name="lastname"
label="lastname"
placeholder="lastname"
/>
<Input
id="email"
name="email"
label="Email"
placeholder="This is your email"
/>
<Button loading={isSubmitting} type="primary" htmlType="submit">
Submit
</Button>
</div>
)}
</Form>
)
}
const people = [
{
value: 1,
label: 'Wade Cooper',
avatar:
'https://images.unsplash.com/photo-1491528323818-fdd1faba62cc?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
value: 2,
label: 'Arlene Mccoy',
avatar:
'https://images.unsplash.com/photo-1550525811-e5869dd03032?ixlib=rb-1.2.1&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
value: 3,
label: 'Devon Webb',
avatar:
'https://images.unsplash.com/photo-1500648767791-00dcc994a43e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2.25&w=256&h=256&q=80',
},
{
value: 4,
label: 'Tom Cook',
avatar:
'https://images.unsplash.com/photo-1472099645785-5658abf4ff4e?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
value: 5,
label: 'Tanya Fox',
avatar:
'https://images.unsplash.com/photo-1494790108377-be9c29b29330?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
value: 6,
label: 'Hellen Schmidt',
avatar:
'https://images.unsplash.com/photo-1487412720507-e7ab37603c6f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
value: 7,
label: 'Caroline Schultz',
avatar:
'https://images.unsplash.com/photo-1568409938619-12e139227838?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
value: 8,
label: 'Mason Heaney',
avatar:
'https://images.unsplash.com/photo-1531427186611-ecfd6d936c79?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
value: 9,
label: 'Claudie Smitham',
avatar:
'https://images.unsplash.com/photo-1584486520270-19eca1efcce5?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
{
value: 10,
label: 'Emil Schaefer',
avatar:
'https://images.unsplash.com/photo-1561505457-3bcad021f8ee?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=facearea&facepad=2&w=256&h=256&q=80',
},
]
export const LargerExample = () => {
return (
<>
<Form
initialValues={INITIAL_VALUES}
onSubmit={(values: any, { setSubmitting }: any) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2))
setSubmitting(false)
}, 400)
}}
validate={(values: Values) => {
const errors: any = {}
console.log('values for validation', values)
if (!values.email) {
errors.email = 'Required'
} else if (
!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}$/i.test(values.email)
) {
errors.email = 'Invalid email address'
}
if (!values.profession) {
errors.profession = 'Required'
}
if (!values.textarea) {
errors.textarea = 'Required'
}
if (!values.number) {
errors.number = 'Required'
}
if (values.number <= 13) {
errors.number = 'Must be a number above 13'
}
if (values.number >= 32) {
errors.number = 'Must be a number below 32'
}
if (!values.favorite_food) {
errors.favorite_food = 'You must select a favourite food'
}
if (!values.toggle) {
errors.toggle = 'This needs to be turned on'
}
// if (!values.people) {
// errors.people = 'Please select a person'
// }
// if (values.remember_me)
return errors
}}
>
{({ isSubmitting }: any) => (
<>
<div className="space-y-8">
<p>{isSubmitting ? 'submitting' : 'not submitting'}</p>
<Input
id="email"
label="Email"
placeholder="something@gmail.com"
/>
<Input
id="last_name"
label="last name"
placeholder="something in here"
/>
<Select
id="profession"
label="Profession"
placeholder="something in here"
>
<Select.Option key="empty-enum" value="">
---
</Select.Option>
<Select.Option value="teacher">Teacher</Select.Option>
<Select.Option value="firefighter">Firefighter</Select.Option>
<Select.Option value="police">Police</Select.Option>
</Select>
<InputNumber
id="number"
label="Number"
placeholder="124"
labelOptional="Must be between 13 - 31"
/>
<Checkbox id="checkbox_alone" label="checkbox_alone" />
<Input.TextArea id="textarea" rows={5} name="textarea" />
<Checkbox.Group
label="Group of checkboxes"
layout="horizontal"
labelOptional="Optional label"
descriptionText="You can also show label hint text here"
>
<Checkbox
name="check_1"
id="check_1"
label="Remember me"
description="hello world"
/>
<Checkbox
name="check_2"
id="check_2"
label="Remember me"
description="hello world"
/>
<Checkbox
name="check_3"
id="check_3"
label="Remember me"
description="hello world"
/>
</Checkbox.Group>
<Toggle id="toggle" label="Remember me" layout="horizontal" />
<Radio.Group
layout="horizontal"
name="favorite_food"
label="favorite_food"
type="list"
>
<Radio value="pizza" label="Pizza" description="hello world" />
<Radio
value="burger"
label="Burger"
description="hello world"
/>
<Radio value="fries" label="Fries" description="hello world" />
</Radio.Group>
<Listbox
id="people"
label="Choose a person"
layout="horizontal"
descriptionText="Choose a person for this role"
>
{people.map((person) => {
return (
<Listbox.Option
key={`people-${person.value}`}
value={person.value}
label={person.label}
addOnBefore={({ active, selected }: any) => (
<img
src={person.avatar}
alt=""
className="h-6 w-6 rounded-full"
/>
)}
children={({ active, selected }: any) => {
// console.log('selected', selected)
// console.log('active', active)
return (
<span className={'font-normal block truncate'}>
{person.label}
</span>
)
}}
/>
)
})}
</Listbox>
<Button loading={isSubmitting} type="primary" htmlType="submit">
Submit
</Button>
</div>
</>
)}
</Form>
</>
)
}
export const CardForm = () => {
// panel
const Panel = ({
children,
header,
footer,
}: {
children: React.ReactNode
header?: React.ReactNode
footer?: React.ReactNode
}) => (
<div className="bg-scale-300 border border-scale-400 rounded-md w-3/4 mx-auto my-8 shadow overflow-hidden">
{header && (
<div className="bg-scale-100 dark:bg-scale-200 px-8 py-4 border-b border-scale-400">
{header}
</div>
)}
<div className="space-y-6 py-6">{children}</div>
{footer}
</div>
)
const Section = ({
children,
header,
}: {
children: React.ReactNode
header?: React.ReactNode
}) => (
<div className="grid grid-cols-12 px-8 py-2">
{header}
{children}
</div>
)
return (
<>
<Form
initialValues={{ stripe_email_choice: 'emails-2' }}
onSubmit={(values: any, { setSubmitting }: any) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2))
setSubmitting(false)
}, 400)
}}
validate={(values: Values) => {
const errors: any = {}
return errors
}}
>
{({ isSubmitting }: any) => (
<Panel
header={
<>
<h3 className="text-scale-1200 text-xl font-semibold">
Custom Options
</h3>
<p className="text-scale-900">
These settings apply to payment pages you create using Stripe
Checkout and Payment Links.
</p>
</>
}
footer={
<>
<div className="border-t border-scale-400"></div>
<div className="py-3 px-6 flex gap-2 justify-end">
<Button
loading={isSubmitting}
type="secondary"
htmlType="submit"
>
Cancel
</Button>
<Button
loading={isSubmitting}
type="primary"
htmlType="submit"
>
Save
</Button>
</div>
</>
}
>
{/* <p>{isSubmitting ? 'submitting' : 'not submitting'}</p> */}
{/* <div className="border-t border-scale-400"></div> */}
<Section
header={
<label className="text-sm text-scale-1200 col-span-4">
Faster checkout
</label>
}
>
<Toggle
className="col-span-8"
id="link_with_stripe"
label="Turn on link with Stripe"
layout="flex"
descriptionText="Go to Payment methods settings to configure Apple Pay and Google Pay."
/>
</Section>
<div className="border-t border-scale-400"></div>
<Section
header={
<label className="text-sm text-scale-1200 col-span-4">
Faster checkout
</label>
}
>
<Radio.Group
className="col-span-8"
name="stripe_email_choice"
id="stripe_email_choice"
type="list"
layout="vertical"
>
<Radio
// id="1642469211631"
value="emails-1"
label="Send emails about upcoming renewals"
description="hello world"
align="horizontal"
/>
<Radio
// id="1642469211606"
value="emails-2"
label="Send emails about expiring cards"
description="hello world"
align="horizontal"
/>
</Radio.Group>
</Section>
<div className="border-t border-scale-400"></div>
<Section
header={
<label className="text-sm text-scale-1200 col-span-4">
Faster checkout
</label>
}
>
<div className="col-span-8 space-y-4">
<Input name="app_id" label="Application ID in Stripe" />
<Input
name="service_id"
label="API key"
descriptionText={
<span>
This can be found in{' '}
<span className="text-brand-900 underline cursor-pointer transition hover:text-brand-800">
the developer settings
</span>
</span>
}
/>
</div>
</Section>
</Panel>
)}
</Form>
</>
)
}
export { default as AuthForm } from './examples/AuthForm'
+96
View File
@@ -0,0 +1,96 @@
import { useReducer } from 'react'
import { useFormik, FormikConfig } from 'formik'
import { FormContextProvider } from './FormContext'
// interface Props extends FormikProps<any>, Partial FormikConfig<any> {
interface Props
extends Omit<FormikConfig<any>, 'validateOnMount' | 'validateOnChange'> {
children: any
handleIsSubmitting?: any
handleIsValidating?: any
name?: string
id?: string
className?: string
style?: React.CSSProperties
}
function errorReducer(state: any, action: any) {
if (!action.error) {
const payload = state
delete payload[action.key]
return payload
}
if (action) {
return {
...state,
[action.key]: action.error,
}
} else {
throw new Error()
}
}
export default function Form({ validate, ...props }: Props) {
const [fieldLevelErrors, dispatchErrors] = useReducer(errorReducer, null)
function handleFieldLevelValidation(key: any, error: string) {
dispatchErrors({ key, error })
}
const formik = useFormik({
validateOnBlur: true,
...props,
validationSchema: props.validationSchema,
initialValues: props.initialValues,
onSubmit: props.onSubmit,
validate:
validate ||
function () {
return fieldLevelErrors
},
})
// console.log('values', formik.values)
// console.log('errors', formik.errors)
// console.log('touched', formik.touched)
return (
<form
id={props.id}
name={props.name}
onSubmit={formik.handleSubmit}
className={props.className}
style={props.style}
>
<FormContextProvider
values={formik.values}
errors={formik.errors}
formContextOnChange={formik.handleChange}
handleBlur={formik.handleBlur}
touched={formik.touched}
fieldLevelValidation={handleFieldLevelValidation}
// children={rest.children}
children={props.children({
/** map of field names to specific error for that field */
errors: formik.errors, // errors,
// /** map of field names to whether the field has been touched */
touched: formik.touched,
/** whether the form is currently submitting */
isSubmitting: formik.isSubmitting,
/** whether the form is currently validating (prior to submission) */
isValidating: formik.isValidating,
/** Number of times user tried to submit the form */
submitCount: formik.submitCount,
/** Initial values of form */
initialValues: formik.initialValues,
/** Current values of form */
values: formik.values,
/** Resets the form back to initialValues */
handleReset: formik.handleReset,
/** Resets the form with custom values */
resetForm: formik.resetForm,
})}
/>
</form>
)
}
@@ -0,0 +1,60 @@
import React, { createContext, useContext } from 'react'
interface ContextProps {
formContextOnChange: any
values: any
errors: any
handleBlur: React.FocusEventHandler | null
touched: any
fieldLevelValidation: any
}
interface Provider extends ContextProps {
children?: React.ReactNode
}
// Make sure the shape of the default value passed to
// createContext matches the shape that the consumers expect!
const FormContext = createContext<ContextProps>({
formContextOnChange: null,
values: null,
errors: null,
handleBlur: null,
touched: null,
fieldLevelValidation: null,
})
export const FormContextProvider = (props: Provider) => {
const {
formContextOnChange,
values,
errors,
handleBlur,
touched,
fieldLevelValidation,
} = props
const value = {
formContextOnChange: formContextOnChange,
values: values,
errors: errors,
handleBlur: handleBlur,
touched: touched,
fieldLevelValidation: fieldLevelValidation,
}
return (
<FormContext.Provider value={value}>{props.children}</FormContext.Provider>
)
}
// context helper to avoid using a consumer component
export const useFormContext = () => {
const context = useContext(FormContext)
if (context === undefined) {
throw new Error(
`useFormContextOnChange must be used within a FormContextProvider.`
)
}
return context
}
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,281 @@
[
{
"name": "Email",
"icon": "email-icon",
"form": [
{
"type": "text",
"name": "email-app-id",
"label": "email App Id",
"description": ""
},
{
"type": "text",
"name": "email-id-key",
"label": "email client ID",
"description": ""
},
{
"type": "text",
"name": "email-id-key",
"label": "email client ID",
"description": ""
},
{
"type": "text",
"name": "email-id-key",
"label": "email client ID",
"description": ""
}
]
},
{
"name": "Phone",
"icon": "phone-icon",
"form": [
{
"type": "select",
"name": "phone-app-provider",
"label": "Phone service provider",
"description": "You can use a provider etc etc"
},
{
"type": "text",
"name": "phone-id-key",
"label": "phone client ID",
"description": ""
},
{
"type": "text",
"name": "phone-id-key",
"label": "phone client ID",
"description": ""
},
{
"type": "text",
"name": "phone-id-key",
"label": "phone client ID",
"description": ""
}
]
},
{
"name": "Google",
"icon": "google-icon",
"form": [
{
"type": "text",
"name": "google-app-id",
"label": "Google App Id",
"description": ""
},
{
"type": "text",
"name": "google-id-key",
"label": "Google client ID",
"description": ""
}
]
},
{
"name": "Facebook",
"icon": "facebook-icon",
"form": [
{
"type": "text",
"name": "facebook-app-id",
"label": "Facebook App Id",
"description": ""
},
{
"type": "text",
"name": "facebook-id-key",
"label": "Facebook client ID",
"description": ""
}
]
},
{
"name": "Twitter",
"icon": "twitter-icon",
"form": [
{
"type": "text",
"name": "twitter-app-id",
"label": "Twitter App Id",
"description": ""
},
{
"type": "text",
"name": "twitter-id-key",
"label": "Twitter client ID",
"description": ""
}
]
},
{
"name": "Apple",
"icon": "apple-icon",
"form": [
{
"type": "text",
"name": "apple-app-id",
"label": "Apple App Id",
"description": ""
},
{
"type": "text",
"name": "apple-id-key",
"label": "Apple client ID",
"description": ""
}
]
},
{
"name": "Microsoft",
"icon": "microsoft-icon",
"form": [
{
"type": "text",
"name": "microsoft-app-id",
"label": "Microsoft App Id",
"description": ""
},
{
"type": "text",
"name": "microsoft-id-key",
"label": "Microsoft client ID",
"description": ""
}
]
},
{
"name": "Gitlab",
"icon": "gitlab-icon",
"form": [
{
"type": "text",
"name": "gitlab-app-id",
"label": "Gitlab App Id",
"description": ""
},
{
"type": "text",
"name": "gitlab-id-key",
"label": "Gitlab client ID",
"description": ""
}
]
},
{
"name": "Bitbucket",
"icon": "bitbucket-icon",
"form": [
{
"type": "text",
"name": "bitbucket-app-id",
"label": "Bitbucket App Id",
"description": ""
},
{
"type": "text",
"name": "bitbucket-id-key",
"label": "Bitbucket client ID",
"description": ""
}
]
},
{
"name": "Discord",
"icon": "discord-icon",
"form": [
{
"type": "text",
"name": "discord-app-id",
"label": "Discord App Id",
"description": ""
},
{
"type": "text",
"name": "discord-id-key",
"label": "Discord client ID",
"description": ""
}
]
},
{
"name": "Github",
"icon": "github-icon-dark",
"form": [
{
"type": "text",
"name": "github-app-id",
"label": "Github App Id",
"description": ""
},
{
"type": "text",
"name": "github-id-key",
"label": "Github client ID",
"description": ""
}
]
},
{
"name": "Slack",
"icon": "slack-icon",
"form": [
{
"type": "text",
"name": "slack-app-id",
"label": "Slack App Id",
"description": ""
},
{
"type": "text",
"name": "slack-id-key",
"label": "Slack client ID",
"description": ""
}
]
},
{
"name": "Spotify",
"icon": "spotify-icon",
"form": [
{
"type": "text",
"name": "spotify-app-id",
"label": "Spotify App Id",
"description": ""
},
{
"type": "text",
"name": "spotify-id-key",
"label": "Spotify client ID",
"description": ""
}
]
},
{
"name": "Twitch",
"icon": "twitch-icon",
"form": [
{
"type": "text",
"name": "twitch-app-id",
"label": "Twitch App Id",
"description": ""
},
{
"type": "text",
"name": "twitch-id-key",
"label": "Twitch client ID",
"description": ""
}
]
}
]
@@ -0,0 +1,36 @@
{
"name": "Twilio",
"icon": "twilio-icon",
"form": [
{
"type": "text",
"name": "twilio-app-id",
"label": "Enable twilio Provider",
"description": ""
},
{
"type": "text",
"name": "twilio-id-key",
"label": "twilio client ID",
"description": ""
}
]
},
{
"name": "Messagebird",
"icon": "messagebird-icon",
"form": [
{
"type": "text",
"name": "messagebird-app-id",
"label": "Enable gitlab messagebird",
"description": ""
},
{
"type": "text",
"name": "messagebird-id-key",
"label": "messagebird client ID",
"description": ""
}
]
}
@@ -0,0 +1 @@
export { default as Form } from './Form'
@@ -0,0 +1,39 @@
/* .sbui-icon-container {
@apply flex-shrink-0 flex items-center justify-center rounded-full p-3;
}
.sbui-icon-container--brand {
@apply bg-brand-800 bg-opacity-10 text-brand-800;
}
.sbui-icon-container--gray {
@apply bg-gray-600 bg-opacity-10 text-gray-500;
}
.sbui-icon-container--red {
@apply bg-red-600 bg-opacity-10 text-red-500;
}
.sbui-icon-container--yellow {
@apply bg-yellow-600 bg-opacity-10 text-yellow-500;
}
.sbui-icon-container--green {
@apply bg-green-600 bg-opacity-10 text-green-500;
}
.sbui-icon-container--blue {
@apply bg-blue-600 bg-opacity-10 text-blue-500;
}
.sbui-icon-container--indigo {
@apply bg-indigo-600 bg-opacity-10 text-indigo-500;
}
.sbui-icon-container--purple {
@apply bg-purple-600 bg-opacity-10 text-purple-500;
}
.sbui-icon-container--pink {
@apply bg-pink-600 bg-opacity-10 text-pink-500;
} */
@@ -0,0 +1,66 @@
import React from 'react'
import { IconMail, Typography } from './../../index'
export default {
title: 'General/Icon',
component: IconMail,
}
export const Default = (args: any) => (
<div className="block font-sans">
<div>
<Typography.Text>
<IconMail {...args} />
</Typography.Text>
</div>
</div>
)
Default.args = {
size: 16,
strokeWidth: 2,
}
// export const IconList = (args: any) => (
// <>
// <div className="font-sans text-xl bg-blue-100 p-5 mb-3 rounded-md">
// This icons uses react-feather from Feather Icons. For detail you can check
// it <a href="https://github.com/feathericons/react-feather">here</a> and{' '}
// <a href="https://feathericons.com/">here</a>
// </div>
// <div className="flex flex-wrap font-sans">
// {LIST_ICONS.map((icon) => (
// <div className="m-2 shadow-lg rounded-lg w-36 h-36 flex flex-col justify-center items-center dark:text-white">
// <Icon type={icon} key={icon} {...args} />
// <span className="mt-2">{icon}</span>
// </div>
// ))}
// </div>
// </>
// )
// IconList.args = {
// size: 16,
// strokeWidth: 2,
// }
// // const SvgMessagesIcon = () => (
// // <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24">
// // <path
// // stroke-linecap="round"
// // stroke-linejoin="round"
// // stroke-width="2"
// // d="M7 8h10M7 12h4m1 8l-4-4H5a2 2 0 01-2-2V6a2 2 0 012-2h14a2 2 0 012 2v8a2 2 0 01-2 2h-3l-4 4z"
// // />
// // </svg>
// // )
// // export const IconWithSVG = (args: any) => (
// // <Icon {...args} src={<SvgMessagesIcon />} />
// // )
// // IconWithSVG.args = {
// // size: 'xxxlarge',
// // strokeWidth: 4,
// // }
@@ -0,0 +1,26 @@
import React from 'react'
import { render, screen } from '@testing-library/react'
import Icon from './Icon'
describe('#Icon', () => {
it('should render Icon correctly', () => {
render(<Icon data-testid="icon" />)
const $elIcon = screen.queryByTestId('icon')
expect($elIcon).toBeInTheDocument()
})
it('should change svg size', () => {
render(<Icon data-testid="icon" size={40} />)
const $elIcon = screen.queryByTestId('icon')
expect($elIcon.getAttribute('width')).toEqual('40')
expect($elIcon.getAttribute('height')).toEqual('40')
})
it('should change strokeWidth value', () => {
render(<Icon data-testid="icon" strokeWidth={1} />)
const $elIcon = screen.queryByTestId('icon')
expect($elIcon.getAttribute('stroke-width')).toEqual('1')
})
})
+133
View File
@@ -0,0 +1,133 @@
import React from 'react'
import styleHandler from '../../lib/theme/styleHandler'
import { IconContext } from './IconContext'
// @ts-ignore
// import IconStyles from './Icon.module.css'
const IconStyles = {}
interface Props {
className?: string
size?:
| 'tiny'
| 'small'
| 'medium'
| 'large'
| 'xlarge'
| 'xxlarge'
| 'xxxlarge'
| number
type?: string
color?: string
strokeWidth?: number
fill?: string
stroke?: string
background?:
| 'brand'
| 'gray'
| 'red'
| 'yellow'
| 'green'
| 'blue'
| 'indigo'
| 'purple'
| 'pink'
src: React.ReactNode
}
interface StringMap {
[key: string]: number
}
function Icon({
className,
size,
type,
color,
strokeWidth,
fill = undefined,
stroke = undefined,
background,
src,
...props
}: Props) {
const __styles = styleHandler('icon')
return (
<IconContext.Consumer>
{({ contextSize, className: contextClassName }) => {
const defaultSizes: StringMap = {
tiny: 14,
small: 18,
medium: 20,
large: 20,
xlarge: 24,
xxlarge: 30,
xxxlarge: 42,
}
const defaultSize = defaultSizes['large']
// const iconSize = typeof size === 'string' ? defaultSizes[contextSize] : 21
let iconSize: any = 21
// use contextSize of parent (via context hook) if one exists
if (contextSize) {
iconSize = contextSize
? typeof contextSize === 'string'
? defaultSizes[contextSize]
: contextSize
: defaultSize
}
// use size prop of this component if one exists
if (size) {
iconSize = size
? typeof size === 'string'
? defaultSizes[size]
: size
: defaultSize
}
// confitional used for Icons with no color settings
// default these icons to use 'currentColor' ie, the text color
const noColor = !color && !fill && !stroke
let classes = ['sbui-icon', className]
if (contextClassName) {
classes.push(contextClassName)
}
const Icon = (
// custom SVG file
<svg
xmlns="http://www.w3.org/2000/svg"
color={!noColor ? color : 'currentColor'}
fill={!noColor ? (fill ? fill : 'none') : 'none'}
stroke={!noColor ? stroke : 'currentColor'}
strokeWidth={strokeWidth}
className={classes.join(' ')}
width={iconSize}
height={iconSize}
{...props}
>
{src}
</svg>
)
return background ? (
<div
// circle coloured background
className={__styles.container}
>
{Icon}
</div>
) : (
Icon
)
}}
</IconContext.Consumer>
)
}
export default Icon
@@ -0,0 +1,144 @@
import React from 'react'
import styleHandler from '../../lib/theme/styleHandler'
import { IconContext } from './IconContext'
// @ts-ignore
// import IconStyles from './Icon.module.css'
interface Props {
className?: string
size?:
| 'tiny'
| 'small'
| 'medium'
| 'large'
| 'xlarge'
| 'xxlarge'
| 'xxxlarge'
| number
type?: string
color?: string
strokeWidth?: number
fill?: string
stroke?: string
background?:
| 'brand'
| 'gray'
| 'red'
| 'yellow'
| 'green'
| 'blue'
| 'indigo'
| 'purple'
| 'pink'
src?: React.ReactNode
icon?: any
}
interface StringMap {
[key: string]: number
}
function IconBase({
className,
size,
type = 'Mail',
color,
strokeWidth,
fill = undefined,
stroke = undefined,
background,
src,
icon,
...props
}: Props) {
const __styles = styleHandler('icon')
return (
<IconContext.Consumer>
{({ contextSize, className: contextClassName }) => {
const defaultSizes: StringMap = {
tiny: 14,
small: 18,
medium: 20,
large: 20,
xlarge: 24,
xxlarge: 30,
xxxlarge: 42,
}
const defaultSize = defaultSizes['large']
// @ts-ignore
const FeatherIcon = icon
// const iconSize = typeof size === 'string' ? defaultSizes[contextSize] : 21
let iconSize: any = 21
// use contextSize of parent (via context hook) if one exists
if (contextSize) {
iconSize = contextSize
? typeof contextSize === 'string'
? defaultSizes[contextSize]
: contextSize
: defaultSize
}
// use size prop of this component if one exists
if (size) {
iconSize = size
? typeof size === 'string'
? defaultSizes[size]
: size
: defaultSize
}
// confitional used for Icons with no color settings
// default these icons to use 'currentColor' ie, the text color
const noColor = !color && !fill && !stroke
let classes = ['sbui-icon', className]
if (contextClassName) {
classes.push(contextClassName)
}
const IconComponent = () => (
<FeatherIcon
color={!noColor ? color : 'currentColor'}
stroke={!noColor ? stroke : 'currentColor'}
className={classes.join(' ')}
strokeWidth={strokeWidth}
size={iconSize}
fill={!noColor ? (fill ? fill : 'none') : 'none'}
{...props}
/>
)
const Icon = src ? (
// custom SVG file
<svg
xmlns="http://www.w3.org/2000/svg"
color={!noColor ? color : 'currentColor'}
fill={!noColor ? (fill ? fill : 'none') : 'none'}
stroke={!noColor ? stroke : 'currentColor'}
className={classes.join(' ')}
width={iconSize}
height={iconSize}
>
{src}
</svg>
) : (
// feather icon
<IconComponent />
)
return background ? (
<div className={__styles.container}>{Icon}</div>
) : (
Icon
)
}}
</IconContext.Consumer>
)
}
export default IconBase
@@ -0,0 +1,10 @@
import { createContext } from 'react'
type ContextValue = { contextSize?: string; className?: string }
// Make sure the shape of the default value passed to
// createContext matches the shape that the consumers expect!
export const IconContext = createContext<ContextValue>({
contextSize: '',
className: '',
})
@@ -0,0 +1,294 @@
import { FC, SVGAttributes } from 'react'
export interface IconProps extends SVGAttributes<SVGElement> {
color?: string
size?: string | number
}
export type Icon = FC<IconProps>
export const Activity: Icon = require(`react-feather/dist/icons/activity`)
export const Airplay: Icon = require(`react-feather/dist/icons/airplay`)
export const AlertCircle: Icon = require(`react-feather/dist/icons/alert-circle`)
export const AlertOctagon: Icon = require(`react-feather/dist/icons/alert-octagon`)
export const AlertTriangle: Icon = require(`react-feather/dist/icons/alert-triangle`)
export const AlignCenter: Icon = require(`react-feather/dist/icons/align-center`)
export const AlignJustify: Icon = require(`react-feather/dist/icons/align-justify`)
export const AlignLeft: Icon = require(`react-feather/dist/icons/align-left`)
export const AlignRight: Icon = require(`react-feather/dist/icons/align-right`)
export const Anchor: Icon = require(`react-feather/dist/icons/anchor`)
export const Aperture: Icon = require(`react-feather/dist/icons/aperture`)
export const Archive: Icon = require(`react-feather/dist/icons/archive`)
export const ArrowDownCircle: Icon = require(`react-feather/dist/icons/arrow-down-circle`)
export const ArrowDownLeft: Icon = require(`react-feather/dist/icons/arrow-down-left`)
export const ArrowDownRight: Icon = require(`react-feather/dist/icons/arrow-down-right`)
export const ArrowDown: Icon = require(`react-feather/dist/icons/arrow-down`)
export const ArrowLeftCircle: Icon = require(`react-feather/dist/icons/arrow-left-circle`)
export const ArrowLeft: Icon = require(`react-feather/dist/icons/arrow-left`)
export const ArrowRightCircle: Icon = require(`react-feather/dist/icons/arrow-right-circle`)
export const ArrowRight: Icon = require(`react-feather/dist/icons/arrow-right`)
export const ArrowUpCircle: Icon = require(`react-feather/dist/icons/arrow-up-circle`)
export const ArrowUpLeft: Icon = require(`react-feather/dist/icons/arrow-up-left`)
export const ArrowUpRight: Icon = require(`react-feather/dist/icons/arrow-up-right`)
export const ArrowUp: Icon = require(`react-feather/dist/icons/arrow-up`)
export const AtSign: Icon = require(`react-feather/dist/icons/at-sign`)
export const Award: Icon = require(`react-feather/dist/icons/award`)
export const BarChart2: Icon = require(`react-feather/dist/icons/bar-chart-2`)
export const BarChart: Icon = require(`react-feather/dist/icons/bar-chart`)
export const BatteryCharging: Icon = require(`react-feather/dist/icons/battery-charging`)
export const Battery: Icon = require(`react-feather/dist/icons/battery`)
export const BellOff: Icon = require(`react-feather/dist/icons/bell-off`)
export const Bell: Icon = require(`react-feather/dist/icons/bell`)
export const Bluetooth: Icon = require(`react-feather/dist/icons/bluetooth`)
export const Bold: Icon = require(`react-feather/dist/icons/bold`)
export const BookOpen: Icon = require(`react-feather/dist/icons/book-open`)
export const Book: Icon = require(`react-feather/dist/icons/book`)
export const Bookmark: Icon = require(`react-feather/dist/icons/bookmark`)
export const Box: Icon = require(`react-feather/dist/icons/box`)
export const Briefcase: Icon = require(`react-feather/dist/icons/briefcase`)
export const Calendar: Icon = require(`react-feather/dist/icons/calendar`)
export const CameraOff: Icon = require(`react-feather/dist/icons/camera-off`)
export const Camera: Icon = require(`react-feather/dist/icons/camera`)
export const Cast: Icon = require(`react-feather/dist/icons/cast`)
export const CheckCircle: Icon = require(`react-feather/dist/icons/check-circle`)
export const CheckSquare: Icon = require(`react-feather/dist/icons/check-square`)
export const Check: Icon = require(`react-feather/dist/icons/check`)
export const ChevronDown: Icon = require(`react-feather/dist/icons/chevron-down`)
export const ChevronLeft: Icon = require(`react-feather/dist/icons/chevron-left`)
export const ChevronRight: Icon = require(`react-feather/dist/icons/chevron-right`)
export const ChevronUp: Icon = require(`react-feather/dist/icons/chevron-up`)
export const ChevronsDown: Icon = require(`react-feather/dist/icons/chevrons-down`)
export const ChevronsLeft: Icon = require(`react-feather/dist/icons/chevrons-left`)
export const ChevronsRight: Icon = require(`react-feather/dist/icons/chevrons-right`)
export const ChevronsUp: Icon = require(`react-feather/dist/icons/chevrons-up`)
export const Chrome: Icon = require(`react-feather/dist/icons/chrome`)
export const Circle: Icon = require(`react-feather/dist/icons/circle`)
export const Clipboard: Icon = require(`react-feather/dist/icons/clipboard`)
export const Clock: Icon = require(`react-feather/dist/icons/clock`)
export const CloudDrizzle: Icon = require(`react-feather/dist/icons/cloud-drizzle`)
export const CloudLightning: Icon = require(`react-feather/dist/icons/cloud-lightning`)
export const CloudOff: Icon = require(`react-feather/dist/icons/cloud-off`)
export const CloudRain: Icon = require(`react-feather/dist/icons/cloud-rain`)
export const CloudSnow: Icon = require(`react-feather/dist/icons/cloud-snow`)
export const Cloud: Icon = require(`react-feather/dist/icons/cloud`)
export const Code: Icon = require(`react-feather/dist/icons/code`)
export const Codepen: Icon = require(`react-feather/dist/icons/codepen`)
export const Codesandbox: Icon = require(`react-feather/dist/icons/codesandbox`)
export const Coffee: Icon = require(`react-feather/dist/icons/coffee`)
export const Columns: Icon = require(`react-feather/dist/icons/columns`)
export const Command: Icon = require(`react-feather/dist/icons/command`)
export const Compass: Icon = require(`react-feather/dist/icons/compass`)
export const Copy: Icon = require(`react-feather/dist/icons/copy`)
export const CornerDownLeft: Icon = require(`react-feather/dist/icons/corner-down-left`)
export const CornerDownRight: Icon = require(`react-feather/dist/icons/corner-down-right`)
export const CornerLeftDown: Icon = require(`react-feather/dist/icons/corner-left-down`)
export const CornerLeftUp: Icon = require(`react-feather/dist/icons/corner-left-up`)
export const CornerRightDown: Icon = require(`react-feather/dist/icons/corner-right-down`)
export const CornerRightUp: Icon = require(`react-feather/dist/icons/corner-right-up`)
export const CornerUpLeft: Icon = require(`react-feather/dist/icons/corner-up-left`)
export const CornerUpRight: Icon = require(`react-feather/dist/icons/corner-up-right`)
export const Cpu: Icon = require(`react-feather/dist/icons/cpu`)
export const CreditCard: Icon = require(`react-feather/dist/icons/credit-card`)
export const Crop: Icon = require(`react-feather/dist/icons/crop`)
export const Crosshair: Icon = require(`react-feather/dist/icons/crosshair`)
export const Database: Icon = require(`react-feather/dist/icons/database`)
export const Delete: Icon = require(`react-feather/dist/icons/delete`)
export const Disc: Icon = require(`react-feather/dist/icons/disc`)
export const DivideCircle: Icon = require(`react-feather/dist/icons/divide-circle`)
export const DivideSquare: Icon = require(`react-feather/dist/icons/divide-square`)
export const Divide: Icon = require(`react-feather/dist/icons/divide`)
export const DollarSign: Icon = require(`react-feather/dist/icons/dollar-sign`)
export const DownloadCloud: Icon = require(`react-feather/dist/icons/download-cloud`)
export const Download: Icon = require(`react-feather/dist/icons/download`)
export const Dribbble: Icon = require(`react-feather/dist/icons/dribbble`)
export const Droplet: Icon = require(`react-feather/dist/icons/droplet`)
export const Edit2: Icon = require(`react-feather/dist/icons/edit-2`)
export const Edit3: Icon = require(`react-feather/dist/icons/edit-3`)
export const Edit: Icon = require(`react-feather/dist/icons/edit`)
export const ExternalLink: Icon = require(`react-feather/dist/icons/external-link`)
export const EyeOff: Icon = require(`react-feather/dist/icons/eye-off`)
export const Eye: Icon = require(`react-feather/dist/icons/eye`)
export const Facebook: Icon = require(`react-feather/dist/icons/facebook`)
export const FastForward: Icon = require(`react-feather/dist/icons/fast-forward`)
export const Feather: Icon = require(`react-feather/dist/icons/feather`)
export const Figma: Icon = require(`react-feather/dist/icons/figma`)
export const FileMinus: Icon = require(`react-feather/dist/icons/file-minus`)
export const FilePlus: Icon = require(`react-feather/dist/icons/file-plus`)
export const FileText: Icon = require(`react-feather/dist/icons/file-text`)
export const File: Icon = require(`react-feather/dist/icons/file`)
export const Film: Icon = require(`react-feather/dist/icons/film`)
export const Filter: Icon = require(`react-feather/dist/icons/filter`)
export const Flag: Icon = require(`react-feather/dist/icons/flag`)
export const FolderMinus: Icon = require(`react-feather/dist/icons/folder-minus`)
export const FolderPlus: Icon = require(`react-feather/dist/icons/folder-plus`)
export const Folder: Icon = require(`react-feather/dist/icons/folder`)
export const Framer: Icon = require(`react-feather/dist/icons/framer`)
export const Frown: Icon = require(`react-feather/dist/icons/frown`)
export const Gift: Icon = require(`react-feather/dist/icons/gift`)
export const GitBranch: Icon = require(`react-feather/dist/icons/git-branch`)
export const GitCommit: Icon = require(`react-feather/dist/icons/git-commit`)
export const GitMerge: Icon = require(`react-feather/dist/icons/git-merge`)
export const GitPullRequest: Icon = require(`react-feather/dist/icons/git-pull-request`)
export const GitHub: Icon = require(`react-feather/dist/icons/github`)
export const Gitlab: Icon = require(`react-feather/dist/icons/gitlab`)
export const Globe: Icon = require(`react-feather/dist/icons/globe`)
export const Grid: Icon = require(`react-feather/dist/icons/grid`)
export const HardDrive: Icon = require(`react-feather/dist/icons/hard-drive`)
export const Hash: Icon = require(`react-feather/dist/icons/hash`)
export const Headphones: Icon = require(`react-feather/dist/icons/headphones`)
export const Heart: Icon = require(`react-feather/dist/icons/heart`)
export const HelpCircle: Icon = require(`react-feather/dist/icons/help-circle`)
export const Hexagon: Icon = require(`react-feather/dist/icons/hexagon`)
export const Home: Icon = require(`react-feather/dist/icons/home`)
export const Image: Icon = require(`react-feather/dist/icons/image`)
export const Inbox: Icon = require(`react-feather/dist/icons/inbox`)
export const Info: Icon = require(`react-feather/dist/icons/info`)
export const Instagram: Icon = require(`react-feather/dist/icons/instagram`)
export const Italic: Icon = require(`react-feather/dist/icons/italic`)
export const Key: Icon = require(`react-feather/dist/icons/key`)
export const Layers: Icon = require(`react-feather/dist/icons/layers`)
export const Layout: Icon = require(`react-feather/dist/icons/layout`)
export const LifeBuoy: Icon = require(`react-feather/dist/icons/life-buoy`)
export const Link2: Icon = require(`react-feather/dist/icons/link-2`)
export const Link: Icon = require(`react-feather/dist/icons/link`)
export const Linkedin: Icon = require(`react-feather/dist/icons/linkedin`)
export const List: Icon = require(`react-feather/dist/icons/list`)
export const Loader: Icon = require(`react-feather/dist/icons/loader`)
export const Lock: Icon = require(`react-feather/dist/icons/lock`)
export const LogIn: Icon = require(`react-feather/dist/icons/log-in`)
export const LogOut: Icon = require(`react-feather/dist/icons/log-out`)
export const Mail: Icon = require(`react-feather/dist/icons/mail`)
export const MapPin: Icon = require(`react-feather/dist/icons/map-pin`)
export const Map: Icon = require(`react-feather/dist/icons/map`)
export const Maximize2: Icon = require(`react-feather/dist/icons/maximize-2`)
export const Maximize: Icon = require(`react-feather/dist/icons/maximize`)
export const Meh: Icon = require(`react-feather/dist/icons/meh`)
export const Menu: Icon = require(`react-feather/dist/icons/menu`)
export const MessageCircle: Icon = require(`react-feather/dist/icons/message-circle`)
export const MessageSquare: Icon = require(`react-feather/dist/icons/message-square`)
export const MicOff: Icon = require(`react-feather/dist/icons/mic-off`)
export const Mic: Icon = require(`react-feather/dist/icons/mic`)
export const Minimize2: Icon = require(`react-feather/dist/icons/minimize-2`)
export const Minimize: Icon = require(`react-feather/dist/icons/minimize`)
export const MinusCircle: Icon = require(`react-feather/dist/icons/minus-circle`)
export const MinusSquare: Icon = require(`react-feather/dist/icons/minus-square`)
export const Minus: Icon = require(`react-feather/dist/icons/minus`)
export const Monitor: Icon = require(`react-feather/dist/icons/monitor`)
export const Moon: Icon = require(`react-feather/dist/icons/moon`)
export const MoreHorizontal: Icon = require(`react-feather/dist/icons/more-horizontal`)
export const MoreVertical: Icon = require(`react-feather/dist/icons/more-vertical`)
export const MousePointer: Icon = require(`react-feather/dist/icons/mouse-pointer`)
export const Move: Icon = require(`react-feather/dist/icons/move`)
export const Music: Icon = require(`react-feather/dist/icons/music`)
export const Navigation2: Icon = require(`react-feather/dist/icons/navigation-2`)
export const Navigation: Icon = require(`react-feather/dist/icons/navigation`)
export const Octagon: Icon = require(`react-feather/dist/icons/octagon`)
export const Package: Icon = require(`react-feather/dist/icons/package`)
export const Paperclip: Icon = require(`react-feather/dist/icons/paperclip`)
export const PauseCircle: Icon = require(`react-feather/dist/icons/pause-circle`)
export const Pause: Icon = require(`react-feather/dist/icons/pause`)
export const PenTool: Icon = require(`react-feather/dist/icons/pen-tool`)
export const Percent: Icon = require(`react-feather/dist/icons/percent`)
export const PhoneCall: Icon = require(`react-feather/dist/icons/phone-call`)
export const PhoneForwarded: Icon = require(`react-feather/dist/icons/phone-forwarded`)
export const PhoneIncoming: Icon = require(`react-feather/dist/icons/phone-incoming`)
export const PhoneMissed: Icon = require(`react-feather/dist/icons/phone-missed`)
export const PhoneOff: Icon = require(`react-feather/dist/icons/phone-off`)
export const PhoneOutgoing: Icon = require(`react-feather/dist/icons/phone-outgoing`)
export const Phone: Icon = require(`react-feather/dist/icons/phone`)
export const PieChart: Icon = require(`react-feather/dist/icons/pie-chart`)
export const PlayCircle: Icon = require(`react-feather/dist/icons/play-circle`)
export const Play: Icon = require(`react-feather/dist/icons/play`)
export const PlusCircle: Icon = require(`react-feather/dist/icons/plus-circle`)
export const PlusSquare: Icon = require(`react-feather/dist/icons/plus-square`)
export const Plus: Icon = require(`react-feather/dist/icons/plus`)
export const Pocket: Icon = require(`react-feather/dist/icons/pocket`)
export const Power: Icon = require(`react-feather/dist/icons/power`)
export const Printer: Icon = require(`react-feather/dist/icons/printer`)
export const Radio: Icon = require(`react-feather/dist/icons/radio`)
export const RefreshCcw: Icon = require(`react-feather/dist/icons/refresh-ccw`)
export const RefreshCw: Icon = require(`react-feather/dist/icons/refresh-cw`)
export const Repeat: Icon = require(`react-feather/dist/icons/repeat`)
export const Rewind: Icon = require(`react-feather/dist/icons/rewind`)
export const RotateCcw: Icon = require(`react-feather/dist/icons/rotate-ccw`)
export const RotateCw: Icon = require(`react-feather/dist/icons/rotate-cw`)
export const Rss: Icon = require(`react-feather/dist/icons/rss`)
export const Save: Icon = require(`react-feather/dist/icons/save`)
export const Scissors: Icon = require(`react-feather/dist/icons/scissors`)
export const Search: Icon = require(`react-feather/dist/icons/search`)
export const Send: Icon = require(`react-feather/dist/icons/send`)
export const Server: Icon = require(`react-feather/dist/icons/server`)
export const Settings: Icon = require(`react-feather/dist/icons/settings`)
export const Share2: Icon = require(`react-feather/dist/icons/share-2`)
export const Share: Icon = require(`react-feather/dist/icons/share`)
export const ShieldOff: Icon = require(`react-feather/dist/icons/shield-off`)
export const Shield: Icon = require(`react-feather/dist/icons/shield`)
export const ShoppingBag: Icon = require(`react-feather/dist/icons/shopping-bag`)
export const ShoppingCart: Icon = require(`react-feather/dist/icons/shopping-cart`)
export const Shuffle: Icon = require(`react-feather/dist/icons/shuffle`)
export const Sidebar: Icon = require(`react-feather/dist/icons/sidebar`)
export const SkipBack: Icon = require(`react-feather/dist/icons/skip-back`)
export const SkipForward: Icon = require(`react-feather/dist/icons/skip-forward`)
export const Slack: Icon = require(`react-feather/dist/icons/slack`)
export const Slash: Icon = require(`react-feather/dist/icons/slash`)
export const Sliders: Icon = require(`react-feather/dist/icons/sliders`)
export const Smartphone: Icon = require(`react-feather/dist/icons/smartphone`)
export const Smile: Icon = require(`react-feather/dist/icons/smile`)
export const Speaker: Icon = require(`react-feather/dist/icons/speaker`)
export const Square: Icon = require(`react-feather/dist/icons/square`)
export const Star: Icon = require(`react-feather/dist/icons/star`)
export const StopCircle: Icon = require(`react-feather/dist/icons/stop-circle`)
export const Sun: Icon = require(`react-feather/dist/icons/sun`)
export const Sunrise: Icon = require(`react-feather/dist/icons/sunrise`)
export const Sunset: Icon = require(`react-feather/dist/icons/sunset`)
export const Tablet: Icon = require(`react-feather/dist/icons/tablet`)
export const Tag: Icon = require(`react-feather/dist/icons/tag`)
export const Target: Icon = require(`react-feather/dist/icons/target`)
export const Terminal: Icon = require(`react-feather/dist/icons/terminal`)
export const Thermometer: Icon = require(`react-feather/dist/icons/thermometer`)
export const ThumbsDown: Icon = require(`react-feather/dist/icons/thumbs-down`)
export const ThumbsUp: Icon = require(`react-feather/dist/icons/thumbs-up`)
export const ToggleLeft: Icon = require(`react-feather/dist/icons/toggle-left`)
export const ToggleRight: Icon = require(`react-feather/dist/icons/toggle-right`)
export const Tool: Icon = require(`react-feather/dist/icons/tool`)
export const Trash2: Icon = require(`react-feather/dist/icons/trash-2`)
export const Trash: Icon = require(`react-feather/dist/icons/trash`)
export const Trello: Icon = require(`react-feather/dist/icons/trello`)
export const TrendingDown: Icon = require(`react-feather/dist/icons/trending-down`)
export const TrendingUp: Icon = require(`react-feather/dist/icons/trending-up`)
export const Triangle: Icon = require(`react-feather/dist/icons/triangle`)
export const Truck: Icon = require(`react-feather/dist/icons/truck`)
export const Tv: Icon = require(`react-feather/dist/icons/tv`)
export const Twitch: Icon = require(`react-feather/dist/icons/twitch`)
export const Twitter: Icon = require(`react-feather/dist/icons/twitter`)
export const Type: Icon = require(`react-feather/dist/icons/type`)
export const Umbrella: Icon = require(`react-feather/dist/icons/umbrella`)
export const Underline: Icon = require(`react-feather/dist/icons/underline`)
export const Unlock: Icon = require(`react-feather/dist/icons/unlock`)
export const UploadCloud: Icon = require(`react-feather/dist/icons/upload-cloud`)
export const Upload: Icon = require(`react-feather/dist/icons/upload`)
export const UserCheck: Icon = require(`react-feather/dist/icons/user-check`)
export const UserMinus: Icon = require(`react-feather/dist/icons/user-minus`)
export const UserPlus: Icon = require(`react-feather/dist/icons/user-plus`)
export const UserX: Icon = require(`react-feather/dist/icons/user-x`)
export const User: Icon = require(`react-feather/dist/icons/user`)
export const Users: Icon = require(`react-feather/dist/icons/users`)
export const VideoOff: Icon = require(`react-feather/dist/icons/video-off`)
export const Video: Icon = require(`react-feather/dist/icons/video`)
export const Voicemail: Icon = require(`react-feather/dist/icons/voicemail`)
export const Volume1: Icon = require(`react-feather/dist/icons/volume-1`)
export const Volume2: Icon = require(`react-feather/dist/icons/volume-2`)
export const VolumeX: Icon = require(`react-feather/dist/icons/volume-x`)
export const Volume: Icon = require(`react-feather/dist/icons/volume`)
export const Watch: Icon = require(`react-feather/dist/icons/watch`)
export const WifiOff: Icon = require(`react-feather/dist/icons/wifi-off`)
export const Wifi: Icon = require(`react-feather/dist/icons/wifi`)
export const Wind: Icon = require(`react-feather/dist/icons/wind`)
export const XCircle: Icon = require(`react-feather/dist/icons/x-circle`)
export const XOctagon: Icon = require(`react-feather/dist/icons/x-octagon`)
export const XSquare: Icon = require(`react-feather/dist/icons/x-square`)
export const X: Icon = require(`react-feather/dist/icons/x`)
export const Youtube: Icon = require(`react-feather/dist/icons/youtube`)
export const ZapOff: Icon = require(`react-feather/dist/icons/zap-off`)
export const Zap: Icon = require(`react-feather/dist/icons/zap`)
export const ZoomIn: Icon = require(`react-feather/dist/icons/zoom-in`)
export const ZoomOut: Icon = require(`react-feather/dist/icons/zoom-out`)
@@ -0,0 +1,13 @@
// DO NOT EDIT
// this file is generated by /internals/populate-icons script
import * as React from 'react'
// @ts-ignore
import { Activity } from 'react-feather'
import IconBase from './../../IconBase'
function IconActivity(props: any) {
return <IconBase icon={Activity} {...props} />
}
export default IconActivity
@@ -0,0 +1 @@
export { default as IconActivity } from './IconActivity'
@@ -0,0 +1,13 @@
// DO NOT EDIT
// this file is generated by /internals/populate-icons script
import * as React from 'react'
// @ts-ignore
import { Airplay } from 'react-feather'
import IconBase from './../../IconBase'
function IconAirplay(props: any) {
return <IconBase icon={Airplay} {...props} />
}
export default IconAirplay
@@ -0,0 +1 @@
export { default as IconAirplay } from './IconAirplay'
@@ -0,0 +1,13 @@
// DO NOT EDIT
// this file is generated by /internals/populate-icons script
import * as React from 'react'
// @ts-ignore
import { AlertCircle } from 'react-feather'
import IconBase from './../../IconBase'
function IconAlertCircle(props: any) {
return <IconBase icon={AlertCircle} {...props} />
}
export default IconAlertCircle
@@ -0,0 +1 @@
export { default as IconAlertCircle } from './IconAlertCircle'
@@ -0,0 +1,13 @@
// DO NOT EDIT
// this file is generated by /internals/populate-icons script
import * as React from 'react'
// @ts-ignore
import { AlertOctagon } from 'react-feather'
import IconBase from './../../IconBase'
function IconAlertOctagon(props: any) {
return <IconBase icon={AlertOctagon} {...props} />
}
export default IconAlertOctagon
@@ -0,0 +1 @@
export { default as IconAlertOctagon } from './IconAlertOctagon'
@@ -0,0 +1,13 @@
// DO NOT EDIT
// this file is generated by /internals/populate-icons script
import * as React from 'react'
// @ts-ignore
import { AlertTriangle } from 'react-feather'
import IconBase from './../../IconBase'
function IconAlertTriangle(props: any) {
return <IconBase icon={AlertTriangle} {...props} />
}
export default IconAlertTriangle
@@ -0,0 +1 @@
export { default as IconAlertTriangle } from './IconAlertTriangle'
@@ -0,0 +1,13 @@
// DO NOT EDIT
// this file is generated by /internals/populate-icons script
import * as React from 'react'
// @ts-ignore
import { AlignCenter } from 'react-feather'
import IconBase from './../../IconBase'
function IconAlignCenter(props: any) {
return <IconBase icon={AlignCenter} {...props} />
}
export default IconAlignCenter
@@ -0,0 +1 @@
export { default as IconAlignCenter } from './IconAlignCenter'
@@ -0,0 +1,13 @@
// DO NOT EDIT
// this file is generated by /internals/populate-icons script
import * as React from 'react'
// @ts-ignore
import { AlignJustify } from 'react-feather'
import IconBase from './../../IconBase'
function IconAlignJustify(props: any) {
return <IconBase icon={AlignJustify} {...props} />
}
export default IconAlignJustify
@@ -0,0 +1 @@
export { default as IconAlignJustify } from './IconAlignJustify'
@@ -0,0 +1,13 @@
// DO NOT EDIT
// this file is generated by /internals/populate-icons script
import * as React from 'react'
// @ts-ignore
import { AlignLeft } from 'react-feather'
import IconBase from './../../IconBase'
function IconAlignLeft(props: any) {
return <IconBase icon={AlignLeft} {...props} />
}
export default IconAlignLeft
@@ -0,0 +1 @@
export { default as IconAlignLeft } from './IconAlignLeft'
@@ -0,0 +1,13 @@
// DO NOT EDIT
// this file is generated by /internals/populate-icons script
import * as React from 'react'
// @ts-ignore
import { AlignRight } from 'react-feather'
import IconBase from './../../IconBase'
function IconAlignRight(props: any) {
return <IconBase icon={AlignRight} {...props} />
}
export default IconAlignRight
@@ -0,0 +1 @@
export { default as IconAlignRight } from './IconAlignRight'
@@ -0,0 +1,13 @@
// DO NOT EDIT
// this file is generated by /internals/populate-icons script
import * as React from 'react'
// @ts-ignore
import { Anchor } from 'react-feather'
import IconBase from './../../IconBase'
function IconAnchor(props: any) {
return <IconBase icon={Anchor} {...props} />
}
export default IconAnchor
@@ -0,0 +1 @@
export { default as IconAnchor } from './IconAnchor'
@@ -0,0 +1,13 @@
// DO NOT EDIT
// this file is generated by /internals/populate-icons script
import * as React from 'react'
// @ts-ignore
import { Aperture } from 'react-feather'
import IconBase from './../../IconBase'
function IconAperture(props: any) {
return <IconBase icon={Aperture} {...props} />
}
export default IconAperture
Loaded 100 of 1130 files, more files were not shown because too many files have changed in this diff. Show more