@rozenite/vite-plugin 1.12.0 → 1.13.0

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 (40) hide show
  1. package/package.json +2 -1
  2. package/src/bundle-dts.ts +125 -0
  3. package/src/client-plugin.ts +392 -0
  4. package/src/dev-config-module.ts +29 -0
  5. package/src/dev-host/App.tsx +567 -0
  6. package/src/dev-host/components/DispatchForm.tsx +169 -0
  7. package/src/dev-host/components/FlowList.tsx +142 -0
  8. package/src/dev-host/components/MessageDetailsPane.tsx +109 -0
  9. package/src/dev-host/components/MessageLogPane.tsx +84 -0
  10. package/src/dev-host/components/MessagePayloadDetail.tsx +32 -0
  11. package/src/dev-host/components/PanelTabs.tsx +22 -0
  12. package/src/dev-host/components/ResizeHandle.tsx +33 -0
  13. package/src/dev-host/components/icons.tsx +79 -0
  14. package/src/dev-host/components/ui/Button.tsx +91 -0
  15. package/src/dev-host/components/ui/DropdownMenu.tsx +84 -0
  16. package/src/dev-host/components/ui/IconButton.tsx +41 -0
  17. package/src/dev-host/components/ui/Input.tsx +73 -0
  18. package/src/dev-host/components/ui/ScrollArea.tsx +20 -0
  19. package/src/dev-host/components/ui/Tabs.tsx +166 -0
  20. package/src/dev-host/components/ui/Textarea.tsx +79 -0
  21. package/src/dev-host/components/ui/ToggleGroup.tsx +120 -0
  22. package/src/dev-host/config.ts +107 -0
  23. package/src/dev-host/constants.ts +31 -0
  24. package/src/dev-host/flow-runtime.ts +297 -0
  25. package/src/dev-host/index.html +12 -0
  26. package/src/dev-host/main.tsx +31 -0
  27. package/src/dev-host/server.ts +55 -0
  28. package/src/dev-host/styles.css +969 -0
  29. package/src/dev-host/types.ts +61 -0
  30. package/src/dev-host/utils.ts +96 -0
  31. package/src/dev-host/vite.config.mts +20 -0
  32. package/src/index.ts +114 -0
  33. package/src/load-config.ts +117 -0
  34. package/src/package-json.ts +16 -0
  35. package/src/react-native-plugin.ts +49 -0
  36. package/src/require-plugin.ts +221 -0
  37. package/src/sdk-plugin.ts +44 -0
  38. package/src/server-plugin.ts +36 -0
  39. package/src/utils.ts +31 -0
  40. package/src/virtual-modules.d.ts +7 -0
