doom-design-system 0.1.6 → 0.1.8

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.
Files changed (96) hide show
  1. package/README.md +23 -20
  2. package/dist/DesignSystemProvider.d.ts +1 -0
  3. package/dist/DesignSystemProvider.js +3 -4
  4. package/dist/components/Accordion/Accordion.js +5 -63
  5. package/dist/components/Accordion/Accordion.module.css +69 -0
  6. package/dist/components/ActionRow/ActionRow.js +3 -28
  7. package/dist/components/ActionRow/ActionRow.module.css +24 -0
  8. package/dist/components/Alert/Alert.js +3 -58
  9. package/dist/components/Alert/Alert.module.css +77 -0
  10. package/dist/components/Avatar/Avatar.js +3 -45
  11. package/dist/components/Avatar/Avatar.module.css +67 -0
  12. package/dist/components/Badge/Badge.d.ts +1 -1
  13. package/dist/components/Badge/Badge.js +4 -42
  14. package/dist/components/Badge/Badge.module.css +31 -0
  15. package/dist/components/Breadcrumbs/Breadcrumbs.js +6 -38
  16. package/dist/components/Breadcrumbs/Breadcrumbs.module.css +34 -0
  17. package/dist/components/Button/Button.d.ts +1 -1
  18. package/dist/components/Button/Button.js +5 -129
  19. package/dist/components/Button/Button.module.css +112 -0
  20. package/dist/components/Card/Card.d.ts +1 -1
  21. package/dist/components/Card/Card.js +4 -13
  22. package/dist/components/Card/Card.module.css +8 -0
  23. package/dist/components/Drawer/Drawer.js +5 -71
  24. package/dist/components/Drawer/Drawer.module.css +75 -0
  25. package/dist/components/Dropdown/Dropdown.d.ts +2 -1
  26. package/dist/components/Dropdown/Dropdown.js +6 -39
  27. package/dist/components/Dropdown/Dropdown.module.css +33 -0
  28. package/dist/components/Form/Form.d.ts +4 -9
  29. package/dist/components/Form/Form.js +9 -43
  30. package/dist/components/Form/Form.module.css +41 -0
  31. package/dist/components/Input/Input.js +3 -59
  32. package/dist/components/Input/Input.module.css +86 -0
  33. package/dist/components/Label/Label.d.ts +1 -1
  34. package/dist/components/Label/Label.js +4 -23
  35. package/dist/components/Label/Label.module.css +16 -0
  36. package/dist/components/Layout/Layout.d.ts +2 -2
  37. package/dist/components/Layout/Layout.js +5 -20
  38. package/dist/components/Layout/Layout.module.css +7 -0
  39. package/dist/components/Link/Link.d.ts +2 -1
  40. package/dist/components/Link/Link.js +4 -62
  41. package/dist/components/Link/Link.module.css +48 -0
  42. package/dist/components/Modal/Modal.js +9 -52
  43. package/dist/components/Modal/Modal.module.css +57 -0
  44. package/dist/components/Page/Page.js +3 -23
  45. package/dist/components/Page/Page.module.css +23 -0
  46. package/dist/components/Pagination/Pagination.js +4 -42
  47. package/dist/components/Pagination/Pagination.module.css +43 -0
  48. package/dist/components/Popover/Popover.js +21 -26
  49. package/dist/components/Popover/Popover.module.css +19 -0
  50. package/dist/components/ProgressBar/ProgressBar.js +7 -37
  51. package/dist/components/ProgressBar/ProgressBar.module.css +31 -0
  52. package/dist/components/RadioGroup/RadioGroup.js +4 -79
  53. package/dist/components/RadioGroup/RadioGroup.module.css +81 -0
  54. package/dist/components/Select/Select.js +6 -80
  55. package/dist/components/Select/Select.module.css +89 -0
  56. package/dist/components/Sheet/Sheet.js +5 -56
  57. package/dist/components/Sheet/Sheet.module.css +64 -0
  58. package/dist/components/Skeleton/Skeleton.js +4 -49
  59. package/dist/components/Skeleton/Skeleton.module.css +29 -0
  60. package/dist/components/Slider/Slider.js +3 -140
  61. package/dist/components/Slider/Slider.module.css +130 -0
  62. package/dist/components/SplitButton/SplitButton.d.ts +2 -1
  63. package/dist/components/SplitButton/SplitButton.js +6 -82
  64. package/dist/components/SplitButton/SplitButton.module.css +79 -0
  65. package/dist/components/Switch/Switch.js +3 -54
  66. package/dist/components/Switch/Switch.module.css +64 -0
  67. package/dist/components/Table/Table.d.ts +1 -1
  68. package/dist/components/Table/Table.js +13 -109
  69. package/dist/components/Table/Table.module.css +111 -0
  70. package/dist/components/Tabs/Tabs.js +7 -56
  71. package/dist/components/Tabs/Tabs.module.css +65 -0
  72. package/dist/components/Text/Text.js +4 -106
  73. package/dist/components/Text/Text.module.css +123 -0
  74. package/dist/components/Textarea/Textarea.d.ts +1 -1
  75. package/dist/components/Textarea/Textarea.js +16 -20
  76. package/dist/components/Textarea/Textarea.module.css +23 -0
  77. package/dist/components/Toast/Toast.js +3 -67
  78. package/dist/components/Toast/Toast.module.css +87 -0
  79. package/dist/components/Tooltip/Tooltip.js +3 -19
  80. package/dist/components/Tooltip/Tooltip.module.css +17 -0
  81. package/dist/index.d.ts +1 -0
  82. package/dist/index.js +1 -0
  83. package/dist/styles/globals.css +999 -0
  84. package/dist/styles/themes/ThemeProvider.js +4 -9
  85. package/dist/tsconfig.tsbuildinfo +1 -1
  86. package/package.json +8 -5
  87. package/dist/styles/index.d.ts +0 -3
  88. package/dist/styles/index.js +0 -3
  89. package/dist/styles/mixins.d.ts +0 -3
  90. package/dist/styles/mixins.js +0 -25
  91. package/dist/styles/reset.d.ts +0 -1
  92. package/dist/styles/reset.js +0 -29
  93. package/dist/styles/theme.d.ts +0 -1
  94. package/dist/styles/theme.js +0 -11
  95. package/dist/styles/utilities.d.ts +0 -1
  96. package/dist/styles/utilities.js +0 -184
