doom-design-system 0.1.1 → 0.1.4
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 +5 -2
- package/dist/DesignSystemProvider.d.ts +2 -1
- package/dist/DesignSystemProvider.js +4 -3
- package/dist/components/Accordion/Accordion.d.ts +17 -0
- package/dist/components/Accordion/Accordion.js +94 -0
- package/dist/components/Accordion/index.d.ts +1 -0
- package/dist/components/Accordion/index.js +1 -0
- package/dist/components/Alert/Alert.d.ts +11 -0
- package/dist/components/Alert/Alert.js +70 -0
- package/dist/components/Alert/index.d.ts +1 -0
- package/dist/components/Alert/index.js +1 -0
- package/dist/components/Avatar/Avatar.d.ts +13 -0
- package/dist/components/Avatar/Avatar.js +51 -0
- package/dist/components/Avatar/index.d.ts +1 -0
- package/dist/components/Avatar/index.js +1 -0
- package/dist/components/Badge/Badge.js +1 -1
- package/dist/components/Breadcrumbs/Breadcrumbs.d.ts +13 -0
- package/dist/components/Breadcrumbs/Breadcrumbs.js +46 -0
- package/dist/components/Breadcrumbs/index.d.ts +1 -0
- package/dist/components/Breadcrumbs/index.js +1 -0
- package/dist/components/Button/Button.js +39 -6
- package/dist/components/Card/Card.js +1 -1
- package/dist/components/Drawer/Drawer.d.ts +12 -0
- package/dist/components/Drawer/Drawer.js +101 -0
- package/dist/components/Drawer/index.d.ts +1 -0
- package/dist/components/Drawer/index.js +1 -0
- package/dist/components/Form/Form.d.ts +20 -7
- package/dist/components/Form/Form.js +49 -9
- package/dist/components/Input/Input.d.ts +1 -1
- package/dist/components/Input/Input.js +27 -60
- package/dist/components/Label/Label.d.ts +6 -0
- package/dist/components/Label/Label.js +38 -0
- package/dist/components/Label/index.d.ts +1 -0
- package/dist/components/Label/index.js +1 -0
- package/dist/components/Link/Link.js +1 -1
- package/dist/components/Modal/Modal.js +7 -7
- package/dist/components/Pagination/Pagination.d.ts +8 -0
- package/dist/components/Pagination/Pagination.js +94 -0
- package/dist/components/Pagination/index.d.ts +1 -0
- package/dist/components/Pagination/index.js +1 -0
- package/dist/components/Popover/Popover.d.ts +1 -1
- package/dist/components/Popover/Popover.js +47 -29
- package/dist/components/RadioGroup/RadioGroup.d.ts +19 -0
- package/dist/components/RadioGroup/RadioGroup.js +101 -0
- package/dist/components/RadioGroup/index.d.ts +1 -0
- package/dist/components/RadioGroup/index.js +1 -0
- package/dist/components/Select/Select.js +5 -17
- package/dist/components/Sheet/Sheet.d.ts +10 -0
- package/dist/components/Sheet/Sheet.js +87 -0
- package/dist/components/Sheet/index.d.ts +1 -0
- package/dist/components/Sheet/index.js +1 -0
- package/dist/components/Slider/Slider.d.ts +10 -0
- package/dist/components/Slider/Slider.js +168 -0
- package/dist/components/Slider/index.d.ts +1 -0
- package/dist/components/Slider/index.js +1 -0
- package/dist/components/Switch/Switch.d.ts +11 -0
- package/dist/components/Switch/Switch.js +77 -0
- package/dist/components/Switch/index.d.ts +1 -0
- package/dist/components/Switch/index.js +1 -0
- package/dist/components/Table/Table.js +6 -6
- package/dist/components/Tabs/Tabs.js +6 -9
- package/dist/components/Textarea/Textarea.js +3 -10
- package/dist/components/Toast/Toast.js +1 -1
- package/dist/components/Tooltip/Tooltip.d.ts +9 -0
- package/dist/components/Tooltip/Tooltip.js +37 -0
- package/dist/components/Tooltip/index.d.ts +1 -0
- package/dist/components/Tooltip/index.js +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.js +12 -0
- package/dist/styles/mixins.d.ts +3 -0
- package/dist/styles/mixins.js +25 -0
- package/dist/styles/themes/definitions.d.ts +112 -0
- package/dist/styles/themes/definitions.js +37 -4
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
|
@@ -1,14 +1,27 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
|
-
|
|
2
|
+
import { Label } from '../Label/Label';
|
|
3
|
+
export { Label };
|
|
4
|
+
export interface FormProps extends React.FormHTMLAttributes<HTMLFormElement> {
|
|
3
5
|
children: React.ReactNode;
|
|
4
6
|
}
|
|
5
|
-
export declare function Form({ children,
|
|
6
|
-
interface
|
|
7
|
+
export declare function Form({ children, ...props }: FormProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export interface FormMessageProps extends React.HTMLAttributes<HTMLSpanElement> {
|
|
7
9
|
children: React.ReactNode;
|
|
10
|
+
variant?: 'error' | 'description';
|
|
8
11
|
}
|
|
9
|
-
export declare function
|
|
10
|
-
interface
|
|
12
|
+
export declare function FormMessage({ children, variant, ...props }: FormMessageProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
export interface FieldProps extends React.HTMLAttributes<HTMLDivElement> {
|
|
11
14
|
children: React.ReactNode;
|
|
15
|
+
label?: string;
|
|
16
|
+
error?: string | boolean;
|
|
17
|
+
description?: string;
|
|
18
|
+
htmlFor?: string;
|
|
19
|
+
required?: boolean;
|
|
12
20
|
}
|
|
13
|
-
export declare function
|
|
14
|
-
export {
|
|
21
|
+
export declare function Field({ children, label, error, description, htmlFor, required, ...props }: FieldProps): import("react/jsx-runtime").JSX.Element;
|
|
22
|
+
export declare const FormGroup: import("@emotion/styled").StyledComponent<{
|
|
23
|
+
theme?: import("@emotion/react").Theme;
|
|
24
|
+
as?: React.ElementType;
|
|
25
|
+
} & {
|
|
26
|
+
error?: boolean;
|
|
27
|
+
}, React.DetailedHTMLProps<React.HTMLAttributes<HTMLDivElement>, HTMLDivElement>, {}>;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
'use client';
|
|
1
2
|
var __rest = (this && this.__rest) || function (s, e) {
|
|
2
3
|
var t = {};
|
|
3
4
|
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
@@ -9,16 +10,55 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
9
10
|
}
|
|
10
11
|
return t;
|
|
11
12
|
};
|
|
12
|
-
import { jsx as _jsx } from "react/jsx-runtime";
|
|
13
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
|
+
import styled from '@emotion/styled';
|
|
15
|
+
import { css } from '@emotion/react';
|
|
16
|
+
const StyledForm = styled.form `
|
|
17
|
+
display: flex;
|
|
18
|
+
flex-direction: column;
|
|
19
|
+
gap: 1.5rem;
|
|
20
|
+
width: 100%;
|
|
21
|
+
`;
|
|
22
|
+
const StyledField = styled.div `
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
gap: 0.5rem;
|
|
26
|
+
width: 100%;
|
|
27
|
+
|
|
28
|
+
`;
|
|
29
|
+
import { Label } from '../Label/Label';
|
|
30
|
+
export { Label };
|
|
31
|
+
const StyledMessage = styled.span `
|
|
32
|
+
font-size: 0.75rem;
|
|
33
|
+
font-weight: 500;
|
|
34
|
+
|
|
35
|
+
${props => props.variant === 'error' && css `
|
|
36
|
+
color: var(--error);
|
|
37
|
+
font-weight: 700;
|
|
38
|
+
text-transform: uppercase;
|
|
39
|
+
animation: shake 0.3s ease-in-out;
|
|
40
|
+
`}
|
|
41
|
+
|
|
42
|
+
${props => props.variant === 'description' && css `
|
|
43
|
+
color: var(--muted-foreground);
|
|
44
|
+
`}
|
|
45
|
+
|
|
46
|
+
@keyframes shake {
|
|
47
|
+
0%, 100% { transform: translateX(0); }
|
|
48
|
+
25% { transform: translateX(-4px); }
|
|
49
|
+
75% { transform: translateX(4px); }
|
|
50
|
+
}
|
|
51
|
+
`;
|
|
13
52
|
export function Form(_a) {
|
|
14
|
-
var { children
|
|
15
|
-
return
|
|
53
|
+
var { children } = _a, props = __rest(_a, ["children"]);
|
|
54
|
+
return _jsx(StyledForm, Object.assign({}, props, { children: children }));
|
|
16
55
|
}
|
|
17
|
-
export function
|
|
18
|
-
var { children,
|
|
19
|
-
return
|
|
56
|
+
export function FormMessage(_a) {
|
|
57
|
+
var { children, variant = 'description' } = _a, props = __rest(_a, ["children", "variant"]);
|
|
58
|
+
return _jsx(StyledMessage, Object.assign({ variant: variant }, props, { children: children }));
|
|
20
59
|
}
|
|
21
|
-
export function
|
|
22
|
-
var { children,
|
|
23
|
-
return (
|
|
60
|
+
export function Field(_a) {
|
|
61
|
+
var { children, label, error, description, htmlFor, required } = _a, props = __rest(_a, ["children", "label", "error", "description", "htmlFor", "required"]);
|
|
62
|
+
return (_jsxs(StyledField, Object.assign({ error: !!error }, props, { children: [label && (_jsx(Label, { htmlFor: htmlFor, required: required, children: label })), children, description && !error && (_jsx(FormMessage, { variant: "description", children: description })), error && typeof error === 'string' && (_jsx(FormMessage, { variant: "error", children: error }))] })));
|
|
24
63
|
}
|
|
64
|
+
export const FormGroup = StyledField;
|
|
@@ -8,5 +8,5 @@ interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {
|
|
|
8
8
|
format?: (value: string | number | readonly string[] | undefined) => string;
|
|
9
9
|
validate?: (value: string | number | readonly string[] | undefined) => string | undefined;
|
|
10
10
|
}
|
|
11
|
-
export declare function Input({ label, error: errorProp, helperText, startAdornment, endAdornment, style, className, format, validate, onBlur, onFocus, value, ...props }: InputProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
export declare function Input({ label, error: errorProp, helperText, startAdornment, endAdornment, style, className, format, validate, onBlur, onFocus, value, id, required, ...props }: InputProps): import("react/jsx-runtime").JSX.Element;
|
|
12
12
|
export {};
|
|
@@ -13,10 +13,13 @@ var __rest = (this && this.__rest) || function (s, e) {
|
|
|
13
13
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
14
14
|
import { useState } from 'react';
|
|
15
15
|
import styled from '@emotion/styled';
|
|
16
|
-
import {
|
|
16
|
+
import { css } from '@emotion/react';
|
|
17
|
+
import { Label } from '../Label/Label';
|
|
18
|
+
import { baseInteractiveStyles, focusStyles, errorStyles } from '../../styles/mixins';
|
|
17
19
|
const InputContainer = styled.div `
|
|
18
20
|
display: flex;
|
|
19
21
|
flex-direction: column;
|
|
22
|
+
gap: 0.5rem;
|
|
20
23
|
width: 100%;
|
|
21
24
|
`;
|
|
22
25
|
const InputWrapper = styled.div `
|
|
@@ -33,67 +36,15 @@ const StyledInput = styled.input `
|
|
|
33
36
|
font-size: var(--text-base);
|
|
34
37
|
background: var(--card-bg);
|
|
35
38
|
color: var(--foreground);
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
outline: none;
|
|
40
|
-
transition: all 0.1s ease;
|
|
41
|
-
|
|
42
|
-
&:focus {
|
|
43
|
-
box-shadow: var(--shadow-hover);
|
|
44
|
-
transform: translate(-2px, -2px);
|
|
45
|
-
border-color: ${props => props.isError ? 'var(--error)' : 'var(--primary)'};
|
|
46
|
-
}
|
|
39
|
+
|
|
40
|
+
${baseInteractiveStyles}
|
|
41
|
+
${focusStyles}
|
|
47
42
|
|
|
48
43
|
&::placeholder {
|
|
49
44
|
color: var(--muted);
|
|
50
45
|
}
|
|
51
46
|
|
|
52
|
-
|
|
53
|
-
background-color: var(--muted-foreground);
|
|
54
|
-
cursor: pointer;
|
|
55
|
-
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
|
|
56
|
-
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Crect x='3' y='4' width='18' height='18' rx='2' ry='2'%3E%3C/rect%3E%3Cline x1='16' y1='2' x2='16' y2='6'%3E%3C/line%3E%3Cline x1='8' y1='2' x2='8' y2='6'%3E%3C/line%3E%3Cline x1='3' y1='10' x2='21' y2='10'%3E%3C/line%3E%3C/svg%3E");
|
|
57
|
-
mask-repeat: no-repeat;
|
|
58
|
-
-webkit-mask-repeat: no-repeat;
|
|
59
|
-
mask-position: center;
|
|
60
|
-
-webkit-mask-position: center;
|
|
61
|
-
mask-size: contain;
|
|
62
|
-
-webkit-mask-size: contain;
|
|
63
|
-
transition: background-color 0.2s;
|
|
64
|
-
width: 1em;
|
|
65
|
-
height: 1em;
|
|
66
|
-
|
|
67
|
-
&:hover {
|
|
68
|
-
background-color: var(--foreground);
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
&[type="time"]::-webkit-calendar-picker-indicator {
|
|
73
|
-
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
|
|
74
|
-
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Ccircle cx='12' cy='12' r='10'%3E%3C/circle%3E%3Cpolyline points='12 6 12 12 16 14'%3E%3C/polyline%3E%3C/svg%3E");
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
&::-webkit-search-cancel-button {
|
|
78
|
-
-webkit-appearance: none;
|
|
79
|
-
background-color: var(--muted-foreground);
|
|
80
|
-
cursor: pointer;
|
|
81
|
-
mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
|
|
82
|
-
-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='24' height='24' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'%3E%3Cline x1='18' y1='6' x2='6' y2='18'%3E%3C/line%3E%3Cline x1='6' y1='6' x2='18' y2='18'%3E%3C/line%3E%3C/svg%3E");
|
|
83
|
-
mask-repeat: no-repeat;
|
|
84
|
-
-webkit-mask-repeat: no-repeat;
|
|
85
|
-
mask-position: center;
|
|
86
|
-
-webkit-mask-position: center;
|
|
87
|
-
mask-size: contain;
|
|
88
|
-
-webkit-mask-size: contain;
|
|
89
|
-
transition: background-color 0.2s;
|
|
90
|
-
width: 1em;
|
|
91
|
-
height: 1em;
|
|
92
|
-
|
|
93
|
-
&:hover {
|
|
94
|
-
background-color: var(--foreground);
|
|
95
|
-
}
|
|
96
|
-
}
|
|
47
|
+
${props => props.isError && errorStyles}
|
|
97
48
|
`;
|
|
98
49
|
const Adornment = styled.span `
|
|
99
50
|
position: absolute;
|
|
@@ -103,8 +54,25 @@ const Adornment = styled.span `
|
|
|
103
54
|
pointer-events: none;
|
|
104
55
|
z-index: 1;
|
|
105
56
|
`;
|
|
57
|
+
const HelperText = styled.span `
|
|
58
|
+
font-size: var(--text-xs);
|
|
59
|
+
font-weight: var(--font-medium);
|
|
60
|
+
color: ${props => props.isError ? 'var(--error)' : 'var(--muted-foreground)'};
|
|
61
|
+
|
|
62
|
+
${props => props.isError && css `
|
|
63
|
+
font-weight: var(--font-bold);
|
|
64
|
+
text-transform: uppercase;
|
|
65
|
+
animation: input-shake 0.3s ease-in-out;
|
|
66
|
+
`}
|
|
67
|
+
|
|
68
|
+
@keyframes input-shake {
|
|
69
|
+
0%, 100% { transform: translateX(0); }
|
|
70
|
+
25% { transform: translateX(-4px); }
|
|
71
|
+
75% { transform: translateX(4px); }
|
|
72
|
+
}
|
|
73
|
+
`;
|
|
106
74
|
export function Input(_a) {
|
|
107
|
-
var { label, error: errorProp, helperText, startAdornment, endAdornment, style, className, format, validate, onBlur, onFocus, value } = _a, props = __rest(_a, ["label", "error", "helperText", "startAdornment", "endAdornment", "style", "className", "format", "validate", "onBlur", "onFocus", "value"]);
|
|
75
|
+
var { label, error: errorProp, helperText, startAdornment, endAdornment, style, className, format, validate, onBlur, onFocus, value, id, required } = _a, props = __rest(_a, ["label", "error", "helperText", "startAdornment", "endAdornment", "style", "className", "format", "validate", "onBlur", "onFocus", "value", "id", "required"]);
|
|
108
76
|
const [isFocused, setIsFocused] = useState(false);
|
|
109
77
|
const [internalError, setInternalError] = useState(undefined);
|
|
110
78
|
const error = errorProp || internalError;
|
|
@@ -121,9 +89,8 @@ export function Input(_a) {
|
|
|
121
89
|
if (onFocus)
|
|
122
90
|
onFocus(e);
|
|
123
91
|
};
|
|
124
|
-
// Use formatted value when not focused, otherwise raw value
|
|
125
92
|
const displayValue = (!isFocused && format && value !== undefined)
|
|
126
93
|
? format(value)
|
|
127
94
|
: value;
|
|
128
|
-
return (_jsxs(InputContainer, { style: style, className: className, children: [label && (_jsx(
|
|
95
|
+
return (_jsxs(InputContainer, { style: style, className: className, children: [label && (_jsx(Label, { htmlFor: id, required: required, children: label })), _jsxs(InputWrapper, { children: [startAdornment && _jsx(Adornment, { position: "start", children: startAdornment }), _jsx(StyledInput, Object.assign({ id: id, required: required, value: displayValue, hasStartAdornment: !!startAdornment, hasEndAdornment: !!endAdornment, isError: !!error, onBlur: handleBlur, onFocus: handleFocus }, props)), endAdornment && _jsx(Adornment, { position: "end", children: endAdornment })] }), helperText && !error && (_jsx(HelperText, { children: helperText })), error && (_jsx(HelperText, { isError: true, children: error }))] }));
|
|
129
96
|
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export interface LabelProps extends React.LabelHTMLAttributes<HTMLLabelElement> {
|
|
3
|
+
children: React.ReactNode;
|
|
4
|
+
required?: boolean;
|
|
5
|
+
}
|
|
6
|
+
export declare function Label({ children, required, ...props }: LabelProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
var __rest = (this && this.__rest) || function (s, e) {
|
|
3
|
+
var t = {};
|
|
4
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
|
|
5
|
+
t[p] = s[p];
|
|
6
|
+
if (s != null && typeof Object.getOwnPropertySymbols === "function")
|
|
7
|
+
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
|
|
8
|
+
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
|
|
9
|
+
t[p[i]] = s[p[i]];
|
|
10
|
+
}
|
|
11
|
+
return t;
|
|
12
|
+
};
|
|
13
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
14
|
+
import styled from '@emotion/styled';
|
|
15
|
+
import { css } from '@emotion/react';
|
|
16
|
+
const StyledLabel = styled.label `
|
|
17
|
+
font-family: var(--font-heading);
|
|
18
|
+
font-weight: var(--font-bold);
|
|
19
|
+
font-size: var(--text-sm);
|
|
20
|
+
color: var(--foreground);
|
|
21
|
+
text-transform: uppercase;
|
|
22
|
+
letter-spacing: 0.05em;
|
|
23
|
+
display: flex;
|
|
24
|
+
align-items: center;
|
|
25
|
+
gap: 0.25rem;
|
|
26
|
+
|
|
27
|
+
${props => props.required && css `
|
|
28
|
+
&::after {
|
|
29
|
+
content: '*';
|
|
30
|
+
color: var(--error);
|
|
31
|
+
margin-left: 0.25rem;
|
|
32
|
+
}
|
|
33
|
+
`}
|
|
34
|
+
`;
|
|
35
|
+
export function Label(_a) {
|
|
36
|
+
var { children, required } = _a, props = __rest(_a, ["children", "required"]);
|
|
37
|
+
return _jsx(StyledLabel, Object.assign({ required: required }, props, { children: children }));
|
|
38
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Label';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './Label';
|
|
@@ -9,13 +9,13 @@ const ModalContext = React.createContext({ onClose: () => { } });
|
|
|
9
9
|
const Overlay = styled.div `
|
|
10
10
|
position: fixed;
|
|
11
11
|
inset: 0;
|
|
12
|
-
z-index:
|
|
12
|
+
z-index: var(--z-modal);
|
|
13
13
|
display: flex;
|
|
14
14
|
align-items: center;
|
|
15
15
|
justify-content: center;
|
|
16
|
-
padding:
|
|
16
|
+
padding: var(--spacing-md);
|
|
17
17
|
backdrop-filter: blur(4px);
|
|
18
|
-
background-color: rgba(0, 0, 0,
|
|
18
|
+
background-color: rgba(0, 0, 0, var(--overlay-opacity));
|
|
19
19
|
animation: fadeIn 0.2s ease-out;
|
|
20
20
|
|
|
21
21
|
@keyframes fadeIn {
|
|
@@ -34,21 +34,21 @@ const ContentContainer = styled.div `
|
|
|
34
34
|
}
|
|
35
35
|
`;
|
|
36
36
|
const StyledHeader = styled(Flex) `
|
|
37
|
-
padding:
|
|
37
|
+
padding: var(--spacing-lg);
|
|
38
38
|
border-bottom: var(--border-width) solid var(--card-border);
|
|
39
39
|
background: var(--background);
|
|
40
40
|
|
|
41
41
|
h2 {
|
|
42
|
-
font-size:
|
|
42
|
+
font-size: var(--text-xl);
|
|
43
43
|
font-weight: bold;
|
|
44
44
|
margin: 0;
|
|
45
45
|
}
|
|
46
46
|
`;
|
|
47
47
|
const StyledBody = styled.div `
|
|
48
|
-
padding:
|
|
48
|
+
padding: var(--spacing-lg);
|
|
49
49
|
`;
|
|
50
50
|
const StyledFooter = styled.div `
|
|
51
|
-
padding:
|
|
51
|
+
padding: var(--spacing-lg);
|
|
52
52
|
border-top: var(--border-width) solid var(--card-border);
|
|
53
53
|
background: var(--background);
|
|
54
54
|
`;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
interface PaginationProps {
|
|
2
|
+
currentPage: number;
|
|
3
|
+
totalPages: number;
|
|
4
|
+
onPageChange: (page: number) => void;
|
|
5
|
+
className?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function Pagination({ currentPage, totalPages, onPageChange, className }: PaginationProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export {};
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import styled from '@emotion/styled';
|
|
4
|
+
import { ChevronLeft, ChevronRight, MoreHorizontal } from 'lucide-react';
|
|
5
|
+
const PaginationNav = styled.nav `
|
|
6
|
+
display: flex;
|
|
7
|
+
justify-content: center;
|
|
8
|
+
align-items: center;
|
|
9
|
+
gap: 0.5rem;
|
|
10
|
+
`;
|
|
11
|
+
const PageButton = styled.button `
|
|
12
|
+
display: inline-flex;
|
|
13
|
+
align-items: center;
|
|
14
|
+
justify-content: center;
|
|
15
|
+
width: 40px;
|
|
16
|
+
height: 40px;
|
|
17
|
+
border: var(--border-width) solid var(--card-border);
|
|
18
|
+
border-radius: var(--radius);
|
|
19
|
+
background-color: ${props => props.isActive ? 'var(--primary)' : 'var(--card-bg)'};
|
|
20
|
+
color: ${props => props.isActive ? 'var(--primary-foreground)' : 'var(--foreground)'};
|
|
21
|
+
font-family: var(--font-heading);
|
|
22
|
+
font-weight: 700;
|
|
23
|
+
cursor: pointer;
|
|
24
|
+
box-shadow: ${props => props.isActive ? 'var(--shadow-sm)' : 'none'};
|
|
25
|
+
|
|
26
|
+
&:hover:not(:disabled) {
|
|
27
|
+
transform: translate(-2px, -2px);
|
|
28
|
+
box-shadow: var(--shadow-sm);
|
|
29
|
+
background-color: var(--primary);
|
|
30
|
+
color: var(--primary-foreground);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
&:active:not(:disabled) {
|
|
34
|
+
transform: translate(0, 0);
|
|
35
|
+
box-shadow: none;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
&:disabled {
|
|
39
|
+
opacity: 0.5;
|
|
40
|
+
cursor: not-allowed;
|
|
41
|
+
background-color: var(--muted);
|
|
42
|
+
}
|
|
43
|
+
`;
|
|
44
|
+
export function Pagination({ currentPage, totalPages, onPageChange, className }) {
|
|
45
|
+
const handlePageChange = (page) => {
|
|
46
|
+
if (page >= 1 && page <= totalPages && page !== currentPage) {
|
|
47
|
+
onPageChange(page);
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const renderPageNumbers = () => {
|
|
51
|
+
const pages = [];
|
|
52
|
+
const maxVisible = 7; // Max buttons to show
|
|
53
|
+
if (totalPages <= maxVisible) {
|
|
54
|
+
for (let i = 1; i <= totalPages; i++) {
|
|
55
|
+
pages.push(i);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
// Complex truncation logic
|
|
60
|
+
if (currentPage <= 4) {
|
|
61
|
+
// Near start: 1 2 3 4 5 ... N
|
|
62
|
+
for (let i = 1; i <= 5; i++)
|
|
63
|
+
pages.push(i);
|
|
64
|
+
pages.push('ellipsis');
|
|
65
|
+
pages.push(totalPages);
|
|
66
|
+
}
|
|
67
|
+
else if (currentPage >= totalPages - 3) {
|
|
68
|
+
// Near end: 1 ... N-4 N-3 N-2 N-1 N
|
|
69
|
+
pages.push(1);
|
|
70
|
+
pages.push('ellipsis');
|
|
71
|
+
for (let i = totalPages - 4; i <= totalPages; i++)
|
|
72
|
+
pages.push(i);
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// Middle: 1 ... C-1 C C+1 ... N
|
|
76
|
+
pages.push(1);
|
|
77
|
+
pages.push('ellipsis');
|
|
78
|
+
pages.push(currentPage - 1);
|
|
79
|
+
pages.push(currentPage);
|
|
80
|
+
pages.push(currentPage + 1);
|
|
81
|
+
pages.push('ellipsis');
|
|
82
|
+
pages.push(totalPages);
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return pages.map((page, index) => {
|
|
86
|
+
if (page === 'ellipsis') {
|
|
87
|
+
return (_jsx("span", { style: { display: 'flex', alignItems: 'center' }, children: _jsx(MoreHorizontal, { size: 20 }) }, `ellipsis-${index}`));
|
|
88
|
+
}
|
|
89
|
+
const pageNum = page;
|
|
90
|
+
return (_jsx(PageButton, { isActive: currentPage === pageNum, onClick: () => handlePageChange(pageNum), "aria-current": currentPage === pageNum ? 'page' : undefined, children: pageNum }, pageNum));
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
return (_jsxs(PaginationNav, { "aria-label": "pagination", className: className, children: [_jsx(PageButton, { onClick: () => handlePageChange(currentPage - 1), disabled: currentPage === 1, "aria-label": "Go to previous page", children: _jsx(ChevronLeft, { size: 20, strokeWidth: 2.5 }) }), renderPageNumbers(), _jsx(PageButton, { onClick: () => handlePageChange(currentPage + 1), disabled: currentPage === totalPages, "aria-label": "Go to next page", children: _jsx(ChevronRight, { size: 20, strokeWidth: 2.5 }) })] }));
|
|
94
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Pagination } from './Pagination';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { Pagination } from './Pagination';
|
|
@@ -4,7 +4,7 @@ interface PopoverProps {
|
|
|
4
4
|
content: React.ReactNode;
|
|
5
5
|
isOpen: boolean;
|
|
6
6
|
onClose: () => void;
|
|
7
|
-
placement?: 'bottom-start' | 'bottom-end' | 'bottom-center';
|
|
7
|
+
placement?: 'bottom-start' | 'bottom-end' | 'bottom-center' | 'top-start' | 'top-end' | 'top-center';
|
|
8
8
|
offset?: number;
|
|
9
9
|
}
|
|
10
10
|
export declare function Popover({ trigger, content, isOpen, onClose, placement, offset }: PopoverProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,7 +1,12 @@
|
|
|
1
1
|
'use client';
|
|
2
|
-
import { jsx as _jsx,
|
|
3
|
-
import { useState, useRef, useEffect, useCallback } from 'react';
|
|
2
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { useState, useRef, useEffect, useCallback, useLayoutEffect } from 'react';
|
|
4
4
|
import { createPortal } from 'react-dom';
|
|
5
|
+
import { keyframes } from '@emotion/react';
|
|
6
|
+
const popoverScale = keyframes `
|
|
7
|
+
from { opacity: 0; transform: scale(0.95); }
|
|
8
|
+
to { opacity: 1; transform: scale(1); }
|
|
9
|
+
`;
|
|
5
10
|
export function Popover({ trigger, content, isOpen, onClose, placement = 'bottom-start', offset = 8 }) {
|
|
6
11
|
const triggerRef = useRef(null);
|
|
7
12
|
const contentRef = useRef(null);
|
|
@@ -14,42 +19,60 @@ export function Popover({ trigger, content, isOpen, onClose, placement = 'bottom
|
|
|
14
19
|
const contentRect = contentRef.current.getBoundingClientRect();
|
|
15
20
|
const viewportWidth = window.innerWidth;
|
|
16
21
|
const viewportHeight = window.innerHeight;
|
|
17
|
-
let top =
|
|
18
|
-
let left =
|
|
19
|
-
let origin = 'top
|
|
20
|
-
|
|
21
|
-
if (
|
|
22
|
+
let top = 0;
|
|
23
|
+
let left = 0;
|
|
24
|
+
let origin = 'top center';
|
|
25
|
+
const isTop = placement.startsWith('top');
|
|
26
|
+
if (isTop) {
|
|
22
27
|
top = triggerRect.top - contentRect.height - offset;
|
|
23
28
|
origin = 'bottom';
|
|
29
|
+
if (top < 0) {
|
|
30
|
+
top = triggerRect.bottom + offset;
|
|
31
|
+
origin = 'top';
|
|
32
|
+
}
|
|
24
33
|
}
|
|
25
34
|
else {
|
|
35
|
+
top = triggerRect.bottom + offset;
|
|
26
36
|
origin = 'top';
|
|
37
|
+
if (top + contentRect.height > viewportHeight) {
|
|
38
|
+
top = triggerRect.top - contentRect.height - offset;
|
|
39
|
+
origin = 'bottom';
|
|
40
|
+
}
|
|
27
41
|
}
|
|
28
|
-
|
|
29
|
-
if (
|
|
42
|
+
const align = placement.split('-')[1];
|
|
43
|
+
if (align === 'start') {
|
|
30
44
|
left = triggerRect.left;
|
|
45
|
+
origin += ' left';
|
|
31
46
|
}
|
|
32
|
-
else if (
|
|
47
|
+
else if (align === 'end') {
|
|
33
48
|
left = triggerRect.right - contentRect.width;
|
|
49
|
+
origin += ' right';
|
|
34
50
|
}
|
|
35
|
-
else
|
|
51
|
+
else {
|
|
36
52
|
left = triggerRect.left + (triggerRect.width / 2) - (contentRect.width / 2);
|
|
53
|
+
origin += ' center';
|
|
54
|
+
}
|
|
55
|
+
// Edge Config
|
|
56
|
+
const padding = 16;
|
|
57
|
+
// Horizontal Clamping
|
|
58
|
+
if (left + contentRect.width > viewportWidth - padding) {
|
|
59
|
+
left = viewportWidth - contentRect.width - padding;
|
|
37
60
|
}
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
left = viewportWidth - contentRect.width - 16; // 16px padding from right edge
|
|
41
|
-
if (origin.includes('left'))
|
|
42
|
-
origin = origin.replace('left', 'right');
|
|
61
|
+
if (left < padding) {
|
|
62
|
+
left = padding;
|
|
43
63
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
64
|
+
// Vertical Clamping (Fail-safe)
|
|
65
|
+
if (top < padding) {
|
|
66
|
+
top = padding;
|
|
67
|
+
}
|
|
68
|
+
if (top + contentRect.height > viewportHeight - padding) {
|
|
69
|
+
top = viewportHeight - contentRect.height - padding;
|
|
48
70
|
}
|
|
49
71
|
setPosition({ top, left });
|
|
50
72
|
setTransformOrigin(origin);
|
|
51
73
|
}, [isOpen, placement, offset]);
|
|
52
|
-
|
|
74
|
+
// Use useLayoutEffect for layout measurements to prevent flash
|
|
75
|
+
useLayoutEffect(() => {
|
|
53
76
|
if (isOpen) {
|
|
54
77
|
updatePosition();
|
|
55
78
|
window.addEventListener('resize', updatePosition);
|
|
@@ -75,17 +98,12 @@ export function Popover({ trigger, content, isOpen, onClose, placement = 'bottom
|
|
|
75
98
|
document.addEventListener('mousedown', handleClickOutside);
|
|
76
99
|
return () => document.removeEventListener('mousedown', handleClickOutside);
|
|
77
100
|
}, [isOpen, onClose]);
|
|
78
|
-
return (_jsxs(_Fragment, { children: [_jsx("div", { ref: triggerRef, style: { display: 'inline-block' }, children: trigger }), isOpen && typeof document !== 'undefined' && createPortal(
|
|
101
|
+
return (_jsxs(_Fragment, { children: [_jsx("div", { ref: triggerRef, style: { display: 'inline-block' }, children: trigger }), isOpen && typeof document !== 'undefined' && createPortal(_jsx("div", { ref: contentRef, style: {
|
|
79
102
|
position: 'fixed',
|
|
80
103
|
top: position.top,
|
|
81
104
|
left: position.left,
|
|
82
105
|
zIndex: 9999, // High z-index to ensure it's on top
|
|
83
106
|
transformOrigin: transformOrigin,
|
|
84
|
-
animation:
|
|
85
|
-
}, children:
|
|
86
|
-
@keyframes popoverScale {
|
|
87
|
-
from { opacity: 0; transform: scale(0.95); }
|
|
88
|
-
to { opacity: 1; transform: scale(1); }
|
|
89
|
-
}
|
|
90
|
-
` })] }), document.body)] }));
|
|
107
|
+
animation: `${popoverScale} 0.1s ease-out`,
|
|
108
|
+
}, children: content }), document.body)] }));
|
|
91
109
|
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface RadioGroupProps {
|
|
3
|
+
name?: string;
|
|
4
|
+
value?: string;
|
|
5
|
+
defaultValue?: string;
|
|
6
|
+
onValueChange?: (value: string) => void;
|
|
7
|
+
disabled?: boolean;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
className?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function RadioGroup({ name, value: controlledValue, defaultValue, onValueChange, disabled, children, className }: RadioGroupProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
interface RadioGroupItemProps {
|
|
13
|
+
value: string;
|
|
14
|
+
children: React.ReactNode;
|
|
15
|
+
disabled?: boolean;
|
|
16
|
+
className?: string;
|
|
17
|
+
}
|
|
18
|
+
export declare function RadioGroupItem({ value, children, disabled, className }: RadioGroupItemProps): import("react/jsx-runtime").JSX.Element;
|
|
19
|
+
export {};
|