@stackshift-ui/select 6.0.12 → 7.0.0-beta.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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@stackshift-ui/select",
3
3
  "description": "",
4
- "version": "6.0.12",
4
+ "version": "7.0.0-beta.0",
5
5
  "private": false,
6
6
  "sideEffects": false,
7
7
  "main": "./dist/index.js",
@@ -29,20 +29,22 @@
29
29
  "typescript": "^5.6.2",
30
30
  "vite-tsconfig-paths": "^5.0.1",
31
31
  "vitest": "^2.1.1",
32
- "@stackshift-ui/typescript-config": "6.0.10",
33
- "@stackshift-ui/eslint-config": "6.0.10"
32
+ "@stackshift-ui/eslint-config": "6.0.10",
33
+ "@stackshift-ui/typescript-config": "6.0.10"
34
34
  },
35
35
  "dependencies": {
36
+ "@radix-ui/react-select": "^2.2.5",
36
37
  "classnames": "^2.5.1",
37
- "@stackshift-ui/system": "6.0.11",
38
- "@stackshift-ui/scripts": "6.0.10"
38
+ "lucide-react": "^0.468.0",
39
+ "@stackshift-ui/system": "6.1.0-beta.0",
40
+ "@stackshift-ui/scripts": "6.1.0-beta.0"
39
41
  },
40
42
  "peerDependencies": {
43
+ "@stackshift-ui/system": ">=6.1.0-beta.0",
41
44
  "@types/react": "16.8 - 19",
42
45
  "next": "10 - 14",
43
46
  "react": "16.8 - 19",
44
- "react-dom": "16.8 - 19",
45
- "@stackshift-ui/system": ">=6.0.11"
47
+ "react-dom": "16.8 - 19"
46
48
  },
