@fragments-sdk/ui 0.1.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 (73) hide show
  1. package/package.json +44 -0
  2. package/src/brand.ts +15 -0
  3. package/src/components/Alert/Alert.fragment.tsx +163 -0
  4. package/src/components/Alert/Alert.module.scss +116 -0
  5. package/src/components/Alert/index.tsx +95 -0
  6. package/src/components/Avatar/Avatar.fragment.tsx +147 -0
  7. package/src/components/Avatar/Avatar.module.scss +136 -0
  8. package/src/components/Avatar/index.tsx +177 -0
  9. package/src/components/Badge/Badge.fragment.tsx +151 -0
  10. package/src/components/Badge/Badge.module.scss +87 -0
  11. package/src/components/Badge/index.tsx +55 -0
  12. package/src/components/Button/Button.fragment.tsx +159 -0
  13. package/src/components/Button/Button.module.scss +97 -0
  14. package/src/components/Button/index.tsx +51 -0
  15. package/src/components/Card/Card.fragment.tsx +156 -0
  16. package/src/components/Card/Card.module.scss +86 -0
  17. package/src/components/Card/index.tsx +79 -0
  18. package/src/components/Checkbox/Checkbox.fragment.tsx +166 -0
  19. package/src/components/Checkbox/Checkbox.module.scss +144 -0
  20. package/src/components/Checkbox/index.tsx +166 -0
  21. package/src/components/Dialog/Dialog.fragment.tsx +179 -0
  22. package/src/components/Dialog/Dialog.module.scss +158 -0
  23. package/src/components/Dialog/index.tsx +230 -0
  24. package/src/components/EmptyState/EmptyState.fragment.tsx +222 -0
  25. package/src/components/EmptyState/EmptyState.module.scss +120 -0
  26. package/src/components/EmptyState/index.tsx +80 -0
  27. package/src/components/Input/Input.fragment.tsx +174 -0
  28. package/src/components/Input/Input.module.scss +64 -0
  29. package/src/components/Input/index.tsx +76 -0
  30. package/src/components/Menu/Menu.fragment.tsx +168 -0
  31. package/src/components/Menu/Menu.module.scss +190 -0
  32. package/src/components/Menu/index.tsx +318 -0
  33. package/src/components/Popover/Popover.fragment.tsx +178 -0
  34. package/src/components/Popover/Popover.module.scss +165 -0
  35. package/src/components/Popover/index.tsx +229 -0
  36. package/src/components/Progress/Progress.fragment.tsx +142 -0
  37. package/src/components/Progress/Progress.module.scss +185 -0
  38. package/src/components/Progress/index.tsx +196 -0
  39. package/src/components/RadioGroup/RadioGroup.fragment.tsx +188 -0
  40. package/src/components/RadioGroup/RadioGroup.module.scss +155 -0
  41. package/src/components/RadioGroup/index.tsx +166 -0
  42. package/src/components/Select/Select.fragment.tsx +173 -0
  43. package/src/components/Select/Select.module.scss +187 -0
  44. package/src/components/Select/index.tsx +233 -0
  45. package/src/components/Separator/Separator.fragment.tsx +148 -0
  46. package/src/components/Separator/Separator.module.scss +92 -0
  47. package/src/components/Separator/index.tsx +89 -0
  48. package/src/components/Skeleton/Skeleton.fragment.tsx +147 -0
  49. package/src/components/Skeleton/Skeleton.module.scss +166 -0
  50. package/src/components/Skeleton/index.tsx +185 -0
  51. package/src/components/Table/Table.fragment.tsx +193 -0
  52. package/src/components/Table/Table.module.scss +152 -0
  53. package/src/components/Table/index.tsx +266 -0
  54. package/src/components/Tabs/Tabs.fragment.tsx +155 -0
  55. package/src/components/Tabs/Tabs.module.scss +142 -0
  56. package/src/components/Tabs/index.tsx +142 -0
  57. package/src/components/Textarea/Textarea.fragment.tsx +171 -0
  58. package/src/components/Textarea/Textarea.module.scss +89 -0
  59. package/src/components/Textarea/index.tsx +128 -0
  60. package/src/components/Toast/Toast.fragment.tsx +210 -0
  61. package/src/components/Toast/Toast.module.scss +227 -0
  62. package/src/components/Toast/index.tsx +315 -0
  63. package/src/components/Toggle/Toggle.fragment.tsx +174 -0
  64. package/src/components/Toggle/Toggle.module.scss +103 -0
  65. package/src/components/Toggle/index.tsx +80 -0
  66. package/src/components/Tooltip/Tooltip.fragment.tsx +158 -0
  67. package/src/components/Tooltip/Tooltip.module.scss +82 -0
  68. package/src/components/Tooltip/index.tsx +135 -0
  69. package/src/index.ts +151 -0
  70. package/src/scss.d.ts +4 -0
  71. package/src/styles/globals.scss +17 -0
  72. package/src/tokens/_mixins.scss +93 -0
  73. package/src/tokens/_variables.scss +276 -0