@@ -0,0 +1,91 @@
1
+ import type { ComponentProps } from 'react';
2
+ import { mergeOverrides } from 'baseui';
3
+ import { Button as BaseButton, KIND, SHAPE, SIZE, WIDTH_TYPE, type ButtonOverrides } from 'baseui/button/index.js';
4
+
5
+ type ButtonVariant = 'default' | 'primary' | 'pill';
6
+
7
+ type BaseButtonProps = ComponentProps<typeof BaseButton>;
8
+
9
+ export type ButtonProps = Omit<BaseButtonProps, 'kind' | 'shape' | 'size' | 'widthType'> & {
10
+ variant?: ButtonVariant;
11
+ };
12
+
13
+ const baseOverrides: ButtonOverrides = {
14
+ BaseButton: {
15
+ style: ({ $disabled, $isFocusVisible }) => ({
16
+ minHeight: 'auto',
17
+ minWidth: 'auto',
18
+ borderWidth: '1px',
19
+ borderStyle: 'solid',
20
+ borderColor: 'rgba(255, 255, 255, 0.08)',
21
+ borderRadius: '4px',
22
+ backgroundColor: 'transparent',
23
+ color: 'rgba(255, 255, 255, 0.56)',
24
+ paddingTop: '0',
25
+ paddingRight: '0',
26
+ paddingBottom: '0',
27
+ paddingLeft: '0',
28
+ boxShadow: 'none',
29
+ cursor: $disabled ? 'default' : 'pointer',
30
+ opacity: $disabled ? 0.4 : 1,
31
+ outline: $isFocusVisible ? '2px solid rgba(130, 50, 255, 0.95)' : 'none',
32
+ outlineOffset: '-2px',
33
+ }),
34
+ },
35
+ };
36
+
37
+ const variantOverrides: Record<ButtonVariant, ButtonOverrides> = {
38
+ default: {
39
+ BaseButton: {
40
+ style: ({ $disabled, $isHovered }) => ({
41
+ borderColor: 'rgba(255, 255, 255, 0.08)',
42
+ backgroundColor: !$disabled && $isHovered ? 'rgba(255, 255, 255, 0.06)' : 'transparent',
43
+ color: 'rgba(255, 255, 255, 0.56)',
44
+ }),
45
+ },
46
+ },
47
+ primary: {
48
+ BaseButton: {
49
+ style: ({ $disabled, $isHovered }) => ({
50
+ borderColor: '#ffffff',
51
+ backgroundColor: '#ffffff',
52
+ color: '#000000',
53
+ opacity: $disabled ? 0.4 : 1,
54
+ ':hover': !$disabled && $isHovered ? { backgroundColor: 'rgba(255, 255, 255, 0.88)' } : undefined,
55
+ }),
56
+ },
57
+ },
58
+ pill: {
59
+ BaseButton: {
60
+ style: ({ $disabled, $isHovered, $isSelected }) => ({
61
+ borderColor: $isSelected ? 'rgba(130, 50, 255, 0.5)' : 'rgba(255, 255, 255, 0.08)',
62
+ borderRadius: '999px',
63
+ backgroundColor: $isSelected
64
+ ? 'rgba(130, 50, 255, 0.18)'
65
+ : !$disabled && $isHovered
66
+ ? 'rgba(255, 255, 255, 0.1)'
67
+ : 'rgba(255, 255, 255, 0.04)',
68
+ color: '#ffffff',
69
+ paddingTop: '6px',
70
+ paddingRight: '10px',
71
+ paddingBottom: '6px',
72
+ paddingLeft: '10px',
73
+ fontSize: '12px',
74
+ lineHeight: '1.4',
75
+ }),
76
+ },
77
+ },
78
+ };
79
+
80
+ export const Button = ({ overrides, variant = 'default', ...props }: ButtonProps) => {
81
+ return (
82
+ <BaseButton
83
+ kind={KIND.tertiary}
84
+ shape={variant === 'pill' ? SHAPE.pill : SHAPE.rectangular}
85
+ size={SIZE.compact}
86
+ widthType={WIDTH_TYPE.hug}
87
+ overrides={mergeOverrides(mergeOverrides(baseOverrides, variantOverrides[variant]), overrides)}
88
+ {...props}
89
+ />
90
+ );
91
+ };
@@ -0,0 +1,84 @@
1
+ import type { ReactNode } from 'react';
2
+ import { StatefulMenu } from 'baseui/menu/index.js';
3
+ import { StatefulPopover, TRIGGER_TYPE } from 'baseui/popover/index.js';
4
+
5
+ export type DropdownMenuItem<T> = {
6
+ id: string;
7
+ label: string;
8
+ item: T;
9
+ };
10
+
11
+ type DropdownMenuProps<T> = {
12
+ items: DropdownMenuItem<T>[];
13
+ onSelect: (item: T) => void;
14
+ children: ReactNode;
15
+ };
16
+
17
+ export const DropdownMenu = <T,>({ items, onSelect, children }: DropdownMenuProps<T>) => {
18
+ return (
19
+ <StatefulPopover
20
+ triggerType={TRIGGER_TYPE.click}
21
+ placement="bottomRight"
22
+ accessibilityType="menu"
23
+ dismissOnClickOutside
24
+ dismissOnEsc
25
+ focusLock={false}
26
+ autoFocus={false}
27
+ showArrow={false}
28
+ content={({ close }: { close: () => void }) => (
29
+ <div className="rz-baseui-preset-menu">
30
+ <StatefulMenu
31
+ items={items}
32
+ onItemSelect={({ item }: { item: DropdownMenuItem<T> }) => {
33
+ onSelect(item.item);
34
+ close();
35
+ }}
36
+ overrides={{
37
+ List: {
38
+ style: {
39
+ backgroundColor: '#111111',
40
+ color: '#ffffff',
41
+ borderRadius: '8px',
42
+ minWidth: '220px',
43
+ maxWidth: 'min(320px, calc(100vw - 24px))',
44
+ paddingTop: '6px',
45
+ paddingBottom: '6px',
46
+ boxShadow: '0 12px 32px rgba(0, 0, 0, 0.35)',
47
+ },
48
+ },
49
+ Option: {
50
+ props: {
51
+ getItemLabel: (menuItem: DropdownMenuItem<T>) => menuItem.label,
52
+ },
53
+ style: ({ $isHighlighted }: { $isHighlighted?: boolean }) => ({
54
+ backgroundColor: $isHighlighted ? 'rgba(255, 255, 255, 0.08)' : 'transparent',
55
+ color: '#ffffff',
56
+ fontSize: '13px',
57
+ lineHeight: '1.4',
58
+ paddingTop: '8px',
59
+ paddingRight: '10px',
60
+ paddingBottom: '8px',
61
+ paddingLeft: '10px',
62
+ }),
63
+ },
64
+ }}
65
+ />
66
+ </div>
67
+ )}
68
+ overrides={{
69
+ Body: {
70
+ style: {
71
+ zIndex: 20,
72
+ },
73
+ },
74
+ Inner: {
75
+ style: {
76
+ backgroundColor: 'transparent',
77
+ },
78
+ },
79
+ }}
80
+ >
81
+ {children}
82
+ </StatefulPopover>
83
+ );
84
+ };
@@ -0,0 +1,41 @@
1
+ import type { ReactNode } from 'react';
2
+ import { mergeOverrides } from 'baseui';
3
+ import type { ButtonProps } from './Button.js';
4
+ import { Button } from './Button.js';
5
+
6
+ export type IconButtonProps = Omit<ButtonProps, 'children'> & {
7
+ children: ReactNode;
8
+ };
9
+
10
+ export const IconButton = ({ overrides, children, ...props }: IconButtonProps) => {
11
+ return (
12
+ <Button
13
+ overrides={mergeOverrides(
14
+ {
15
+ BaseButton: {
16
+ style: ({ $disabled, $isHovered, $isFocusVisible }: { $disabled?: boolean; $isHovered?: boolean; $isFocusVisible?: boolean }) => ({
17
+ width: '28px',
18
+ height: '28px',
19
+ minWidth: '28px',
20
+ minHeight: '28px',
21
+ borderWidth: '0',
22
+ borderRadius: '4px',
23
+ backgroundColor: !$disabled && $isHovered ? 'rgba(255, 255, 255, 0.06)' : 'transparent',
24
+ color: !$disabled && $isHovered ? '#ffffff' : 'rgba(255, 255, 255, 0.56)',
25
+ paddingTop: '0',
26
+ paddingRight: '0',
27
+ paddingBottom: '0',
28
+ paddingLeft: '0',
29
+ outline: $isFocusVisible ? '2px solid rgba(130, 50, 255, 0.95)' : 'none',
30
+ outlineOffset: '-2px',
31
+ }),
32
+ },
33
+ },
34
+ overrides,
35
+ )}
36
+ {...props}
37
+ >
38
+ {children}
39
+ </Button>
40
+ );
41
+ };
@@ -0,0 +1,73 @@
1
+ import type { ComponentProps } from 'react';
2
+ import { mergeOverrides } from 'baseui';
3
+ import { Input as BaseInput, SIZE } from 'baseui/input/index.js';
4
+
5
+ type BaseInputProps = ComponentProps<typeof BaseInput>;
6
+
7
+ export type InputProps = BaseInputProps & {
8
+ spellCheck?: boolean;
9
+ };
10
+
11
+ const inputOverrides = {
12
+ Root: {
13
+ style: {
14
+ width: '100%',
15
+ borderWidth: '0',
16
+ backgroundColor: 'transparent',
17
+ paddingLeft: '0',
18
+ paddingRight: '0',
19
+ },
20
+ },
21
+ InputContainer: {
22
+ style: ({ $isFocused }: { $isFocused?: boolean }) => ({
23
+ borderWidth: '1px',
24
+ borderStyle: 'solid',
25
+ borderColor: 'rgba(255, 255, 255, 0.08)',
26
+ borderRadius: '4px',
27
+ backgroundColor: 'rgba(255, 255, 255, 0.03)',
28
+ outline: $isFocused ? '2px solid rgba(130, 50, 255, 0.95)' : 'none',
29
+ outlineOffset: '-2px',
30
+ }),
31
+ },
32
+ Input: {
33
+ style: {
34
+ paddingTop: '10px',
35
+ paddingRight: '12px',
36
+ paddingBottom: '10px',
37
+ paddingLeft: '12px',
38
+ fontFamily: '"Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace',
39
+ fontWeight: 400,
40
+ color: 'rgba(255, 255, 255, 0.9)',
41
+ fontSize: '12px',
42
+ lineHeight: '1.5',
43
+ letterSpacing: '-0.02em',
44
+ '::placeholder': {
45
+ color: 'rgba(255, 255, 255, 0.36)',
46
+ },
47
+ },
48
+ },
49
+ };
50
+
51
+ export const Input = ({ overrides, spellCheck, ...props }: InputProps) => {
52
+ return (
53
+ <BaseInput
54
+ size={SIZE.compact}
55
+ overrides={mergeOverrides(
56
+ inputOverrides,
57
+ spellCheck === undefined
58
+ ? overrides
59
+ : mergeOverrides(
60
+ {
61
+ Input: {
62
+ props: {
63
+ spellCheck,
64
+ },
65
+ },
66
+ },
67
+ overrides,
68
+ ),
69
+ )}
70
+ {...props}
71
+ />
72
+ );
73
+ };
@@ -0,0 +1,20 @@
1
+ import {
2
+ forwardRef,
3
+ type ComponentPropsWithoutRef,
4
+ type ReactNode,
5
+ } from 'react';
6
+ import { cn } from '../../utils.js';
7
+
8
+ type ScrollAreaProps = ComponentPropsWithoutRef<'div'> & {
9
+ children: ReactNode;
10
+ };
11
+
12
+ export const ScrollArea = forwardRef<HTMLDivElement, ScrollAreaProps>(({ className, children, ...props }, ref) => {
13
+ return (
14
+ <div ref={ref} className={cn('rz-scroll-area', className)} {...props}>
15
+ <div className="rz-scroll-viewport">{children}</div>
16
+ </div>
17
+ );
18
+ });
19
+
20
+ ScrollArea.displayName = 'ScrollArea';
@@ -0,0 +1,166 @@
1
+ import { Children, createContext, isValidElement, useContext, type ReactElement, type ReactNode } from 'react';
2
+ import { Tab, Tabs as BaseTabs } from 'baseui/tabs/index.js';
3
+ import { cn } from '../../utils.js';
4
+
5
+ type TabsContextValue = {
6
+ activeKey: string;
7
+ };
8
+
9
+ const TabsContext = createContext<TabsContextValue | null>(null);
10
+
11
+ type TabsProps = {
12
+ className?: string;
13
+ value: string;
14
+ onValueChange: (value: string) => void;
15
+ children: ReactNode;
16
+ };
17
+
18
+ type TabsListProps = {
19
+ className?: string;
20
+ children: ReactNode;
21
+ 'aria-label'?: string;
22
+ };
23
+
24
+ type TabsTriggerProps = {
25
+ value: string;
26
+ disabled?: boolean;
27
+ children: ReactNode;
28
+ };
29
+
30
+ type TabsContentProps = {
31
+ value: string;
32
+ className?: string;
33
+ children: ReactNode;
34
+ };
35
+
36
+ type ElementWithChildren = ReactElement<{ children?: ReactNode }>;
37
+ type TabTriggerElement = ReactElement<TabsTriggerProps>;
38
+ type TabsContentElement = ReactElement<TabsContentProps>;
39
+
40
+ const collectElements = <T,>(
41
+ children: ReactNode,
42
+ matcher: (element: ReactElement) => element is ReactElement<T>,
43
+ ): Array<ReactElement<T>> => {
44
+ const matches: Array<ReactElement<T>> = [];
45
+
46
+ Children.forEach(children, (child) => {
47
+ if (!isValidElement(child)) {
48
+ return;
49
+ }
50
+
51
+ if (matcher(child)) {
52
+ matches.push(child);
53
+ return;
54
+ }
55
+
56
+ const childWithChildren = child as ElementWithChildren;
57
+
58
+ if (childWithChildren.props.children !== undefined) {
59
+ matches.push(...collectElements(childWithChildren.props.children, matcher));
60
+ }
61
+ });
62
+
63
+ return matches;
64
+ };
65
+
66
+ const tabsOverrides = {
67
+ Root: {
68
+ style: {
69
+ width: '100%',
70
+ minWidth: 0,
71
+ },
72
+ },
73
+ TabBar: {
74
+ style: {
75
+ display: 'inline-flex',
76
+ minHeight: '26px',
77
+ maxWidth: '100%',
78
+ alignItems: 'center',
79
+ gap: '2px',
80
+ overflowX: 'auto',
81
+ overflowY: 'hidden',
82
+ border: '1px solid rgba(255, 255, 255, 0.08)',
83
+ borderRadius: '4px',
84
+ background: 'rgba(255, 255, 255, 0.04)',
85
+ paddingTop: '2px',
86
+ paddingRight: '2px',
87
+ paddingBottom: '2px',
88
+ paddingLeft: '2px',
89
+ scrollbarWidth: 'none',
90
+ },
91
+ },
92
+ Tab: {
93
+ style: ({ $active, $disabled, $isFocusVisible }: { $active?: boolean; $disabled?: boolean; $isFocusVisible?: boolean }) => ({
94
+ display: 'inline-flex',
95
+ alignItems: 'center',
96
+ justifyContent: 'center',
97
+ whiteSpace: 'nowrap',
98
+ borderRadius: '2px',
99
+ backgroundColor: $active ? '#ffffff' : 'transparent',
100
+ minHeight: '22px',
101
+ paddingTop: '3px',
102
+ paddingRight: '9px',
103
+ paddingBottom: '3px',
104
+ paddingLeft: '9px',
105
+ color: $active ? '#000000' : 'rgba(255, 255, 255, 0.6)',
106
+ fontSize: '12px',
107
+ fontWeight: 500,
108
+ lineHeight: 1.2,
109
+ transitionProperty: 'background-color, color',
110
+ transitionDuration: '120ms',
111
+ outline: $isFocusVisible ? '2px solid rgba(130, 50, 255, 0.95)' : 'none',
112
+ outlineOffset: '-2px',
113
+ cursor: $disabled ? 'default' : 'pointer',
114
+ opacity: $disabled ? 0.4 : 1,
115
+ ':hover': $disabled || $active ? undefined : {
116
+ color: '#ffffff',
117
+ },
118
+ }),
119
+ },
120
+ };
121
+
122
+ export const Tabs = ({ className, value, onValueChange, children }: TabsProps) => {
123
+ const lists = collectElements(children, (child): child is ReactElement<TabsListProps> => child.type === TabsList);
124
+ const content = collectElements(children, (child): child is TabsContentElement => child.type === TabsContent);
125
+ const list = lists[0];
126
+
127
+ if (!list) {
128
+ return null;
129
+ }
130
+
131
+ const triggers = Children.toArray(list.props.children).filter(
132
+ (child): child is TabTriggerElement => isValidElement(child) && child.type === TabsTrigger,
133
+ );
134
+
135
+ return (
136
+ <TabsContext.Provider value={{ activeKey: value }}>
137
+ <div className={cn('rz-tabs-root', className)}>
138
+ <BaseTabs activeKey={value} onChange={({ activeKey }) => onValueChange(String(activeKey))} overrides={tabsOverrides}>
139
+ {triggers.map((trigger) => (
140
+ <Tab key={trigger.props.value} title={trigger.props.children} disabled={trigger.props.disabled} />
141
+ ))}
142
+ </BaseTabs>
143
+ {content}
144
+ </div>
145
+ </TabsContext.Provider>
146
+ );
147
+ };
148
+
149
+ export const TabsList = ({ children }: TabsListProps) => {
150
+ return <>{children}</>;
151
+ };
152
+
153
+ export const TabsTrigger: (_props: TabsTriggerProps) => null = () => {
154
+ return null;
155
+ };
156
+
157
+ export const TabsContent = ({ value, className, children }: TabsContentProps) => {
158
+ const context = useContext(TabsContext);
159
+ const isActive = context?.activeKey === value;
160
+
161
+ if (!isActive) {
162
+ return null;
163
+ }
164
+
165
+ return <div className={className}>{children}</div>;
166
+ };
@@ -0,0 +1,79 @@
1
+ import type { ComponentProps } from 'react';
2
+ import { mergeOverrides } from 'baseui';
3
+ import { SIZE, Textarea as BaseTextarea } from 'baseui/textarea/index.js';
4
+
5
+ type BaseTextareaProps = ComponentProps<typeof BaseTextarea>;
6
+
7
+ export type TextareaProps = BaseTextareaProps & {
8
+ spellCheck?: boolean;
9
+ };
10
+
11
+ const textareaOverrides = {
12
+ Root: {
13
+ style: {
14
+ width: '100%',
15
+ borderWidth: '0',
16
+ backgroundColor: 'transparent',
17
+ paddingLeft: '0',
18
+ paddingRight: '0',
19
+ },
20
+ },
21
+ InputContainer: {
22
+ style: ({ $isFocused }: { $isFocused?: boolean }) => ({
23
+ borderWidth: '1px',
24
+ borderStyle: 'solid',
25
+ borderColor: 'rgba(255, 255, 255, 0.08)',
26
+ borderRadius: '4px',
27
+ backgroundColor: 'rgba(255, 255, 255, 0.03)',
28
+ outline: $isFocused ? '2px solid rgba(130, 50, 255, 0.95)' : 'none',
29
+ outlineOffset: '-2px',
30
+ alignItems: 'stretch',
31
+ }),
32
+ },
33
+ Input: {
34
+ style: {
35
+ minHeight: '112px',
36
+ display: 'block',
37
+ alignSelf: 'stretch',
38
+ resize: 'none',
39
+ paddingTop: '12px',
40
+ paddingRight: '12px',
41
+ paddingBottom: '12px',
42
+ paddingLeft: '12px',
43
+ fontFamily: '"Geist Mono", ui-monospace, SFMono-Regular, Menlo, monospace',
44
+ fontWeight: 400,
45
+ color: 'rgba(255, 255, 255, 0.9)',
46
+ fontSize: '12px',
47
+ lineHeight: '1.5',
48
+ letterSpacing: '-0.02em',
49
+ '::placeholder': {
50
+ color: 'rgba(255, 255, 255, 0.36)',
51
+ },
52
+ },
53
+ },
54
+ };
55
+
56
+ export const Textarea = ({ overrides, rows = 6, spellCheck, ...props }: TextareaProps) => {
57
+ return (
58
+ <BaseTextarea
59
+ rows={rows}
60
+ size={SIZE.compact}
61
+ overrides={mergeOverrides(
62
+ textareaOverrides,
63
+ spellCheck === undefined
64
+ ? overrides
65
+ : mergeOverrides(
66
+ {
67
+ Input: {
68
+ props: {
69
+ spellCheck,
70
+ },
71
+ },
72
+ },
73
+ overrides,
74
+ ),
75
+ )}
76
+ {...props}
77
+ />
78
+ );
79
+ };
@@ -0,0 +1,120 @@
1
+ import type { Key, ReactNode } from 'react';
2
+ import { mergeOverrides } from 'baseui';
3
+ import { Segment } from 'baseui/segmented-control/segment.js';
4
+ import { SegmentedControl } from 'baseui/segmented-control/index.js';
5
+
6
+ export type ToggleGroupOption = {
7
+ key: Key;
8
+ label: ReactNode;
9
+ disabled?: boolean;
10
+ };
11
+
12
+ type ToggleGroupProps = {
13
+ value: Key;
14
+ options: ToggleGroupOption[];
15
+ onChange: (value: string) => void;
16
+ 'aria-label'?: string;
17
+ };
18
+
19
+ const overrides = {
20
+ Root: {
21
+ style: {
22
+ display: 'inline-flex',
23
+ width: 'fit-content',
24
+ maxWidth: '100%',
25
+ paddingTop: '2px',
26
+ paddingRight: '2px',
27
+ paddingBottom: '2px',
28
+ paddingLeft: '2px',
29
+ border: '1px solid rgba(255, 255, 255, 0.08)',
30
+ borderRadius: '4px',
31
+ backgroundColor: 'rgba(255, 255, 255, 0.04)',
32
+ overflow: 'hidden',
33
+ },
34
+ },
35
+ SegmentList: {
36
+ style: {
37
+ display: 'inline-flex',
38
+ width: 'fit-content',
39
+ minHeight: '22px',
40
+ maxWidth: '100%',
41
+ alignItems: 'center',
42
+ gap: '2px',
43
+ overflow: 'hidden',
44
+ minWidth: 'unset',
45
+ backgroundColor: 'transparent',
46
+ zIndex: 0,
47
+ },
48
+ },
49
+ Active: {
50
+ style: {
51
+ backgroundColor: '#ffffff',
52
+ borderRadius: '2px',
53
+ zIndex: -1,
54
+ },
55
+ },
56
+ };
57
+
58
+ const segmentOverrides = {
59
+ Segment: {
60
+ style: ({ $isActive, $disabled, $isFocusVisible }: { $isActive?: boolean; $disabled?: boolean; $isFocusVisible?: boolean }) => ({
61
+ minHeight: '22px',
62
+ minWidth: 'auto',
63
+ paddingTop: '3px',
64
+ paddingRight: '9px',
65
+ paddingBottom: '3px',
66
+ paddingLeft: '9px',
67
+ borderRadius: '2px',
68
+ backgroundColor: 'transparent',
69
+ color: $isActive ? '#000000' : 'rgba(255, 255, 255, 0.6)',
70
+ fontSize: '12px',
71
+ fontWeight: 500,
72
+ lineHeight: 1.2,
73
+ transitionProperty: 'background-color, color',
74
+ transitionDuration: '120ms',
75
+ outline: $isFocusVisible ? '2px solid rgba(130, 50, 255, 0.95)' : 'none',
76
+ outlineOffset: '-2px',
77
+ cursor: $disabled ? 'default' : 'pointer',
78
+ opacity: $disabled ? 0.4 : 1,
79
+ ':hover': $disabled || $isActive ? undefined : {
80
+ color: '#ffffff',
81
+ },
82
+ }),
83
+ },
84
+ LabelBlock: {
85
+ style: {
86
+ paddingTop: '0',
87
+ paddingRight: '0',
88
+ paddingBottom: '0',
89
+ paddingLeft: '0',
90
+ },
91
+ },
92
+ Label: {
93
+ style: {
94
+ fontSize: '12px',
95
+ fontWeight: 500,
96
+ lineHeight: 1.2,
97
+ color: 'inherit',
98
+ },
99
+ },
100
+ };
101
+
102
+ export const ToggleGroup = ({ value, options, onChange, 'aria-label': ariaLabel }: ToggleGroupProps) => {
103
+ return (
104
+ <SegmentedControl
105
+ activeKey={value}
106
+ onChange={({ activeKey }) => onChange(String(activeKey))}
107
+ overrides={mergeOverrides(overrides, {
108
+ Root: {
109
+ props: {
110
+ 'aria-label': ariaLabel,
111
+ },
112
+ },
113
+ })}
114
+ >
115
+ {options.map((option) => (
116
+ <Segment key={option.key} label={option.label} disabled={option.disabled} overrides={segmentOverrides} />
117
+ ))}
118
+ </SegmentedControl>
119
+ );
120
+ };