@stackshift-ui/input-file 6.0.2 → 6.0.3
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 +7 -6
- package/src/index.ts +4 -0
- package/src/input-file.test.tsx +15 -0
- package/src/input-file.tsx +81 -0
package/package.json
CHANGED
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stackshift-ui/input-file",
|
|
3
3
|
"description": "",
|
|
4
|
-
"version": "6.0.
|
|
4
|
+
"version": "6.0.3",
|
|
5
5
|
"private": false,
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"main": "./dist/index.js",
|
|
8
8
|
"module": "./dist/index.mjs",
|
|
9
9
|
"types": "./dist/index.d.ts",
|
|
10
10
|
"files": [
|
|
11
|
-
"dist/**"
|
|
11
|
+
"dist/**",
|
|
12
|
+
"src"
|
|
12
13
|
],
|
|
13
14
|
"author": "WebriQ <info@webriq.com>",
|
|
14
15
|
"devDependencies": {
|
|
@@ -28,13 +29,13 @@
|
|
|
28
29
|
"typescript": "^5.6.2",
|
|
29
30
|
"vite-tsconfig-paths": "^5.0.1",
|
|
30
31
|
"vitest": "^2.1.1",
|
|
31
|
-
"@stackshift-ui/
|
|
32
|
-
"@stackshift-ui/
|
|
32
|
+
"@stackshift-ui/eslint-config": "6.0.2",
|
|
33
|
+
"@stackshift-ui/typescript-config": "6.0.2"
|
|
33
34
|
},
|
|
34
35
|
"dependencies": {
|
|
35
36
|
"classnames": "^2.5.1",
|
|
36
|
-
"@stackshift-ui/
|
|
37
|
-
"@stackshift-ui/
|
|
37
|
+
"@stackshift-ui/system": "6.0.3",
|
|
38
|
+
"@stackshift-ui/scripts": "6.0.2"
|
|
38
39
|
},
|
|
39
40
|
"peerDependencies": {
|
|
40
41
|
"@types/react": "16.8 - 19",
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { cleanup, render, screen } from "@testing-library/react";
|
|
2
|
+
import { afterEach, describe, test } from "vitest";
|
|
3
|
+
import { InputFile } from "./input-file";
|
|
4
|
+
|
|
5
|
+
describe.concurrent("input-file", () => {
|
|
6
|
+
afterEach(cleanup);
|
|
7
|
+
|
|
8
|
+
test("Common: Input File - test if renders without errors", ({ expect }) => {
|
|
9
|
+
const clx = "inputfile-class";
|
|
10
|
+
render(
|
|
11
|
+
<InputFile className={clx} name="stackshift-inputfile" ariaLabel="stackshift input file" />,
|
|
12
|
+
);
|
|
13
|
+
expect(screen.getByTestId("inputfile").classList).toBeDefined();
|
|
14
|
+
});
|
|
15
|
+
});
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { DefaultComponent, useStackShiftUIComponents } from "@stackshift-ui/system";
|
|
2
|
+
import cn from "classnames";
|
|
3
|
+
import type { ElementType, HTMLProps, ReactNode } from "react";
|
|
4
|
+
import { useState } from "react";
|
|
5
|
+
|
|
6
|
+
type StyleVariants<T extends string> = Record<T, string>;
|
|
7
|
+
type Variant = "primary" | "outline";
|
|
8
|
+
|
|
9
|
+
export interface InputFileProps extends Omit<HTMLProps<HTMLInputElement>, "as"> {
|
|
10
|
+
required?: boolean;
|
|
11
|
+
variant?: Variant;
|
|
12
|
+
name: string;
|
|
13
|
+
ariaLabel: string;
|
|
14
|
+
[key: string]: any;
|
|
15
|
+
children?: ReactNode;
|
|
16
|
+
className?: string;
|
|
17
|
+
as?: ElementType;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const displayName = "InputFile";
|
|
21
|
+
|
|
22
|
+
export const InputFile: React.FC<InputFileProps> = ({
|
|
23
|
+
required = false,
|
|
24
|
+
variant = "primary",
|
|
25
|
+
name,
|
|
26
|
+
ariaLabel,
|
|
27
|
+
children,
|
|
28
|
+
className,
|
|
29
|
+
as,
|
|
30
|
+
...props
|
|
31
|
+
}) => {
|
|
32
|
+
const { [displayName]: Component = DefaultComponent } = useStackShiftUIComponents();
|
|
33
|
+
|
|
34
|
+
const [filename, setFilename] = useState("");
|
|
35
|
+
|
|
36
|
+
const commonStyle =
|
|
37
|
+
"my-1 ml-auto cursor-pointer rounded px-4 py-3 text-xs font-semibold leading-none transition duration-200";
|
|
38
|
+
const primary = `${commonStyle} bg-primary-foreground hover:bg-primary`;
|
|
39
|
+
const outline = `${commonStyle} text-primary-foreground border border-solid border-primary-foreground hover:bg-slate-100`;
|
|
40
|
+
|
|
41
|
+
const variants: StyleVariants<Variant> = {
|
|
42
|
+
primary,
|
|
43
|
+
outline,
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
const variantClass = variants[variant] ?? primary;
|
|
47
|
+
|
|
48
|
+
const handleFileChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
49
|
+
const file = event.target.files?.[0];
|
|
50
|
+
if (file) {
|
|
51
|
+
setFilename(file.name);
|
|
52
|
+
} else {
|
|
53
|
+
setFilename("");
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
return (
|
|
58
|
+
<div
|
|
59
|
+
className={"relative rounded bg-white px-2 w-full"}
|
|
60
|
+
data-testid={displayName?.toLowerCase()}>
|
|
61
|
+
<input
|
|
62
|
+
aria-label={ariaLabel ?? "Attach file"}
|
|
63
|
+
className="absolute w-full h-full opacity-0 cursor-pointer"
|
|
64
|
+
type="file"
|
|
65
|
+
name={name}
|
|
66
|
+
required={required}
|
|
67
|
+
id={name}
|
|
68
|
+
onChange={handleFileChange}
|
|
69
|
+
{...props}
|
|
70
|
+
/>
|
|
71
|
+
<div className="flex">
|
|
72
|
+
<span className="px-2 py-4 text-xs font-semibold leading-none">{filename}</span>
|
|
73
|
+
<label htmlFor={name} className={cn(variantClass, className)}>
|
|
74
|
+
{name}
|
|
75
|
+
</label>
|
|
76
|
+
</div>
|
|
77
|
+
</div>
|
|
78
|
+
);
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
InputFile.displayName = displayName;
|