47
49
  "peerDependenciesMeta": {
48
50
  "next": {
@@ -1,20 +1,26 @@
1
1
  import { cleanup, render, screen } from "@testing-library/react";
2
2
  import { afterEach, describe, test } from "vitest";
3
- import { Select } from "./select";
3
+ import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "./select";
4
4
 
5
5
  describe.concurrent("select", () => {
6
6
  afterEach(cleanup);
7
7
 
8
8
  test("Common: Select - test if renders without errors", ({ expect }) => {
9
9
  const clx = "select-class";
10
- render(
11
- <Select
12
- className={clx}
13
- name="stackshift-select"
14
- ariaLabel="stackshift select"
15
- items={["Option 1", "Option 2", "Option 3"]}
16
- />,
10
+ const { unmount } = render(
11
+ <Select data-testid="select-container">
12
+ <SelectTrigger data-testid="select" className={clx}>
13
+ <SelectValue placeholder="Select an option" />
14
+ </SelectTrigger>
15
+ <SelectContent data-testid="select-content" className={clx}>
16
+ <SelectItem value="option1">Option 1</SelectItem>
17
+ <SelectItem value="option2">Option 2</SelectItem>
18
+ <SelectItem value="option3">Option 3</SelectItem>
19
+ </SelectContent>
20
+ </Select>,
17
21
  );
22
+
18
23
  expect(screen.getByTestId("select").classList).toContain(clx);
24
+ unmount();
19
25
  });
20
26
  });
package/src/select.tsx CHANGED
@@ -1,86 +1,227 @@
1
- import { DefaultComponent, useStackShiftUIComponents } from "@stackshift-ui/system";
2
- import cn from "classnames";
3
- import type { ElementType, HTMLProps, ReactNode } from "react";
4
-
5
- type StyleVariants<T extends string> = Record<T, string>;
6
- type Variant = "primary" | "outline";
7
-
8
- export interface SelectProps extends Omit<HTMLProps<HTMLSelectElement>, "as"> {
9
- defaultValue?: string;
10
- variant?: Variant;
11
- label?: string;
12
- labelClass?: string;
13
- onChange?: () => void;
14
- required?: boolean;
15
- name: string;
16
- items: string[];
17
- ariaLabel: string;
18
- noLabel?: boolean;
19
- [key: string]: any;
20
- children?: ReactNode;
21
- className?: string;
22
- as?: ElementType;
23
- }
1
+ import * as SelectPrimitive from "@radix-ui/react-select";
2
+ import { Check, ChevronDown, ChevronUp } from "lucide-react";
3
+ import * as React from "react";
4
+
5
+ import { cn, DefaultComponent, useStackShiftUIComponents } from "@stackshift-ui/system";
24
6
 
25
7
  const displayName = "Select";
8
+ const displayNameTrigger = "SelectTrigger";
9
+ const displayNameValue = "SelectValue";
10
+ const displayNameContent = "SelectContent";
11
+ const displayNameItem = "SelectItem";
12
+ const displayNameGroup = "SelectGroup";
13
+ const displayNameLabel = "SelectLabel";
14
+ const displayNameSeparator = "SelectSeparator";
15
+ const displayNameScrollUpButton = "SelectScrollUpButton";
16
+ const displayNameScrollDownButton = "SelectScrollDownButton";
17
+
18
+ // bypass typescript "SelectSharedProps" error
19
+ interface SelectProps extends React.ComponentPropsWithoutRef<typeof SelectPrimitive.Root> {}
20
+
21
+ const Select = React.forwardRef<React.ElementRef<typeof SelectPrimitive.Root>, SelectProps>(
22
+ ({ ...props }, ref) => {
23
+ const { [displayName]: Component = DefaultComponent } = useStackShiftUIComponents();
26
24
 
27
- export const Select: React.FC<SelectProps> = ({
28
- defaultValue,
29
- variant = "primary",
30
- label,
31
- labelClass,
32
- onChange,
33
- required = false,
34
- name,
35
- items,
36
- ariaLabel,
37
- noLabel = false,
38
- children,
39
- className,
40
- as = "select",
41
- ...props
42
- }) => {
43
- const { [displayName]: Component = DefaultComponent } = useStackShiftUIComponents();
44
-
45
- const commonStyle =
46
- "w-full rounded-global bg-white p-4 text-xs font-semibold leading-none outline-none";
47
- const primary = `${commonStyle}`;
48
- const outline = `${commonStyle} border border-solid border-primary-foreground`;
49
-
50
- const variants: StyleVariants<Variant> = {
51
- primary,
52
- outline,
53
- };
54
- const variantClass = variants[variant] ?? primary;
25
+ return <Component as={SelectPrimitive.Root} ref={ref} {...props} />;
26
+ },
27
+ );
28
+ Select.displayName = displayName;
29
+
30
+ const SelectGroup = React.forwardRef<
31
+ React.ElementRef<typeof SelectPrimitive.Group>,
32
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Group>
33
+ >(({ className, ...props }, ref) => {
34
+ const { [displayNameGroup]: Component = DefaultComponent } = useStackShiftUIComponents();
55
35
 
56
36
  return (
57
- <>
58
- {!noLabel && (
59
- <label htmlFor={name} className={labelClass}>
60
- {label || name}
61
- </label>
37
+ <Component as={SelectPrimitive.Group} ref={ref} className={cn("p-1", className)} {...props} />
38
+ );
39
+ });
40
+ SelectGroup.displayName = displayNameGroup;
41
+
42
+ const SelectValue = React.forwardRef<
43
+ React.ElementRef<typeof SelectPrimitive.Value>,
44
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Value>
45
+ >(({ className, ...props }, ref) => {
46
+ const { [displayNameValue]: Component = DefaultComponent } = useStackShiftUIComponents();
47
+
48
+ return (
49
+ <Component
50
+ as={SelectPrimitive.Value}
51
+ ref={ref}
52
+ className={cn("text-sm outline-none", className)}
53
+ {...props}
54
+ />
55
+ );
56
+ });
57
+ SelectValue.displayName = displayNameValue;
58
+
59
+ const SelectTrigger = React.forwardRef<
60
+ React.ElementRef<typeof SelectPrimitive.Trigger>,
61
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Trigger>
62
+ >(({ className, children, ...props }, ref) => {
63
+ const { [displayNameTrigger]: Component = DefaultComponent } = useStackShiftUIComponents();
64
+
65
+ return (
66
+ <Component
67
+ as={SelectPrimitive.Trigger}
68
+ ref={ref}
69
+ className={cn(
70
+ "flex h-10 w-full items-center justify-between rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background data-[placeholder]:text-muted-foreground focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 [&>span]:line-clamp-1",
71
+ className,
62
72
  )}
73
+ {...props}>
74
+ {children}
75
+ <SelectPrimitive.Icon asChild>
76
+ <ChevronDown className="h-4 w-4 opacity-50" />
77
+ </SelectPrimitive.Icon>
78
+ </Component>
79
+ );
80
+ });
81
+ SelectTrigger.displayName = displayNameTrigger;
82
+
83
+ const SelectScrollUpButton = React.forwardRef<
84
+ React.ElementRef<typeof SelectPrimitive.ScrollUpButton>,
85
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollUpButton>
86
+ >(({ className, ...props }, ref) => {
87
+ const { [displayNameScrollUpButton]: Component = DefaultComponent } = useStackShiftUIComponents();
88
+
89
+ return (
90
+ <Component
91
+ as={SelectPrimitive.ScrollUpButton}
92
+ ref={ref}
93
+ className={cn("flex cursor-default items-center justify-center py-1", className)}
94
+ {...props}>
95
+ <ChevronUp className="h-4 w-4" />
96
+ </Component>
97
+ );
98
+ });
99
+ SelectScrollUpButton.displayName = displayNameScrollUpButton;
100
+
101
+ const SelectScrollDownButton = React.forwardRef<
102
+ React.ElementRef<typeof SelectPrimitive.ScrollDownButton>,
103
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.ScrollDownButton>
104
+ >(({ className, ...props }, ref) => {
105
+ const { [displayNameScrollDownButton]: Component = DefaultComponent } =
106
+ useStackShiftUIComponents();
107
+
108
+ return (
109
+ <Component
110
+ as={SelectPrimitive.ScrollDownButton}
111
+ ref={ref}
112
+ className={cn("flex cursor-default items-center justify-center py-1", className)}
113
+ {...props}>
114
+ <ChevronDown className="h-4 w-4" />
115
+ </Component>
116
+ );
117
+ });
118
+ SelectScrollDownButton.displayName = displayNameScrollDownButton;
119
+
120
+ const SelectContent = React.forwardRef<
121
+ React.ElementRef<typeof SelectPrimitive.Content>,
122
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Content>
123
+ >(({ className, children, position = "popper", ...props }, ref) => {
124
+ const { [displayNameContent]: Component = DefaultComponent } = useStackShiftUIComponents();
125
+
126
+ return (
127
+ <SelectPrimitive.Portal>
63
128
  <Component
64
- onChange={onChange}
65
- name={name}
66
- defaultValue={defaultValue}
67
- required={required}
68
- as={as}
69
- className={cn(variantClass, className)}
70
- {...props}
71
- data-testid={displayName}>
72
- {items &&
73
- items.length > 0 &&
74
- items.map(opt => {
75
- return (
76
- <option value={opt} key={opt}>
77
- {opt}
78
- </option>
79
- );
80
- })}
129
+ as={SelectPrimitive.Content}
130
+ ref={ref}
131
+ className={cn(
132
+ "relative z-50 max-h-[--radix-select-content-available-height] min-w-[8rem] overflow-y-auto overflow-x-hidden rounded-md border bg-popover text-popover-foreground shadow-md data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 origin-[--radix-select-content-transform-origin]",
133
+ position === "popper" &&
134
+ "data-[side=bottom]:translate-y-1 data-[side=left]:-translate-x-1 data-[side=right]:translate-x-1 data-[side=top]:-translate-y-1",
135
+ className,
136
+ )}
137
+ position={position}
138
+ {...props}>
139
+ <SelectScrollUpButton />
140
+ <SelectPrimitive.Viewport
141
+ className={cn(
142
+ "p-1",
143
+ position === "popper" &&
144
+ "h-[var(--radix-select-trigger-height)] w-full min-w-[var(--radix-select-trigger-width)]",
145
+ )}>
146
+ {children}
147
+ </SelectPrimitive.Viewport>
148
+ <SelectScrollDownButton />
81
149
  </Component>
82
- </>
150
+ </SelectPrimitive.Portal>
83
151
  );
84
- };
152
+ });
153
+ SelectContent.displayName = displayNameContent;
85
154
 
86
- Select.displayName = displayName;
155
+ const SelectLabel = React.forwardRef<
156
+ React.ElementRef<typeof SelectPrimitive.Label>,
157
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Label>
158
+ >(({ className, ...props }, ref) => {
159
+ const { [displayNameLabel]: Component = DefaultComponent } = useStackShiftUIComponents();
160
+
161
+ return (
162
+ <Component
163
+ as={SelectPrimitive.Label}
164
+ ref={ref}
165
+ className={cn("py-1.5 pl-8 pr-2 text-sm font-semibold", className)}
166
+ {...props}
167
+ />
168
+ );
169
+ });
170
+ SelectLabel.displayName = displayNameLabel;
171
+
172
+ const SelectItem = React.forwardRef<
173
+ React.ElementRef<typeof SelectPrimitive.Item>,
174
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Item>
175
+ >(({ className, children, ...props }, ref) => {
176
+ const { [displayNameItem]: Component = DefaultComponent } = useStackShiftUIComponents();
177
+
178
+ return (
179
+ <Component
180
+ as={SelectPrimitive.Item}
181
+ ref={ref}
182
+ className={cn(
183
+ "relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none focus:bg-accent focus:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50",
184
+ className,
185
+ )}
186
+ {...props}>
187
+ <span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
188
+ <SelectPrimitive.ItemIndicator>
189
+ <Check className="h-4 w-4" />
190
+ </SelectPrimitive.ItemIndicator>
191
+ </span>
192
+
193
+ <SelectPrimitive.ItemText>{children}</SelectPrimitive.ItemText>
194
+ </Component>
195
+ );
196
+ });
197
+ SelectItem.displayName = displayNameItem;
198
+
199
+ const SelectSeparator = React.forwardRef<
200
+ React.ElementRef<typeof SelectPrimitive.Separator>,
201
+ React.ComponentPropsWithoutRef<typeof SelectPrimitive.Separator>
202
+ >(({ className, ...props }, ref) => {
203
+ const { [displayNameSeparator]: Component = DefaultComponent } = useStackShiftUIComponents();
204
+
205
+ return (
206
+ <Component
207
+ as={SelectPrimitive.Separator}
208
+ ref={ref}
209
+ className={cn("-mx-1 my-1 h-px bg-muted", className)}
210
+ {...props}
211
+ />
212
+ );
213
+ });
214
+ SelectSeparator.displayName = displayNameSeparator;
215
+
216
+ export {
217
+ Select,
218
+ SelectContent,
219
+ SelectGroup,
220
+ SelectItem,
221
+ SelectLabel,
222
+ SelectScrollDownButton,
223
+ SelectScrollUpButton,
224
+ SelectSeparator,
225
+ SelectTrigger,
226
+ SelectValue,
227
+ };