@@ -0,0 +1,57 @@
1
+ @keyframes fadeIn {
2
+ from {
3
+ opacity: 0;
4
+ }
5
+ to {
6
+ opacity: 1;
7
+ }
8
+ }
9
+ @keyframes slideUp {
10
+ from {
11
+ transform: translateY(20px);
12
+ opacity: 0;
13
+ }
14
+ to {
15
+ transform: translateY(0);
16
+ opacity: 1;
17
+ }
18
+ }
19
+ .overlay {
20
+ position: fixed;
21
+ inset: 0;
22
+ z-index: var(--z-modal);
23
+ display: flex;
24
+ align-items: center;
25
+ justify-content: center;
26
+ padding: var(--spacing-md);
27
+ backdrop-filter: blur(4px);
28
+ background-color: rgba(0, 0, 0, var(--overlay-opacity));
29
+ animation: fadeIn 0.2s ease-out;
30
+ }
31
+
32
+ .contentContainer {
33
+ width: 100%;
34
+ max-width: 28rem;
35
+ animation: slideUp 0.3s ease-out;
36
+ }
37
+
38
+ .header {
39
+ padding: var(--spacing-lg);
40
+ border-bottom: var(--border-width) solid var(--card-border);
41
+ background: var(--background);
42
+ }
43
+ .header h2 {
44
+ font-size: var(--text-xl);
45
+ font-weight: bold;
46
+ margin: 0;
47
+ }
48
+
49
+ .body {
50
+ padding: var(--spacing-lg);
51
+ }
52
+
53
+ .footer {
54
+ padding: var(--spacing-lg);
55
+ border-top: var(--border-width) solid var(--card-border);
56
+ background: var(--background);
57
+ }
@@ -1,27 +1,7 @@
1
1
  'use client';
