torch-glare 1.0.8 → 1.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.
- package/dist/bin/index.js +1 -1
- package/dist/src/shared/detectPackageManager.d.ts +1 -1
- package/dist/src/shared/detectPackageManager.d.ts.map +1 -1
- package/dist/src/shared/detectPackageManager.js +5 -1
- package/dist/src/shared/detectPackageManager.js.map +1 -1
- package/dist/src/shared/tailwindInit.d.ts.map +1 -1
- package/dist/src/shared/tailwindInit.js +20 -100
- package/dist/src/shared/tailwindInit.js.map +1 -1
- package/docs/Cover.png +0 -0
- package/docs/README.md +207 -0
- package/lib/components/AlertDialog.tsx +29 -18
- package/lib/components/BadgeField.tsx +7 -8
- package/lib/components/Checkbox.tsx +1 -1
- package/lib/components/Dialog.tsx +1 -1
- package/lib/components/ImageAttachment.tsx +2 -2
- package/lib/components/Input.tsx +16 -14
- package/lib/components/InputField.tsx +5 -5
- package/lib/components/InputOTP.tsx +1 -1
- package/lib/components/LinkButton.tsx +2 -3
- package/lib/components/Select.tsx +3 -3
- package/lib/components/Skeleton.tsx +1 -1
- package/lib/components/TabFormItem.tsx +1 -1
- package/lib/components/Table.tsx +2 -1
- package/lib/hooks/useClickOutside.tsx +1 -1
- package/lib/hooks/useTagSelection.tsx +43 -8
- package/lib/layouts/FieldSection.tsx +1 -1
- package/package.json +4 -3
package/dist/bin/index.js
CHANGED
|
@@ -11,7 +11,7 @@ const program = new Command();
|
|
|
11
11
|
program
|
|
12
12
|
.name("torch-glare")
|
|
13
13
|
.description("Torch Glare for managing React components")
|
|
14
|
-
.version("1.0.
|
|
14
|
+
.version("1.0.8");
|
|
15
15
|
program
|
|
16
16
|
.command("init")
|
|
17
17
|
.description("Initialize torch.json configuration file")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Detect the package manager used in the project.
|
|
3
|
-
* @returns {string} - The detected package manager (pnpm, yarn,
|
|
3
|
+
* @returns {string} - The detected package manager (pnpm, yarn, npm, bun, etc).
|
|
4
4
|
*/
|
|
5
5
|
export declare function detectPackageManager(): string;
|
|
6
6
|
//# sourceMappingURL=detectPackageManager.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detectPackageManager.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/detectPackageManager.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,
|
|
1
|
+
{"version":3,"file":"detectPackageManager.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/detectPackageManager.ts"],"names":[],"mappings":"AAGA;;;GAGG;AACH,wBAAgB,oBAAoB,IAAI,MAAM,CAO7C"}
|
|
@@ -2,7 +2,7 @@ import * as fs from "fs";
|
|
|
2
2
|
import path from "path";
|
|
3
3
|
/**
|
|
4
4
|
* Detect the package manager used in the project.
|
|
5
|
-
* @returns {string} - The detected package manager (pnpm, yarn,
|
|
5
|
+
* @returns {string} - The detected package manager (pnpm, yarn, npm, bun, etc).
|
|
6
6
|
*/
|
|
7
7
|
export function detectPackageManager() {
|
|
8
8
|
if (fs.existsSync(path.join(process.cwd(), "pnpm-lock.yaml")))
|
|
@@ -11,6 +11,10 @@ export function detectPackageManager() {
|
|
|
11
11
|
return "yarn";
|
|
12
12
|
if (fs.existsSync(path.join(process.cwd(), "package-lock.json")))
|
|
13
13
|
return "npm";
|
|
14
|
+
if (fs.existsSync(path.join(process.cwd(), "bun.lockb")))
|
|
15
|
+
return "bun";
|
|
16
|
+
if (fs.existsSync(path.join(process.cwd(), ".yarnrc.yml")))
|
|
17
|
+
return "yarn";
|
|
14
18
|
return "npm"; // Default to npm if no lock file is found
|
|
15
19
|
}
|
|
16
20
|
//# sourceMappingURL=detectPackageManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"detectPackageManager.js","sourceRoot":"","sources":["../../../cli/src/shared/detectPackageManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAChC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC7E,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IACxE,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/E,OAAO,KAAK,CAAC,CAAC,0CAA0C;AAC5D,CAAC"}
|
|
1
|
+
{"version":3,"file":"detectPackageManager.js","sourceRoot":"","sources":["../../../cli/src/shared/detectPackageManager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB;;;GAGG;AACH,MAAM,UAAU,oBAAoB;IAChC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,gBAAgB,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC7E,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IACxE,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,mBAAmB,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC/E,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,WAAW,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACvE,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,CAAC,CAAC;QAAE,OAAO,MAAM,CAAC;IAC1E,OAAO,KAAK,CAAC,CAAC,0CAA0C;AAC5D,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tailwindInit.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/tailwindInit.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"tailwindInit.d.ts","sourceRoot":"","sources":["../../../cli/src/shared/tailwindInit.ts"],"names":[],"mappings":"AAGA,wBAAgB,YAAY,IAAI,IAAI,CASnC"}
|
|
@@ -1,21 +1,14 @@
|
|
|
1
|
-
import path from "path";
|
|
2
|
-
import fs from "fs";
|
|
3
1
|
import { execSync } from "child_process";
|
|
4
2
|
import { detectPackageManager } from "./detectPackageManager.js";
|
|
5
|
-
|
|
6
|
-
const
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
function ({ addVariant }: any) {
|
|
15
|
-
addVariant("rtl", '&[dir="rtl"]');
|
|
16
|
-
addVariant("ltr", '&[dir="ltr"]');
|
|
17
|
-
},
|
|
18
|
-
`;
|
|
3
|
+
export function tailwindInit() {
|
|
4
|
+
const dependencies = [
|
|
5
|
+
"tailwindcss-animate",
|
|
6
|
+
"tailwind-scrollbar-hide",
|
|
7
|
+
"glare-typography",
|
|
8
|
+
"mapping-color-system",
|
|
9
|
+
"glare-torch-mode",
|
|
10
|
+
];
|
|
11
|
+
installDependencies(dependencies);
|
|
19
12
|
}
|
|
20
13
|
/**
|
|
21
14
|
* Installs dependencies using the detected package manager.
|
|
@@ -31,21 +24,23 @@ function installDependencies(dependencies = []) {
|
|
|
31
24
|
console.log(`📦 Detected package manager: ${packageManager}`);
|
|
32
25
|
// Generate the install command based on the package manager
|
|
33
26
|
let installCommand;
|
|
34
|
-
const latestDeps = dependencies.map(dep => `${dep}
|
|
27
|
+
const latestDeps = dependencies.map(dep => `${dep}`).join(" ");
|
|
35
28
|
switch (packageManager) {
|
|
36
29
|
case "pnpm":
|
|
37
|
-
installCommand = `pnpm add ${latestDeps}`;
|
|
30
|
+
installCommand = `pnpm add ${latestDeps} --prefer-offline`;
|
|
38
31
|
break;
|
|
39
32
|
case "yarn":
|
|
40
|
-
installCommand = `yarn add ${latestDeps}`;
|
|
33
|
+
installCommand = `yarn add ${latestDeps} --ignore-engines --ignore-platform --prefer-offline`;
|
|
41
34
|
break;
|
|
42
|
-
case "
|
|
43
|
-
|
|
44
|
-
installCommand = `npm install ${latestDeps}`;
|
|
35
|
+
case "bun":
|
|
36
|
+
installCommand = `bun add ${latestDeps} --no-save && bun install`;
|
|
45
37
|
break;
|
|
38
|
+
default:
|
|
39
|
+
installCommand = `npm install ${latestDeps} --legacy-peer-deps`;
|
|
46
40
|
}
|
|
47
41
|
try {
|
|
48
42
|
// Execute the install command
|
|
43
|
+
console.log(`Running: ${installCommand}`);
|
|
49
44
|
execSync(installCommand, { stdio: "inherit" });
|
|
50
45
|
console.log("✅ Dependencies installed successfully.");
|
|
51
46
|
}
|
|
@@ -59,86 +54,11 @@ function installDependencies(dependencies = []) {
|
|
|
59
54
|
else if (error.message.includes("not found")) {
|
|
60
55
|
console.error("💡 The package manager might not be installed. Please ensure it is installed and available in your PATH.");
|
|
61
56
|
}
|
|
62
|
-
else {
|
|
63
|
-
console.error("💡
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
function createTailwindConfig() {
|
|
68
|
-
const tailwindConfig = `
|
|
69
|
-
import type { Config } from "tailwindcss";
|
|
70
|
-
export default {
|
|
71
|
-
content: [
|
|
72
|
-
"./app/**/*.{js,ts,jsx,tsx}",
|
|
73
|
-
"./index.html",
|
|
74
|
-
"./src/**/*.{js,ts,jsx,tsx}",
|
|
75
|
-
"./pages/**/*.{js,ts,jsx,tsx,mdx}",
|
|
76
|
-
"./features/**/*.{js,ts,jsx,tsx,mdx}",
|
|
77
|
-
"./components/**/*.{js,ts,jsx,tsx,mdx}",
|
|
78
|
-
"./layout/**/*.{js,ts,jsx,tsx,mdx}",
|
|
79
|
-
],
|
|
80
|
-
theme: {
|
|
81
|
-
extend: {},
|
|
82
|
-
},
|
|
83
|
-
screens: {
|
|
84
|
-
sm: "600px",
|
|
85
|
-
md: "768px",
|
|
86
|
-
lg: "1024px",
|
|
87
|
-
xl: "1280px",
|
|
88
|
-
"2xl": "1536px",
|
|
89
|
-
},
|
|
90
|
-
plugins: [${generatePlugins()}],
|
|
91
|
-
}satisfies Config;
|
|
92
|
-
`;
|
|
93
|
-
fs.writeFileSync(tailwindConfigPath, tailwindConfig);
|
|
94
|
-
console.log("✅ Created tailwind.config.ts");
|
|
95
|
-
}
|
|
96
|
-
function modifyTailwindConfig() {
|
|
97
|
-
let tailwindConfigContent = fs.readFileSync(tailwindConfigPath, "utf-8");
|
|
98
|
-
if (!tailwindConfigContent.includes("glare-typography") && !tailwindConfigContent.includes("glare-themes")) {
|
|
99
|
-
if (!tailwindConfigContent.includes("plugins")) {
|
|
100
|
-
tailwindConfigContent = tailwindConfigContent.replace("],", `],plugins: [${generatePlugins()}],`);
|
|
57
|
+
else if (error.message.includes("ERESOLVE") || error.message.includes("peer dependency conflict")) {
|
|
58
|
+
console.error("💡 There are dependency conflicts. Try manually installing with 'npm install --force' or 'npm install --legacy-peer-deps'.");
|
|
101
59
|
}
|
|
102
60
|
else {
|
|
103
|
-
|
|
104
|
-
}
|
|
105
|
-
console.log("✅ Modified tailwind.config.ts");
|
|
106
|
-
}
|
|
107
|
-
fs.writeFileSync(tailwindConfigPath, tailwindConfigContent);
|
|
108
|
-
}
|
|
109
|
-
/**
|
|
110
|
-
* Checks if the installed Tailwind CSS version is less than v4.
|
|
111
|
-
* @param {string} version - The version string of Tailwind CSS.
|
|
112
|
-
* @returns {boolean} - True if the version is less than v4, otherwise false.
|
|
113
|
-
*/
|
|
114
|
-
function isTailwindVersionLessThanV4(version) {
|
|
115
|
-
if (!version) {
|
|
116
|
-
console.warn("⚠️ Tailwind CSS is not installed.");
|
|
117
|
-
return false; // Assume it needs to be installed
|
|
118
|
-
}
|
|
119
|
-
// Extract the major version number
|
|
120
|
-
const majorVersion = parseInt(version?.replace(/^[^0-9]*/, "").split(".")[0] || "3", 10);
|
|
121
|
-
return majorVersion < 4;
|
|
122
|
-
}
|
|
123
|
-
export function tailwindInit() {
|
|
124
|
-
const dependencies = [
|
|
125
|
-
"tailwindcss-animate",
|
|
126
|
-
"tailwind-scrollbar-hide",
|
|
127
|
-
"glare-typography",
|
|
128
|
-
"glare-themes",
|
|
129
|
-
"glare-torch-mode",
|
|
130
|
-
];
|
|
131
|
-
installDependencies(dependencies);
|
|
132
|
-
const { depsNamesAndVersions } = getCurrentInstalledDependencies();
|
|
133
|
-
if (depsNamesAndVersions["tailwindcss"]) {
|
|
134
|
-
const tailwindVersion = depsNamesAndVersions["tailwindcss"];
|
|
135
|
-
if (isTailwindVersionLessThanV4(tailwindVersion)) {
|
|
136
|
-
if (!fs.existsSync(tailwindConfigPath)) {
|
|
137
|
-
createTailwindConfig();
|
|
138
|
-
}
|
|
139
|
-
else {
|
|
140
|
-
modifyTailwindConfig();
|
|
141
|
-
}
|
|
61
|
+
console.error("💡 Check your internet connection and try again.");
|
|
142
62
|
}
|
|
143
63
|
}
|
|
144
64
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tailwindInit.js","sourceRoot":"","sources":["../../../cli/src/shared/tailwindInit.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"tailwindInit.js","sourceRoot":"","sources":["../../../cli/src/shared/tailwindInit.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAEjE,MAAM,UAAU,YAAY;IAC1B,MAAM,YAAY,GAAG;QACnB,qBAAqB;QACrB,yBAAyB;QACzB,kBAAkB;QAClB,sBAAsB;QACtB,kBAAkB;KACnB,CAAC;IACF,mBAAmB,CAAC,YAAY,CAAC,CAAC;AACpC,CAAC;AAGD;;;GAGG;AACH,SAAS,mBAAmB,CAAC,eAAyB,EAAE;IACtD,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,CAAC;QACzB,OAAO,CAAC,IAAI,CAAC,yCAAyC,CAAC,CAAC;QACxD,OAAO;IACT,CAAC;IAED,6BAA6B;IAC7B,MAAM,cAAc,GAAG,oBAAoB,EAAE,CAAC;IAC9C,OAAO,CAAC,GAAG,CAAC,gCAAgC,cAAc,EAAE,CAAC,CAAC;IAE9D,4DAA4D;IAC5D,IAAI,cAAc,CAAC;IACnB,MAAM,UAAU,GAAG,YAAY,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAE/D,QAAQ,cAAc,EAAE,CAAC;QACvB,KAAK,MAAM;YACT,cAAc,GAAG,YAAY,UAAU,mBAAmB,CAAC;YAC3D,MAAM;QACR,KAAK,MAAM;YACT,cAAc,GAAG,YAAY,UAAU,sDAAsD,CAAC;YAC9F,MAAM;QACR,KAAK,KAAK;YACR,cAAc,GAAG,WAAW,UAAU,2BAA2B,CAAC;YAClE,MAAM;QACR;YACE,cAAc,GAAG,eAAe,UAAU,qBAAqB,CAAC;IACpE,CAAC;IAED,IAAI,CAAC;QAEH,8BAA8B;QAC9B,OAAO,CAAC,GAAG,CAAC,YAAY,cAAc,EAAE,CAAC,CAAC;QAC1C,QAAQ,CAAC,cAAc,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;IACxD,CAAC;IAAC,OAAO,KAAU,EAAE,CAAC;QACpB,OAAO,CAAC,KAAK,CAAC,kCAAkC,CAAC,CAAC;QAClD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAE7B,0CAA0C;QAC1C,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YACrC,OAAO,CAAC,KAAK,CACX,oIAAoI,CACrI,CAAC;QACJ,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/C,OAAO,CAAC,KAAK,CACX,0GAA0G,CAC3G,CAAC;QACJ,CAAC;aAAM,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,IAAI,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,0BAA0B,CAAC,EAAE,CAAC;YACpG,OAAO,CAAC,KAAK,CACX,4HAA4H,CAC7H,CAAC;QACJ,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,KAAK,CAAC,kDAAkD,CAAC,CAAC;QACpE,CAAC;IACH,CAAC;AACH,CAAC"}
|
package/docs/Cover.png
ADDED
|
Binary file
|
package/docs/README.md
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
1
|
+
# TORCH Glare Components Library
|
|
2
|
+
|
|
3
|
+
Welcome to the **TORCH Glare Components Library**! This library provides a collection of reusable React components to help you build user interfaces efficiently. Additionally, a CLI tool (**torch-glare CLI**) is available to streamline component management.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
1. [Installation](#installation)
|
|
8
|
+
2. [Usage](#usage)
|
|
9
|
+
3. [CLI Commands](#cli-commands)
|
|
10
|
+
4. [Theming](#theming)
|
|
11
|
+
5. [Contributing](#contributing)
|
|
12
|
+
6. [License](#license)
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
## 1. Initialize Your Project
|
|
18
|
+
|
|
19
|
+
To install the TORCH Glare Components Library, run the following command:
|
|
20
|
+
|
|
21
|
+
```sh
|
|
22
|
+
npx torch-glare@latest init
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
This command will:
|
|
26
|
+
- Create or modify the `tailwind.config.js` file to support Tailwind CSS for Tailwind versions less then 4.
|
|
27
|
+
- Generate a `torch.json` file where you can customize the installation path for components.
|
|
28
|
+
|
|
29
|
+
### Tailwind CSS Requirement
|
|
30
|
+
Ensure that Tailwind CSS is installed in your project before running the initialization command.
|
|
31
|
+
|
|
32
|
+
## 2. Add Essential Plugins for Tailwind CSS
|
|
33
|
+
|
|
34
|
+
If you're using Tailwind CSS version 4 or above, add the following plugins to your global CSS file:
|
|
35
|
+
|
|
36
|
+
```css
|
|
37
|
+
@import "tailwindcss";
|
|
38
|
+
/* Essential plugins */
|
|
39
|
+
@plugin 'glare-typography';
|
|
40
|
+
@plugin 'mapping-color-system';
|
|
41
|
+
@plugin 'glare-torch-mode';
|
|
42
|
+
@plugin 'tailwind-scrollbar-hide';
|
|
43
|
+
@plugin 'tailwindcss-animate';
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
### 2. Add Remix Icon Library
|
|
48
|
+
Include the following in `index.html` or nextjs `layout.tsx` or meta data for icon support:
|
|
49
|
+
|
|
50
|
+
```html
|
|
51
|
+
<html>
|
|
52
|
+
<head>
|
|
53
|
+
<link
|
|
54
|
+
href="https://cdn.jsdelivr.net/npm/remixicon@4.5.0/fonts/remixicon.css"
|
|
55
|
+
rel="stylesheet"
|
|
56
|
+
/>
|
|
57
|
+
</head>
|
|
58
|
+
<body></body>
|
|
59
|
+
</html>
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## 3. Configure Installation Path
|
|
64
|
+
|
|
65
|
+
Adjust the `glare.json` file to specify where you want to install components:
|
|
66
|
+
|
|
67
|
+
```json
|
|
68
|
+
{
|
|
69
|
+
"path": "./src" // The directory where components will be installed
|
|
70
|
+
}
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 4. Add Components
|
|
74
|
+
To add a specific component, run:
|
|
75
|
+
|
|
76
|
+
```sh
|
|
77
|
+
npx torch-glare@latest add [component-name]
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Or, to add components interactively:
|
|
81
|
+
|
|
82
|
+
```sh
|
|
83
|
+
npx torch-glare@latest add
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
## Usage
|
|
87
|
+
|
|
88
|
+
Once installed, import and use the components as needed:
|
|
89
|
+
|
|
90
|
+
```tsx
|
|
91
|
+
import React from "react";
|
|
92
|
+
import { Button } from "./components";
|
|
93
|
+
|
|
94
|
+
const App = () => {
|
|
95
|
+
return (
|
|
96
|
+
<div>
|
|
97
|
+
<Button >Hello.</Button>
|
|
98
|
+
</div>
|
|
99
|
+
);
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
export default App;
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## CLI Commands
|
|
106
|
+
|
|
107
|
+
### Initialize Configuration
|
|
108
|
+
```sh
|
|
109
|
+
npx torch-glare@latest init
|
|
110
|
+
```
|
|
111
|
+
- Creates a `torch.json` configuration file.
|
|
112
|
+
- Create or modify `tailwind.config.ts` file for tailwind support.
|
|
113
|
+
|
|
114
|
+
### Add Components
|
|
115
|
+
```sh
|
|
116
|
+
npx torch-glare@latest add [component]
|
|
117
|
+
```
|
|
118
|
+
Adds a specific component or runs an interactive prompt if no name is provided.
|
|
119
|
+
|
|
120
|
+
### Add Hooks
|
|
121
|
+
```sh
|
|
122
|
+
npx torch-glare@latest hook [hook]
|
|
123
|
+
```
|
|
124
|
+
Adds a specific hook or runs an interactive prompt if no name is provided.
|
|
125
|
+
|
|
126
|
+
### Add Utilities
|
|
127
|
+
```sh
|
|
128
|
+
npx torch-glare@latest util [util]
|
|
129
|
+
```
|
|
130
|
+
Adds a specific utility or runs an interactive prompt if no name is provided.
|
|
131
|
+
|
|
132
|
+
### Providers
|
|
133
|
+
```sh
|
|
134
|
+
npx torch-glare@latest provider [provider]
|
|
135
|
+
```
|
|
136
|
+
Adds a specific provider or runs an interactive prompt if no name is provided.
|
|
137
|
+
|
|
138
|
+
### Update Installed Resources
|
|
139
|
+
|
|
140
|
+
```sh
|
|
141
|
+
npx torch-glare@latest update
|
|
142
|
+
```
|
|
143
|
+
Updates all installed components, hooks, utilities, and providers.
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
## Theming
|
|
147
|
+
|
|
148
|
+
The TORCH Glare Components Library supports both light and dark themes. You can set a fixed theme for your components using the `theme` attribute.
|
|
149
|
+
|
|
150
|
+
### Setting a Fixed Theme
|
|
151
|
+
|
|
152
|
+
To apply a fixed theme (dark or light) to a component, add the `theme `attribute with the desired theme value:
|
|
153
|
+
|
|
154
|
+
```tsx
|
|
155
|
+
import React from "react";
|
|
156
|
+
import { Button } from "./components";
|
|
157
|
+
|
|
158
|
+
const App = () => {
|
|
159
|
+
return (
|
|
160
|
+
<div>
|
|
161
|
+
<Button theme="dark">Dark Theme Button</Button>
|
|
162
|
+
<Button theme="light">Light Theme Button</Button>
|
|
163
|
+
</div>
|
|
164
|
+
);
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
export default App;
|
|
168
|
+
```
|
|
169
|
+
|
|
170
|
+
### Global Theme
|
|
171
|
+
|
|
172
|
+
To apply a theme globally, wrap your application with the `ThemeProvider` and set the optional `defaultTheme` props:
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
```tsx
|
|
176
|
+
import { ThemeProvider } from "./components";
|
|
177
|
+
|
|
178
|
+
const App = () => {
|
|
179
|
+
ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render(
|
|
180
|
+
<ThemeProvider defaultTheme="light" defaultThemeMode="TORCH">
|
|
181
|
+
<App />
|
|
182
|
+
</ThemeProvider>
|
|
183
|
+
);
|
|
184
|
+
};
|
|
185
|
+
|
|
186
|
+
export default App;
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
## Contributing
|
|
190
|
+
|
|
191
|
+
We welcome contributions! Follow these steps:
|
|
192
|
+
|
|
193
|
+
1. Fork the repository.
|
|
194
|
+
2. Create a new branch.
|
|
195
|
+
3. Implement your changes.
|
|
196
|
+
4. Commit with a clear message.
|
|
197
|
+
5. Push your changes and open a pull request.
|
|
198
|
+
|
|
199
|
+
### Contribution Guidelines
|
|
200
|
+
- Follow existing code style.
|
|
201
|
+
- Update documentation if necessary.
|
|
202
|
+
|
|
203
|
+
## License
|
|
204
|
+
|
|
205
|
+
This project is licensed under the **MIT License**.
|
|
206
|
+
|
|
207
|
+
|
|
@@ -4,8 +4,8 @@ import * as React from "react"
|
|
|
4
4
|
import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"
|
|
5
5
|
|
|
6
6
|
import { cn } from "../utils/cn"
|
|
7
|
-
import { buttonVariants } from "./Button"
|
|
8
|
-
import { ButtonVariant } from "
|
|
7
|
+
import { Button, buttonVariants } from "./Button"
|
|
8
|
+
import { ButtonVariant } from "../utils/types"
|
|
9
9
|
import { cva } from "class-variance-authority"
|
|
10
10
|
|
|
11
11
|
const StatusTextStyle = cva("", {
|
|
@@ -55,10 +55,18 @@ const AlertDialogContent = React.forwardRef<
|
|
|
55
55
|
<AlertDialogOverlay />
|
|
56
56
|
<AlertDialogPrimitive.Content
|
|
57
57
|
ref={ref}
|
|
58
|
-
className={cn(
|
|
59
|
-
|
|
60
|
-
"fixed left-[50%] top-[50%] z-50 grid w-full translate-x-[-50%] translate-y-[-50%]
|
|
61
|
-
"rounded-[16px] border-2 border-border-presentation-global-primary",
|
|
58
|
+
className={cn(
|
|
59
|
+
StatusTextStyle({ variant }),
|
|
60
|
+
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-[800px] translate-x-[-50%] translate-y-[-50%]",
|
|
61
|
+
"gap-2 rounded-[16px] border-2 border-border-presentation-global-primary",
|
|
62
|
+
"bg-background-presentation-body-overlay-primary p-[12px]",
|
|
63
|
+
"text-content-presentation-global-primary",
|
|
64
|
+
"shadow-lg duration-200",
|
|
65
|
+
"data-[state=open]:animate-in data-[state=closed]:animate-out",
|
|
66
|
+
"data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0",
|
|
67
|
+
"data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95",
|
|
68
|
+
"data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%]",
|
|
69
|
+
"data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
|
|
62
70
|
className
|
|
63
71
|
)}
|
|
64
72
|
{...props}
|
|
@@ -120,11 +128,11 @@ const AlertDialogLabel = React.forwardRef<
|
|
|
120
128
|
return (
|
|
121
129
|
<AlertDialogPrimitive.Title
|
|
122
130
|
ref={ref}
|
|
123
|
-
className={cn("
|
|
131
|
+
className={cn("typography-display-medium-semibold", className)}
|
|
124
132
|
{...props}
|
|
125
133
|
>
|
|
126
|
-
<p className="first-letter:uppercase" >
|
|
127
|
-
<strong >{firstWord}</strong>
|
|
134
|
+
<p className="first-letter:uppercase typography-display-medium-semibold" >
|
|
135
|
+
<strong className="typography-display-medium-semibold" >{firstWord}</strong>
|
|
128
136
|
{restOfTitle.length > 0 && ' ' + restOfTitle}
|
|
129
137
|
</p>
|
|
130
138
|
</AlertDialogPrimitive.Title>
|
|
@@ -139,14 +147,15 @@ const AlertDialogDescription = React.forwardRef<
|
|
|
139
147
|
<AlertDialogPrimitive.Description
|
|
140
148
|
data-description=""
|
|
141
149
|
ref={ref}
|
|
142
|
-
className={cn(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
150
|
+
className={cn(
|
|
151
|
+
"typography-body-large-medium",
|
|
152
|
+
"bg-background-presentation-form-base",
|
|
153
|
+
"border border-border-presentation-global-primary",
|
|
154
|
+
"rounded-[8px] p-[24px_48px_48px_48px]",
|
|
155
|
+
className
|
|
156
|
+
)}
|
|
146
157
|
{...props}
|
|
147
|
-
|
|
148
|
-
{props.children}
|
|
149
|
-
</AlertDialogPrimitive.Description>
|
|
158
|
+
/>
|
|
150
159
|
))
|
|
151
160
|
AlertDialogDescription.displayName =
|
|
152
161
|
AlertDialogPrimitive.Description.displayName
|
|
@@ -166,8 +175,10 @@ const AlertDialogAction = React.forwardRef<
|
|
|
166
175
|
<AlertDialogPrimitive.Action
|
|
167
176
|
ref={ref}
|
|
168
177
|
className={cn(buttonVariants({ variant: variant, size: size, buttonType: buttonType }), className)}
|
|
169
|
-
|
|
170
|
-
|
|
178
|
+
asChild
|
|
179
|
+
>
|
|
180
|
+
<Button size={size} variant={variant} buttonType={buttonType} {...props} />
|
|
181
|
+
</AlertDialogPrimitive.Action>
|
|
171
182
|
))
|
|
172
183
|
AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName
|
|
173
184
|
|
|
@@ -11,9 +11,9 @@ import { Tooltip, ToolTipSide } from "./Tooltip";
|
|
|
11
11
|
import { Popover, PopoverContent, PopoverTrigger } from "./Popover";
|
|
12
12
|
import { Themes } from "../utils/types";
|
|
13
13
|
import { Icon, Input, Group, Trilling } from "./Input";
|
|
14
|
-
import { useClickOutside } from "
|
|
14
|
+
import { useClickOutside } from "../hooks/useClickOutside";
|
|
15
15
|
import { Badge } from "./Badge";
|
|
16
|
-
import { Tag, useTagSelection } from "
|
|
16
|
+
import { Tag, useTagSelection } from "../hooks/useTagSelection";
|
|
17
17
|
|
|
18
18
|
|
|
19
19
|
interface Props
|
|
@@ -30,6 +30,7 @@ interface Props
|
|
|
30
30
|
actionButton?: ReactNode
|
|
31
31
|
tags: Tag[]
|
|
32
32
|
onValueChange?: (tags: Tag[]) => void
|
|
33
|
+
singleSelect?: boolean
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
|
|
@@ -50,9 +51,9 @@ export const BadgeField = forwardRef<HTMLInputElement, Props>(
|
|
|
50
51
|
tags,
|
|
51
52
|
onValueChange,
|
|
52
53
|
children,
|
|
54
|
+
singleSelect = false,
|
|
53
55
|
...props
|
|
54
56
|
},
|
|
55
|
-
forwardedRef
|
|
56
57
|
) => {
|
|
57
58
|
const [dropDownListWidth, setDropDownListWidth] = useState(0);
|
|
58
59
|
const popoverContentRef = useRef<HTMLDivElement>(null);
|
|
@@ -79,7 +80,7 @@ export const BadgeField = forwardRef<HTMLInputElement, Props>(
|
|
|
79
80
|
focusedPopoverIndex,
|
|
80
81
|
isPopoverOpen,
|
|
81
82
|
setIsPopoverOpen,
|
|
82
|
-
} = useTagSelection({ Tags: tags, onTagsChange: onValueChange, inputRef });
|
|
83
|
+
} = useTagSelection({ Tags: tags, onTagsChange: onValueChange, inputRef, singleSelect });
|
|
83
84
|
|
|
84
85
|
return (
|
|
85
86
|
<Popover open={isPopoverOpen}>
|
|
@@ -93,7 +94,6 @@ export const BadgeField = forwardRef<HTMLInputElement, Props>(
|
|
|
93
94
|
<Group
|
|
94
95
|
error={errorMessage !== undefined}
|
|
95
96
|
onTable={onTable}
|
|
96
|
-
data-theme={theme}
|
|
97
97
|
variant={variant}
|
|
98
98
|
tabIndex={isPopoverOpen ? 0 : -1}
|
|
99
99
|
onKeyDown={handleKeyDown}
|
|
@@ -102,9 +102,9 @@ export const BadgeField = forwardRef<HTMLInputElement, Props>(
|
|
|
102
102
|
onFocus={(e: any) => {
|
|
103
103
|
setDropDownListWidth(e.currentTarget.offsetWidth);
|
|
104
104
|
}}
|
|
105
|
-
className={cn("flex gap-1 flex-row w-full relative p-1 flex-nowrap overflow-hidden justify-
|
|
105
|
+
className={cn("flex gap-1 flex-row w-full relative p-1 flex-nowrap overflow-hidden justify-start items-center",
|
|
106
106
|
{
|
|
107
|
-
"flex-wrap justify-start": isPopoverOpen,
|
|
107
|
+
"flex-wrap justify-start h-fit": isPopoverOpen && !singleSelect,
|
|
108
108
|
},
|
|
109
109
|
className
|
|
110
110
|
)}
|
|
@@ -163,7 +163,6 @@ export const BadgeField = forwardRef<HTMLInputElement, Props>(
|
|
|
163
163
|
</Tooltip>
|
|
164
164
|
|
|
165
165
|
<PopoverContent
|
|
166
|
-
data-theme={theme}
|
|
167
166
|
ref={popoverContentRef}
|
|
168
167
|
style={{ width: dropDownListWidth }}
|
|
169
168
|
variant={variant}
|
|
@@ -12,7 +12,7 @@ const glareCheckBoxStyles = cva(
|
|
|
12
12
|
"border border-border-presentation-action-checkbox-primary",
|
|
13
13
|
"bg-background-presentation-action-borderstyle",
|
|
14
14
|
"focus:bg-blue-sparkle-alpha-15 focus:border-border-presentation-state-focus",
|
|
15
|
-
'disabled:bg-background-presentation-
|
|
15
|
+
'disabled:bg-background-presentation-action-disabled disabled:border-border-presentation-action-disabled disabled:cursor-not-allowed',
|
|
16
16
|
"data-[state=checked]:bg-blue-sparkle-600 data-[state=checked]:border-blue-sparkle-600",
|
|
17
17
|
"hover:border-border-presentation-action-hover",
|
|
18
18
|
],
|
|
@@ -37,7 +37,7 @@ const DialogContent = React.forwardRef<
|
|
|
37
37
|
<DialogPrimitive.Content
|
|
38
38
|
ref={ref}
|
|
39
39
|
className={cn(
|
|
40
|
-
"fixed left-[50%] top-[50%] z-50 flex flex-col items-start w-
|
|
40
|
+
"fixed left-[50%] top-[50%] z-50 flex flex-col items-start w-fit translate-x-[-50%] translate-y-[-50%] shadow-lg duration-200 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-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%]",
|
|
41
41
|
"flex justify-center items-center",
|
|
42
42
|
className
|
|
43
43
|
)}
|
|
@@ -7,7 +7,7 @@ import { AlertDialog, AlertDialogTrigger, AlertDialogContent, AlertDialogCancel
|
|
|
7
7
|
|
|
8
8
|
const dropZoneStyles = cva(
|
|
9
9
|
[
|
|
10
|
-
"w-full
|
|
10
|
+
"w-full h-[65px] flex flex-col rounded-lg border-dashed !border-2 transition-all duration-300 ease-in-out ",
|
|
11
11
|
"!border-border-presentation-action-borderstyle bg-background-presentation-badge-gray",
|
|
12
12
|
"hover:border-border-presentation-action-borderstyle hover:bg-background-presentation-badge-gray",
|
|
13
13
|
],
|
|
@@ -60,7 +60,7 @@ const ImageAttachment = forwardRef<HTMLInputElement, Props>(
|
|
|
60
60
|
<h1 className="text-content-presentation-action-light-primary typography-body-large-medium">
|
|
61
61
|
{mainLabel}
|
|
62
62
|
</h1>
|
|
63
|
-
<p className="text-content-presentation-action-light-secondary typography-body-small-medium">
|
|
63
|
+
<p className="text-content-presentation-action-light-secondary typography-body-small-medium text-wrap whitespace-pre-wrap text-center">
|
|
64
64
|
{secondaryLabel}
|
|
65
65
|
</p>
|
|
66
66
|
<input ref={ref} {...props} type="file" hidden />
|
package/lib/components/Input.tsx
CHANGED
|
@@ -11,17 +11,19 @@ interface InputGroupProps extends Omit<HTMLAttributes<HTMLDivElement>, "size"> {
|
|
|
11
11
|
className?: string;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
export const Group =
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
14
|
+
export const Group = forwardRef<HTMLDivElement, InputGroupProps>(
|
|
15
|
+
({ size = 'M', variant = "PresentationStyle", error = false, onTable = false, className, ...props }, ref) => {
|
|
16
|
+
return (
|
|
17
|
+
<div
|
|
18
|
+
className={cn(GroupStyles({ size, variant, error, onTable }), className)}
|
|
19
|
+
ref={ref}
|
|
20
|
+
{...props}>
|
|
21
|
+
</div>
|
|
22
|
+
)
|
|
23
|
+
}
|
|
24
|
+
);
|
|
24
25
|
|
|
26
|
+
Group.displayName = "Group";
|
|
25
27
|
|
|
26
28
|
interface IconProps {
|
|
27
29
|
children: React.ReactNode;
|
|
@@ -116,10 +118,10 @@ export const GroupStyles = cva(
|
|
|
116
118
|
"transition-all duration-200 ease-in-out",
|
|
117
119
|
"hover:shadow-[0px_1px_6px_0px_rgba(0,0,0,0.30)]",
|
|
118
120
|
"[&_i]:leading-[0px] leading-[0px]",
|
|
119
|
-
'[&:has(input[disabled
|
|
120
|
-
'[&:has(input[disabled
|
|
121
|
-
'[&:has(input[disabled
|
|
122
|
-
'[&:has(input[disabled
|
|
121
|
+
'[&:has(input[disabled])]:!border-border-presentation-action-disabled',
|
|
122
|
+
'[&:has(input[disabled])]:!bg-background-presentation-action-disabled',
|
|
123
|
+
'[&:has(input[disabled])]:hover:border-border-presentation-action-disabled',
|
|
124
|
+
'[&:has(input[disabled])]:hover:bg-background-presentation-action-disabled',
|
|
123
125
|
],
|
|
124
126
|
{
|
|
125
127
|
variants: {
|
|
@@ -98,7 +98,7 @@ export const InputField = forwardRef<HTMLInputElement, Props>(
|
|
|
98
98
|
<Trilling >
|
|
99
99
|
{childrenSide}
|
|
100
100
|
{popoverChildren && (
|
|
101
|
-
<PopoverActionButton size={size} variant={variant} isPopoverOpen={isPopoverOpen} />
|
|
101
|
+
<PopoverActionButton size={size} variant={variant} isPopoverOpen={isPopoverOpen} disabled={props.disabled} />
|
|
102
102
|
)}
|
|
103
103
|
</Trilling>
|
|
104
104
|
</Group>
|
|
@@ -107,7 +107,7 @@ export const InputField = forwardRef<HTMLInputElement, Props>(
|
|
|
107
107
|
|
|
108
108
|
|
|
109
109
|
{
|
|
110
|
-
popoverChildren && (
|
|
110
|
+
(popoverChildren && !props.disabled) && (
|
|
111
111
|
<PopoverContent
|
|
112
112
|
theme={theme}
|
|
113
113
|
variant={variant}
|
|
@@ -125,16 +125,16 @@ export const InputField = forwardRef<HTMLInputElement, Props>(
|
|
|
125
125
|
|
|
126
126
|
InputField.displayName = "InputField";
|
|
127
127
|
|
|
128
|
-
const PopoverActionButton = ({ size, variant, isPopoverOpen }: { size: "S" | "M", variant: "SystemStyle" | "PresentationStyle", isPopoverOpen: boolean }) => {
|
|
128
|
+
const PopoverActionButton = ({ size, variant, isPopoverOpen, disabled }: { size: "S" | "M", variant: "SystemStyle" | "PresentationStyle", isPopoverOpen: boolean, disabled?: boolean }) => {
|
|
129
129
|
return (
|
|
130
|
-
<ActionButton size={size}>
|
|
130
|
+
<ActionButton disabled={disabled} size={size}>
|
|
131
131
|
<i
|
|
132
132
|
className={cn(
|
|
133
133
|
"ri-arrow-down-s-line",
|
|
134
134
|
"transition-[transform,rotate]",
|
|
135
135
|
"duration-200",
|
|
136
136
|
"ease-in-out",
|
|
137
|
-
{ "rotate-180": isPopoverOpen },
|
|
137
|
+
{ "rotate-180": (isPopoverOpen && !disabled) },
|
|
138
138
|
{ "!text-[16px]": size === "S" },
|
|
139
139
|
{ "!text-[26px]": size === "M" },
|
|
140
140
|
{ "text-white": variant === "SystemStyle" }
|
|
@@ -77,7 +77,7 @@ const InputOTPSeparator = React.forwardRef<
|
|
|
77
77
|
React.ComponentPropsWithoutRef<"div">
|
|
78
78
|
>(({ ...props }, ref) => (
|
|
79
79
|
<div ref={ref} role="separator" {...props}>
|
|
80
|
-
<i className="ri-subtract-line"></i>
|
|
80
|
+
<i className="ri-subtract-line text-border-presentation-global-primary"></i>
|
|
81
81
|
</div>
|
|
82
82
|
))
|
|
83
83
|
InputOTPSeparator.displayName = "InputOTPSeparator"
|
|
@@ -49,15 +49,14 @@ export const LinkButton: React.FC<Props> = ({ theme, className, size = "S", asCh
|
|
|
49
49
|
className
|
|
50
50
|
)}
|
|
51
51
|
>
|
|
52
|
-
<div className="px-[3px]">{props.children}</div>
|
|
52
|
+
<div className="px-[3px] whitespace-nowrap break-keep">{props.children}</div>
|
|
53
53
|
<div
|
|
54
54
|
className={cn(
|
|
55
55
|
"rounded-[4px]",
|
|
56
56
|
"bg-background-presentation-state-information-primary",
|
|
57
57
|
"transition-all duration-[100] ease-in-out",
|
|
58
58
|
"h-0 w-0 p-0",
|
|
59
|
-
"opacity-0 group-hover:opacity-100",
|
|
60
|
-
"p-[3px]",
|
|
59
|
+
"opacity-0 group-hover:opacity-100 group-hover:p-[3px]",
|
|
61
60
|
{
|
|
62
61
|
"group-hover:w-[20px] group-hover:h-[20px]": size === "S",
|
|
63
62
|
"group-hover:w-[22px] group-hover:h-[22px]": size === "M",
|
|
@@ -227,9 +227,8 @@ const SelectContentStyles = cva(
|
|
|
227
227
|
[
|
|
228
228
|
"p-1",
|
|
229
229
|
"rounded-[8px]",
|
|
230
|
-
"border",
|
|
231
|
-
"max-h-[200px]",
|
|
232
230
|
"min-w-[240px]",
|
|
231
|
+
"border",
|
|
233
232
|
"outline-none",
|
|
234
233
|
"overflow-scroll",
|
|
235
234
|
"data-[state=open]:animate-in",
|
|
@@ -238,6 +237,7 @@ const SelectContentStyles = cva(
|
|
|
238
237
|
"data-[state=open]:fade-in-0",
|
|
239
238
|
"overflow-x-hidden",
|
|
240
239
|
"scrollbar-hide",
|
|
240
|
+
"z-[1000]",
|
|
241
241
|
],
|
|
242
242
|
{
|
|
243
243
|
variants: {
|
|
@@ -408,7 +408,7 @@ const PopoverTriggerStyles = cva(
|
|
|
408
408
|
"[&_span]:h-[28px] [&_span]:w-[28px] [&_p]:typography-body-large-medium",
|
|
409
409
|
],
|
|
410
410
|
XL: [
|
|
411
|
-
"h-[40px] p-[4px] rounded-[6px] [&_span]:h-[32px] [&_span]:w-[32px] [&_p]:typography-body-
|
|
411
|
+
"h-[40px] p-[4px] rounded-[6px] [&_span]:h-[32px] [&_span]:w-[32px] [&_p]:typography-body-large-regular [&_p]:px-[4px]",
|
|
412
412
|
],
|
|
413
413
|
},
|
|
414
414
|
},
|
|
@@ -6,7 +6,7 @@ function Skeleton({
|
|
|
6
6
|
}: React.HTMLAttributes<HTMLDivElement>) {
|
|
7
7
|
return (
|
|
8
8
|
<div
|
|
9
|
-
className={cn("animate-pulse rounded-md bg-primary
|
|
9
|
+
className={cn("animate-pulse rounded-md bg-border-presentation-global-primary", className)}
|
|
10
10
|
{...props}
|
|
11
11
|
/>
|
|
12
12
|
)
|
package/lib/components/Table.tsx
CHANGED
|
@@ -188,9 +188,10 @@ const TableCell = React.forwardRef<
|
|
|
188
188
|
>
|
|
189
189
|
<div
|
|
190
190
|
className={cn(
|
|
191
|
-
"flex justify-start items-center gap-1 w-[200px] min-w-full overflow-hidden",
|
|
191
|
+
"flex justify-start items-center gap-1 w-[200px] min-w-full overflow-hidden has-input:bg-blue-200",
|
|
192
192
|
"[mask-image:linear-gradient(to_right,black_0%,black_0%,black_75%,transparent_100%)]",
|
|
193
193
|
"rtl:[mask-image:linear-gradient(to_left,black_0%,black_0%,black_75%,transparent_100%)]",
|
|
194
|
+
"[&:has(input)]:[mask-image:none]",
|
|
194
195
|
{ "w-auto justify-center": isDummy }, childrenClassName)}
|
|
195
196
|
>
|
|
196
197
|
{props.children}
|
|
@@ -5,7 +5,7 @@ export function useClickOutside<T extends HTMLElement>(callback: (event?: any) =
|
|
|
5
5
|
|
|
6
6
|
useEffect(() => {
|
|
7
7
|
function handleOutsideClick(event: MouseEvent) {
|
|
8
|
-
if (ref.current) {
|
|
8
|
+
if (ref.current && !ref.current.contains(event.target as Node)) {
|
|
9
9
|
callback(event);
|
|
10
10
|
}
|
|
11
11
|
}
|
|
@@ -12,17 +12,27 @@ export interface Tag {
|
|
|
12
12
|
export const useTagSelection = ({
|
|
13
13
|
Tags,
|
|
14
14
|
onTagsChange,
|
|
15
|
-
inputRef
|
|
15
|
+
inputRef,
|
|
16
|
+
singleSelect = false
|
|
16
17
|
}: {
|
|
17
18
|
Tags: Tag[],
|
|
18
19
|
onTagsChange?: (selectedTags: Tag[]) => void,
|
|
19
|
-
inputRef?: React.RefObject<HTMLInputElement | null
|
|
20
|
+
inputRef?: React.RefObject<HTMLInputElement | null>,
|
|
21
|
+
singleSelect?: boolean
|
|
20
22
|
}) => {
|
|
23
|
+
// Split initial tags into selected and unselected
|
|
24
|
+
const initialSelectedTags = Tags.filter(tag => tag.isSelected);
|
|
25
|
+
const initialUnselectedTags = Tags.filter(tag => !tag.isSelected);
|
|
26
|
+
|
|
21
27
|
// Initialize with available tags (excluding any initially selected ones)
|
|
22
|
-
const [tags, setTags] = useState<Tag[]>(
|
|
28
|
+
const [tags, setTags] = useState<Tag[]>(initialUnselectedTags);
|
|
23
29
|
|
|
24
30
|
// Initialize with any pre-selected tags
|
|
25
|
-
const [selectedTagsStack, setSelectedTagsStack] = useState<Tag[]>(
|
|
31
|
+
const [selectedTagsStack, setSelectedTagsStack] = useState<Tag[]>(
|
|
32
|
+
singleSelect && initialSelectedTags.length > 0
|
|
33
|
+
? [initialSelectedTags[0]]
|
|
34
|
+
: initialSelectedTags
|
|
35
|
+
);
|
|
26
36
|
const [searchTags, filterTagsBySearch] = useState('');
|
|
27
37
|
const [focusedTagIndex, setFocusedTagIndex] = useState<number | null>(null);
|
|
28
38
|
const [focusedPopoverIndex, setFocusedPopoverIndex] = useState<number | null>(null);
|
|
@@ -47,11 +57,29 @@ export const useTagSelection = ({
|
|
|
47
57
|
tag.name.toLowerCase().includes(searchTags.toLowerCase())
|
|
48
58
|
);
|
|
49
59
|
|
|
60
|
+
// Filter selected tags based on search input
|
|
61
|
+
const filteredSelectedTags = searchTags.length > 0
|
|
62
|
+
? selectedTagsStack.filter(tag =>
|
|
63
|
+
tag.name.toLowerCase().includes(searchTags.toLowerCase()))
|
|
64
|
+
: selectedTagsStack;
|
|
65
|
+
|
|
50
66
|
const handleSelectTag = (id: string) => {
|
|
51
67
|
const tagToSelect = tags.find(tag => tag.id === id);
|
|
52
68
|
if (tagToSelect) {
|
|
53
|
-
|
|
54
|
-
|
|
69
|
+
// If in single select mode, replace the current selection
|
|
70
|
+
if (singleSelect) {
|
|
71
|
+
// Move any currently selected tag back to available tags
|
|
72
|
+
if (selectedTagsStack.length > 0) {
|
|
73
|
+
const currentSelected = selectedTagsStack[0];
|
|
74
|
+
setTags(prev => [...prev, { ...currentSelected, isSelected: false }]);
|
|
75
|
+
}
|
|
76
|
+
setSelectedTagsStack([{ ...tagToSelect, isSelected: true }]);
|
|
77
|
+
setTags(prev => prev.filter(tag => tag.id !== id));
|
|
78
|
+
} else {
|
|
79
|
+
// Multi-select behavior (original)
|
|
80
|
+
setSelectedTagsStack(prev => [...prev, { ...tagToSelect, isSelected: true }]);
|
|
81
|
+
setTags(prev => prev.filter(tag => tag.id !== id));
|
|
82
|
+
}
|
|
55
83
|
}
|
|
56
84
|
filterTagsBySearch('');
|
|
57
85
|
setFocusedPopoverIndex(null);
|
|
@@ -68,8 +96,13 @@ export const useTagSelection = ({
|
|
|
68
96
|
|
|
69
97
|
// Reset the hook state with new data
|
|
70
98
|
const reset = (newTags: Tag[] = [], newSelectedTags: Tag[] = []) => {
|
|
99
|
+
// In single select mode, ensure we only have at most one selected tag
|
|
100
|
+
const selectedTags = singleSelect && newSelectedTags.length > 0
|
|
101
|
+
? [newSelectedTags[0]]
|
|
102
|
+
: newSelectedTags;
|
|
103
|
+
|
|
71
104
|
setTags(newTags);
|
|
72
|
-
setSelectedTagsStack(
|
|
105
|
+
setSelectedTagsStack(selectedTags);
|
|
73
106
|
filterTagsBySearch('');
|
|
74
107
|
setFocusedTagIndex(null);
|
|
75
108
|
setFocusedPopoverIndex(null);
|
|
@@ -169,11 +202,13 @@ export const useTagSelection = ({
|
|
|
169
202
|
setFocusedPopoverIndex,
|
|
170
203
|
filterTagsBySearch,
|
|
171
204
|
filteredTags,
|
|
205
|
+
filteredSelectedTags,
|
|
172
206
|
focusedTagIndex,
|
|
173
207
|
focusedPopoverIndex,
|
|
174
208
|
isPopoverOpen,
|
|
175
209
|
setIsPopoverOpen,
|
|
176
|
-
reset
|
|
210
|
+
reset,
|
|
211
|
+
singleSelect
|
|
177
212
|
};
|
|
178
213
|
};
|
|
179
214
|
|
|
@@ -58,7 +58,7 @@ export function FieldSection({
|
|
|
58
58
|
</div>
|
|
59
59
|
|
|
60
60
|
{/* Flexible section that takes up the remaining space */}
|
|
61
|
-
<div className="
|
|
61
|
+
<div className="grid grid-cols-1 place-items-end gap-[12px]">{children}</div>
|
|
62
62
|
</section>
|
|
63
63
|
);
|
|
64
64
|
}
|
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "torch-glare",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.1.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"files": [
|
|
7
7
|
"dist",
|
|
8
|
-
"lib"
|
|
8
|
+
"lib",
|
|
9
|
+
"docs"
|
|
9
10
|
],
|
|
10
11
|
"bin": {
|
|
11
12
|
"torch-glare": "dist/bin/index.js"
|
|
@@ -15,7 +16,7 @@
|
|
|
15
16
|
},
|
|
16
17
|
"scripts": {
|
|
17
18
|
"build": "tsc -b",
|
|
18
|
-
"deploy": "tsc && node ./scripts/publish/index.js"
|
|
19
|
+
"deploy": "tsc && node ./scripts/bin/publish/index.js"
|
|
19
20
|
},
|
|
20
21
|
"dependencies": {
|
|
21
22
|
"commander": "^13.1.0",
|