@glyph-ui/textarea 0.1.0-alpha.2
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/README.md +22 -0
- package/files/src/components/glyph/GTextarea.tsx +45 -0
- package/files/src/lib/utils.ts +6 -0
- package/manifest.json +11 -0
- package/package.json +41 -0
- package/scripts/check-alpha-version.mjs +35 -0
- package/scripts/postinstall.mjs +50 -0
package/README.md
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# @glyph-ui/textarea
|
|
2
|
+
|
|
3
|
+
Glyph UI's **GTextarea** component.
|
|
4
|
+
|
|
5
|
+
```bash
|
|
6
|
+
npm install @glyph-ui/textarea
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Installing runs a postinstall step that copies these files into your own project (not into a runtime dependency):
|
|
10
|
+
|
|
11
|
+
- `src/components/glyph/GTextarea.tsx`
|
|
12
|
+
- `src/lib/utils.ts`
|
|
13
|
+
|
|
14
|
+
You'll also need: `clsx`, `tailwind-merge`.
|
|
15
|
+
|
|
16
|
+
Once the files land, **this package is done its job** — feel free to run:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm uninstall @glyph-ui/textarea
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Your project keeps the copied source either way; nothing at runtime ever imports from this package.
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { TextareaHTMLAttributes, forwardRef, useState } from "react";
|
|
2
|
+
import { cn } from "@/lib/utils";
|
|
3
|
+
|
|
4
|
+
interface Props extends TextareaHTMLAttributes<HTMLTextAreaElement> {
|
|
5
|
+
label?: string;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
export const GTextarea = forwardRef<HTMLTextAreaElement, Props>(
|
|
9
|
+
({ className, label, onFocus, onBlur, ...rest }, ref) => {
|
|
10
|
+
const [focused, setFocused] = useState(false);
|
|
11
|
+
return (
|
|
12
|
+
<label className="block w-full">
|
|
13
|
+
{label && (
|
|
14
|
+
<span className="label-mono text-muted block mb-2">{label}</span>
|
|
15
|
+
)}
|
|
16
|
+
<div
|
|
17
|
+
className={cn(
|
|
18
|
+
"relative rounded-[8px] border bg-surface transition-all duration-200",
|
|
19
|
+
focused
|
|
20
|
+
? "border-signal [box-shadow:0_0_18px_hsl(var(--signal-glow)/var(--glow-soft)),inset_0_0_0_1px_hsl(var(--signal)/0.3)]"
|
|
21
|
+
: "border-[hsl(var(--border-subtle))]"
|
|
22
|
+
)}
|
|
23
|
+
>
|
|
24
|
+
<textarea
|
|
25
|
+
ref={ref}
|
|
26
|
+
onFocus={(e) => {
|
|
27
|
+
setFocused(true);
|
|
28
|
+
onFocus?.(e);
|
|
29
|
+
}}
|
|
30
|
+
onBlur={(e) => {
|
|
31
|
+
setFocused(false);
|
|
32
|
+
onBlur?.(e);
|
|
33
|
+
}}
|
|
34
|
+
className={cn(
|
|
35
|
+
"w-full bg-transparent px-3.5 py-2.5 min-h-[88px] text-sm text-foreground placeholder:text-muted/70 outline-none font-mono resize-y",
|
|
36
|
+
className
|
|
37
|
+
)}
|
|
38
|
+
{...rest}
|
|
39
|
+
/>
|
|
40
|
+
</div>
|
|
41
|
+
</label>
|
|
42
|
+
);
|
|
43
|
+
}
|
|
44
|
+
);
|
|
45
|
+
GTextarea.displayName = "GTextarea";
|
package/manifest.json
ADDED
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@glyph-ui/textarea",
|
|
3
|
+
"version": "0.1.0-alpha.2",
|
|
4
|
+
"description": "Glyph UI — GTextarea. Installing this copies its source into your project; it is not a runtime dependency and is safe to remove once copied.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"private": false,
|
|
8
|
+
"publishConfig": {
|
|
9
|
+
"tag": "alpha",
|
|
10
|
+
"access": "public"
|
|
11
|
+
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
14
|
+
"prepublishOnly": "node scripts/check-alpha-version.mjs"
|
|
15
|
+
},
|
|
16
|
+
"files": [
|
|
17
|
+
"files",
|
|
18
|
+
"manifest.json",
|
|
19
|
+
"scripts",
|
|
20
|
+
"README.md"
|
|
21
|
+
],
|
|
22
|
+
"peerDependencies": {
|
|
23
|
+
"react": ">=18",
|
|
24
|
+
"clsx": "*",
|
|
25
|
+
"tailwind-merge": "*"
|
|
26
|
+
},
|
|
27
|
+
"peerDependenciesMeta": {
|
|
28
|
+
"clsx": {
|
|
29
|
+
"optional": true
|
|
30
|
+
},
|
|
31
|
+
"tailwind-merge": {
|
|
32
|
+
"optional": true
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"react",
|
|
37
|
+
"ui",
|
|
38
|
+
"component",
|
|
39
|
+
"gtextarea"
|
|
40
|
+
]
|
|
41
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Runs as "prepublishOnly" — a non-zero exit here aborts `npm publish`
|
|
4
|
+
* before anything reaches the registry. Refuses to publish unless the
|
|
5
|
+
* version is a proper alpha prerelease and publishConfig.tag is "alpha",
|
|
6
|
+
* so a stable/"latest" release can't happen by accident during the alpha
|
|
7
|
+
* phase. See the package's README for how to graduate out of alpha
|
|
8
|
+
* deliberately.
|
|
9
|
+
*/
|
|
10
|
+
import { readFileSync } from "node:fs";
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
import { fileURLToPath } from "node:url";
|
|
13
|
+
|
|
14
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
15
|
+
const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf8"));
|
|
16
|
+
|
|
17
|
+
const ALPHA_VERSION = /^\d+\.\d+\.\d+-alpha\.\d+$/;
|
|
18
|
+
|
|
19
|
+
if (!ALPHA_VERSION.test(pkg.version)) {
|
|
20
|
+
console.error(
|
|
21
|
+
`\nRefusing to publish: version "${pkg.version}" is not an alpha prerelease.\n` +
|
|
22
|
+
`Expected x.y.z-alpha.N, e.g. "0.1.0-alpha.2".\n` +
|
|
23
|
+
`Bump with: npm version prerelease --preid=alpha\n`
|
|
24
|
+
);
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (pkg.publishConfig?.tag !== "alpha") {
|
|
29
|
+
console.error(
|
|
30
|
+
`\nRefusing to publish: publishConfig.tag is "${pkg.publishConfig?.tag ?? "(unset)"}", expected "alpha".\n`
|
|
31
|
+
);
|
|
32
|
+
process.exit(1);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
console.log(`\u2713 ${pkg.name}@${pkg.version} is a valid alpha prerelease.`);
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Runs automatically after `npm install` for this package. Copies this
|
|
4
|
+
* component's real source file(s) out of node_modules and into the
|
|
5
|
+
* consumer's own project, at the same relative path they'd have if they'd
|
|
6
|
+
* copy-pasted it by hand.
|
|
7
|
+
*
|
|
8
|
+
* npm sets INIT_CWD to the directory the user actually ran `npm install`
|
|
9
|
+
* from (their project root) — not this package's folder inside
|
|
10
|
+
* node_modules, which is what `process.cwd()` would give during a
|
|
11
|
+
* postinstall hook. That's the whole trick that makes this behave like
|
|
12
|
+
* shadcn's copy-paste model instead of a normal installed dependency.
|
|
13
|
+
*/
|
|
14
|
+
import { cpSync, mkdirSync, existsSync, readFileSync } from "node:fs";
|
|
15
|
+
import { dirname, join } from "node:path";
|
|
16
|
+
import { fileURLToPath } from "node:url";
|
|
17
|
+
|
|
18
|
+
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
19
|
+
const pkgRoot = join(__dirname, "..");
|
|
20
|
+
const pkg = JSON.parse(readFileSync(join(pkgRoot, "package.json"), "utf8"));
|
|
21
|
+
const manifest = JSON.parse(readFileSync(join(pkgRoot, "manifest.json"), "utf8"));
|
|
22
|
+
|
|
23
|
+
const targetRoot = process.env.INIT_CWD || process.cwd();
|
|
24
|
+
|
|
25
|
+
// Guard against this ever running inside the glyph-ui monorepo itself
|
|
26
|
+
// (e.g. `npm install` at the repo root) and overwriting the source of
|
|
27
|
+
// truth these packages were generated from.
|
|
28
|
+
if (targetRoot.split(/[/\\]/).includes("packages")) {
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
console.log(`\nglyph-ui: ${pkg.name} \u2014 copying source into your project\n`);
|
|
33
|
+
|
|
34
|
+
let copied = 0;
|
|
35
|
+
for (const relPath of manifest.files) {
|
|
36
|
+
const src = join(pkgRoot, "files", relPath);
|
|
37
|
+
const dest = join(targetRoot, relPath);
|
|
38
|
+
if (!existsSync(src)) continue;
|
|
39
|
+
mkdirSync(dirname(dest), { recursive: true });
|
|
40
|
+
cpSync(src, dest);
|
|
41
|
+
console.log(` + ${relPath}`);
|
|
42
|
+
copied++;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
console.log(`\n${copied} file(s) copied.`);
|
|
46
|
+
if (manifest.dependencies.length) {
|
|
47
|
+
console.log(`Make sure these are installed: ${manifest.dependencies.join(", ")}`);
|
|
48
|
+
}
|
|
49
|
+
console.log(`This package's job is done. It is safe to remove:`);
|
|
50
|
+
console.log(` npm uninstall ${pkg.name}\n`);
|