@hellboy/ds 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +111 -0
- package/dist/index.css +3699 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.mts +1087 -0
- package/dist/index.d.ts +1087 -0
- package/dist/index.js +3391 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3287 -0
- package/dist/index.mjs.map +1 -0
- package/dist/theme.css +55 -0
- package/hellboy-ds-0.1.2.tgz +0 -0
- package/package.json +42 -0
- package/src/components/badge/Badge.tsx +29 -0
- package/src/components/badge/index.ts +1 -0
- package/src/components/banner/Banner.tsx +48 -0
- package/src/components/banner/banner.css +44 -0
- package/src/components/banner/index.ts +1 -0
- package/src/components/button/button.tsx +127 -0
- package/src/components/button/index.ts +1 -0
- package/src/components/card/card.tsx +57 -0
- package/src/components/card/index.ts +1 -0
- package/src/components/checkbox/Checkbox.tsx +98 -0
- package/src/components/checkbox/index.ts +1 -0
- package/src/components/code-block/code-block.tsx +44 -0
- package/src/components/code-block/index.ts +1 -0
- package/src/components/color-control/color-control.tsx +322 -0
- package/src/components/color-control/index.ts +1 -0
- package/src/components/drag-handle/DragHandle.tsx +78 -0
- package/src/components/drag-handle/index.ts +1 -0
- package/src/components/drawer/drawer.tsx +82 -0
- package/src/components/drawer/index.ts +1 -0
- package/src/components/floating-bar/floating-bar.tsx +52 -0
- package/src/components/floating-bar/index.ts +2 -0
- package/src/components/footer/footer.tsx +28 -0
- package/src/components/footer/index.ts +1 -0
- package/src/components/grid/Grid.tsx +53 -0
- package/src/components/grid/index.ts +1 -0
- package/src/components/header/header.tsx +57 -0
- package/src/components/header/index.ts +1 -0
- package/src/components/icons/icons.tsx +44 -0
- package/src/components/icons/index.ts +1 -0
- package/src/components/index.ts +29 -0
- package/src/components/input/DatePicker.tsx +133 -0
- package/src/components/input/Input.tsx +220 -0
- package/src/components/input/InputDate.tsx +10 -0
- package/src/components/input/InputDateTime.tsx +10 -0
- package/src/components/input/InputEmail.tsx +10 -0
- package/src/components/input/InputField.tsx +137 -0
- package/src/components/input/InputNumber.tsx +10 -0
- package/src/components/input/InputPassword.tsx +10 -0
- package/src/components/input/InputSearch.tsx +10 -0
- package/src/components/input/InputTel.tsx +10 -0
- package/src/components/input/InputText.tsx +10 -0
- package/src/components/input/InputTime.tsx +10 -0
- package/src/components/input/InputUrl.tsx +10 -0
- package/src/components/input/TimePicker.tsx +151 -0
- package/src/components/input/index.ts +11 -0
- package/src/components/layout/Layout.tsx +244 -0
- package/src/components/layout/index.ts +1 -0
- package/src/components/list/List.tsx +159 -0
- package/src/components/list/index.ts +1 -0
- package/src/components/navbar/MenuCategory.tsx +20 -0
- package/src/components/navbar/MenuGroup.tsx +288 -0
- package/src/components/navbar/MenuItem.tsx +65 -0
- package/src/components/navbar/Navbar.tsx +23 -0
- package/src/components/navbar/index.ts +4 -0
- package/src/components/page/index.ts +1 -0
- package/src/components/page/page.tsx +46 -0
- package/src/components/page-index/PageIndex.tsx +275 -0
- package/src/components/page-index/index.ts +1 -0
- package/src/components/popover/index.ts +1 -0
- package/src/components/popover/popover.tsx +199 -0
- package/src/components/radio/Radio.tsx +176 -0
- package/src/components/radio/index.ts +1 -0
- package/src/components/section/index.ts +1 -0
- package/src/components/section/section.tsx +66 -0
- package/src/components/select/Select.tsx +212 -0
- package/src/components/select/index.ts +1 -0
- package/src/components/slider/Slider.tsx +267 -0
- package/src/components/slider/index.ts +1 -0
- package/src/components/switch/index.ts +1 -0
- package/src/components/switch/switch.tsx +99 -0
- package/src/components/table/Table.tsx +147 -0
- package/src/components/table/index.ts +1 -0
- package/src/components/theme-control/index.ts +1 -0
- package/src/components/theme-control/theme-control.tsx +78 -0
- package/src/components/tooltip/index.ts +1 -0
- package/src/components/tooltip/tooltip.tsx +207 -0
- package/src/contexts/NavbarTooltipContext.tsx +48 -0
- package/src/contexts/index.ts +1 -0
- package/src/foundations/motion.md +136 -0
- package/src/index.ts +40 -0
- package/src/style/_shared/field.css +69 -0
- package/src/style/components/badge/badge.css +74 -0
- package/src/style/components/button/button.css +244 -0
- package/src/style/components/card/card.css +69 -0
- package/src/style/components/checkbox.css +142 -0
- package/src/style/components/code-block/code-block.css +34 -0
- package/src/style/components/color-control/color-control.css +126 -0
- package/src/style/components/drag-handle/drag-handle.css +68 -0
- package/src/style/components/drawer/drawer.css +210 -0
- package/src/style/components/floating-bar/floating-bar.css +39 -0
- package/src/style/components/footer/footer.css +108 -0
- package/src/style/components/grid/grid.css +33 -0
- package/src/style/components/header/header.css +44 -0
- package/src/style/components/icons/icons.css +44 -0
- package/src/style/components/input/input.css +393 -0
- package/src/style/components/layout/layout.css +205 -0
- package/src/style/components/list/list.css +140 -0
- package/src/style/components/navbar/navbar.css +342 -0
- package/src/style/components/page/page.css +46 -0
- package/src/style/components/page-index/page-index.css +158 -0
- package/src/style/components/popover/popover.css +44 -0
- package/src/style/components/radio.css +178 -0
- package/src/style/components/section/section.css +67 -0
- package/src/style/components/select/select.css +143 -0
- package/src/style/components/slider/slider.css +159 -0
- package/src/style/components/switch/switch.css +267 -0
- package/src/style/components/table/table.css +108 -0
- package/src/style/components/theme-control/theme-control.css +35 -0
- package/src/style/components/tooltip/tooltip.css +52 -0
- package/src/style/foundations/global.css +316 -0
- package/src/style/foundations/motion.css +164 -0
- package/src/style/foundations/spacing.css +51 -0
- package/src/style/foundations/typography.css +39 -0
- package/src/style/foundations/z-index.css +81 -0
- package/src/style/modes/dark.css +146 -0
- package/src/style/modes/light.css +147 -0
- package/src/style/semantic.css +52 -0
- package/src/style/styles.css +51 -0
- package/src/style/themes/theme.json +37 -0
- package/src/utils/README.md +305 -0
- package/src/utils/USER_PREFERENCES.md +558 -0
- package/src/utils/theme.ts +127 -0
- package/src/utils/user-preferences.ts +577 -0
- package/tsconfig.json +25 -0
- package/tsup.config.ts +52 -0
package/dist/theme.css
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Theme Configuration (generated from theme.json)
|
|
3
|
+
* Generated during build from src/style/themes/theme.json
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
:root {
|
|
7
|
+
/* Primary Color */
|
|
8
|
+
--primary-hue: 0;
|
|
9
|
+
--primary-saturation: 69%;
|
|
10
|
+
--primary-lightness: 31%;
|
|
11
|
+
--primary-lightness-hover: undefined%;
|
|
12
|
+
--primary-lightness-active: undefined%;
|
|
13
|
+
--primary-lightness-disabled: undefined%;
|
|
14
|
+
|
|
15
|
+
/* Secondary Color */
|
|
16
|
+
--secondary-hue: 16;
|
|
17
|
+
--secondary-saturation: 63%;
|
|
18
|
+
--secondary-lightness: 23%;
|
|
19
|
+
--secondary-lightness-hover: undefined%;
|
|
20
|
+
--secondary-lightness-active: undefined%;
|
|
21
|
+
--secondary-lightness-disabled: undefined%;
|
|
22
|
+
|
|
23
|
+
/* Accent Color */
|
|
24
|
+
--accent-hue: 0;
|
|
25
|
+
--accent-saturation: 89%;
|
|
26
|
+
--accent-lightness: 41%;
|
|
27
|
+
--accent-lightness-hover: undefined%;
|
|
28
|
+
--accent-lightness-active: undefined%;
|
|
29
|
+
--accent-lightness-disabled: undefined%;
|
|
30
|
+
|
|
31
|
+
/* Status Colors */
|
|
32
|
+
--success-hue: 140;
|
|
33
|
+
--success-saturation: 100%;
|
|
34
|
+
--success-lightness: 19%;
|
|
35
|
+
--success-lightness-hover: undefined%;
|
|
36
|
+
--success-lightness-active: undefined%;
|
|
37
|
+
|
|
38
|
+
--warning-hue: 34;
|
|
39
|
+
--warning-saturation: 100%;
|
|
40
|
+
--warning-lightness: 31%;
|
|
41
|
+
--warning-lightness-hover: undefined%;
|
|
42
|
+
--warning-lightness-active: undefined%;
|
|
43
|
+
|
|
44
|
+
--error-hue: 264;
|
|
45
|
+
--error-saturation: 0%;
|
|
46
|
+
--error-lightness: 14%;
|
|
47
|
+
--error-lightness-hover: undefined%;
|
|
48
|
+
--error-lightness-active: undefined%;
|
|
49
|
+
|
|
50
|
+
--info-hue: 261;
|
|
51
|
+
--info-saturation: 69%;
|
|
52
|
+
--info-lightness: 31%;
|
|
53
|
+
--info-lightness-hover: undefined%;
|
|
54
|
+
--info-lightness-active: undefined%;
|
|
55
|
+
}
|
|
Binary file
|
package/package.json
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@hellboy/ds",
|
|
3
|
+
"version": "0.1.2",
|
|
4
|
+
"description": "Hellboy Design System - Core components",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"module": "dist/index.mjs",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.mjs",
|
|
12
|
+
"require": "./dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"./dist/index.css": "./dist/index.css",
|
|
15
|
+
"./dist/theme.css": "./dist/theme.css"
|
|
16
|
+
},
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsup src/index.ts --dts",
|
|
19
|
+
"dev": "tsup src/index.ts --dts --watch"
|
|
20
|
+
},
|
|
21
|
+
"keywords": [
|
|
22
|
+
"design-system",
|
|
23
|
+
"components",
|
|
24
|
+
"ui"
|
|
25
|
+
],
|
|
26
|
+
"author": "",
|
|
27
|
+
"license": "MIT",
|
|
28
|
+
"dependencies": {
|
|
29
|
+
"@ariakit/react": "^0.4.0",
|
|
30
|
+
"@iconify/react": "^6.0.2",
|
|
31
|
+
"famicons": "^7.2.3"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@types/react": "^18.2.0",
|
|
35
|
+
"tsup": "^8.5.1",
|
|
36
|
+
"typescript": "^5.3.0"
|
|
37
|
+
},
|
|
38
|
+
"peerDependencies": {
|
|
39
|
+
"react": "^18.0.0",
|
|
40
|
+
"react-dom": "^18.0.0"
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import '../../style/components/badge/badge.css';
|
|
3
|
+
|
|
4
|
+
export type BadgeVariant = 'primary' | 'secondary' | 'tertiary' | 'accent' | 'success' | 'warning' | 'error' | 'info';
|
|
5
|
+
export type BadgeSize = 'sm' | 'md' | 'lg';
|
|
6
|
+
|
|
7
|
+
export interface BadgeProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
8
|
+
variant?: BadgeVariant;
|
|
9
|
+
size?: BadgeSize;
|
|
10
|
+
children: React.ReactNode;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const Badge: React.FC<BadgeProps> = ({
|
|
14
|
+
variant = 'primary',
|
|
15
|
+
size = 'md',
|
|
16
|
+
className = '',
|
|
17
|
+
children,
|
|
18
|
+
...props
|
|
19
|
+
}) => {
|
|
20
|
+
const classes = ['badge', `badge--${variant}`, `badge--${size}`, className]
|
|
21
|
+
.filter(Boolean)
|
|
22
|
+
.join(' ');
|
|
23
|
+
|
|
24
|
+
return (
|
|
25
|
+
<span className={classes} {...props}>
|
|
26
|
+
{children}
|
|
27
|
+
</span>
|
|
28
|
+
);
|
|
29
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Badge';
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { Icon } from '../icons';
|
|
3
|
+
import { Button } from '../button';
|
|
4
|
+
import './banner.css';
|
|
5
|
+
|
|
6
|
+
export type BannerType = 'info' | 'warning' | 'error' | 'success';
|
|
7
|
+
|
|
8
|
+
export interface BannerProps {
|
|
9
|
+
type?: BannerType;
|
|
10
|
+
children: ReactNode;
|
|
11
|
+
icon?: string;
|
|
12
|
+
onDismiss?: () => void;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export const Banner: React.FC<BannerProps> = ({
|
|
16
|
+
type = 'info',
|
|
17
|
+
children,
|
|
18
|
+
icon,
|
|
19
|
+
onDismiss
|
|
20
|
+
}) => {
|
|
21
|
+
const defaultIcons: Record<BannerType, string> = {
|
|
22
|
+
info: 'information-circle',
|
|
23
|
+
warning: 'warning',
|
|
24
|
+
error: 'close-circle',
|
|
25
|
+
success: 'checkmark-circle'
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
const displayIcon = icon || defaultIcons[type];
|
|
29
|
+
|
|
30
|
+
return (
|
|
31
|
+
<div className={`banner banner--${type}`}>
|
|
32
|
+
<div className="banner__content">
|
|
33
|
+
<Icon name={displayIcon as any} size={32} />
|
|
34
|
+
<div className="banner__message">{children}</div>
|
|
35
|
+
</div>
|
|
36
|
+
{onDismiss && (
|
|
37
|
+
<Button
|
|
38
|
+
variant="ghost"
|
|
39
|
+
size="xs"
|
|
40
|
+
onClick={onDismiss}
|
|
41
|
+
aria-label="Dismiss banner"
|
|
42
|
+
>
|
|
43
|
+
<Icon name="close" size={20} />
|
|
44
|
+
</Button>
|
|
45
|
+
)}
|
|
46
|
+
</div>
|
|
47
|
+
);
|
|
48
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
.banner {
|
|
2
|
+
display: flex;
|
|
3
|
+
align-items: flex-start;
|
|
4
|
+
justify-content: space-between;
|
|
5
|
+
padding: var(--spacing-4);
|
|
6
|
+
border-radius: var(--border-radius-md, 8px);
|
|
7
|
+
margin-bottom: var(--spacing-4);
|
|
8
|
+
font-weight: 500;
|
|
9
|
+
gap: var(--spacing-3);
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.banner__content {
|
|
13
|
+
display: flex;
|
|
14
|
+
align-items: flex-start;
|
|
15
|
+
gap: var(--spacing-3);
|
|
16
|
+
flex: 1;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.banner__message {
|
|
20
|
+
flex: 1;
|
|
21
|
+
line-height: 1.5;
|
|
22
|
+
margin: var(--spacing-1) var(--spacing-1) var(--spacing-1) 0;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/* Type variants */
|
|
26
|
+
.banner--info {
|
|
27
|
+
background-color: hsla(var(--info-hue), var(--info-saturation), var(--info-lightness), 1);
|
|
28
|
+
color: hsla(var(--info-hue), 0%, 100%, 1);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.banner--warning {
|
|
32
|
+
background-color: hsla(var(--warning-hue), var(--warning-saturation), var(--warning-lightness), 1);
|
|
33
|
+
color: hsla(var(--warning-hue), 0%, 100%, 1);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
.banner--error {
|
|
37
|
+
background-color: hsla(var(--error-hue), var(--error-saturation), var(--error-lightness), 1);
|
|
38
|
+
color: hsla(var(--error-hue), 0%, 100%, 1);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
.banner--success {
|
|
42
|
+
background-color: hsla(var(--success-hue), var(--success-saturation), var(--success-lightness), 1);
|
|
43
|
+
color: hsla(var(--success-hue), 0%, 100%, 1);
|
|
44
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from "./Banner";
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import { Button as AriakitButton, ButtonProps as AriakitButtonProps } from '@ariakit/react';
|
|
3
|
+
import { Icon, IconName } from '../icons';
|
|
4
|
+
|
|
5
|
+
export type ButtonVariant = 'primary' | 'secondary' | 'tertiary' | 'ghost';
|
|
6
|
+
export type ButtonSize = 'xs' | 'sm' | 'md' | 'lg';
|
|
7
|
+
|
|
8
|
+
export interface ButtonProps extends Omit<AriakitButtonProps, 'children'> {
|
|
9
|
+
/**
|
|
10
|
+
* Visual variant of the button
|
|
11
|
+
* @default 'primary'
|
|
12
|
+
*/
|
|
13
|
+
variant?: ButtonVariant;
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Size of the button
|
|
17
|
+
* @default 'md'
|
|
18
|
+
*/
|
|
19
|
+
size?: ButtonSize;
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Button content
|
|
23
|
+
*/
|
|
24
|
+
children?: ReactNode;
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Whether the button is in a loading state
|
|
28
|
+
* @default false
|
|
29
|
+
*/
|
|
30
|
+
isLoading?: boolean;
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Full width button
|
|
34
|
+
* @default false
|
|
35
|
+
*/
|
|
36
|
+
fullWidth?: boolean;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Icon to display at the start of the button
|
|
40
|
+
*/
|
|
41
|
+
startIcon?: IconName;
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Icon to display at the end of the button
|
|
45
|
+
*/
|
|
46
|
+
endIcon?: IconName;
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Whether the button should only display an icon (no text)
|
|
50
|
+
* @default false
|
|
51
|
+
*/
|
|
52
|
+
iconOnly?: boolean;
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* URL to navigate to when button is clicked (makes it work like a link)
|
|
56
|
+
*/
|
|
57
|
+
href?: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
|
|
61
|
+
(
|
|
62
|
+
{
|
|
63
|
+
variant = 'primary',
|
|
64
|
+
size = 'md',
|
|
65
|
+
children,
|
|
66
|
+
isLoading = false,
|
|
67
|
+
disabled = false,
|
|
68
|
+
fullWidth = false,
|
|
69
|
+
startIcon,
|
|
70
|
+
endIcon,
|
|
71
|
+
iconOnly = false,
|
|
72
|
+
href,
|
|
73
|
+
className,
|
|
74
|
+
onClick,
|
|
75
|
+
...props
|
|
76
|
+
},
|
|
77
|
+
ref
|
|
78
|
+
) => {
|
|
79
|
+
const buttonClasses = [
|
|
80
|
+
'btn',
|
|
81
|
+
`btn--${variant}`,
|
|
82
|
+
`btn--${size}`,
|
|
83
|
+
fullWidth && 'btn--full-width',
|
|
84
|
+
iconOnly && 'btn--icon-only',
|
|
85
|
+
className,
|
|
86
|
+
]
|
|
87
|
+
.filter(Boolean)
|
|
88
|
+
.join(' ');
|
|
89
|
+
|
|
90
|
+
const iconSize = size === 'xs' ? 14 : size === 'sm' ? 16 : size === 'lg' ? 24 : 20;
|
|
91
|
+
|
|
92
|
+
const buttonContent = (
|
|
93
|
+
<>
|
|
94
|
+
{isLoading && <span className="btn__spinner" />}
|
|
95
|
+
{startIcon && (
|
|
96
|
+
isLoading ? (
|
|
97
|
+
<span className="btn__icon-placeholder" style={{ width: iconSize, height: iconSize }} />
|
|
98
|
+
) : (
|
|
99
|
+
<Icon name={startIcon} size={iconSize} className="btn__icon" />
|
|
100
|
+
)
|
|
101
|
+
)}
|
|
102
|
+
{!iconOnly && children}
|
|
103
|
+
{endIcon && <Icon name={endIcon} size={iconSize} className="btn__icon" />}
|
|
104
|
+
</>
|
|
105
|
+
);
|
|
106
|
+
|
|
107
|
+
const handleClick = (e: React.MouseEvent<HTMLButtonElement>) => {
|
|
108
|
+
if (href && !isLoading && !disabled) {
|
|
109
|
+
window.location.href = href;
|
|
110
|
+
}
|
|
111
|
+
onClick?.(e);
|
|
112
|
+
};
|
|
113
|
+
|
|
114
|
+
return (
|
|
115
|
+
<AriakitButton
|
|
116
|
+
ref={ref}
|
|
117
|
+
disabled={disabled || isLoading}
|
|
118
|
+
className={buttonClasses}
|
|
119
|
+
onClick={handleClick}
|
|
120
|
+
{...props}
|
|
121
|
+
>
|
|
122
|
+
{buttonContent}
|
|
123
|
+
</AriakitButton>
|
|
124
|
+
);
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
Button.displayName = 'Button';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Button, type ButtonProps, type ButtonVariant, type ButtonSize } from './button';
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
import '../../style/components/card/card.css';
|
|
3
|
+
|
|
4
|
+
export type CardVariant = 'default' | 'elevated' | 'outlined';
|
|
5
|
+
|
|
6
|
+
export interface CardProps {
|
|
7
|
+
/**
|
|
8
|
+
* Visual variant of the card
|
|
9
|
+
* @default 'default'
|
|
10
|
+
*/
|
|
11
|
+
variant?: CardVariant;
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Card content
|
|
15
|
+
*/
|
|
16
|
+
children: ReactNode;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Additional CSS classes
|
|
20
|
+
*/
|
|
21
|
+
className?: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Click handler for interactive cards
|
|
25
|
+
*/
|
|
26
|
+
onClick?: () => void;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export const Card: React.FC<CardProps> = ({
|
|
30
|
+
variant = 'default',
|
|
31
|
+
children,
|
|
32
|
+
className = '',
|
|
33
|
+
onClick,
|
|
34
|
+
...props
|
|
35
|
+
}) => {
|
|
36
|
+
const cardClasses = [
|
|
37
|
+
'card',
|
|
38
|
+
`card--${variant}`,
|
|
39
|
+
onClick && 'card--interactive',
|
|
40
|
+
className,
|
|
41
|
+
]
|
|
42
|
+
.filter(Boolean)
|
|
43
|
+
.join(' ');
|
|
44
|
+
|
|
45
|
+
const Component = onClick ? 'button' : 'div';
|
|
46
|
+
|
|
47
|
+
return (
|
|
48
|
+
<Component
|
|
49
|
+
className={cardClasses}
|
|
50
|
+
onClick={onClick}
|
|
51
|
+
{...(onClick && { type: 'button' })}
|
|
52
|
+
{...props}
|
|
53
|
+
>
|
|
54
|
+
{children}
|
|
55
|
+
</Component>
|
|
56
|
+
);
|
|
57
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './card';
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Checkbox as AriakitCheckbox, CheckboxProps as AriakitCheckboxProps } from '@ariakit/react';
|
|
3
|
+
import { Icon } from '../icons';
|
|
4
|
+
|
|
5
|
+
export type CheckboxSize = 'sm' | 'md' | 'lg';
|
|
6
|
+
|
|
7
|
+
export interface CheckboxProps extends Omit<AriakitCheckboxProps, 'children' | 'size'> {
|
|
8
|
+
/**
|
|
9
|
+
* Size of the checkbox
|
|
10
|
+
* @default 'md'
|
|
11
|
+
*/
|
|
12
|
+
size?: CheckboxSize;
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Label text for the checkbox
|
|
16
|
+
*/
|
|
17
|
+
label?: React.ReactNode;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Error message to display below the checkbox
|
|
21
|
+
*/
|
|
22
|
+
error?: string;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Helper text to display below the checkbox
|
|
26
|
+
*/
|
|
27
|
+
helperText?: string;
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Whether the checkbox is in an indeterminate state
|
|
31
|
+
* @default false
|
|
32
|
+
*/
|
|
33
|
+
indeterminate?: boolean;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export const Checkbox = React.forwardRef<HTMLInputElement, CheckboxProps>(
|
|
37
|
+
(
|
|
38
|
+
{
|
|
39
|
+
size = 'md',
|
|
40
|
+
label,
|
|
41
|
+
error,
|
|
42
|
+
helperText,
|
|
43
|
+
indeterminate = false,
|
|
44
|
+
disabled = false,
|
|
45
|
+
className,
|
|
46
|
+
checked,
|
|
47
|
+
...props
|
|
48
|
+
},
|
|
49
|
+
ref
|
|
50
|
+
) => {
|
|
51
|
+
const checkboxClasses = [
|
|
52
|
+
'checkbox',
|
|
53
|
+
`checkbox--${size}`,
|
|
54
|
+
error && 'checkbox--error',
|
|
55
|
+
disabled && 'checkbox--disabled',
|
|
56
|
+
className,
|
|
57
|
+
]
|
|
58
|
+
.filter(Boolean)
|
|
59
|
+
.join(' ');
|
|
60
|
+
|
|
61
|
+
const iconSize = size === 'sm' ? 14 : size === 'lg' ? 20 : 16;
|
|
62
|
+
|
|
63
|
+
// Determine checked state for icon display
|
|
64
|
+
const isChecked = checked === true;
|
|
65
|
+
const isIndeterminate = indeterminate && !isChecked;
|
|
66
|
+
|
|
67
|
+
return (
|
|
68
|
+
<div className={checkboxClasses}>
|
|
69
|
+
<label className="checkbox__container">
|
|
70
|
+
<AriakitCheckbox
|
|
71
|
+
ref={ref}
|
|
72
|
+
checked={checked}
|
|
73
|
+
disabled={disabled}
|
|
74
|
+
className="checkbox__input"
|
|
75
|
+
{...props}
|
|
76
|
+
/>
|
|
77
|
+
<span className="checkbox__box">
|
|
78
|
+
{isChecked && (
|
|
79
|
+
<Icon name="checkmark-sharp" size={iconSize} className="checkbox__icon" />
|
|
80
|
+
)}
|
|
81
|
+
{isIndeterminate && (
|
|
82
|
+
<Icon name="minus" size={iconSize} className="checkbox__icon" />
|
|
83
|
+
)}
|
|
84
|
+
</span>
|
|
85
|
+
{label && <span className="checkbox__label">{label}</span>}
|
|
86
|
+
</label>
|
|
87
|
+
{(error || helperText) && (
|
|
88
|
+
<div className="checkbox__feedback">
|
|
89
|
+
{error && <span className="checkbox__error-text">{error}</span>}
|
|
90
|
+
{!error && helperText && <span className="checkbox__helper-text">{helperText}</span>}
|
|
91
|
+
</div>
|
|
92
|
+
)}
|
|
93
|
+
</div>
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
);
|
|
97
|
+
|
|
98
|
+
Checkbox.displayName = 'Checkbox';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Checkbox';
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import React, { ReactNode } from 'react';
|
|
2
|
+
|
|
3
|
+
export type CodeBlockVariant = 'block' | 'inline';
|
|
4
|
+
|
|
5
|
+
export interface CodeBlockProps {
|
|
6
|
+
/**
|
|
7
|
+
* Code content
|
|
8
|
+
*/
|
|
9
|
+
children: ReactNode;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Variant of the code block
|
|
13
|
+
* @default 'block'
|
|
14
|
+
*/
|
|
15
|
+
variant?: CodeBlockVariant;
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Custom class name
|
|
19
|
+
*/
|
|
20
|
+
className?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* CodeBlock component for displaying code snippets
|
|
25
|
+
*/
|
|
26
|
+
export const CodeBlock: React.FC<CodeBlockProps> = ({ children, variant = 'block', className }) => {
|
|
27
|
+
const classes = [
|
|
28
|
+
'code-block',
|
|
29
|
+
variant === 'inline' && 'code-block--inline',
|
|
30
|
+
className,
|
|
31
|
+
]
|
|
32
|
+
.filter(Boolean)
|
|
33
|
+
.join(' ');
|
|
34
|
+
|
|
35
|
+
if (variant === 'inline') {
|
|
36
|
+
return <code className={classes}>{children}</code>;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return (
|
|
40
|
+
<pre className={classes}>
|
|
41
|
+
<code>{children}</code>
|
|
42
|
+
</pre>
|
|
43
|
+
);
|
|
44
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { CodeBlock, type CodeBlockProps, type CodeBlockVariant } from './code-block';
|