2
2
  import { jsx as _jsx } from "react/jsx-runtime";
3
- import styled from '@emotion/styled';
4
- const PageContainer = styled.main `
5
- flex: 1;
6
- width: 100%;
7
-
8
- /* Variant Styles */
9
- ${props => props.variant === 'default' ? `
10
- width: 90%;
11
- max-width: 1920px;
12
- margin: 0 auto;
13
- padding: 2rem 1rem;
14
-
15
- @media (max-width: 1024px) {
16
- width: 95%;
17
- padding: 1rem;
18
- }
19
- ` : `
20
- max-width: 100%;
21
- margin: 0;
22
- padding: 0;
23
- `}
24
- `;
3
+ import clsx from 'clsx';
4
+ import styles from './Page.module.css';
25
5
  export function Page({ children, variant = 'default', className, style }) {
26
- return (_jsx(PageContainer, { variant: variant, className: className, style: style, children: children }));
6
+ return (_jsx("main", { className: clsx(styles.container, styles[variant], className), style: style, children: children }));
27
7
  }
@@ -0,0 +1,23 @@
1
+ .container {
2
+ flex: 1;
3
+ width: 100%;
4
+ }
5
+
6
+ .default {
7
+ width: 90%;
8
+ max-width: 1920px;
9
+ margin: 0 auto;
10
+ padding: 2rem 1rem;
11
+ }
12
+ @media (max-width: 1024px) {
13
+ .default {
14
+ width: 95%;
15
+ padding: 1rem;
16
+ }
17
+ }
18
+
19
+ .fullWidth {
20
+ max-width: 100%;
21
+ margin: 0;
22
+ padding: 0;
23
+ }
@@ -1,46 +1,8 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import styled from '@emotion/styled';
3
+ import clsx from 'clsx';
4
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
- `;
5
+ import styles from './Pagination.module.css';
44
6
  export function Pagination({ currentPage, totalPages, onPageChange, className }) {
45
7
  const handlePageChange = (page) => {
46
8
  if (page >= 1 && page <= totalPages && page !== currentPage) {
@@ -87,8 +49,8 @@ export function Pagination({ currentPage, totalPages, onPageChange, className })
87
49
  return (_jsx("span", { style: { display: 'flex', alignItems: 'center' }, children: _jsx(MoreHorizontal, { size: 20 }) }, `ellipsis-${index}`));
88
50
  }
89
51
  const pageNum = page;
90
- return (_jsx(PageButton, { isActive: currentPage === pageNum, onClick: () => handlePageChange(pageNum), "aria-current": currentPage === pageNum ? 'page' : undefined, children: pageNum }, pageNum));
52
+ return (_jsx("button", { className: clsx(styles.button, currentPage === pageNum && styles.active), onClick: () => handlePageChange(pageNum), "aria-current": currentPage === pageNum ? 'page' : undefined, children: pageNum }, pageNum));
91
53
  });
92
54
  };
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 }) })] }));
55
+ return (_jsxs("nav", { "aria-label": "pagination", className: clsx(styles.nav, className), children: [_jsx("button", { className: styles.button, onClick: () => handlePageChange(currentPage - 1), disabled: currentPage === 1, "aria-label": "Go to previous page", children: _jsx(ChevronLeft, { size: 20, strokeWidth: 2.5 }) }), renderPageNumbers(), _jsx("button", { className: styles.button, onClick: () => handlePageChange(currentPage + 1), disabled: currentPage === totalPages, "aria-label": "Go to next page", children: _jsx(ChevronRight, { size: 20, strokeWidth: 2.5 }) })] }));
94
56
  }
@@ -0,0 +1,43 @@
1
+ .nav {
2
+ display: flex;
3
+ justify-content: center;
4
+ align-items: center;
5
+ gap: 0.5rem;
6
+ }
7
+
8
+ .button {
9
+ display: inline-flex;
10
+ align-items: center;
11
+ justify-content: center;
12
+ width: 40px;
13
+ height: 40px;
14
+ border: var(--border-width) solid var(--card-border);
15
+ border-radius: var(--radius);
16
+ background-color: var(--card-bg);
17
+ color: var(--foreground);
18
+ font-family: var(--font-heading);
19
+ font-weight: 700;
20
+ cursor: pointer;
21
+ box-shadow: none;
22
+ transition: all 0.2s ease;
23
+ }
24
+ .button:hover:not(:disabled) {
25
+ transform: translate(-2px, -2px);
26
+ box-shadow: var(--shadow-sm);
27
+ background-color: var(--primary);
28
+ color: var(--primary-foreground);
29
+ }
30
+ .button:active:not(:disabled) {
31
+ transform: translate(0, 0);
32
+ box-shadow: none;
33
+ }
34
+ .button:disabled {
35
+ opacity: 0.5;
36
+ cursor: not-allowed;
37
+ background-color: var(--muted);
38
+ }
39
+ .button.active {
40
+ background-color: var(--primary);
41
+ color: var(--primary-foreground);
42
+ box-shadow: var(--shadow-sm);
43
+ }
@@ -1,12 +1,8 @@
1
1
  'use client';
2
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
3
  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
- `;
4
+ import styles from './Popover.module.css';
5
+ import { useState, useRef, useEffect, useCallback, useLayoutEffect } from 'react';
10
6
  export function Popover({ trigger, content, isOpen, onClose, placement = 'bottom-start', offset = 8 }) {
11
7
  const triggerRef = useRef(null);
12
8
  const contentRef = useRef(null);
@@ -22,6 +18,8 @@ export function Popover({ trigger, content, isOpen, onClose, placement = 'bottom
22
18
  let top = 0;
23
19
  let left = 0;
24
20
  let origin = 'top center';
21
+ // Edge Config
22
+ const padding = 16;
25
23
  const isTop = placement.startsWith('top');
26
24
  if (isTop) {
27
25
  top = triggerRect.top - contentRect.height - offset;
@@ -37,8 +35,24 @@ export function Popover({ trigger, content, isOpen, onClose, placement = 'bottom
37
35
  if (top + contentRect.height > viewportHeight) {
38
36
  top = triggerRect.top - contentRect.height - offset;
39
37
  origin = 'bottom';
38
+ if (top < 0)
39
+ top = padding;
40
40
  }
41
41
  }
42
+ // Vertical Clamping (Fail-safe)
43
+ if (top < padding) {
44
+ top = padding;
45
+ }
46
+ if (top + contentRect.height > viewportHeight - padding) {
47
+ top = viewportHeight - contentRect.height - padding;
48
+ }
49
+ // Horizontal Clamping
50
+ if (left + contentRect.width > viewportWidth - padding) {
51
+ left = viewportWidth - contentRect.width - padding;
52
+ }
53
+ if (left < padding) {
54
+ left = padding;
55
+ }
42
56
  const align = placement.split('-')[1];
43
57
  if (align === 'start') {
44
58
  left = triggerRect.left;
@@ -52,22 +66,6 @@ export function Popover({ trigger, content, isOpen, onClose, placement = 'bottom
52
66
  left = triggerRect.left + (triggerRect.width / 2) - (contentRect.width / 2);
53
67
  origin += ' center';
54
68
  }
55
- // Edge Config
56
- const padding = 16;
57
- // Horizontal Clamping
58
- if (left + contentRect.width > viewportWidth - padding) {
59
- left = viewportWidth - contentRect.width - padding;
60
- }
61
- if (left < padding) {
62
- left = padding;
63
- }
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;
70
- }
71
69
  setPosition({ top, left });
72
70
  setTransformOrigin(origin);
73
71
  }, [isOpen, placement, offset]);
@@ -98,12 +96,9 @@ export function Popover({ trigger, content, isOpen, onClose, placement = 'bottom
98
96
  document.addEventListener('mousedown', handleClickOutside);
99
97
  return () => document.removeEventListener('mousedown', handleClickOutside);
100
98
  }, [isOpen, onClose]);
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: {
102
- position: 'fixed',
99
+ return (_jsxs(_Fragment, { children: [_jsx("div", { ref: triggerRef, className: styles.triggerWrapper, children: trigger }), isOpen && typeof document !== 'undefined' && createPortal(_jsx("div", { ref: contentRef, className: styles.popover, style: {
103
100
  top: position.top,
104
101
  left: position.left,
105
- zIndex: 9999, // High z-index to ensure it's on top
106
102
  transformOrigin: transformOrigin,
107
- animation: `${popoverScale} 0.1s ease-out`,
108
103
  }, children: content }), document.body)] }));
109
104
  }
@@ -0,0 +1,19 @@
1
+ .popover {
2
+ position: fixed;
3
+ z-index: 9999;
4
+ animation: popoverScale 0.1s ease-out;
5
+ }
6
+
7
+ @keyframes popoverScale {
8
+ from {
9
+ opacity: 0;
10
+ transform: scale(0.95);
11
+ }
12
+ to {
13
+ opacity: 1;
14
+ transform: scale(1);
15
+ }
16
+ }
17
+ .triggerWrapper {
18
+ display: inline-block;
19
+ }
@@ -1,42 +1,12 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
- import styled from '@emotion/styled';
4
- const StyledContainer = styled.div `
5
- height: ${props => typeof props.height === 'number' ? `${props.height}px` : props.height};
6
- width: 100%;
7
- background: var(--card-bg);
8
- border-radius: var(--radius);
9
- overflow: hidden;
10
- border: var(--border-width) solid var(--card-border);
11
- position: relative;
12
- `;
13
- const StyledFill = styled.div `
14
- height: 100%;
15
- width: ${props => props.percentage}%;
16
- background: ${props => props.color};
17
- border-right: ${props => props.percentage < 100 ? `var(--border-width) solid var(--card-border)` : 'none'};
18
- transition: width 0.5s ease-out;
19
- `;
20
- const StyledStripes = styled.div `
21
- position: absolute;
22
- top: 0;
23
- left: 0;
24
- right: 0;
25
- bottom: 0;
26
- background-image: linear-gradient(
27
- 45deg,
28
- rgba(0, 0, 0, 0.05) 25%,
29
- transparent 25%,
30
- transparent 50%,
31
- rgba(0, 0, 0, 0.05) 50%,
32
- rgba(0, 0, 0, 0.05) 75%,
33
- transparent 75%,
34
- transparent
35
- );
36
- background-size: 20px 20px;
37
- pointer-events: none;
38
- `;
3
+ import clsx from 'clsx';
4
+ import styles from './ProgressBar.module.css';
39
5
  export function ProgressBar({ value, max = 100, height = '24px', color = 'var(--primary)', showStripes = true, className, style }) {
40
6
  const percentage = Math.min(Math.max((value / max) * 100, 0), 100);
41
- return (_jsxs(StyledContainer, { height: height, className: className, style: style, children: [_jsx(StyledFill, { percentage: percentage, color: color }), showStripes && _jsx(StyledStripes, {})] }));
7
+ const heightStyle = typeof height === 'number' ? `${height}px` : height;
8
+ return (_jsxs("div", { className: clsx(styles.container, className), style: Object.assign({ '--height': heightStyle }, style), children: [_jsx("div", { className: styles.fill, style: {
9
+ '--percentage': `${percentage}%`,
10
+ '--color': color
11
+ }, "data-complete": percentage >= 100 }), showStripes && _jsx("div", { className: styles.stripes })] }));
42
12
  }
@@ -0,0 +1,31 @@
1
+ .container {
2
+ height: var(--height, 24px);
3
+ width: 100%;
4
+ background: var(--card-bg);
5
+ border-radius: var(--radius);
6
+ overflow: hidden;
7
+ border: var(--border-width) solid var(--card-border);
8
+ position: relative;
9
+ }
10
+
11
+ .fill {
12
+ height: 100%;
13
+ width: var(--percentage, 0%);
14
+ background: var(--color, var(--primary));
15
+ border-right: var(--border-width) solid var(--card-border);
16
+ transition: width 0.5s ease-out;
17
+ }
18
+ .fill[data-complete=true] {
19
+ border-right: none;
20
+ }
21
+
22
+ .stripes {
23
+ position: absolute;
24
+ top: 0;
25
+ left: 0;
26
+ right: 0;
27
+ bottom: 0;
28
+ background-image: linear-gradient(45deg, rgba(0, 0, 0, 0.05) 25%, transparent 25%, transparent 50%, rgba(0, 0, 0, 0.05) 50%, rgba(0, 0, 0, 0.05) 75%, transparent 75%, transparent);
29
+ background-size: 20px 20px;
30
+ pointer-events: none;
31
+ }
@@ -1,83 +1,8 @@
1
1
  'use client';
2
2
  import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
3
3
  import React, { createContext, useContext } from 'react';
4
- import styled from '@emotion/styled';
5
- const Group = styled.div `
6
- display: flex;
7
- flex-direction: column;
8
- gap: 0.5rem;
9
- `;
10
- const ItemLabel = styled.label `
11
- display: flex;
12
- align-items: center;
13
- gap: 0.75rem;
14
- cursor: ${props => props.disabled ? 'not-allowed' : 'pointer'};
15
- position: relative;
16
- padding: 0.75rem 1rem;
17
- border-radius: var(--radius);
18
- transition: all 0.15s ease;
19
- opacity: ${props => props.disabled ? 0.5 : 1};
20
-
21
- &:hover:not([aria-disabled="true"]) {
22
- background-color: var(--muted);
23
- background-color: color-mix(in srgb, var(--primary) 8%, transparent);
24
- }
25
- `;
26
- const RadioCircle = styled.div `
27
- width: 22px;
28
- height: 22px;
29
- border: 2px solid ${props => props.checked ? 'var(--primary)' : 'var(--foreground)'};
30
- border-radius: 50%;
31
- background: var(--background);
32
- display: flex;
33
- align-items: center;
34
- justify-content: center;
35
- transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
36
- flex-shrink: 0;
37
- position: relative;
38
-
39
- ${props => props.checked && `
40
- border-color: var(--primary);
41
- background: var(--primary);
42
- box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 15%, transparent);
43
- `}
44
- `;
45
- const InnerDot = styled.div `
46
- width: 10px;
47
- height: 10px;
48
- background: var(--primary-foreground);
49
- border-radius: 50%;
50
- transform: scale(0);
51
- animation: radioScale 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
52
-
53
- @keyframes radioScale {
54
- from {
55
- transform: scale(0);
56
- }
57
- to {
58
- transform: scale(1);
59
- }
60
- }
61
- `;
62
- const HiddenInput = styled.input `
63
- position: absolute;
64
- opacity: 0;
65
- width: 1px;
66
- height: 1px;
67
- pointer-events: none;
68
-
69
- &:focus-visible ~ div {
70
- outline: var(--outline-width) solid var(--primary);
71
- outline-offset: var(--outline-offset);
72
- }
73
- `;
74
- const LabelText = styled.span `
75
- font-family: var(--font-body);
76
- font-weight: 500;
77
- font-size: var(--text-base);
78
- color: var(--foreground);
79
- user-select: none;
80
- `;
4
+ import clsx from 'clsx';
5
+ import styles from './RadioGroup.module.css';
81
6
  const RadioGroupContext = createContext(undefined);
82
7
  export function RadioGroup({ name, value: controlledValue, defaultValue, onValueChange, disabled, children, className }) {
83
8
  const [internalValue, setInternalValue] = React.useState(defaultValue || '');
@@ -89,7 +14,7 @@ export function RadioGroup({ name, value: controlledValue, defaultValue, onValue
89
14
  }
90
15
  onValueChange === null || onValueChange === void 0 ? void 0 : onValueChange(newValue);
91
16
  };
92
- return (_jsx(RadioGroupContext.Provider, { value: { name, value: currentValue, onChange: handleChange, disabled }, children: _jsx(Group, { role: "radiogroup", className: className, children: children }) }));
17
+ return (_jsx(RadioGroupContext.Provider, { value: { name, value: currentValue, onChange: handleChange, disabled }, children: _jsx("div", { role: "radiogroup", className: clsx(styles.group, className), children: children }) }));
93
18
  }
94
19
  export function RadioGroupItem({ value, children, disabled, className }) {
95
20
  const context = useContext(RadioGroupContext);
@@ -97,5 +22,5 @@ export function RadioGroupItem({ value, children, disabled, className }) {
97
22
  throw new Error('RadioGroupItem must be used within RadioGroup');
98
23
  const checked = context.value === value;
99
24
  const isDisabled = disabled || context.disabled;
100
- return (_jsxs(ItemLabel, { disabled: isDisabled, "aria-disabled": isDisabled, className: className, children: [_jsx(HiddenInput, { type: "radio", name: context.name, value: value, checked: checked, onChange: () => !isDisabled && context.onChange(value), disabled: isDisabled }), _jsx(RadioCircle, { checked: checked, "aria-hidden": "true", children: checked && _jsx(InnerDot, {}) }), _jsx(LabelText, { children: children })] }));
25
+ return (_jsxs("label", { className: clsx(styles.itemLabel, isDisabled && styles.disabled, className), "aria-disabled": isDisabled, children: [_jsx("input", { className: styles.hiddenInput, type: "radio", name: context.name, value: value, checked: checked, onChange: () => !isDisabled && context.onChange(value), disabled: isDisabled }), _jsx("div", { className: clsx(styles.radioCircle, checked && styles.checked), "aria-hidden": "true", children: checked && _jsx("div", { className: styles.innerDot }) }), _jsx("span", { className: styles.labelText, children: children })] }));
101
26
  }
@@ -0,0 +1,81 @@
1
+ .group {
2
+ display: flex;
3
+ flex-direction: column;
4
+ gap: 0.5rem;
5
+ }
6
+
7
+ .itemLabel {
8
+ display: flex;
9
+ align-items: center;
10
+ gap: 0.75rem;
11
+ cursor: pointer;
12
+ position: relative;
13
+ padding: 0.75rem 1rem;
14
+ border-radius: var(--radius);
15
+ transition: all 0.15s ease;
16
+ opacity: 1;
17
+ }
18
+ .itemLabel:hover:not([aria-disabled=true]) {
19
+ background-color: var(--muted);
20
+ background-color: color-mix(in srgb, var(--primary) 8%, transparent);
21
+ }
22
+ .itemLabel.disabled {
23
+ cursor: not-allowed;
24
+ opacity: 0.5;
25
+ }
26
+
27
+ .radioCircle {
28
+ width: 22px;
29
+ height: 22px;
30
+ border: 2px solid var(--foreground);
31
+ border-radius: 50%;
32
+ background: var(--background);
33
+ display: flex;
34
+ align-items: center;
35
+ justify-content: center;
36
+ transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);
37
+ flex-shrink: 0;
38
+ position: relative;
39
+ }
40
+ .radioCircle.checked {
41
+ border-color: var(--primary);
42
+ background: var(--primary);
43
+ box-shadow: 0 0 0 4px color-mix(in srgb, var(--primary) 15%, transparent);
44
+ }
45
+
46
+ .innerDot {
47
+ width: 10px;
48
+ height: 10px;
49
+ background: var(--primary-foreground);
50
+ border-radius: 50%;
51
+ transform: scale(0);
52
+ animation: radioScale 0.2s cubic-bezier(0.4, 0, 0.2, 1) forwards;
53
+ }
54
+
55
+ @keyframes radioScale {
56
+ from {
57
+ transform: scale(0);
58
+ }
59
+ to {
60
+ transform: scale(1);
61
+ }
62
+ }
63
+ .hiddenInput {
64
+ position: absolute;
65
+ opacity: 0;
66
+ width: 1px;
67
+ height: 1px;
68
+ pointer-events: none;
69
+ }
70
+ .hiddenInput:focus-visible ~ .radioCircle {
71
+ outline: var(--outline-width) solid var(--primary);
72
+ outline-offset: var(--outline-offset);
73
+ }
74
+
75
+ .labelText {
76
+ font-family: var(--font-body);
77
+ font-weight: 500;
78
+ font-size: var(--text-base);
79
+ color: var(--foreground);
80
+ user-select: none;
81
+ }