@@ -0,0 +1,173 @@
1
+ import React, { useState } from 'react';
2
+ import { defineSegment } from '@fragments/core';
3
+ import { Select } from './index.js';
4
+
5
+ // Stateful wrapper for interactive demos
6
+ function StatefulSelect(props: React.ComponentProps<typeof Select> & {
7
+ children: React.ReactNode;
8
+ initialValue?: string;
9
+ }) {
10
+ const { initialValue, children, ...rest } = props;
11
+ const [value, setValue] = useState<string | null>(initialValue ?? null);
12
+ return (
13
+ <Select {...rest} value={value} onValueChange={setValue}>
14
+ {children}
15
+ </Select>
16
+ );
17
+ }
18
+
19
+ export default defineSegment({
20
+ component: Select,
21
+
22
+ meta: {
23
+ name: 'Select',
24
+ description: 'Dropdown for choosing from a list of options. Use when there are more than 4-5 choices that would clutter the UI.',
25
+ category: 'forms',
26
+ status: 'stable',
27
+ tags: ['select', 'dropdown', 'form', 'options', 'picker'],
28
+ since: '0.1.0',
29
+ },
30
+
31
+ usage: {
32
+ when: [
33
+ 'Choosing from a predefined list of options',
34
+ 'More than 4-5 options that would clutter UI as radio buttons',
35
+ 'Space-constrained forms',
36
+ 'When users need to see all options at once',
37
+ ],
38
+ whenNot: [
39
+ 'Very few options (2-3) - use radio buttons',
40
+ 'Users might type custom values - use Combobox',
41
+ 'Multiple selections needed - use Checkbox group or MultiSelect',
42
+ 'Actions, not selection - use Menu',
43
+ ],
44
+ guidelines: [
45
+ 'Include a placeholder that explains what to select',
46
+ 'Group related options with SelectGroup',
47
+ 'Keep option text concise',
48
+ 'Order options logically (alphabetical, by frequency, or by category)',
49
+ ],
50
+ accessibility: [
51
+ 'Full keyboard navigation support',
52
+ 'Type-ahead search within options',
53
+ 'Proper ARIA roles and attributes',
54
+ ],
55
+ },
56
+
57
+ props: {
58
+ children: {
59
+ type: 'node',
60
+ description: 'Select trigger and content',
61
+ required: true,
62
+ },
63
+ value: {
64
+ type: 'string',
65
+ description: 'Controlled selected value',
66
+ },
67
+ defaultValue: {
68
+ type: 'string',
69
+ description: 'Default selected value (uncontrolled)',
70
+ },
71
+ onValueChange: {
72
+ type: 'function',
73
+ description: 'Called when selection changes',
74
+ },
75
+ placeholder: {
76
+ type: 'string',
77
+ description: 'Placeholder text when no value selected',
78
+ },
79
+ disabled: {
80
+ type: 'boolean',
81
+ description: 'Disable the select',
82
+ default: 'false',
83
+ },
84
+ },
85
+
86
+ relations: [
87
+ { component: 'Menu', relationship: 'alternative', note: 'Use Menu for action-based dropdowns' },
88
+ { component: 'Input', relationship: 'sibling', note: 'Use Input for free-form text entry' },
89
+ { component: 'Checkbox', relationship: 'alternative', note: 'Use Checkbox group for multiple selections' },
90
+ ],
91
+
92
+ contract: {
93
+ propsSummary: [
94
+ 'value: string - controlled selected value',
95
+ 'onValueChange: (value) => void - selection handler',
96
+ 'placeholder: string - placeholder text',
97
+ 'disabled: boolean - disable select',
98
+ ],
99
+ scenarioTags: [
100
+ 'form.select',
101
+ 'form.dropdown',
102
+ 'input.options',
103
+ ],
104
+ a11yRules: ['A11Y_SELECT_KEYBOARD', 'A11Y_SELECT_LABEL'],
105
+ },
106
+
107
+ variants: [
108
+ {
109
+ name: 'Default',
110
+ description: 'Basic select dropdown',
111
+ render: () => (
112
+ <StatefulSelect placeholder="Select a fruit">
113
+ <Select.Trigger />
114
+ <Select.Content>
115
+ <Select.Item value="apple">Apple</Select.Item>
116
+ <Select.Item value="banana">Banana</Select.Item>
117
+ <Select.Item value="orange">Orange</Select.Item>
118
+ <Select.Item value="grape">Grape</Select.Item>
119
+ </Select.Content>
120
+ </StatefulSelect>
121
+ ),
122
+ },
123
+ {
124
+ name: 'With Groups',
125
+ description: 'Options organized into groups',
126
+ render: () => (
127
+ <StatefulSelect placeholder="Select a country">
128
+ <Select.Trigger />
129
+ <Select.Content>
130
+ <Select.Group>
131
+ <Select.GroupLabel>North America</Select.GroupLabel>
132
+ <Select.Item value="us">United States</Select.Item>
133
+ <Select.Item value="ca">Canada</Select.Item>
134
+ <Select.Item value="mx">Mexico</Select.Item>
135
+ </Select.Group>
136
+ <Select.Group>
137
+ <Select.GroupLabel>Europe</Select.GroupLabel>
138
+ <Select.Item value="uk">United Kingdom</Select.Item>
139
+ <Select.Item value="de">Germany</Select.Item>
140
+ <Select.Item value="fr">France</Select.Item>
141
+ </Select.Group>
142
+ </Select.Content>
143
+ </StatefulSelect>
144
+ ),
145
+ },
146
+ {
147
+ name: 'With Disabled Options',
148
+ description: 'Some options are disabled',
149
+ render: () => (
150
+ <StatefulSelect placeholder="Select a plan">
151
+ <Select.Trigger />
152
+ <Select.Content>
153
+ <Select.Item value="free">Free</Select.Item>
154
+ <Select.Item value="pro">Pro</Select.Item>
155
+ <Select.Item value="enterprise" disabled>Enterprise (Contact Sales)</Select.Item>
156
+ </Select.Content>
157
+ </StatefulSelect>
158
+ ),
159
+ },
160
+ {
161
+ name: 'Disabled',
162
+ description: 'Disabled select',
163
+ render: () => (
164
+ <Select disabled placeholder="Select an option">
165
+ <Select.Trigger />
166
+ <Select.Content>
167
+ <Select.Item value="1">Option 1</Select.Item>
168
+ </Select.Content>
169
+ </Select>
170
+ ),
171
+ },
172
+ ],
173
+ });
@@ -0,0 +1,187 @@
1
+ @use '../../tokens/variables' as *;
2
+ @use '../../tokens/mixins' as *;
3
+
4
+ // Trigger button
5
+ .trigger {
6
+ @include button-reset;
7
+ @include interactive-base;
8
+ @include text-base;
9
+
10
+ display: inline-flex;
11
+ align-items: center;
12
+ justify-content: space-between;
13
+ gap: var(--fui-space-2, $fui-space-2);
14
+ width: 100%;
15
+ min-width: 10rem;
16
+ height: var(--fui-input-height, $fui-input-height);
17
+ padding: 0 var(--fui-space-3, $fui-space-3);
18
+ background-color: var(--fui-bg-elevated, $fui-bg-elevated);
19
+ border: 1px solid var(--fui-border-strong, $fui-border-strong);
20
+ border-radius: var(--fui-radius-md, $fui-radius-md);
21
+ text-align: left;
22
+
23
+ &:hover:not([data-disabled]) {
24
+ border-color: var(--fui-text-tertiary, $fui-text-tertiary);
25
+ }
26
+
27
+ &[data-popup-open] {
28
+ border-color: var(--fui-color-accent, $fui-color-accent);
29
+ }
30
+
31
+ &[data-disabled] {
32
+ background-color: var(--fui-bg-tertiary, $fui-bg-tertiary);
33
+ color: var(--fui-text-tertiary, $fui-text-tertiary);
34
+ }
35
+ }
36
+
37
+ // Value display
38
+ .value {
39
+ flex: 1;
40
+ overflow: hidden;
41
+ text-overflow: ellipsis;
42
+ white-space: nowrap;
43
+
44
+ &[data-placeholder] {
45
+ color: var(--fui-text-tertiary, $fui-text-tertiary);
46
+ }
47
+ }
48
+
49
+ // Chevron icon
50
+ .icon {
51
+ display: flex;
52
+ align-items: center;
53
+ justify-content: center;
54
+ color: var(--fui-text-secondary, $fui-text-secondary);
55
+ transition: transform var(--fui-transition-fast, $fui-transition-fast);
56
+
57
+ [data-popup-open] > & {
58
+ transform: rotate(180deg);
59
+ }
60
+
61
+ svg {
62
+ width: 1rem;
63
+ height: 1rem;
64
+ }
65
+ }
66
+
67
+ // Positioner
68
+ .positioner {
69
+ z-index: 50;
70
+ outline: none;
71
+ }
72
+
73
+ // Popup container
74
+ .popup {
75
+ @include surface-elevated;
76
+
77
+ min-width: var(--anchor-width);
78
+ max-height: 20rem;
79
+ overflow-y: auto;
80
+ padding: var(--fui-space-1, $fui-space-1);
81
+ box-shadow: var(--fui-shadow-md, $fui-shadow-md);
82
+
83
+ // Animation
84
+ opacity: 0;
85
+ transform: scale(0.95);
86
+ transform-origin: var(--transform-origin);
87
+ transition:
88
+ opacity var(--fui-transition-fast, $fui-transition-fast),
89
+ transform var(--fui-transition-fast, $fui-transition-fast);
90
+
91
+ &[data-open] {
92
+ opacity: 1;
93
+ transform: scale(1);
94
+ }
95
+
96
+ &[data-starting-style],
97
+ &[data-ending-style] {
98
+ opacity: 0;
99
+ transform: scale(0.95);
100
+ }
101
+ }
102
+
103
+ // Individual option
104
+ .item {
105
+ @include button-reset;
106
+ @include text-base;
107
+
108
+ display: flex;
109
+ align-items: center;
110
+ gap: var(--fui-space-2, $fui-space-2);
111
+ width: 100%;
112
+ padding: var(--fui-space-2, $fui-space-2) var(--fui-space-3, $fui-space-3);
113
+ border-radius: var(--fui-radius-sm, $fui-radius-sm);
114
+ cursor: pointer;
115
+ outline: none;
116
+
117
+ &[data-highlighted] {
118
+ background-color: var(--fui-bg-hover, $fui-bg-hover);
119
+ }
120
+
121
+ &[data-selected] {
122
+ background-color: var(--fui-color-accent, $fui-color-accent);
123
+ color: var(--fui-text-inverse, $fui-text-inverse);
124
+
125
+ &[data-highlighted] {
126
+ background-color: var(--fui-color-accent-hover, $fui-color-accent-hover);
127
+ }
128
+ }
129
+
130
+ &[data-disabled] {
131
+ color: var(--fui-text-tertiary, $fui-text-tertiary);
132
+ cursor: not-allowed;
133
+ }
134
+ }
135
+
136
+ // Selection indicator (checkmark)
137
+ .itemIndicator {
138
+ display: flex;
139
+ align-items: center;
140
+ justify-content: center;
141
+ width: 1rem;
142
+ height: 1rem;
143
+ margin-left: auto;
144
+
145
+ svg {
146
+ width: 0.875rem;
147
+ height: 0.875rem;
148
+ }
149
+ }
150
+
151
+ // Group container
152
+ .group {
153
+ &:not(:first-child) {
154
+ margin-top: var(--fui-space-1, $fui-space-1);
155
+ padding-top: var(--fui-space-1, $fui-space-1);
156
+ border-top: 1px solid var(--fui-border, $fui-border);
157
+ }
158
+ }
159
+
160
+ // Group label
161
+ .groupLabel {
162
+ padding: var(--fui-space-1, $fui-space-1) var(--fui-space-3, $fui-space-3);
163
+ font-size: var(--fui-font-size-xs, $fui-font-size-xs);
164
+ font-weight: var(--fui-font-weight-medium, $fui-font-weight-medium);
165
+ color: var(--fui-text-tertiary, $fui-text-tertiary);
166
+ text-transform: uppercase;
167
+ letter-spacing: 0.05em;
168
+ }
169
+
170
+ // Arrow
171
+ .arrow {
172
+ width: 10px;
173
+ height: 10px;
174
+ transform: rotate(45deg);
175
+ background-color: var(--fui-bg-elevated, $fui-bg-elevated);
176
+ border: 1px solid var(--fui-border, $fui-border);
177
+
178
+ &[data-side='top'] {
179
+ border-top: none;
180
+ border-left: none;
181
+ }
182
+
183
+ &[data-side='bottom'] {
184
+ border-bottom: none;
185
+ border-right: none;
186
+ }
187
+ }
@@ -0,0 +1,233 @@
1
+ import * as React from 'react';
2
+ import { Select as BaseSelect } from '@base-ui/react/select';
3
+ import styles from './Select.module.scss';
4
+ // Import globals to ensure CSS variables are defined
5
+ import '../../styles/globals.scss';
6
+
7
+ // ============================================
8
+ // Types
9
+ // ============================================
10
+
11
+ export type SelectValue = string;
12
+
13
+ export interface SelectOption {
14
+ value: SelectValue;
15
+ label: string;
16
+ disabled?: boolean;
17
+ }
18
+
19
+ export interface SelectProps {
20
+ children: React.ReactNode;
21
+ value?: SelectValue | null;
22
+ defaultValue?: SelectValue;
23
+ onValueChange?: (value: SelectValue | null) => void;
24
+ open?: boolean;
25
+ defaultOpen?: boolean;
26
+ onOpenChange?: (open: boolean) => void;
27
+ disabled?: boolean;
28
+ required?: boolean;
29
+ name?: string;
30
+ placeholder?: string;
31
+ }
32
+
33
+ export interface SelectTriggerProps {
34
+ children?: React.ReactNode;
35
+ placeholder?: string;
36
+ className?: string;
37
+ }
38
+
39
+ export interface SelectContentProps {
40
+ children: React.ReactNode;
41
+ className?: string;
42
+ sideOffset?: number;
43
+ align?: 'start' | 'center' | 'end';
44
+ }
45
+
46
+ export interface SelectItemProps {
47
+ children: React.ReactNode;
48
+ value: SelectValue;
49
+ disabled?: boolean;
50
+ className?: string;
51
+ }
52
+
53
+ export interface SelectGroupProps {
54
+ children: React.ReactNode;
55
+ className?: string;
56
+ }
57
+
58
+ export interface SelectGroupLabelProps {
59
+ children: React.ReactNode;
60
+ className?: string;
61
+ }
62
+
63
+ // ============================================
64
+ // Icons
65
+ // ============================================
66
+
67
+ function ChevronDownIcon() {
68
+ return (
69
+ <svg
70
+ xmlns="http://www.w3.org/2000/svg"
71
+ width="16"
72
+ height="16"
73
+ viewBox="0 0 24 24"
74
+ fill="none"
75
+ stroke="currentColor"
76
+ strokeWidth="2"
77
+ strokeLinecap="round"
78
+ strokeLinejoin="round"
79
+ aria-hidden="true"
80
+ >
81
+ <polyline points="6 9 12 15 18 9" />
82
+ </svg>
83
+ );
84
+ }
85
+
86
+ function CheckIcon() {
87
+ return (
88
+ <svg
89
+ xmlns="http://www.w3.org/2000/svg"
90
+ width="14"
91
+ height="14"
92
+ viewBox="0 0 24 24"
93
+ fill="none"
94
+ stroke="currentColor"
95
+ strokeWidth="2.5"
96
+ strokeLinecap="round"
97
+ strokeLinejoin="round"
98
+ aria-hidden="true"
99
+ >
100
+ <polyline points="20 6 9 17 4 12" />
101
+ </svg>
102
+ );
103
+ }
104
+
105
+ // ============================================
106
+ // Context for placeholder
107
+ // ============================================
108
+
109
+ const SelectContext = React.createContext<{ placeholder?: string }>({});
110
+
111
+ // ============================================
112
+ // Components
113
+ // ============================================
114
+
115
+ function SelectRoot({
116
+ children,
117
+ value,
118
+ defaultValue,
119
+ onValueChange,
120
+ open,
121
+ defaultOpen,
122
+ onOpenChange,
123
+ disabled,
124
+ required,
125
+ name,
126
+ placeholder,
127
+ }: SelectProps) {
128
+ return (
129
+ <SelectContext.Provider value={{ placeholder }}>
130
+ <BaseSelect.Root
131
+ value={value}
132
+ defaultValue={defaultValue}
133
+ onValueChange={onValueChange}
134
+ open={open}
135
+ defaultOpen={defaultOpen}
136
+ onOpenChange={onOpenChange}
137
+ disabled={disabled}
138
+ required={required}
139
+ name={name}
140
+ >
141
+ {children}
142
+ </BaseSelect.Root>
143
+ </SelectContext.Provider>
144
+ );
145
+ }
146
+
147
+ function SelectTrigger({ children, placeholder, className }: SelectTriggerProps) {
148
+ const context = React.useContext(SelectContext);
149
+ const placeholderText = placeholder ?? context.placeholder;
150
+
151
+ const classes = [styles.trigger, className].filter(Boolean).join(' ');
152
+
153
+ return (
154
+ <BaseSelect.Trigger className={classes}>
155
+ {children ?? (
156
+ <>
157
+ <BaseSelect.Value placeholder={placeholderText} className={styles.value} />
158
+ <BaseSelect.Icon className={styles.icon}>
159
+ <ChevronDownIcon />
160
+ </BaseSelect.Icon>
161
+ </>
162
+ )}
163
+ </BaseSelect.Trigger>
164
+ );
165
+ }
166
+
167
+ function SelectContent({
168
+ children,
169
+ className,
170
+ sideOffset = 4,
171
+ align = 'start',
172
+ }: SelectContentProps) {
173
+ const popupClasses = [styles.popup, className].filter(Boolean).join(' ');
174
+
175
+ return (
176
+ <BaseSelect.Portal>
177
+ <BaseSelect.Positioner
178
+ sideOffset={sideOffset}
179
+ align={align}
180
+ className={styles.positioner}
181
+ >
182
+ <BaseSelect.Popup className={popupClasses}>
183
+ {children}
184
+ </BaseSelect.Popup>
185
+ </BaseSelect.Positioner>
186
+ </BaseSelect.Portal>
187
+ );
188
+ }
189
+
190
+ function SelectItem({ children, value, disabled, className }: SelectItemProps) {
191
+ const classes = [styles.item, className].filter(Boolean).join(' ');
192
+
193
+ return (
194
+ <BaseSelect.Item value={value} disabled={disabled} className={classes}>
195
+ <BaseSelect.ItemText>{children}</BaseSelect.ItemText>
196
+ <BaseSelect.ItemIndicator className={styles.itemIndicator}>
197
+ <CheckIcon />
198
+ </BaseSelect.ItemIndicator>
199
+ </BaseSelect.Item>
200
+ );
201
+ }
202
+
203
+ function SelectGroup({ children, className }: SelectGroupProps) {
204
+ const classes = [styles.group, className].filter(Boolean).join(' ');
205
+ return <BaseSelect.Group className={classes}>{children}</BaseSelect.Group>;
206
+ }
207
+
208
+ function SelectGroupLabel({ children, className }: SelectGroupLabelProps) {
209
+ const classes = [styles.groupLabel, className].filter(Boolean).join(' ');
210
+ return <BaseSelect.GroupLabel className={classes}>{children}</BaseSelect.GroupLabel>;
211
+ }
212
+
213
+ // ============================================
214
+ // Export compound component
215
+ // ============================================
216
+
217
+ export const Select = Object.assign(SelectRoot, {
218
+ Trigger: SelectTrigger,
219
+ Content: SelectContent,
220
+ Item: SelectItem,
221
+ Group: SelectGroup,
222
+ GroupLabel: SelectGroupLabel,
223
+ });
224
+
225
+ // Re-export individual components
226
+ export {
227
+ SelectRoot,
228
+ SelectTrigger,
229
+ SelectContent,
230
+ SelectItem,
231
+ SelectGroup,
232
+ SelectGroupLabel,
233
+ };